static UniqueResponse message_received_cb (UniqueApp *app, UniqueCommand command, UniqueMessageData *message, guint time_, gpointer user_data) { UniqueResponse res; gchar *feed; debug1(DEBUG_GUI, "libunique command received >>>%d<<<", command); switch (command) { case UNIQUE_ACTIVATE: /* Raise the liferea window */ debug0 (DEBUG_GUI, "-> raise window requested"); liferea_shell_present (); res = UNIQUE_RESPONSE_OK; break; case COMMAND_ADD_FEED: feed = unique_message_data_get_text (message); feedlist_add_subscription (feed, NULL, NULL, 0); res = UNIQUE_RESPONSE_OK; break; default: g_warning ("Received unknown libunique command: >>>%d<<<", command); res = UNIQUE_RESPONSE_OK; break; } return res; }
static void on_newdialog_response (GtkDialog *dialog, gint response_id, gpointer user_data) { NewSubscriptionDialog *nsd = (NewSubscriptionDialog *)user_data; if (response_id == GTK_RESPONSE_OK) { gchar *source = NULL; const gchar *filter = NULL; updateOptionsPtr options; /* Source */ source = ui_subscription_dialog_decode_source (nsd->priv); /* Filter handling */ filter = gtk_entry_get_text (GTK_ENTRY (liferea_dialog_lookup (nsd->priv->dialog, "filterEntry"))); if (!gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (liferea_dialog_lookup (nsd->priv->dialog, "filterCheckbox"))) || !strcmp(filter,"")) { /* Maybe this should be a test to see if the file exists? */ filter = NULL; } options = g_new0 (struct updateOptions, 1); options->dontUseProxy = gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (liferea_dialog_lookup(GTK_WIDGET (dialog), "dontUseProxyCheck"))); feedlist_add_subscription (source, filter, options, FEED_REQ_PRIORITY_HIGH); g_free (source); }
gboolean liferea_dbus_subscribe (LifereaDBus *self, gchar *url, gboolean *ret, GError **err) { liferea_shell_present (); feedlist_add_subscription (url, NULL, NULL, 0); *ret = TRUE; return TRUE; }
/* methods to receive URLs which were dropped anywhere in the main window */ static void liferea_shell_URL_received (GtkWidget *widget, GdkDragContext *context, gint x, gint y, GtkSelectionData *data, guint info, guint time_received) { gchar *tmp1, *tmp2, *freeme; GtkWidget *mainwindow; GtkAllocation alloc; GtkTreeView *treeview; GtkTreeModel *model; GtkTreePath *path; GtkTreeIter iter; nodePtr node; gint tx, ty; g_return_if_fail (gtk_selection_data_get_data (data) != NULL); mainwindow = GTK_WIDGET (shell->priv->window); treeview = GTK_TREE_VIEW (shell->priv->feedlistView); model = gtk_tree_view_get_model (treeview); /* x and y are relative to the main window, make them relative to the treeview */ gtk_widget_translate_coordinates (mainwindow, GTK_WIDGET (treeview), x, y, &tx, &ty); /* Allow link drops only over feed list widget. This is to avoid the frequent accidental text drops in the HTML view. */ gtk_widget_get_allocation(GTK_WIDGET(treeview), &alloc); if((x > alloc.x+alloc.width) || (x < alloc.x) || (y > alloc.y+alloc.height) || (y < alloc.y)) { gtk_drag_finish (context, FALSE, FALSE, time_received); return; } if ((gtk_selection_data_get_length (data) >= 0) && (gtk_selection_data_get_format (data) == 8)) { /* extra handling to accept multiple drops */ freeme = tmp1 = g_strdup (gtk_selection_data_get_data (data)); while ((tmp2 = strsep (&tmp1, "\n\r"))) { if (strlen (tmp2)) { /* if the drop is over a node, select it so that feedlist_add_subscription() * adds it in the correct folder */ if (gtk_tree_view_get_dest_row_at_pos (treeview, tx, ty, &path, NULL)) { if (gtk_tree_model_get_iter (model, &iter, path)) { gtk_tree_model_get (model, &iter, FS_PTR, &node, -1); /* if node is NULL, feed_list_view_select() will unselect the tv */ feed_list_view_select (node); } gtk_tree_path_free (path); } feedlist_add_subscription (g_strdup (tmp2), NULL, NULL, FEED_REQ_PRIORITY_HIGH); } } g_free (freeme); gtk_drag_finish (context, TRUE, FALSE, time_received); } else { gtk_drag_finish (context, FALSE, FALSE, time_received); } }
/* GApplication "open" callback for receiving feed-add requests from remote */ static void on_feed_add (GApplication *application, gpointer files, gint n_files, gchar *hint, gpointer user_data) { GFile **uris = (GFile **)files; /* we always expect only one URI */ g_assert(uris); g_assert(n_files == 1); feedlist_add_subscription (g_file_get_uri (uris[0]), NULL, NULL, 0); }
/* GApplication "activate" callback for normal startup and also processing local feed-add requests (URI passed in user_data). */ static void on_app_activate (GtkApplication *app, gpointer user_data) { GList *list; gchar *feedUri = (gchar *)user_data; list = gtk_application_get_windows (app); if (list) { gtk_window_present (GTK_WINDOW (list->data)); } else { liferea_shell_create (app, initialStateOption); if (feedUri) feedlist_add_subscription (feedUri, NULL, NULL, 0); } }
static void feed_list_view_add_duplicate_url_cb (GtkDialog *dialog, gint response_id, gpointer user_data) { subscriptionPtr tempSubscription = (subscriptionPtr) user_data; if (GTK_RESPONSE_ACCEPT == response_id) { feedlist_add_subscription ( subscription_get_source (tempSubscription), subscription_get_filter (tempSubscription), update_options_copy (tempSubscription->updateOptions), FEED_REQ_PRIORITY_HIGH ); } subscription_free (tempSubscription); gtk_widget_destroy (GTK_WIDGET (dialog)); }
static void on_popup_subscribe_url_activate (GtkWidget *widget, gpointer user_data) { feedlist_add_subscription ((gchar *)user_data, NULL, NULL, 0); }
int main (int argc, char *argv[]) { UniqueApp *app; UniqueMessageData *msg; GError *error = NULL; GOptionContext *context; GOptionGroup *debug; gulong debug_flags = 0; LifereaDBus *dbus = NULL; const gchar *initial_state = "shown"; gchar *feed = NULL; int initialState; gboolean show_tray_icon, start_in_tray; #ifdef USE_SM gchar *opt_session_arg = NULL; #endif GOptionEntry entries[] = { { "mainwindow-state", 'w', 0, G_OPTION_ARG_STRING, &initial_state, N_("Start Liferea with its main window in STATE. STATE may be `shown', `iconified', or `hidden'"), N_("STATE") }, #ifdef USE_SM { "session", 0, G_OPTION_FLAG_HIDDEN, G_OPTION_ARG_STRING, &opt_session_arg, NULL, NULL }, #endif { "version", 'v', G_OPTION_FLAG_NO_ARG, G_OPTION_ARG_CALLBACK, show_version, N_("Show version information and exit"), NULL }, { "add-feed", 'a', 0, G_OPTION_ARG_STRING, &feed, N_("Add a new subscription"), N_("uri") }, { NULL } }; GOptionEntry debug_entries[] = { { "debug-all", 0, G_OPTION_FLAG_NO_ARG, G_OPTION_ARG_CALLBACK, debug_entries_parse_callback, N_("Print debugging messages of all types"), NULL }, { "debug-cache", 0, G_OPTION_FLAG_NO_ARG, G_OPTION_ARG_CALLBACK, debug_entries_parse_callback, N_("Print debugging messages for the cache handling"), NULL }, { "debug-conf", 0, G_OPTION_FLAG_NO_ARG, G_OPTION_ARG_CALLBACK, debug_entries_parse_callback, N_("Print debugging messages for the configuration handling"), NULL }, { "debug-db", 0, G_OPTION_FLAG_NO_ARG, G_OPTION_ARG_CALLBACK, debug_entries_parse_callback, N_("Print debugging messages of the database handling"), NULL }, { "debug-gui", 0, G_OPTION_FLAG_NO_ARG, G_OPTION_ARG_CALLBACK, debug_entries_parse_callback, N_("Print debugging messages of all GUI functions"), NULL }, { "debug-html", 0, G_OPTION_FLAG_NO_ARG, G_OPTION_ARG_CALLBACK, debug_entries_parse_callback, N_("Enables HTML rendering debugging. Each time Liferea renders HTML output it will also dump the generated HTML into ~/.liferea_1.6/output.xhtml"), NULL }, { "debug-net", 0, G_OPTION_FLAG_NO_ARG, G_OPTION_ARG_CALLBACK, debug_entries_parse_callback, N_("Print debugging messages of all network activity"), NULL }, { "debug-parsing", 0, G_OPTION_FLAG_NO_ARG, G_OPTION_ARG_CALLBACK, debug_entries_parse_callback, N_("Print debugging messages of all parsing functions"), NULL }, { "debug-performance", 0, G_OPTION_FLAG_NO_ARG, G_OPTION_ARG_CALLBACK, debug_entries_parse_callback, N_("Print debugging messages when a function takes too long to process"), NULL }, { "debug-trace", 0, G_OPTION_FLAG_NO_ARG, G_OPTION_ARG_CALLBACK, debug_entries_parse_callback, N_("Print debugging messages when entering/leaving functions"), NULL }, { "debug-update", 0, G_OPTION_FLAG_NO_ARG, G_OPTION_ARG_CALLBACK, debug_entries_parse_callback, N_("Print debugging messages of the feed update processing"), NULL }, { "debug-vfolder", 0, G_OPTION_FLAG_NO_ARG, G_OPTION_ARG_CALLBACK, debug_entries_parse_callback, N_("Print debugging messages of the search folder matching"), NULL }, { "debug-verbose", 0, G_OPTION_FLAG_NO_ARG, G_OPTION_ARG_CALLBACK, debug_entries_parse_callback, N_("Print verbose debugging messages"), NULL }, { NULL } }; if (!g_thread_supported ()) g_thread_init (NULL); #ifdef ENABLE_NLS bindtextdomain (GETTEXT_PACKAGE, PACKAGE_LOCALE_DIR); bind_textdomain_codeset (GETTEXT_PACKAGE, "UTF-8"); textdomain (GETTEXT_PACKAGE); #endif debug = g_option_group_new ("debug", _("Print debugging messages for the given topic"), _("Print debugging messages for the given topic"), &debug_flags, NULL); g_option_group_set_translation_domain(debug, GETTEXT_PACKAGE); g_option_group_add_entries (debug, debug_entries); context = g_option_context_new (NULL); g_option_context_set_summary (context, N_("Liferea, the Linux Feed Reader")); g_option_context_set_description (context, N_("For more information, please visit http://liferea.sourceforge.net/")); g_option_context_add_main_entries (context, entries, GETTEXT_PACKAGE); g_option_context_set_translation_domain(context, GETTEXT_PACKAGE); g_option_context_add_group (context, debug); g_option_context_add_group (context, gtk_get_option_group (FALSE)); g_option_context_parse (context, &argc, &argv, &error); g_option_context_free (context); if (error) { g_print ("Error parsing options: %s\n", error->message); } set_debug_level (debug_flags); /* Configuration necessary for network options, so it has to be initialized before update_init() */ conf_init (); #ifdef USE_DBUS dbus_g_thread_init (); #endif /* We need to do the network initialization here to allow network-manager to be setup before gtk_init() */ update_init (); gtk_init (&argc, &argv); /* Single instance checks */ app = unique_app_new_with_commands ("net.sourceforge.liferea", NULL, "add_feed", COMMAND_ADD_FEED, NULL); if (unique_app_is_running (app)) { g_print ("Liferea is already running\n"); unique_app_send_message (app, UNIQUE_ACTIVATE, NULL); if (feed) { msg = unique_message_data_new (); unique_message_data_set_text (msg, feed, -1); unique_app_send_message (app, COMMAND_ADD_FEED, msg); } return 1; } else { g_signal_connect (app, "message-received", G_CALLBACK (message_received_cb), NULL); } /* GTK theme support */ g_set_application_name (_("Liferea")); gtk_window_set_default_icon_name ("liferea"); debug_start_measurement (DEBUG_DB); /* order is important! */ db_init (); /* initialize sqlite */ xml_init (); /* initialize libxml2 */ #ifdef HAVE_LIBNOTIFY notification_plugin_register (&libnotify_plugin); #endif social_init (); /* initialize social bookmarking */ #ifdef USE_DBUS dbus = liferea_dbus_new (); #else debug0 (DEBUG_GUI, "Compiled without DBUS support."); #endif #ifdef USE_AVAHI if (conf_get_bool_value (SYNC_AVAHI_ENABLED)) { LifereaAvahiPublisher *avahiPublisher = NULL; debug0 (DEBUG_CACHE, "Registering with AVAHI"); avahiPublisher = liferea_avahi_publisher_new (); liferea_avahi_publisher_publish (avahiPublisher, conf_get_str_value (SYNC_AVAHI_SERVICE_NAME), 23632); } else { debug0 (DEBUG_CACHE, "Avahi support available, but disabled by preferences."); } #else debug0 (DEBUG_CACHE, "Compiled without AVAHI support"); #endif /* how to start liferea, command line takes precedence over preferences */ conf_get_bool_value (SHOW_TRAY_ICON, &show_tray_icon); conf_get_bool_value (START_IN_TRAY, &start_in_tray); if (g_str_equal(initial_state, "iconified")) { initialState = MAINWINDOW_ICONIFIED; } else if (g_str_equal(initial_state, "hidden") || (show_tray_icon && start_in_tray)) { initialState = MAINWINDOW_HIDDEN; } else { initialState = MAINWINDOW_SHOWN; } liferea_shell_create (initialState); g_set_prgname ("liferea"); #ifdef USE_SM /* This must be after feedlist reading because some session managers will tell Liferea to exit if Liferea does not respond to SM requests within a minute or two. This starts the main loop soon after opening the SM connection. */ session_init (BIN_DIR G_DIR_SEPARATOR_S "liferea", opt_session_arg); session_set_cmd (NULL, initialState); #endif signal (SIGTERM, signal_handler); signal (SIGINT, signal_handler); signal (SIGHUP, signal_handler); #ifndef G_OS_WIN32 signal (SIGBUS, fatal_signal_handler); signal (SIGSEGV, fatal_signal_handler); #endif /* Note: we explicitely do not use the gdk_thread_* locking in Liferea because it freezes the program when running Flash applets in gtkmozembed */ runState = STATE_STARTING; debug_end_measurement (DEBUG_DB, "startup"); if (feed) feedlist_add_subscription (feed, NULL, NULL, 0); gtk_main (); g_object_unref (G_OBJECT (dbus)); return 0; }