public PodcastPropertiesDialog (DatabaseTrackInfo track)
        {
            PodcastTrackInfo pi = PodcastTrackInfo.From (track);
            if (pi == null)
            {
                throw new ArgumentNullException ("pi");
            }

            this.pi = pi;

            Title = track.TrackTitle;
            BuildWindow ();
            //IconThemeUtils.SetWindowIcon (this);
        }
        private void MigrateLegacyIfNeeded ()
        {
            if (DatabaseConfigurationClient.Client.Get<int> ("Podcast", "Version", 0) == 0) {
                if (ServiceManager.DbConnection.TableExists ("Podcasts") &&
                        ServiceManager.DbConnection.Query<int> ("select count(*) from podcastsyndications") == 0) {
                    Hyena.Log.Information ("Migrating Podcast Feeds and Items");
                    ServiceManager.DbConnection.Execute(@"
                        INSERT INTO PodcastSyndications (FeedID, Title, Url, Link,
                            Description, ImageUrl, LastBuildDate, AutoDownload, IsSubscribed)
                            SELECT
                                PodcastFeedID,
                                Title,
                                FeedUrl,
                                Link,
                                Description,
                                Image,
                                strftime(""%s"", LastUpdated),
                                SyncPreference,
                                1
                            FROM PodcastFeeds
                    ");

                    ServiceManager.DbConnection.Execute(@"
                        INSERT INTO PodcastItems (ItemID, FeedID, Title, Link, PubDate,
                            Description, Author, Active, Guid)
                            SELECT
                                PodcastID,
                                PodcastFeedID,
                                Title,
                                Link,
                                strftime(""%s"", PubDate),
                                Description,
                                Author,
                                Active,
                                Url
                            FROM Podcasts
                    ");

                    // Note: downloaded*3 is because the value was 0 or 1, but is now 0 or 3 (FeedDownloadStatus.None/Downloaded)
                    ServiceManager.DbConnection.Execute(@"
                        INSERT INTO PodcastEnclosures (ItemID, LocalPath, Url, MimeType, FileSize, DownloadStatus)
                            SELECT
                                PodcastID,
                                LocalPath,
                                Url,
                                MimeType,
                                Length,
                                Downloaded*3
                            FROM Podcasts
                    ");

                    // Finally, move podcast items from the Music Library to the Podcast source
                    int [] primary_source_ids = new int [] { ServiceManager.SourceManager.MusicLibrary.DbId };
                    int moved = 0;
                    foreach (FeedEnclosure enclosure in FeedEnclosure.Provider.FetchAllMatching ("LocalPath IS NOT NULL AND LocalPath != ''")) {
                        SafeUri uri = new SafeUri (enclosure.LocalPath);
                        int track_id = DatabaseTrackInfo.GetTrackIdForUri (uri, primary_source_ids);

                        if (track_id > 0) {
                            PodcastTrackInfo pi = new PodcastTrackInfo (DatabaseTrackInfo.Provider.FetchSingle (track_id));
                            pi.Item = enclosure.Item;
                            pi.Track.PrimarySourceId = source.DbId;
                            pi.SyncWithFeedItem ();
                            pi.Track.Save (false);
                            moved++;
                        }
                    }

                    if (moved > 0) {
                        ServiceManager.SourceManager.MusicLibrary.Reload ();
                        source.Reload ();
                    }

                    Hyena.Log.Information ("Done Migrating Podcast Feeds and Items");
                }
                DatabaseConfigurationClient.Client.Set<int> ("Podcast", "Version", 1);
            }

            if (DatabaseConfigurationClient.Client.Get<int> ("Podcast", "Version", 0) < 3) {
                // We were using the Link as the fallback if the actual Guid was missing, but that was a poor choice
                // since it is not always unique.  We now use the title and pubdate combined.
                ServiceManager.DbConnection.Execute ("UPDATE PodcastItems SET Guid = NULL");
                foreach (FeedItem item in FeedItem.Provider.FetchAll ()) {
                    item.Guid = null;
                    if (item.Feed == null || FeedItem.Exists (item.Feed.DbId, item.Guid)) {
                        item.Delete (false);
                    } else {
                        item.Save ();
                    }
                }

                DatabaseConfigurationClient.Client.Set<int> ("Podcast", "Version", 3);
            }

            // Intentionally skpping 4 here because this needs to get run again for anybody who ran it
            // before it was fixed, but only once if you never ran it
            if (DatabaseConfigurationClient.Client.Get<int> ("Podcast", "Version", 0) < 5) {
                ReplaceNewlines ("CoreTracks", "Title");
                ReplaceNewlines ("CoreTracks", "TitleLowered");
                ReplaceNewlines ("PodcastItems", "Title");
                ReplaceNewlines ("PodcastItems", "Description");
                DatabaseConfigurationClient.Client.Set<int> ("Podcast", "Version", 5);
            }

            // Initialize the new StrippedDescription field
            if (DatabaseConfigurationClient.Client.Get<int> ("Podcast", "Version", 0) < 6) {
                foreach (FeedItem item in FeedItem.Provider.FetchAll ()) {
                    item.UpdateStrippedDescription ();
                    item.Save ();
                }
                DatabaseConfigurationClient.Client.Set<int> ("Podcast", "Version", 6);
            }
        }
        /*private void OnFeedAddedHandler (object sender, FeedEventArgs args)
        {
            lock (sync) {
                source.FeedModel.Add (args.Feed);
            }
        }

        private void OnFeedRemovedHandler (object sender, FeedEventArgs args)
        {
            lock (sync) {
                source.FeedModel.Remove (args.Feed);
                args.Feed.Delete ();
            }
        }

        private void OnFeedRenamedHandler (object sender, FeedEventArgs args)
        {
            lock (sync) {
                source.FeedModel.Sort ();
            }
        }

        private void OnFeedUpdatingHandler (object sender, FeedEventArgs args)
        {
            lock (sync) {
                source.FeedModel.Reload ();
            }
        }

        private void OnFeedDownloadCountChangedHandler (object sender, FeedDownloadCountChangedEventArgs args)
        {
            lock (sync) {
                source.FeedModel.Reload ();
            }
        }*/

        /*private void OnFeedItemAddedHandler (object sender, FeedItemEventArgs args)
        {
            lock (sync) {
                if (args.Item != null) {
                    AddFeedItem (args.Item);
                } else if (args.Items != null) {
                    foreach (FeedItem item in args.Items) {
                        AddFeedItem (item);
                    }
                }
            }
        }*/

        public void AddFeedItem (FeedItem item)
        {
            if (item.Enclosure != null) {
                PodcastTrackInfo pi = new PodcastTrackInfo (new DatabaseTrackInfo (), item);
                pi.Track.PrimarySource = source;
                pi.Track.Save (true);
                source.NotifyUser ();
            } else {
                item.Delete (false);
            }
        }