void subscription_update (subscriptionPtr subscription, guint flags) { updateRequestPtr request; GTimeVal now; if (!subscription) return; if (subscription->updateJob) return; debug1 (DEBUG_UPDATE, "Scheduling %s to be updated", node_get_title (subscription->node)); if (subscription_can_be_updated (subscription)) { liferea_shell_set_status_bar (_("Updating \"%s\""), node_get_title (subscription->node)); g_get_current_time (&now); subscription_reset_update_counter (subscription, &now); request = update_request_new (); request->updateState = update_state_copy (subscription->updateState); request->options = update_options_copy (subscription->updateOptions); request->source = g_strdup (subscription_get_source (subscription)); if (subscription_get_filter (subscription)) request->filtercmd = g_strdup (subscription_get_filter (subscription)); if (SUBSCRIPTION_TYPE (subscription)->prepare_update_request (subscription, request)) subscription->updateJob = update_execute_request (subscription, request, subscription_process_update_result, subscription, flags); else update_request_free (request); } }
void subscription_update_favicon (subscriptionPtr subscription) { debug1 (DEBUG_UPDATE, "trying to download favicon.ico for \"%s\"", node_get_title (subscription->node)); liferea_shell_set_status_bar (_("Updating favicon for \"%s\""), node_get_title (subscription->node)); g_get_current_time (&subscription->updateState->lastFaviconPoll); favicon_download (subscription, node_get_base_url (subscription->node), subscription_get_source (subscription), subscription->updateOptions, // FIXME: correct? subscription_favicon_downloaded, (gpointer)subscription->node); }
void feed_list_view_add_duplicate_url_subscription (subscriptionPtr tempSubscription, nodePtr exNode) { GtkWidget *dialog; GtkWindow *mainwindow; gchar *text; text = g_strdup_printf ( _("Are you sure that you want to add a new subscription with URL \"%s\"? Another subscription with the same URL already exists (\"%s\")."), tempSubscription->source, node_get_title (exNode) ); mainwindow = GTK_WINDOW (liferea_shell_get_window ()); dialog = gtk_message_dialog_new (mainwindow, GTK_DIALOG_DESTROY_WITH_PARENT | GTK_DIALOG_MODAL, GTK_MESSAGE_QUESTION, GTK_BUTTONS_NONE, "%s", text); gtk_dialog_add_buttons (GTK_DIALOG (dialog), _("_Cancel"), GTK_RESPONSE_CANCEL, _("_Add"), GTK_RESPONSE_ACCEPT, NULL); gtk_window_set_title (GTK_WINDOW (dialog), _("Adding Duplicate Subscription Confirmation")); gtk_window_set_transient_for (GTK_WINDOW (dialog), mainwindow); g_free (text); gtk_widget_show_all (dialog); g_signal_connect (G_OBJECT (dialog), "response", G_CALLBACK (feed_list_view_add_duplicate_url_cb), tempSubscription); }
/* * Check if folder of a node changed in Google Reader and move * node to the folder with the same name. */ static void aol_source_update_folder (xmlNodePtr match, AolSourcePtr gsource, nodePtr node) { xmlNodePtr xml; xmlChar *label; const gchar *ptitle; nodePtr parent; /* check if label of a feed changed */ parent = node->parent; ptitle = node_get_title (parent); xml = xpath_find (match, "./list[@name='categories']/object/string[@name='label']"); if (xml) { label = xmlNodeListGetString (xml->doc, xml->xmlChildrenNode, 1); if (parent == gsource->root || ! g_str_equal (label, ptitle)) { debug2 (DEBUG_UPDATE, "GSource feed label changed for %s to '%s'", node->id, label); parent = aol_source_find_or_create_folder ((gchar*)label, gsource->root); node_reparent (node, parent); } xmlFree (label); } else { /* if feed has no label and parent is not gsource root, reparent to gsource root */ if (parent != gsource->root) node_reparent (node, gsource->root); } }
void feedlist_selection_changed (nodePtr node) { debug_enter ("feedlist_selection_changed"); debug1 (DEBUG_GUI, "new selected node: %s", node?node_get_title (node):"none"); if (node != SELECTED) { /* When the user selects a feed in the feed list we assume that he got notified of the new items or isn't interested in the event anymore... */ if (0 != feedlist->priv->newCount) feedlist_reset_new_item_count (); /* Unload visible items. */ itemlist_unload (TRUE); /* Load items of new selected node. */ SELECTED = node; if (SELECTED) { itemlist_set_view_mode (node_get_view_mode (SELECTED)); itemlist_load (SELECTED); } else { itemview_clear (); } } debug_exit ("feedlist_selection_changed"); }
/** * To be called whenever a node was selected and should * replace the current itemlist. */ void itemlist_load (nodePtr node) { itemSetPtr itemSet; gint folder_display_mode; gboolean folder_display_hide_read; debug_enter ("itemlist_load"); g_return_if_fail (NULL != node); debug1 (DEBUG_GUI, "loading item list with node \"%s\"", node_get_title (node)); g_assert (!itemlist->priv->guids); g_assert (!itemlist->priv->filter); /* 1. Filter check. Don't continue if folder is selected and no folder viewing is configured. If folder viewing is enabled set up a "unread items only" rule depending on the prefences. */ /* for folders and other heirarchic nodes do filtering */ if (IS_FOLDER (node) || node->children) { liferea_shell_update_allitems_actions (FALSE, 0 != node->unreadCount); conf_get_int_value (FOLDER_DISPLAY_MODE, &folder_display_mode); if (!folder_display_mode) return; conf_get_bool_value (FOLDER_DISPLAY_HIDE_READ, &folder_display_hide_read); if (folder_display_hide_read) { itemlist->priv->filter = g_new0(struct itemSet, 1); itemlist->priv->filter->anyMatch = TRUE; itemset_add_rule (itemlist->priv->filter, "unread", "", TRUE); } } else {
static void feed_list_view_selection_changed_cb (GtkTreeSelection *selection, gpointer data) { GtkTreeIter iter; GtkTreeModel *model; nodePtr node; if (gtk_tree_selection_get_selected (selection, &model, &iter)) { gtk_tree_model_get (model, &iter, FS_PTR, &node, -1); debug1 (DEBUG_GUI, "feed list selection changed to \"%s\"", node_get_title (node)); /* 1.) update feed list and item list states */ g_signal_emit_by_name (FEED_LIST_VIEW (flv), "selection-changed", node->id); /* 2.) Refilter the GtkTreeView to get rid of nodes with 0 unread messages when in reduced mode. */ gtk_tree_model_filter_refilter (GTK_TREE_MODEL_FILTER (flv->filter)); if (node) { gboolean allowModify = (NODE_SOURCE_TYPE (node->source->root)->capabilities & NODE_SOURCE_CAPABILITY_WRITABLE_FEEDLIST); liferea_shell_update_update_menu ((NODE_TYPE (node)->capabilities & NODE_CAPABILITY_UPDATE) || (NODE_TYPE (node)->capabilities & NODE_CAPABILITY_UPDATE_CHILDS)); liferea_shell_update_feed_menu (allowModify, TRUE, allowModify); } else { liferea_shell_update_feed_menu (TRUE, FALSE, FALSE); } } else { /* If we cannot get the new selection we keep the old one this happens when we're doing drag&drop for example. */ } }
/* * Find a node by the name under root or create it. */ static nodePtr theoldreader_source_find_or_create_folder (const gchar *name, nodePtr root) { nodePtr folder = NULL; GSList *iter_parent; /* find a node by the name under root */ iter_parent = root->children; while (iter_parent) { if (g_str_equal (name, node_get_title (iter_parent->data))) { folder = (nodePtr)iter_parent->data; break; } iter_parent = g_slist_next (iter_parent); } /* if not found, create new folder */ if (!folder) { folder = node_new (folder_get_node_type ()); node_set_title (folder, name); node_set_parent (folder, root, -1); feedlist_node_imported (folder); subscription_update (folder->subscription, FEED_REQ_RESET_TITLE | FEED_REQ_PRIORITY_HIGH); } return folder; }
void feed_list_node_remove (nodePtr node) { GtkWidget *dialog; GtkWindow *mainwindow; gchar *text; g_assert (node == feedlist_get_selected ()); liferea_shell_set_status_bar ("%s \"%s\"", _("Deleting entry"), node_get_title (node)); text = g_strdup_printf (IS_FOLDER (node)?_("Are you sure that you want to delete \"%s\" and its contents?"):_("Are you sure that you want to delete \"%s\"?"), node_get_title (node)); mainwindow = GTK_WINDOW (liferea_shell_get_window ()); dialog = gtk_message_dialog_new (mainwindow, GTK_DIALOG_DESTROY_WITH_PARENT | GTK_DIALOG_MODAL, GTK_MESSAGE_QUESTION, GTK_BUTTONS_NONE, "%s", text); gtk_dialog_add_buttons (GTK_DIALOG (dialog), "_Cancel", GTK_RESPONSE_CANCEL, "_Delete", GTK_RESPONSE_ACCEPT, NULL); gtk_window_set_title (GTK_WINDOW (dialog), _("Deletion Confirmation")); gtk_window_set_modal (GTK_WINDOW (dialog), TRUE); gtk_window_set_transient_for (GTK_WINDOW (dialog), mainwindow); g_free (text); gtk_widget_show_all (dialog); g_signal_connect (G_OBJECT (dialog), "response", G_CALLBACK (feed_list_node_remove_cb), node); }
/** Use to create new search folders and to edit existing ones */ SearchFolderDialog * search_folder_dialog_new (nodePtr node) { GtkWidget *dialog; SearchFolderDialog *sfd; sfd = SEARCH_FOLDER_DIALOG (g_object_new (SEARCH_FOLDER_DIALOG_TYPE, NULL)); sfd->priv->node = node; sfd->priv->vfolder = (vfolderPtr)node->data; sfd->priv->re = rule_editor_new (sfd->priv->vfolder->itemset); /* Create the dialog */ dialog = liferea_dialog_new (NULL, "vfolderdialog"); /* Setup search folder name */ sfd->priv->nameEntry = liferea_dialog_lookup (dialog, "searchNameEntry"); gtk_entry_set_text (GTK_ENTRY (sfd->priv->nameEntry), node_get_title (node)); /* Set up rule match type */ gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (liferea_dialog_lookup (dialog, sfd->priv->vfolder->itemset->anyMatch?"anyRuleRadioBtn":"allRuleRadioBtn")), TRUE); /* Set up rule list vbox */ gtk_container_add (GTK_CONTAINER (liferea_dialog_lookup (dialog, "ruleview_vfolder_dialog")), rule_editor_get_widget (sfd->priv->re)); /* bind buttons */ g_signal_connect (liferea_dialog_lookup (dialog, "addrulebtn"), "clicked", G_CALLBACK (on_addrulebtn_clicked), sfd); g_signal_connect (G_OBJECT (dialog), "response", G_CALLBACK (on_propdialog_response), sfd); return sfd; }
void node_reparent (nodePtr node, nodePtr new_parent) { nodePtr old_parent; g_assert (NULL != new_parent); g_assert (NULL != node); debug2 (DEBUG_GUI, "Reparenting node '%s' to a parent '%s'", node_get_title(node), node_get_title(new_parent)); old_parent = node->parent; if (NULL != old_parent) old_parent->children = g_slist_remove (old_parent->children, node); new_parent->children = g_slist_insert (new_parent->children, node, -1); node->parent = new_parent; feed_list_view_remove_node (node); feed_list_view_add_node (node); }
static void ui_update_merge_request(nodePtr node, GtkTreeStore *store, GHashTable *hash) { GtkTreeIter *iter; if(NULL != (iter = (GtkTreeIter *)g_hash_table_lookup(hash, (gpointer)node->id))) return; iter = g_new0(GtkTreeIter, 1); gtk_tree_store_append(store, iter, NULL); gtk_tree_store_set(store, iter, UM_REQUEST_TITLE, node_get_title(node), UM_FAVICON, node_get_icon(node), -1); g_hash_table_insert(hash, (gpointer)node->id, (gpointer)iter); }
void feed_list_view_rename_node (nodePtr node) { GtkWidget *nameentry, *dialog; dialog = liferea_dialog_new ("rename_node"); nameentry = liferea_dialog_lookup (dialog, "nameentry"); gtk_entry_set_text (GTK_ENTRY (nameentry), node_get_title (node)); g_signal_connect (G_OBJECT (dialog), "response", G_CALLBACK (on_nodenamedialog_response), node); gtk_widget_show (dialog); }
static void google_source_check_for_removal (nodePtr node, gpointer user_data) { gchar *expr = NULL; if (g_str_equal (node->subscription->source, GOOGLE_READER_BROADCAST_FRIENDS_URL)) return ; if (IS_FEED (node)) { expr = g_strdup_printf ("/object/list[@name='subscriptions']/object/string[@name='id'][. = 'feed/%s']", node->subscription->source); } else { g_warning ("opml_source_check_for_removal(): This should never happen..."); return; } if (!xpath_find ((xmlNodePtr)user_data, expr)) { debug1 (DEBUG_UPDATE, "removing %s...", node_get_title (node)); feedlist_node_removed (node); } else { debug1 (DEBUG_UPDATE, "keeping %s...", node_get_title (node)); } g_free (expr); }
static void theoldreader_source_check_for_removal (nodePtr node, gpointer user_data) { gchar *expr = NULL; if (IS_FEED (node)) { expr = g_strdup_printf ("/object/list[@name='subscriptions']/object/string[@name='id'][. = 'feed/%s']", node->subscription->source); } else if (IS_FOLDER (node)) { node_foreach_child_data (node, theoldreader_source_check_for_removal, user_data); expr = g_strdup_printf ("/object/list[@name='subscriptions']/object/list[@name='categories']/object[string='%s']", node->title); } else { g_warning ("theoldreader_source_check_for_removal(): This should never happen..."); return; } if (!xpath_find ((xmlNodePtr)user_data, expr)) { debug1 (DEBUG_UPDATE, "removing %s...", node_get_title (node)); feedlist_node_removed (node); } else { debug1 (DEBUG_UPDATE, "keeping %s...", node_get_title (node)); } g_free (expr); }
void feed_list_node_rename (nodePtr node) { GtkWidget *nameentry; if (!nodenamedialog || !G_IS_OBJECT (nodenamedialog)) nodenamedialog = liferea_dialog_new (NULL, "nodenamedialog"); nameentry = liferea_dialog_lookup (nodenamedialog, "nameentry"); gtk_entry_set_text (GTK_ENTRY (nameentry), node_get_title (node)); g_signal_connect (G_OBJECT (nodenamedialog), "response", G_CALLBACK (on_nodenamedialog_response), node); gtk_widget_show (nodenamedialog); }
static void vfolder_import (nodePtr node, nodePtr parent, xmlNodePtr cur, gboolean trusted) { vfolderPtr vfolder; debug1 (DEBUG_CACHE, "import vfolder: title=%s", node_get_title (node)); vfolder = vfolder_new (node); vfolder->itemset = db_search_folder_load (node->id); vfolder_import_rules (cur, vfolder); }
static void vfolder_import_rules (xmlNodePtr cur, vfolderPtr vfolder) { xmlChar *matchType, *type, *ruleId, *value, *additive; matchType = xmlGetProp (cur, BAD_CAST"matchType"); if (matchType) { /* currently we only OR or AND the rules, "any" is the value for OR'ing, "all" for AND'ing */ vfolder->itemset->anyMatch = (0 != xmlStrcmp (matchType, BAD_CAST"all")); } else { vfolder->itemset->anyMatch = TRUE; } xmlFree (matchType); /* process any children */ cur = cur->xmlChildrenNode; while (cur) { if (!xmlStrcmp (cur->name, BAD_CAST"outline")) { type = xmlGetProp (cur, BAD_CAST"type"); if (type && !xmlStrcmp (type, BAD_CAST"rule")) { ruleId = xmlGetProp (cur, BAD_CAST"rule"); value = xmlGetProp (cur, BAD_CAST"value"); additive = xmlGetProp (cur, BAD_CAST"additive"); if (ruleId && value) { debug2 (DEBUG_CACHE, "loading rule \"%s\" \"%s\"", ruleId, value); if (additive && !xmlStrcmp (additive, BAD_CAST"true")) itemset_add_rule (vfolder->itemset, ruleId, value, TRUE); else itemset_add_rule (vfolder->itemset, ruleId, value, FALSE); } else { g_warning ("ignoring invalid rule entry for vfolder \"%s\"...\n", node_get_title (vfolder->node)); } xmlFree (ruleId); xmlFree (value); xmlFree (additive); } xmlFree (type); } cur = cur->next; } }
static void auth_dialog_load (AuthDialog *ad, subscriptionPtr subscription, gint flags) { AuthDialogPrivate *ui_data = ad->priv; gchar *promptStr; gchar *source = NULL; xmlURIPtr uri; subscription->activeAuth = TRUE; ui_data->subscription = subscription; ui_data->flags = flags; ui_data->username = liferea_dialog_lookup (ui_data->dialog, "usernameEntry"); ui_data->password = liferea_dialog_lookup (ui_data->dialog, "passwordEntry"); uri = xmlParseURI (BAD_CAST subscription_get_source (ui_data->subscription)); if (uri) { if (uri->user) { gchar *user = uri->user; gchar *pass = strstr (user, ":"); if(pass) { pass[0] = '\0'; pass++; gtk_entry_set_text (GTK_ENTRY (ui_data->password), pass); } gtk_entry_set_text (GTK_ENTRY (ui_data->username), user); xmlFree (uri->user); uri->user = NULL; } xmlFree (uri->user); uri->user = NULL; source = xmlSaveUri (uri); xmlFreeURI (uri); } promptStr = g_strdup_printf ( _("Enter the username and password for \"%s\" (%s):"), node_get_title (ui_data->subscription->node), source?source:_("Unknown source")); gtk_label_set_text (GTK_LABEL (liferea_dialog_lookup (ui_data->dialog, "prompt")), promptStr); g_free (promptStr); if (source) xmlFree (source); }
/** * To be called whenever an itemset was updated. If it is the * displayed itemset it will be merged against the item list * tree view. */ void itemlist_merge_itemset (itemSetPtr itemSet) { gint folder_display_mode; debug_enter ("itemlist_merge_itemset"); debug_start_measurement (DEBUG_GUI); /* No node check when loading search results directly */ if (!itemlist_priv.isSearchResult) { nodePtr node = node_from_id (itemSet->nodeId); if (!itemlist_priv.currentNode) return; /* Nothing to do if nothing is displayed */ if (!IS_VFOLDER (itemlist_priv.currentNode) && (itemlist_priv.currentNode != node) && !node_is_ancestor (itemlist_priv.currentNode, node)) return; /* Nothing to do if the item set does not belong to this node, or this is a search folder */ conf_get_int_value (FOLDER_DISPLAY_MODE, &folder_display_mode); if (IS_FOLDER (itemlist_priv.currentNode) && !folder_display_mode) return; /* Bail out if it is a folder without the recursive display preference set */ debug1 (DEBUG_GUI, "reloading item list with node \"%s\"", node_get_title (node)); } else { /* If we are loading a search result we must never merge anything besides the search items. In fact if we already have items we just return. */ if (itemlist_priv.searchResultComplete) return; itemlist_priv.searchResultComplete = TRUE; } /* merge items into item view */ itemset_foreach (itemSet, itemlist_merge_item); itemview_update (); debug_end_measurement (DEBUG_GUI, "itemlist merge"); debug_exit ("itemlist_merge_itemset"); }
/* Checks whether updating a feed makes sense. */ static gboolean subscription_can_be_updated (subscriptionPtr subscription) { if (subscription->updateJob) { liferea_shell_set_status_bar (_("Subscription \"%s\" is already being updated!"), node_get_title (subscription->node)); return FALSE; } if (subscription->discontinued) { liferea_shell_set_status_bar (_("The subscription \"%s\" was discontinued. Liferea won't update it anymore!"), node_get_title (subscription->node)); return FALSE; } if (!subscription_get_source (subscription)) { g_warning ("Feed source is NULL! This should never happen - cannot update!"); return FALSE; } return TRUE; }
void on_action_mark_all_read (GSimpleAction *action, GVariant *parameter, gpointer user_data) { nodePtr feedlist; gboolean confirm_mark_read; gboolean do_mark_read = TRUE; if (!g_strcmp0 (g_action_get_name (G_ACTION (action)), "mark-all-feeds-read")) feedlist = feedlist_get_root (); else if (user_data) feedlist = (nodePtr) user_data; else feedlist = feedlist_get_selected (); conf_get_bool_value (CONFIRM_MARK_ALL_READ, &confirm_mark_read); if (confirm_mark_read) { gint result; GtkMessageDialog *confirm_dialog = GTK_MESSAGE_DIALOG (liferea_dialog_new ("mark_read_dialog")); GtkWidget *dont_ask_toggle = liferea_dialog_lookup (GTK_WIDGET (confirm_dialog), "dontAskAgainToggle"); const gchar *feed_title = (feedlist_get_root () == feedlist) ? _("all feeds"):node_get_title (feedlist); gchar *primary_message = g_strdup_printf (_("Mark %s as read ?"), feed_title); g_object_set (confirm_dialog, "text", primary_message, NULL); g_free (primary_message); gtk_message_dialog_format_secondary_text (confirm_dialog, _("Are you sure you want to mark all items in %s as read ?"), feed_title); conf_bind (CONFIRM_MARK_ALL_READ, dont_ask_toggle, "active", G_SETTINGS_BIND_DEFAULT | G_SETTINGS_BIND_INVERT_BOOLEAN); result = gtk_dialog_run (GTK_DIALOG (confirm_dialog)); if (result != GTK_RESPONSE_OK) do_mark_read = FALSE; gtk_widget_destroy (GTK_WIDGET (confirm_dialog)); } if (do_mark_read) feedlist_mark_all_read (feedlist); }
static xmlDocPtr node_to_xml (nodePtr node) { xmlDocPtr doc; xmlNodePtr rootNode; gchar *tmp; doc = xmlNewDoc("1.0"); rootNode = xmlNewDocNode(doc, NULL, "node", NULL); xmlDocSetRootElement(doc, rootNode); xmlNewTextChild(rootNode, NULL, "title", node_get_title(node)); tmp = g_strdup_printf("%u", node->unreadCount); xmlNewTextChild(rootNode, NULL, "unreadCount", tmp); g_free(tmp); tmp = g_strdup_printf("%u", g_slist_length(node->children)); xmlNewTextChild(rootNode, NULL, "children", tmp); g_free(tmp); return doc; }
void feed_list_node_add (nodePtr node) { gint position; GtkTreeIter *iter, *parentIter = NULL; debug2 (DEBUG_GUI, "adding node \"%s\" as child of parent=\"%s\"", node_get_title(node), (NULL != node->parent)?node_get_title(node->parent):"feed list root"); g_assert (NULL != node->parent); g_assert (NULL == feed_list_node_to_iter (node->id)); /* if parent is NULL we have the root folder and don't create a new row! */ iter = (GtkTreeIter *)g_new0 (GtkTreeIter, 1); /* if reduced feedlist, show flat treeview */ if (feedlist_reduced_unread) parentIter = NULL; else if (node->parent != feedlist_get_root ()) parentIter = feed_list_node_to_iter (node->parent->id); position = g_slist_index (node->parent->children, node); if (feedlist_reduced_unread || position < 0) gtk_tree_store_append (feedstore, iter, parentIter); else gtk_tree_store_insert (feedstore, iter, parentIter, position); gtk_tree_store_set (feedstore, iter, FS_PTR, node, -1); feed_list_node_add_iter (node->id, iter); feed_list_node_update (node->id); if (node->parent != feedlist_get_root ()) feed_list_node_check_if_folder_is_empty (node->parent->id); if (IS_FOLDER (node)) feed_list_node_check_if_folder_is_empty (node->id); }
/* Helper method checking if the passed item set is relevant for the currently item list content. */ static gboolean itemlist_itemset_is_valid (itemSetPtr itemSet) { gint folder_display_mode; nodePtr node; node = node_from_id (itemSet->nodeId); if (!itemlist->priv->currentNode) return FALSE; /* Nothing to do if nothing is displayed */ if (!IS_VFOLDER (itemlist->priv->currentNode) && (itemlist->priv->currentNode != node) && !node_is_ancestor (itemlist->priv->currentNode, node)) return FALSE; /* Nothing to do if the item set does not belong to this node, or this is a search folder */ conf_get_int_value (FOLDER_DISPLAY_MODE, &folder_display_mode); if (IS_FOLDER (itemlist->priv->currentNode) && !folder_display_mode) return FALSE; /* Bail out if it is a folder without the recursive display preference set */ debug1 (DEBUG_GUI, "reloading item list with node \"%s\"", node_get_title (node)); return TRUE; }
static void vfolder_export (nodePtr node, xmlNodePtr cur, gboolean trusted) { vfolderPtr vfolder = (vfolderPtr) node->data; xmlNodePtr ruleNode; rulePtr rule; GSList *iter; debug_enter ("vfolder_export"); g_assert (TRUE == trusted); xmlNewProp (cur, BAD_CAST"matchType", BAD_CAST (vfolder->itemset->anyMatch?"any":"all")); iter = vfolder->itemset->rules; while (iter) { rule = iter->data; ruleNode = xmlNewChild (cur, NULL, BAD_CAST"outline", NULL); xmlNewProp (ruleNode, BAD_CAST"type", BAD_CAST "rule"); xmlNewProp (ruleNode, BAD_CAST"text", BAD_CAST rule->ruleInfo->title); xmlNewProp (ruleNode, BAD_CAST"rule", BAD_CAST rule->ruleInfo->ruleId); xmlNewProp (ruleNode, BAD_CAST"value", BAD_CAST rule->value); if (rule->additive) xmlNewProp (ruleNode, BAD_CAST"additive", BAD_CAST "true"); else xmlNewProp (ruleNode, BAD_CAST"additive", BAD_CAST "false"); iter = g_slist_next (iter); } debug1 (DEBUG_CACHE, "adding vfolder: title=%s", node_get_title (node)); debug_exit ("vfolder_export"); }
static void subscription_prop_dialog_load (SubscriptionPropDialog *spd, subscriptionPtr subscription) { gint interval; gint default_update_interval; gint defaultInterval, spinSetInterval; gchar *defaultIntervalStr; nodePtr node = subscription->node; feedPtr feed = (feedPtr)node->data; spd->priv->subscription = subscription; /* General */ gtk_entry_set_text(GTK_ENTRY(spd->priv->feedNameEntry), node_get_title(node)); spd->priv->refreshInterval = liferea_dialog_lookup(spd->priv->dialog,"refreshIntervalSpinButton"); interval = subscription_get_update_interval(subscription); defaultInterval = subscription_get_default_update_interval(subscription); conf_get_int_value (DEFAULT_UPDATE_INTERVAL, &default_update_interval); spinSetInterval = defaultInterval > 0 ? defaultInterval : default_update_interval; if (-2 >= interval) { gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (liferea_dialog_lookup(spd->priv->dialog, "updateIntervalNever")), TRUE); } else if (-1 == interval) { gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (liferea_dialog_lookup(spd->priv->dialog, "updateIntervalDefault")), TRUE); } else { gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (liferea_dialog_lookup(spd->priv->dialog, "updateIntervalSpecific")), TRUE); spinSetInterval = interval; } /* Set refresh interval spin button and combo box */ if (spinSetInterval % 1440 == 0) { /* days */ gtk_combo_box_set_active (GTK_COMBO_BOX (spd->priv->refreshIntervalUnit), 2); spinSetInterval /= 1440; } else if (spinSetInterval % 60 == 0) { /* hours */ gtk_combo_box_set_active (GTK_COMBO_BOX (spd->priv->refreshIntervalUnit), 1); spinSetInterval /= 60; } else { gtk_combo_box_set_active (GTK_COMBO_BOX (spd->priv->refreshIntervalUnit), 0); } gtk_spin_button_set_value (GTK_SPIN_BUTTON (spd->priv->refreshInterval), spinSetInterval); gtk_widget_set_sensitive (spd->priv->refreshInterval, interval > 0); gtk_widget_set_sensitive (spd->priv->refreshIntervalUnit, interval > 0); /* setup info label about default update interval */ if(-1 != defaultInterval) defaultIntervalStr = g_strdup_printf(ngettext("The provider of this feed suggests an update interval of %d minute.", "The provider of this feed suggests an update interval of %d minutes.", defaultInterval), defaultInterval); else defaultIntervalStr = g_strdup(_("This feed specifies no default update interval.")); gtk_label_set_text(GTK_LABEL(liferea_dialog_lookup(spd->priv->dialog, "feedUpdateInfo")), defaultIntervalStr); g_free(defaultIntervalStr); /* Source (only for feeds) */ if (SUBSCRIPTION_TYPE(subscription) == feed_get_subscription_type ()) { if(subscription_get_source(subscription)[0] == '|') { gtk_entry_set_text(GTK_ENTRY(spd->priv->sourceEntry), &(subscription_get_source(subscription)[1])); gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(spd->priv->cmdRadio), TRUE); ui_subscription_prop_enable_httpauth(spd->priv, FALSE); gtk_widget_set_sensitive(spd->priv->selectFile, TRUE); } else if(strstr(subscription_get_source(subscription), "://") != NULL) { xmlURIPtr uri = xmlParseURI(BAD_CAST subscription_get_source(subscription)); xmlChar *parsedUrl; if(uri) { if(uri->user) { gchar *user = uri->user; gchar *pass = strstr(user, ":"); if(pass) { pass[0] = '\0'; pass++; gtk_entry_set_text(GTK_ENTRY(spd->priv->password), pass); } gtk_entry_set_text(GTK_ENTRY(spd->priv->username), user); xmlFree(uri->user); uri->user = NULL; gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(spd->priv->authcheckbox), TRUE); } parsedUrl = xmlSaveUri(uri); gtk_entry_set_text(GTK_ENTRY(spd->priv->sourceEntry), parsedUrl); xmlFree(parsedUrl); xmlFreeURI(uri); } else { gtk_entry_set_text(GTK_ENTRY(spd->priv->sourceEntry), subscription_get_source(subscription)); } ui_subscription_prop_enable_httpauth(spd->priv, TRUE); gtk_widget_set_sensitive(spd->priv->selectFile, FALSE); } else { /* File */ gtk_entry_set_text(GTK_ENTRY(spd->priv->sourceEntry), subscription_get_source(subscription)); gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(spd->priv->fileRadio), TRUE); ui_subscription_prop_enable_httpauth(spd->priv, FALSE); gtk_widget_set_sensitive(spd->priv->selectFile, TRUE); } if(subscription_get_filter(subscription)) { gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(liferea_dialog_lookup(spd->priv->dialog, "filterCheckbox")), TRUE); gtk_entry_set_text(GTK_ENTRY(liferea_dialog_lookup(spd->priv->dialog, "filterEntry")), subscription_get_filter(subscription)); } } /* Archive */ if(feed->cacheLimit == CACHE_DISABLE) { gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(liferea_dialog_lookup(spd->priv->dialog, "feedCacheDisable")), TRUE); } else if(feed->cacheLimit == CACHE_DEFAULT) { gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(liferea_dialog_lookup(spd->priv->dialog, "feedCacheDefault")), TRUE); } else if(feed->cacheLimit == CACHE_UNLIMITED) { gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(liferea_dialog_lookup(spd->priv->dialog, "feedCacheUnlimited")), TRUE); } else { gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(liferea_dialog_lookup(spd->priv->dialog, "feedCacheLimited")), TRUE); gtk_spin_button_set_value(GTK_SPIN_BUTTON(liferea_dialog_lookup(spd->priv->dialog, "cacheItemLimit")), feed->cacheLimit); } gtk_widget_set_sensitive(liferea_dialog_lookup(spd->priv->dialog, "cacheItemLimit"), feed->cacheLimit > 0); on_feed_prop_filtercheck(GTK_TOGGLE_BUTTON(liferea_dialog_lookup(spd->priv->dialog, "filterCheckbox")), spd->priv); /* Download */ gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(liferea_dialog_lookup(spd->priv->dialog, "dontUseProxyCheck")), subscription->updateOptions->dontUseProxy); /* Advanced */ gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (liferea_dialog_lookup (spd->priv->dialog, "enclosureDownloadCheck")), feed->encAutoDownload); gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (liferea_dialog_lookup (spd->priv->dialog, "loadItemLinkCheck")), node->loadItemLink); gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (liferea_dialog_lookup (spd->priv->dialog, "ignoreCommentFeeds")), feed->ignoreComments); gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (liferea_dialog_lookup (spd->priv->dialog, "enforcePopupCheck")), feed->enforcePopup); gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (liferea_dialog_lookup (spd->priv->dialog, "preventPopupCheck")), feed->preventPopup); gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (liferea_dialog_lookup (spd->priv->dialog, "markAsReadCheck")), feed->markAsRead); /* Remove tabs we do not need... */ if (SUBSCRIPTION_TYPE(subscription) != feed_get_subscription_type ()) { /* Remove "Allgemein", "Source" and "Download" tab */ gtk_notebook_remove_page (GTK_NOTEBOOK (liferea_dialog_lookup (spd->priv->dialog, "subscriptionPropNotebook")), 0); gtk_notebook_remove_page (GTK_NOTEBOOK (liferea_dialog_lookup (spd->priv->dialog, "subscriptionPropNotebook")), 0); gtk_notebook_remove_page (GTK_NOTEBOOK (liferea_dialog_lookup (spd->priv->dialog, "subscriptionPropNotebook")), 1); } }
void feed_list_node_update (const gchar *nodeId) { GtkTreeIter *iter; gchar *label, *count = NULL; guint labeltype; nodePtr node; static gchar *countColor = NULL; node = node_from_id (nodeId); iter = feed_list_node_to_iter (nodeId); if (!iter) return; /* Initialize unread item color Pango CSS */ if (!countColor) { const gchar *bg = NULL, *fg = NULL; bg = render_get_theme_color ("FEEDLIST_UNREAD_BG"); fg = render_get_theme_color ("FEEDLIST_UNREAD_FG"); if (fg && bg) { countColor = g_strdup_printf ("foreground='#%s' background='#%s'", fg, bg); debug1 (DEBUG_HTML, "Feed list unread CSS: %s\n", countColor); } } labeltype = NODE_TYPE (node)->capabilities; labeltype &= (NODE_CAPABILITY_SHOW_UNREAD_COUNT | NODE_CAPABILITY_SHOW_ITEM_COUNT); if (node->unreadCount == 0 && (labeltype & NODE_CAPABILITY_SHOW_UNREAD_COUNT)) labeltype -= NODE_CAPABILITY_SHOW_UNREAD_COUNT; label = g_markup_escape_text (node_get_title (node), -1); switch (labeltype) { case NODE_CAPABILITY_SHOW_UNREAD_COUNT | NODE_CAPABILITY_SHOW_ITEM_COUNT: /* treat like show unread count */ case NODE_CAPABILITY_SHOW_UNREAD_COUNT: count = g_strdup_printf ("<span weight='bold' %s> %u </span>", countColor?countColor:"", node->unreadCount); break; case NODE_CAPABILITY_SHOW_ITEM_COUNT: count = g_strdup_printf ("<span weight='bold' %s> %u </span>", countColor?countColor:"", node->itemCount); break; default: break; } /* Extra message for search folder rebuilds */ if (IS_VFOLDER (node) && node->data) { if (((vfolderPtr)node->data)->reloading) { gchar *tmp = label; label = g_strdup_printf (_("%s\n<i>Rebuilding</i>"), label); g_free (tmp); } } gtk_tree_store_set (feedstore, iter, FS_LABEL, label, FS_UNREAD, node->unreadCount, FS_ICON, node->available?node_get_icon (node):icon_get (ICON_UNAVAILABLE), FS_COUNT, count, -1); g_free (label); if (node->parent) feed_list_node_update (node->parent->id); }
static void notif_libnotify_node_has_new_items (nodePtr node, gboolean enforced) { itemSetPtr itemSet; GList *iter; NotifyNotification *n; gchar *labelSummary_p; gint item_count = 0; gboolean show_popup_windows; conf_get_bool_value(SHOW_POPUP_WINDOWS, &show_popup_windows); if (!show_popup_windows && !enforced) return; /* Count updated feed */ itemSet = node_get_itemset (node); iter = itemSet->ids; while (iter) { itemPtr item = item_load (GPOINTER_TO_UINT (iter->data)); if (item->popupStatus && !item->readStatus) item_count++; item_unload (item); iter = g_list_next (iter); } itemset_free (itemSet); if (item_count == 0) return; labelSummary_p = g_strdup_printf (ngettext ("<b>%s</b> has <b>%d</b> update", "<b>%s</b> has <b>%d</b> updates", item_count), node_get_title (node), item_count); n = notify_notification_new (_("Feed Update"), labelSummary_p, "liferea", NULL); g_free (labelSummary_p); if (supports_append) { notify_notification_set_hint_string(n, "append", "allow"); } else { notify_notification_set_icon_from_pixbuf (n, node_get_icon (node)); } notify_notification_set_timeout (n, NOTIFY_EXPIRES_DEFAULT); if (supports_actions) { notify_notification_add_action (n, "show_details", _("Show details"), (NotifyActionCallback)notif_libnotify_callback_show_details, node->id, NULL); notify_notification_add_action (n, "open", _("Open feed"), (NotifyActionCallback)notif_libnotify_callback_open, node->id, NULL); notify_notification_add_action (n, "mark_read", _("Mark all as read"), (NotifyActionCallback)notif_libnotify_callback_mark_read, node->id, NULL); } notify_notification_set_category (n, "feed"); notify_notification_attach_to_status_icon (n, ui_tray_get_status_icon ()); if (!notify_notification_show (n, NULL)) g_warning ("notif_libnotify.c - failed to send notification via libnotify"); }
static void notif_libnotify_callback_show_details (NotifyNotification *n, gchar *action, gpointer user_data) { nodePtr node_p; GList *list_p; itemPtr item_p; gchar *labelText_p; gchar *labelText_now_p = NULL; gchar *labelText_prev_p; gchar *labelHeadline_p; const gchar *labelURL_p; gint item_count = 0; g_assert (action != NULL); g_assert (strcmp(action, "show_details") == 0); node_p = node_from_id (user_data); if (node_p) { itemSetPtr itemSet = node_get_itemset (node_p); labelText_now_p = g_strdup (""); /* Gather the feed's headlines */ list_p = itemSet->ids; while (list_p) { item_p = item_load (GPOINTER_TO_UINT (list_p->data)); if (item_p->popupStatus && !item_p->readStatus) { item_p->popupStatus = FALSE; item_count += 1; labelHeadline_p = g_strdup (item_get_title (item_p)); if (labelHeadline_p == NULL ) { labelHeadline_p = g_strdup_printf (_("This news entry has no headline")); } labelURL_p = item_get_base_url (item_p); if (labelURL_p) { labelText_p = g_strdup_printf ("%s <a href='%s'>%s</a>\n", labelHeadline_p, labelURL_p, _("Visit")); } else { labelText_p = g_strdup_printf ("%s\n", labelHeadline_p); } labelText_prev_p = labelText_now_p; labelText_now_p = g_strconcat(labelText_now_p, labelText_p, NULL); g_free(labelHeadline_p); g_free(labelText_p); g_free(labelText_prev_p); } item_unload (item_p); list_p = g_list_next (list_p); } itemset_free (itemSet); if (item_count == 0) { g_free (labelText_now_p); return; } } else { ui_show_error_box(_("This feed does not exist anymore!")); } notify_notification_close (n, NULL); if (node_p) { // notify_notification_update ( n, node_get_title(node_p), labelText_now_p, NULL); // notify_notification_clear_actions(n); n = notify_notification_new (node_get_title (node_p), labelText_now_p, NULL, NULL); notify_notification_set_icon_from_pixbuf (n, node_get_icon (node_p)); notify_notification_set_category (n, "feed"); notify_notification_set_timeout (n, NOTIFY_EXPIRES_NEVER); if (supports_actions) { notify_notification_add_action (n, "open", _("Open feed"), (NotifyActionCallback)notif_libnotify_callback_open, node_p->id, NULL); notify_notification_add_action (n, "mark_read", _("Mark all as read"), (NotifyActionCallback)notif_libnotify_callback_mark_read, node_p->id, NULL); } notify_notification_attach_to_status_icon (n, ui_tray_get_status_icon ()); if (!notify_notification_show (n, NULL)) { g_warning ("libnotify.c - failed to update notification via libnotify\n"); } g_free (labelText_now_p); } }