コード例 #1
0
        /// <summary>
        /// Called by <see cref="FeedSource"/> if a category is moved from outside the application
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void OnMovedCategory(object sender, FeedSource.CategoryChangedEventArgs e)
        {
            FeedSourceEntry entry = sourceManager.SourceOf((FeedSource)sender);

            InvokeOnGui(delegate
            {
                TreeFeedsNodeBase parent, tn = TreeHelper.FindCategoryNode(guiMain.GetSubscriptionRootNode(entry), e.CategoryName);
                int index = e.NewCategoryName.LastIndexOf(FeedSource.CategorySeparator);

                if (index == -1)
                {
                    parent = guiMain.GetSubscriptionRootNode(entry);
                }
                else
                {
                    parent = TreeHelper.FindCategoryNode(guiMain.GetSubscriptionRootNode(entry), e.NewCategoryName.Substring(0, index));
                }

                if (tn != null && parent != null)
                {
                    guiMain.MoveNode(tn, parent, false);
                    SubscriptionModified(entry, NewsFeedProperty.FeedCategoryAdded);
                }
            });
        }
コード例 #2
0
 /// <summary>
 /// Initializes a new instance of the <see cref="UnreadItemsFeed"/> class.
 /// </summary>
 public UnreadItemsFeed(FeedSourceEntry migratedItemsOwner) :
     base(migratedItemsOwner, "virtualfeed://rssbandit.org/local/unreaditems",
          SR.FeedNodeUnreadItemsCaption,
          SR.FeedNodeUnreadItemsDesc,
          false)
 {
 }
コード例 #3
0
        /// <summary>
        /// Removes the entries for the specified feed URL.
        /// </summary>
        /// <param name="entry">The entry.</param>
        /// <param name="feedUrl">The feed URL.</param>
        public void RemoveFeed(FeedSourceEntry entry, string feedUrl)
        {
            if (string.IsNullOrEmpty(feedUrl) || feedInfo.ItemsList.Count == 0)
            {
                return;
            }

            Stack removeAtIndex = new Stack();

            for (int i = 0; i < feedInfo.ItemsList.Count; i++)
            {
                INewsItem n = feedInfo.ItemsList[i];
                if (n != null)
                {
                    int    sourceId;
                    string feedUrlRef = OptionalItemElement.GetOriginalFeedReference(n, out sourceId);

                    if (!String.IsNullOrEmpty(feedUrlRef) && sourceId == entry.ID &&
                        String.Equals(feedUrlRef, feedUrl, StringComparison.OrdinalIgnoreCase))
                    {
                        removeAtIndex.Push(i);
                    }
                }
            }

            while (removeAtIndex.Count > 0)
            {
                feedInfo.ItemsList.RemoveAt((int)removeAtIndex.Pop());
            }
        }
コード例 #4
0
            /// <summary>
            /// Initializes a new instance of the <see cref="FeedException"/> class.
            /// </summary>
            /// <param name="ownerFeed">The owner feed.</param>
            /// <param name="e">The e.</param>
            /// <param name="entry">The entry.</param>
            public FeedException(ExceptionManager ownerFeed, Exception e, FeedSourceEntry entry)
            {
                idCounter++;
                this._ID = String.Concat("#", idCounter.ToString());

                if (entry != null)
                {
                    _feedSourceName = entry.Name;
                    _feedSourceID   = entry.ID;
                }

                if (e is FeedRequestException)
                {
                    this.InitWith(ownerFeed, (FeedRequestException)e);
                }
                else if (e is XmlException)
                {
                    this.InitWith(ownerFeed, (XmlException)e);
                }
                else if (e is WebException)
                {
                    this.InitWith(ownerFeed, (WebException)e);
                }
                else if (e is ProtocolViolationException)
                {
                    this.InitWith(ownerFeed, (ProtocolViolationException)e);
                }
                else
                {
                    this.InitWith(ownerFeed, e);
                }
            }
コード例 #5
0
        protected override void MarkItemUnread(INewsItem item)
        {
            if (item == null)
            {
                return;
            }
            int idx = itemsFeed.Items.IndexOf(item);

            if (idx < 0)
            {
                itemsFeed.Items.Add(item);
            }
            else
            {
                // should not happen, just if we get called this way:
                (itemsFeed.Items[idx]).BeenRead = false;
            }

            if (HasNodes)
            {
                // child handle this:
                FeedSourceEntry          entry = app.FeedSources.SourceOf(item.Feed);
                UnreadItemsNodePerSource child;
                if (childrenBySourceID.TryGetValue(entry.ID, out child))
                {
                    child.UpdateReadStatus(child, 1);
                }
            }
            else
            {
                // handle by myself:
                UpdateReadStatus(this, 1);
            }
        }
コード例 #6
0
        protected override void MarkItemRead(INewsItem item)
        {
            if (item == null)
            {
                return;
            }
            int idx = itemsFeed.Items.IndexOf(item);

            if (idx >= 0)
            {
                itemsFeed.Items.RemoveAt(idx);

                if (HasNodes)
                {
                    // child handle this:
                    FeedSourceEntry          entry = app.FeedSources.SourceOf(item.Feed);
                    UnreadItemsNodePerSource child;
                    if (childrenBySourceID.TryGetValue(entry.ID, out child))
                    {
                        child.UpdateReadStatus(child, -1);
                    }
                }
                else
                {
                    // handle by myself:
                    UpdateReadStatus(this, -1);
                }
            }
        }
コード例 #7
0
        internal void MarkAllItemsRead(FeedSourceEntry entry)
        {
            if (entry == null)
            {
                return;
            }

            UnreadItemsNodePerSource child;

            childrenBySourceID.TryGetValue(entry.ID, out child);

            for (int i = itemsFeed.Items.Count - 1; i >= 0; i--)
            {
                INewsItem       item  = itemsFeed.Items[i];
                FeedSourceEntry owner = app.FeedSources.SourceOf(item.Feed);
                if (owner != null && owner.ID.Equals(entry.ID))
                {
                    itemsFeed.Items.RemoveAt(i);
                    if (child != null)
                    {
                        // child handle this:
                        child.UpdateReadStatus(child, -1);
                    }
                    else
                    {
                        // handle by myself:
                        UpdateReadStatus(this, -1);
                    }
                }
            }
        }
コード例 #8
0
 public UnreadItemsNodePerSource(FeedSourceEntry entry, LocalFeedsFeed itemStore, int imageIndex, int selectedImageIndex, ContextMenuStrip menu) :
     base(itemStore, entry.Name, imageIndex, selectedImageIndex, menu)
 {
     base.ColumnLayout = entry.UnreadItemsColumnLayoutId;
     Text     = entry.Name;
     _entryId = entry.ID;
     DataKey  = itemStore.link + "#" + _entryId;
 }
コード例 #9
0
        /// <summary>
        /// Called by FeedSource if a category is added from outside the application
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void OnAddedCategory(object sender, FeedSource.CategoryEventArgs e)
        {
            FeedSourceEntry entry = sourceManager.SourceOf((FeedSource)sender);

            InvokeOnGui(delegate
            {
                this.AddCategory(entry, e.CategoryName);
                SubscriptionModified(entry, NewsFeedProperty.FeedCategoryAdded);
            });
        }
コード例 #10
0
        /// <summary>
        /// Called by FeedSource if a feed is deleted from outside the application
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void OnDeletedFeed(object sender, FeedSource.FeedDeletedEventArgs e)
        {
            FeedSourceEntry entry = sourceManager.SourceOf((FeedSource)sender);

            InvokeOnGui(delegate
            {
                RaiseFeedDeleted(entry, e.FeedUrl, e.Title);
                SubscriptionModified(entry, NewsFeedProperty.FeedRemoved);
            });
        }
コード例 #11
0
        /// <summary>
        /// Initializes a new instance of the <see cref="DeletedItemsFeed"/> class.
        /// </summary>
        /// <param name="migratedItemsOwner">The migrated items owner.</param>
        public DeletedItemsFeed(FeedSourceEntry migratedItemsOwner) :
            base(migratedItemsOwner, RssBanditApplication.GetDeletedItemsFileName(),
                 SR.FeedNodeDeletedItemsCaption,
                 SR.FeedNodeDeletedItemsDesc, false)
        {
            // set this to indicate required migration:
            migrationRequired = RssBanditApplication.PersistedSettings.GetProperty(Ps.DeletedItemsFeedMigrationRequired, true);

            using (XmlReader reader = this.GetDefaultReader())
                LoadItems(reader, migratedItemsOwner);
        }
コード例 #12
0
        /// <summary>
        /// Called by FeedSource, if a feed start's to download.
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void BeforeDownloadFeedStarted(object sender, FeedSource.DownloadFeedCancelEventArgs e)
        {
            FeedSourceEntry entry = sourceManager.SourceOf((FeedSource)sender);

            InvokeOnGui(
                delegate
            {
                bool cancel = e.Cancel;
                guiMain.OnFeedUpdateStart(entry, e.FeedUri, ref cancel);
                e.Cancel = cancel;
            });
        }
コード例 #13
0
        /// <summary>
        /// Called by FeedSource, if all pending feed updates are done.
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void OnAllRequestsCompleted(object sender, EventArgs e)
        {
            FeedSourceEntry entry = sourceManager.SourceOf((FeedSource)sender);

            InvokeOnGui(delegate
            {
                stateManager.MoveNewsHandlerStateTo(FeedSourceBusyState.RefreshAllDone);
                guiMain.TriggerGUIStateOnNewFeeds(true);
                guiMain.OnAllAsyncUpdateFeedsFinished(entry);
                // GC.Collect();
            });
        }
コード例 #14
0
        public void Add(Exception e, FeedSourceEntry entry)
        {
            FeedException fe = new FeedException(this, e, entry);

            Add(fe.NewsItemInstance);
            try
            {
                Save();
            }
            catch (Exception ex)
            {
                Log.Fatal("ExceptionManager.Save() failed", ex);
            }
        }
コード例 #15
0
        /// <summary>
        /// Called by FeedSource if a category is deleted from outside the application
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void OnDeletedCategory(object sender, FeedSource.CategoryEventArgs e)
        {
            FeedSourceEntry entry = sourceManager.SourceOf((FeedSource)sender);

            InvokeOnGui(delegate
            {
                TreeFeedsNodeBase tn = TreeHelper.FindChildNode(guiMain.GetRoot(RootFolderType.MyFeeds), e.CategoryName, FeedNodeType.Category);
                if (tn != null)
                {
                    guiMain.DeleteCategory(tn);
                    SubscriptionModified(entry, NewsFeedProperty.FeedCategoryRemoved);
                }
            });
        }
コード例 #16
0
        /// <summary>
        /// Called by FeedSource if feed is renamed from outside the application
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void OnRenamedFeed(object sender, FeedSource.FeedRenamedEventArgs e)
        {
            FeedSourceEntry entry = sourceManager.SourceOf((FeedSource)sender);

            InvokeOnGui(delegate
            {
                TreeFeedsNodeBase tn = TreeHelper.FindNode(guiMain.GetSubscriptionRootNode(entry), e.FeedUrl);
                if (tn != null)
                {
                    guiMain.RenameTreeNode(tn, e.NewName);
                    SubscriptionModified(entry, NewsFeedProperty.FeedTitle);
                }
            });
        }
コード例 #17
0
        /// <summary>
        /// Called by FeedSource if a category is renamed from outside the application
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void OnRenamedCategory(object sender, FeedSource.CategoryChangedEventArgs e)
        {
            FeedSourceEntry entry = sourceManager.SourceOf((FeedSource)sender);

            InvokeOnGui(delegate
            {
                TreeFeedsNodeBase tn = TreeHelper.FindChildNode(guiMain.GetSubscriptionRootNode(entry), e.CategoryName, FeedNodeType.Category);
                if (tn != null)
                {
                    guiMain.RenameTreeNode(tn, e.NewCategoryName);
                    SubscriptionModified(entry, NewsFeedProperty.FeedCategoryAdded);
                }
            });
        }
コード例 #18
0
        /// <summary>
        /// Overridden to migrate an item.
        /// Base implementation just return the <paramref name="newsItem"/>.
        /// </summary>
        /// <param name="newsItem">The news item.</param>
        /// <param name="migratedItemsOwner">The migrated items owner.</param>
        /// <returns></returns>
        protected override NewsItem MigrateItem(NewsItem newsItem, FeedSourceEntry migratedItemsOwner)
        {
            if (migratedItemsOwner != null)
            {
                if (runSelfHealingFlagStatus)
                {
                    if (newsItem.FlagStatus == Flagged.None)
                    {
                        // correction: older Bandit versions are not able to store flagStatus
                        newsItem.FlagStatus = Flagged.FollowUp;
                        Modified            = true;
                    }
                }

                XmlQualifiedName key = AdditionalElements.GetQualifiedName(
                    OptionalItemElement.OldVersion.FeedUrlElementName, OptionalItemElement.OldVersion.Namespace);
                string feedUrl = AdditionalElements.GetElementValue(key, newsItem);
                if (!String.IsNullOrEmpty(feedUrl))
                {
                    if (runSelfHealingFlagStatus && migratedItemsOwner.Source.IsSubscribed(feedUrl))
                    {
                        //check if feed exists
                        IList <INewsItem> itemsForFeed = migratedItemsOwner.Source.GetItemsForFeed(feedUrl, false);

                        //find this item
                        int itemIndex = itemsForFeed.IndexOf(newsItem);

                        if (itemIndex != -1)
                        {
                            //check if item still exists
                            INewsItem item = itemsForFeed[itemIndex];
                            if (item.FlagStatus != newsItem.FlagStatus)
                            {
                                // correction: older Bandit versions are not able to store flagStatus
                                item.FlagStatus = newsItem.FlagStatus;
                                Modified        = true;
                                //FeedWasModified(feedUrl, NewsFeedProperty.FeedItemFlag); // self-healing
                            }
                        }
                    }

                    AdditionalElements.RemoveElement(key, newsItem);
                    OptionalItemElement.AddOrReplaceOriginalFeedReference(newsItem, feedUrl, migratedItemsOwner.ID);
                    Modified = true;
                }
            }

            return(base.MigrateItem(newsItem, migratedItemsOwner));
        }
コード例 #19
0
        private void cboFeedSources_SelectedIndexChanged(object sender, System.EventArgs e)
        {
            FeedSourceEntry entry = this.sourcesNnodes.Keys.ElementAt(cboFeedSources.SelectedIndex);

            if (!entry.Name.Equals(this.treeExportFeedsSelection.Nodes[0].Text))
            {
                this.treeExportFeedsSelection.Nodes.Clear();

                TreeHelper.CopyNodes(this.sourcesNnodes[entry], this.treeExportFeedsSelection, true);
                if (this.treeExportFeedsSelection.Nodes.Count > 0)
                {
                    this.treeExportFeedsSelection.Nodes[0].Expand();
                }
            }
        }
コード例 #20
0
        /// <summary>
        /// Called by <see cref="FeedSource"/> if a feed is added from outside the application
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void OnAddedFeed(object sender, FeedSource.FeedChangedEventArgs e)
        {
            FeedSourceEntry entry = sourceManager.SourceOf((FeedSource)sender);

            InvokeOnGui(delegate
            {
                INewsFeed f;
                entry.Source.GetFeeds().TryGetValue(e.FeedUrl, out f);

                if (f != null)
                {
                    guiMain.AddNewFeedNode(entry, f.category, f);
                    SubscriptionModified(entry, NewsFeedProperty.FeedAdded);
                }
            });
        }
コード例 #21
0
        /// <summary>
        /// Called by FeedSource if feed moved from outside the application
        /// </summary>
        /// <param name="sender">The sender.</param>
        /// <param name="e">The <see cref="NewsComponents.FeedSource.FeedMovedEventArgs"/> instance containing the event data.</param>
        private void OnMovedFeed(object sender, FeedSource.FeedMovedEventArgs e)
        {
            FeedSourceEntry entry = sourceManager.SourceOf((FeedSource)sender);

            InvokeOnGui(delegate
            {
                TreeFeedsNodeBase start  = guiMain.GetSubscriptionRootNode(entry);
                TreeFeedsNodeBase tn     = TreeHelper.FindNode(start, e.FeedUrl);
                TreeFeedsNodeBase parent = TreeHelper.FindCategoryNode(start, e.NewCategory);
                if (tn != null && parent != null)
                {
                    guiMain.MoveNode(tn, parent, false);
                    SubscriptionModified(entry, NewsFeedProperty.FeedAdded);
                }
            });
        }
コード例 #22
0
 /// <summary>
 /// Overridden to migrate an item.
 /// Base implementation just return the <paramref name="newsItem"/>.
 /// </summary>
 /// <param name="newsItem">The news item.</param>
 /// <param name="migratedItemsOwner">The migrated items owner.</param>
 /// <returns></returns>
 protected override NewsItem MigrateItem(NewsItem newsItem, FeedSourceEntry migratedItemsOwner)
 {
     if (migratedItemsOwner != null)
     {
         XmlQualifiedName key =
             AdditionalElements.GetQualifiedName(
                 OptionalItemElement.OldVersion.ContainerUrlElementName, OptionalItemElement.OldVersion.Namespace);
         string feedUrl = AdditionalElements.GetElementValue(key, newsItem);
         if (!String.IsNullOrEmpty(feedUrl))
         {
             AdditionalElements.RemoveElement(key, newsItem);
             OptionalItemElement.AddOrReplaceOriginalFeedReference(newsItem, feedUrl, migratedItemsOwner.ID);
             Modified = true;
         }
     }
     return(base.MigrateItem(newsItem, migratedItemsOwner));
 }
コード例 #23
0
        /// <summary>
        /// Called by <see cref="FeedSource"/>, after a feed was updated.
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        internal void OnUpdatedFeed(object sender, FeedSource.UpdatedFeedEventArgs e)
        {
            FeedSourceEntry entry = sourceManager.SourceOf((FeedSource)sender);

            InvokeOnGui(delegate
            {
                guiMain.UpdateFeed(entry, e.UpdatedFeedUri, e.NewFeedUri, e.UpdateState == RequestResult.OK);

                if (e.FirstSuccessfulDownload)
                {
                    //new <cacheurl> entry in subscriptions.xml
                    SubscriptionModified(entry, NewsFeedProperty.FeedCacheUrl);
                    //this.FeedlistModified = true;
                }
                stateManager.MoveNewsHandlerStateTo(FeedSourceBusyState.RefreshOneDone);
            });
        }
コード例 #24
0
ファイル: ImportFeedsDialog.cs プロジェクト: romesc/RssBandit
        private void comboFeedSource_SelectedIndexChanged(object sender, EventArgs e)
        {
            FeedSourceEntry fs = comboFeedSource.SelectedItem as FeedSourceEntry;

            this.comboCategory.Items.Clear();

            //initialize category combo box
            if (fs != null)
            {
                foreach (string category in fs.Source.GetCategories().Keys)
                {
                    this.comboCategory.Items.Add(category);
                }
            }

            this.comboCategory.Items.Add(defaultCategory);
            this.comboCategory.Text = defaultCategory;
        }
コード例 #25
0
 public FeedSourceProperties(FeedSourceEntry entry) : this()
 {
     txtFeedSourceName.Text = entry.Name;
     grpCredentials.Enabled = entry.Source.SubscriptionLocation.CredentialsSupported;
     //&& entry.SourceType != FeedSourceType.Facebook;
     if (grpCredentials.Enabled)
     {
         if (String.IsNullOrEmpty(entry.Source.SubscriptionLocation.Credentials.Domain))
         {
             txtUsername.Text = entry.Source.SubscriptionLocation.Credentials.UserName;
         }
         else
         {
             txtUsername.Text = entry.Source.SubscriptionLocation.Credentials.Domain + @"\" +
                                entry.Source.SubscriptionLocation.Credentials.UserName;
         }
         txtPassword.Text = entry.Source.SubscriptionLocation.Credentials.Password;
     }
 }
コード例 #26
0
        public LocalFeedsFeed(FeedSourceEntry migratedItemsOwner, string feedUrl, string feedTitle, string feedDescription, bool loadItems) : this()
        {
            filePath = feedUrl;
            try {
                Uri feedUri = new Uri(feedUrl);
                base.link = feedUri.CanonicalizedUri();
            } catch {
                base.link = feedUrl;
            }
            base.title = feedTitle;

            this.feedInfo = new FeedInfo(null, filePath, new List <INewsItem>(), feedTitle, base.link, feedDescription);

            if (loadItems)
            {
                using (XmlReader reader = this.GetDefaultReader())
                    LoadItems(reader, migratedItemsOwner);
            }
        }
コード例 #27
0
        /// <summary>
        /// Loads the items.
        /// </summary>
        /// <param name="reader">The reader.</param>
        /// <param name="migratedItemsOwner">The migrated items owner.</param>
        protected void LoadItems(XmlReader reader, FeedSourceEntry migratedItemsOwner)
        {
            if (feedInfo.ItemsList.Count > 0)
            {
                feedInfo.ItemsList.Clear();
            }

            bool success = false;

            if (reader != null)
            {
                try{
                    XmlDocument doc = new XmlDocument();
                    doc.Load(reader);
                    foreach (XmlElement elem in doc.SelectNodes("//item"))
                    {
                        NewsItem item = RssParser.MakeRssItem(this, new XmlNodeReader(elem));

                        // We do this because the flagged items are stored in one "feed",
                        // but gets displayed one node per flag status. If one item is unread,
                        // all flag nodes gets the "unread" state.
                        item.BeenRead = true;

                        item.FeedDetails = this.feedInfo;
                        if (migrationRequired)
                        {
                            item = MigrateItem(item, migratedItemsOwner);
                        }

                        if (item != null)
                        {
                            feedInfo.ItemsList.Add(item);
                        }
                    }

                    success = true;
                }catch (Exception e) {
                    ExceptionManager.GetInstance().Add(RssBanditApplication.CreateLocalFeedRequestException(e, this, this.feedInfo), migratedItemsOwner);
                }
            }

            OnItemsLoaded(success);
        }
コード例 #28
0
        /// <summary>
        /// Does the actual work of determining the top stories
        /// </summary>
        protected override void Run()
        {
            try {
                FeedSourceEntry entry = rssBanditApp.CurrentFeedSource;

                if (entry != null)
                {
                    int numDays = RssBanditApplication.ReadAppSettingsEntry("TopStoriesTimeSpanInDays", 7);
                    TopStories = new List <RelationHRefEntry>(entry.Source.GetTopStories(new TimeSpan(numDays, 0, 0, 0), 10));
                    this.GenerateTopStoriesPage(entry.Name);
                }
            } catch (ThreadAbortException) {
                // eat up
            } catch (Exception ex) {
                p_operationException = ex;
                _log.Error("GetTopStories() exception", ex);
            } finally {
                WorkDone.Set();
            }
        }
コード例 #29
0
        /// <summary>
        /// Called by FeedSource, after an enclosure has been downloaded.
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        internal void OnDownloadedEnclosure(object sender, DownloadItemEventArgs e)
        {
            FeedSourceEntry entry = sourceManager.SourceOfFeed(e.DownloadItem.OwnerFeedId);

            /* create playlists in media players if that option is selected */
            if (Preferences.AddPodcasts2WMP)
            {
                AddPodcastToWMP(e.DownloadItem);
            }

            if (Preferences.AddPodcasts2ITunes)
            {
                AddPodcastToITunes(e.DownloadItem);
            }

            /* update GUI if needed */
            InvokeOnGui(delegate
            {
                guiMain.OnEnclosureReceived(entry, e.DownloadItem);
            });
        }
コード例 #30
0
        /// <summary>
        /// Initializes a new instance of the <see cref="FlaggedItemsFeed"/> class.
        /// </summary>
        /// <param name="migratedItemsOwner">The migrated items owner.</param>
        /// <param name="reader">The reader.</param>
        public FlaggedItemsFeed(FeedSourceEntry migratedItemsOwner, XmlReader reader) :
            base(migratedItemsOwner, RssBanditApplication.GetFlagItemsFileName(),
                 SR.FeedNodeFlaggedFeedsCaption,
                 SR.FeedNodeFlaggedFeedsDesc, false)
        {
            runSelfHealingFlagStatus = RssBanditApplication.PersistedSettings.GetProperty(
                Ps.FlaggedItemsFeedSelfHealingFlagStatusRequired, true);

            // set this to indicate required migration:
            migrationRequired = runSelfHealingFlagStatus || RssBanditApplication.PersistedSettings.GetProperty(
                Ps.FlaggedItemsFeedMigrationRequired, true);

            if (reader != null)
            {
                LoadItems(reader, migratedItemsOwner);
            }
            else
            {
                using (reader = this.GetDefaultReader())
                    LoadItems(reader, migratedItemsOwner);
            }
        }