commit 60d6f9354357c4d6c22f6c89604f6dfa5bf7b6a9 Author: Chris Kaczor Date: Wed Apr 30 17:47:28 2014 -0400 Initial commit diff --git a/.gitattributes b/.gitattributes new file mode 100644 index 0000000..1ff0c42 --- /dev/null +++ b/.gitattributes @@ -0,0 +1,63 @@ +############################################################################### +# Set default behavior to automatically normalize line endings. +############################################################################### +* text=auto + +############################################################################### +# Set default behavior for command prompt diff. +# +# This is need for earlier builds of msysgit that does not have it on by +# default for csharp files. +# Note: This is only used by command line +############################################################################### +#*.cs diff=csharp + +############################################################################### +# Set the merge driver for project and solution files +# +# Merging from the command prompt will add diff markers to the files if there +# are conflicts (Merging from VS is not affected by the settings below, in VS +# the diff markers are never inserted). Diff markers may cause the following +# file extensions to fail to load in VS. An alternative would be to treat +# these files as binary and thus will always conflict and require user +# intervention with every merge. To do so, just uncomment the entries below +############################################################################### +#*.sln merge=binary +#*.csproj merge=binary +#*.vbproj merge=binary +#*.vcxproj merge=binary +#*.vcproj merge=binary +#*.dbproj merge=binary +#*.fsproj merge=binary +#*.lsproj merge=binary +#*.wixproj merge=binary +#*.modelproj merge=binary +#*.sqlproj merge=binary +#*.wwaproj merge=binary + +############################################################################### +# behavior for image files +# +# image files are treated as binary by default. +############################################################################### +#*.jpg binary +#*.png binary +#*.gif binary + +############################################################################### +# diff behavior for common document formats +# +# Convert binary document formats to text before diffing them. This feature +# is only available from the command line. Turn it on by uncommenting the +# entries below. +############################################################################### +#*.doc diff=astextplain +#*.DOC diff=astextplain +#*.docx diff=astextplain +#*.DOCX diff=astextplain +#*.dot diff=astextplain +#*.DOT diff=astextplain +#*.pdf diff=astextplain +#*.PDF diff=astextplain +#*.rtf diff=astextplain +#*.RTF diff=astextplain diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..1bc915c --- /dev/null +++ b/.gitignore @@ -0,0 +1,156 @@ +## Ignore Visual Studio temporary files, build results, and +## files generated by popular Visual Studio add-ons. + +# User-specific files +*.suo +*.user +*.sln.docstates + +# Build results + +[Dd]ebug/ +[Rr]elease/ +x64/ +build/ +[Bb]in/ +[Oo]bj/ + +# Enable "build/" folder in the NuGet Packages folder since NuGet packages use it for MSBuild targets +!packages/*/build/ + +# MSTest test Results +[Tt]est[Rr]esult*/ +[Bb]uild[Ll]og.* + +*_i.c +*_p.c +*.ilk +*.meta +*.obj +*.pch +*.pdb +*.pgc +*.pgd +*.rsp +*.sbr +*.tlb +*.tli +*.tlh +*.tmp +*.tmp_proj +*.log +*.vspscc +*.vssscc +.builds +*.pidb +*.log +*.scc + +# Visual C++ cache files +ipch/ +*.aps +*.ncb +*.opensdf +*.sdf +*.cachefile + +# Visual Studio profiler +*.psess +*.vsp +*.vspx + +# Guidance Automation Toolkit +*.gpState + +# ReSharper is a .NET coding add-in +_ReSharper*/ +*.[Rr]e[Ss]harper + +# TeamCity is a build add-in +_TeamCity* + +# DotCover is a Code Coverage Tool +*.dotCover + +# NCrunch +*.ncrunch* +.*crunch*.local.xml + +# Installshield output folder +[Ee]xpress/ + +# DocProject is a documentation generator add-in +DocProject/buildhelp/ +DocProject/Help/*.HxT +DocProject/Help/*.HxC +DocProject/Help/*.hhc +DocProject/Help/*.hhk +DocProject/Help/*.hhp +DocProject/Help/Html2 +DocProject/Help/html + +# Click-Once directory +publish/ + +# Publish Web Output +*.Publish.xml + +# NuGet Packages Directory +## TODO: If you have NuGet Package Restore enabled, uncomment the next line +#packages/ + +# Windows Azure Build Output +csx +*.build.csdef + +# Windows Store app package directory +AppPackages/ + +# Others +sql/ +*.Cache +ClientBin/ +[Ss]tyle[Cc]op.* +~$* +*~ +*.dbmdl +*.[Pp]ublish.xml +*.pfx +*.publishsettings + +# RIA/Silverlight projects +Generated_Code/ + +# Backup & report files from converting an old project file to a newer +# Visual Studio version. Backup files are not needed, because we have git ;-) +_UpgradeReport_Files/ +Backup*/ +UpgradeLog*.XML +UpgradeLog*.htm + +# SQL Server files +App_Data/*.mdf +App_Data/*.ldf + + +#LightSwitch generated files +GeneratedArtifacts/ +_Pvt_Extensions/ +ModelManifest.xml + +# ========================= +# Windows detritus +# ========================= + +# Windows image file caches +Thumbs.db +ehthumbs.db + +# Folder config file +Desktop.ini + +# Recycle Bin used on file shares +$RECYCLE.BIN/ + +# Mac desktop service store files +.DS_Store diff --git a/App.xaml b/App.xaml new file mode 100644 index 0000000..d1ce5b2 --- /dev/null +++ b/App.xaml @@ -0,0 +1,12 @@ + + + + + + + + + + diff --git a/App.xaml.cs b/App.xaml.cs new file mode 100644 index 0000000..862387b --- /dev/null +++ b/App.xaml.cs @@ -0,0 +1,228 @@ +using System; +using System.Diagnostics; +using System.Globalization; +using System.IO; +using System.Reflection; +using System.Threading; +using Microsoft.Win32; + +using Common.Debug; +using Common.Helpers; +using Common.IO; +using Common.Wpf.Extensions; +using Common.Settings; + +using FeedCenter.Properties; + +namespace FeedCenter +{ + public partial class App + { + #region Debug properties + + public static bool UseDebugPath; + + #endregion + + #region Properties + + public bool Restart; + + #endregion + + #region Main function + + [STAThread] + public static void Main() + { + // Create and initialize the app object + App app = new App(); + app.InitializeComponent(); + + // Create an isolation handle to see if we are already running + IDisposable isolationHandle = ApplicationIsolation.GetIsolationHandle(FeedCenter.Properties.Resources.ApplicationName); + + // If there is another copy then pass it the command line and exit + if (isolationHandle == null) + { + InterprocessMessageSender.SendMessage(FeedCenter.Properties.Resources.ApplicationName, Environment.CommandLine); + return; + } + + // Use the handle over the lifetime of the application + using (isolationHandle) + { + // Set the data directory based on debug or not + AppDomain.CurrentDomain.SetData("DataDirectory", + UseDebugPath + ? Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location) + : UserSettingsPath); + + // Get the generic provider + var genericProvider = (GenericSettingsProvider) Settings.Default.Providers[typeof(GenericSettingsProvider).Name]; + + if (genericProvider == null) + return; + + // Set the callbacks into the provider + genericProvider.OpenDataStore = SettingsStore.OpenDataStore; + genericProvider.CloseDataStore = SettingsStore.CloseDataStore; + genericProvider.GetSettingValue = SettingsStore.GetSettingValue; + genericProvider.SetSettingValue = SettingsStore.SetSettingValue; + genericProvider.DeleteSettingsForVersion = SettingsStore.DeleteSettingsForVersion; + genericProvider.GetVersionList = SettingsStore.GetVersionList; + + // Initialize the tracer with the current process ID + Tracer.Initialize(UserSettingsPath, FeedCenter.Properties.Resources.ApplicationName, Process.GetCurrentProcess().Id.ToString(CultureInfo.InvariantCulture), false); + + Current.DispatcherUnhandledException += HandleCurrentDispatcherUnhandledException; + AppDomain.CurrentDomain.UnhandledException += HandleCurrentDomainUnhandledException; + + // Check if we need to upgrade settings from a previous version + if (Settings.Default.FirstRun) + { + Settings.Default.Upgrade(); + Settings.Default.FirstRun = false; + Settings.Default.Save(); + } + + // Create the main window before the splash otherwise WPF gets messed up + MainWindow mainWindow = new MainWindow(); + + // Show the splash window + SplashWindow splashWindow = new SplashWindow(); + splashWindow.ShowDialog(); + + // If we don't need to restart then fire up the main window + if (!app.Restart) + { + // Update the registry settings + SetStartWithWindows(Settings.Default.StartWithWindows); + SetDefaultFeedReader(Settings.Default.RegisterAsDefaultFeedReader); + + // Initialize the window + mainWindow.Initialize(); + + // Run the app + app.Run(mainWindow); + } + + // If we need to restart + if (app.Restart) + { + // Wait a bit to make sure any previous upgrade has settled + Thread.Sleep(2000); + + // Restart the application + Current.Restart(); + } + + // Terminate the tracer + Tracer.Dispose(); + } + } + + private static void HandleCurrentDomainUnhandledException(object sender, UnhandledExceptionEventArgs e) + { + Tracer.WriteException((Exception) e.ExceptionObject); + Tracer.Flush(); + } + + private static void HandleCurrentDispatcherUnhandledException(object sender, System.Windows.Threading.DispatcherUnhandledExceptionEventArgs e) + { + Tracer.WriteException(e.Exception); + Tracer.Flush(); + } + + #endregion + + #region Helpers + + public static string UserSettingsPath + { + get + { + // If we're running in debug mode then use a local path for the database and logs + if (UseDebugPath) + return Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location); + + // Get the path to the local application data directory + string path = Path.Combine( + Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData), + FeedCenter.Properties.Resources.ApplicationName); + + // Make sure it exists - create it if needed + if (!Directory.Exists(path)) + Directory.CreateDirectory(path); + + return path; + } + } + + public static void SetStartWithWindows(bool value) + { + // Get the application name + string applicationName = FeedCenter.Properties.Resources.ApplicationDisplayName; + + // Get application details + string publisherName = applicationName; + string productName = applicationName; + string allProgramsPath = Environment.GetFolderPath(Environment.SpecialFolder.Programs); + string shortcutPath = Path.Combine(allProgramsPath, publisherName); + + // Build the auto start path + shortcutPath = "\"" + Path.Combine(shortcutPath, productName) + ".appref-ms\""; + + // Set auto start + Current.SetStartWithWindows(applicationName, shortcutPath, value); + } + + public static void SetDefaultFeedReader(bool value) + { + // Get the location of the assembly + string assemblyLocation = Assembly.GetExecutingAssembly().Location; + + // Open the registry key (creating if needed) + using (RegistryKey registryKey = Registry.CurrentUser.CreateSubKey("Software\\Classes\\feed", RegistryKeyPermissionCheck.ReadWriteSubTree)) + { + if (registryKey == null) + return; + + // Write the handler settings + registryKey.SetValue(string.Empty, "URL:Feed Handler"); + registryKey.SetValue("URL Protocol", string.Empty); + + // Open the icon subkey (creating if needed) + using (RegistryKey subKey = registryKey.CreateSubKey("DefaultIcon", RegistryKeyPermissionCheck.ReadWriteSubTree)) + { + if (subKey != null) + { + // Write the assembly location + subKey.SetValue(string.Empty, assemblyLocation); + + // Close the subkey + subKey.Close(); + } + } + + // Open the subkey for the command (creating if needed) + using (RegistryKey subKey = registryKey.CreateSubKey("shell\\open\\command", RegistryKeyPermissionCheck.ReadWriteSubTree)) + { + if (subKey != null) + { + // Write the assembly location and parameter + subKey.SetValue(string.Empty, string.Format("\"{0}\" %1", assemblyLocation)); + + // Close the subkey + subKey.Close(); + } + } + + // Close the registry key + registryKey.Close(); + } + } + + #endregion + } +} diff --git a/BrowserCommon.cs b/BrowserCommon.cs new file mode 100644 index 0000000..d7739b8 --- /dev/null +++ b/BrowserCommon.cs @@ -0,0 +1,65 @@ +using System; +using System.Diagnostics; +using Common.Debug; +using Common.Internet; +using FeedCenter.Properties; + +namespace FeedCenter +{ + public static class BrowserCommon + { + public static Browser FindBrowser(string browserKey) + { + Browser browser = null; + + // Get the list of installed browsers + var browsers = Browser.DetectInstalledBrowsers(); + + // Make sure the desired browser exists + if (browsers.ContainsKey(browserKey)) + { + // Get the browser + browser = browsers[browserKey]; + } + + return browser; + } + + public static bool OpenLink(string url) + { + // Get the browser + Browser browser = FindBrowser(Settings.Default.Browser); + + // Start the browser + return OpenLink(browser, url); + } + + public static bool OpenLink(Browser browser, string url) + { + try + { + // Don't bother with empty links + if (String.IsNullOrEmpty(url)) + return true; + + // Add quotes around the URL for safety + url = string.Format("\"{0}\"", url); + + // Start the browser + if (browser == null) + Process.Start(url); + else + Process.Start(browser.Command, url); + + return true; + } + catch (Exception exception) + { + // Just log the exception + Tracer.WriteException(exception); + + return false; + } + } + } +} diff --git a/Data/Database.cs b/Data/Database.cs new file mode 100644 index 0000000..91cec9f --- /dev/null +++ b/Data/Database.cs @@ -0,0 +1,228 @@ +using System; +using System.Data.SqlServerCe; +using System.IO; +using System.Collections.Generic; +using System.Linq; + +using Common.Debug; + +using FeedCenter.Properties; + +namespace FeedCenter.Data +{ + public static class Database + { + #region Static database settings + + public static string DatabasePath; + + #endregion + + #region File version + + private enum SqlServerCeFileVersion + { + Unknown, + Version20, + Version30, + Version35, + Version40, + } + + private static SqlServerCeFileVersion GetFileVersion(string databasePath) + { + // Create a mapping of version numbers to the version enumeration + var versionMapping = new Dictionary + { + { 0x73616261, SqlServerCeFileVersion.Version20 }, + { 0x002dd714, SqlServerCeFileVersion.Version30 }, + { 0x00357b9d, SqlServerCeFileVersion.Version35 }, + { 0x003d0900, SqlServerCeFileVersion.Version40 } + }; + + int signature; + + try + { + // Open the database file + using (FileStream stream = new FileStream(databasePath, FileMode.Open, FileAccess.Read)) + { + // Read the file using the binary reader + BinaryReader reader = new BinaryReader(stream); + + // Seek to the version signature + stream.Seek(16, SeekOrigin.Begin); + + // Read the version signature + signature = reader.ReadInt32(); + + } + } + catch (Exception exception) + { + Tracer.WriteException(exception); + + throw; + } + + // If we know about the version number then return the right enumeration - otherwise unknown + return versionMapping.ContainsKey(signature) ? versionMapping[signature] : SqlServerCeFileVersion.Unknown; + } + + #endregion + + public static bool DatabaseExists + { + get { return File.Exists(DatabasePath); } + } + + public static void CreateDatabase() + { + Tracer.WriteLine("Creating database engine"); + + // Create the database engine + using (SqlCeEngine engine = new SqlCeEngine(string.Format("Data Source={0}", DatabasePath))) + { + Tracer.WriteLine("Creating database"); + + // Create the database itself + engine.CreateDatabase(); + + Tracer.WriteLine("Running database script"); + + // Run the creation script + ExecuteScript(Resources.CreateDatabase); + } + } + + private static int getVersion(SqlCeConnection connection) + { + string versionString = string.Empty; + + try + { + // Check the database version table + using (SqlCeCommand command = new SqlCeCommand("SELECT Value FROM DatabaseVersion", connection)) + versionString = command.ExecuteScalar().ToString(); + } + catch (SqlCeException) + { + // Check the setting table for the version + using (SqlCeCommand command = new SqlCeCommand("SELECT Value FROM Setting WHERE Name = 'DatabaseVersion'", connection)) + versionString = command.ExecuteScalar().ToString(); + } + + if (string.IsNullOrEmpty(versionString)) + versionString = "0"; + + Tracer.WriteLine("Database version: {0}", versionString); + + return int.Parse(versionString); + } + + public static void UpdateDatabase() + { + Tracer.WriteLine("Getting database file version"); + + // Get the database file version + SqlServerCeFileVersion fileVersion = GetFileVersion(DatabasePath); + + Tracer.WriteLine("Database file version: {0}", fileVersion); + + // See if we need to upgrade the database file version + if (fileVersion != SqlServerCeFileVersion.Version40) + { + Tracer.WriteLine("Creating database engine"); + + // Create the database engine + using (SqlCeEngine engine = new SqlCeEngine(string.Format("Data Source={0}", DatabasePath))) + { + Tracer.WriteLine("Upgrading database"); + + // Upgrade the database (if needed) + engine.Upgrade(); + } + } + + Tracer.WriteLine("Getting database version"); + + // Create a database connection + using (SqlCeConnection connection = new SqlCeConnection(string.Format("Data Source={0}", DatabasePath))) + { + // Open the connection + connection.Open(); + + // Get the database version + int databaseVersion = getVersion(connection); + + // Create a dictionary of database upgrade scripts and their version numbers + var scriptList = new Dictionary(); + + // Loop over the properties of the resource object looking for update scripts + foreach (var property in typeof(Resources).GetProperties().Where(property => property.Name.StartsWith("DatabaseUpdate"))) + { + // Get the name of the property + string propertyName = property.Name; + + // Extract the version from the name + int version = int.Parse(propertyName.Substring(propertyName.IndexOf("_", StringComparison.Ordinal) + 1)); + + // Add to the script list + scriptList[version] = propertyName; + } + + // Loop over the scripts ordered by version + foreach (var pair in scriptList.OrderBy(pair => pair.Key)) + { + // If the database version is less than or equal to the script version the script needs to run + if (databaseVersion <= pair.Key) + { + // Get the script text + string scriptText = Resources.ResourceManager.GetString(pair.Value); + + // Run the script + ExecuteScript(scriptText); + } + } + } + } + + public static void MaintainDatabase() + { + Tracer.WriteLine("Creating database engine"); + + // Create the database engine + using (SqlCeEngine engine = new SqlCeEngine(string.Format("Data Source={0}", DatabasePath))) + { + Tracer.WriteLine("Shrinking database"); + + // Compact the database + engine.Shrink(); + } + } + + private static void ExecuteScript(string scriptText) + { + // Create a database connection + using (SqlCeConnection connection = new SqlCeConnection(string.Format("Data Source={0}", DatabasePath))) + { + // Open the connection + connection.Open(); + + // Setup the delimiters + string[] delimiters = new[] { "\r\nGO\r\n" }; + + // Split the script at the delimiters + string[] statements = scriptText.Split(delimiters, StringSplitOptions.RemoveEmptyEntries); + + // Loop over each statement in the script + foreach (string statement in statements) + { + // Execute the statement + using (SqlCeCommand command = new SqlCeCommand(statement, connection)) + command.ExecuteNonQuery(); + } + } + } + } +} diff --git a/Data/Extensions.cs b/Data/Extensions.cs new file mode 100644 index 0000000..450d561 --- /dev/null +++ b/Data/Extensions.cs @@ -0,0 +1,155 @@ +using System; +using System.Data; +using System.Data.SqlServerCe; +using System.Data.SqlTypes; + +namespace FeedCenter.Data +{ + public static class Extensions + { + #region SqlDateTime + + public static SqlDateTime SqlDateTimeZero = new SqlDateTime(0, 0); + + #endregion + + #region DataSet + + public static DataRow GetFirstDataRow(this DataSet dataSet) + { + // If we get no data set then return nothing + if (dataSet == null) + return null; + + // If there were no tables returns then return nothing + if (dataSet.Tables.Count == 0) + return null; + + // Get the first table + DataTable firstTable = dataSet.Tables[0]; + + // If the table has no rows then return nothing + if (firstTable.Rows.Count == 0) + return null; + + // Return the first row + return firstTable.Rows[0]; + } + + #endregion + + #region SqlCeCommand + + public static void SetStatement(this SqlCeCommand command, string statement, params object[] parameters) + { + // Create a new array to hold the updated parameters + object[] formattedParameters = new object[parameters.Length]; + + // Initialize our position + int position = 0; + + // Loop over each parameter + foreach (object parameter in parameters) + { + // If the parameter is a DateTime then we need to reformat + if (parameter == null) + { + // Use a explicit null value + formattedParameters[position++] = "NULL"; + } + else if (parameter is DateTime) + { + // Cast the parameter back to a DateTime + DateTime dateTime = (DateTime) parameter; + + // Convert the DateTime to sortable format + string formatted = dateTime.ToString("s"); + + // Set into the formatted array + formattedParameters[position++] = formatted; + } + else if (parameter is bool) + { + // Convert the boolean to a number + formattedParameters[position++] = Convert.ToInt32(parameter); + } + else if (parameter.GetType().IsEnum) + { + // Convert the enum to a number + formattedParameters[position++] = Convert.ToInt32(parameter); + } + else if (parameter is string) + { + // Escape single quotes + formattedParameters[position++] = (parameter as string).Replace("'", "''"); + } + else + { + // Just put the original value in + formattedParameters[position++] = parameter; + } + } + + // Build the full statement + command.CommandText = string.Format(statement, formattedParameters); + } + + #endregion + + #region SqlCeConnection + + public static void ExecuteNonQuery(this SqlCeConnection connection, string query, params object[] parameters) + { + // Create the command object + SqlCeCommand command = connection.CreateCommand(); + + // Set the statement based on the query and parameters + command.SetStatement(query, parameters); + + //Tracer.WriteLine("Executing SQL statement: {0}", command.CommandText); + + // Execute the command + command.ExecuteNonQuery(); + } + + public static DataSet ExecuteDataSet(this SqlCeConnection connection, string query, params object[] parameters) + { + // Create the command object + SqlCeCommand command = connection.CreateCommand(); + + // Set the statement based on the query and parameters + command.SetStatement(query, parameters); + + // Create a new data adapter + using (SqlCeDataAdapter adapter = new SqlCeDataAdapter(command)) + { + // Create the new data set + using (DataSet dataSet = new DataSet()) + { + //Tracer.WriteLine("Executing SQL query: {0}", command.CommandText); + + // Fill the data set + adapter.Fill(dataSet); + + return dataSet; + } + } + } + + public static object ExecuteScalar(this SqlCeConnection connection, string query, params object[] parameters) + { + // Create the command object + SqlCeCommand command = connection.CreateCommand(); + + // Set the statement based on the query and parameters + command.SetStatement(query, parameters); + + //Tracer.WriteLine("Executing SQL statement: {0}", command.CommandText); + + // Execute the command + return command.ExecuteScalar(); + } + + #endregion + } +} diff --git a/Entities.cs b/Entities.cs new file mode 100644 index 0000000..44960a6 --- /dev/null +++ b/Entities.cs @@ -0,0 +1,127 @@ +using System.Collections.ObjectModel; +using System.ComponentModel; + +namespace FeedCenter +{ + public partial class FeedCenterEntities + { + #region Dispose + + protected override void Dispose(bool disposing) + { + if (disposing) + { + ObjectStateManager.ObjectStateManagerChanged -= HandleObjectStateManagerObjectStateManagerChanged; + _hookedStateManager = false; + } + + base.Dispose(disposing); + } + + #endregion + + private bool _hookedStateManager; + + #region All categories + + private ObservableCollection _allCategories; + + public ObservableCollection AllCategories + { + get + { + if (_allCategories == null) + { + _allCategories = new ObservableCollection(Categories); + + if (!_hookedStateManager) + { + ObjectStateManager.ObjectStateManagerChanged += HandleObjectStateManagerObjectStateManagerChanged; + _hookedStateManager = true; + } + } + + return _allCategories; + } + } + + #endregion + + #region All feeds + + private ObservableCollection _allFeeds; + + public ObservableCollection AllFeeds + { + get + { + if (_allFeeds == null) + { + _allFeeds = new ObservableCollection(Feeds); + + if (!_hookedStateManager) + { + ObjectStateManager.ObjectStateManagerChanged += HandleObjectStateManagerObjectStateManagerChanged; + _hookedStateManager = true; + } + } + + return _allFeeds; + } + } + + #endregion + + #region Object state manager + + void HandleObjectStateManagerObjectStateManagerChanged(object sender, CollectionChangeEventArgs e) + { + if (e.Element is Category) + { + if (_allCategories == null) + return; + + Category category = e.Element as Category; + + switch (e.Action) + { + case CollectionChangeAction.Add: + _allCategories.Add(category); + break; + case CollectionChangeAction.Remove: + _allCategories.Remove(category); + break; + case CollectionChangeAction.Refresh: + _allCategories.Clear(); + foreach (Category loopCategory in Categories) + _allCategories.Add(loopCategory); + break; + } + } + else if (e.Element is Feed) + { + if (_allFeeds == null) + return; + + Feed feed = e.Element as Feed; + + switch (e.Action) + { + case CollectionChangeAction.Add: + _allFeeds.Add(feed); + break; + case CollectionChangeAction.Remove: + _allFeeds.Remove(feed); + break; + case CollectionChangeAction.Refresh: + _allFeeds.Clear(); + foreach (Feed loopfeed in Feeds) + _allFeeds.Add(loopfeed); + break; + } + } + } + + #endregion + } +} diff --git a/FeedCenter.csproj b/FeedCenter.csproj new file mode 100644 index 0000000..b9742e4 --- /dev/null +++ b/FeedCenter.csproj @@ -0,0 +1,471 @@ + + + + Debug + x86 + 8.0.30703 + 2.0 + {BD3D12F2-DE23-4466-83B1-1EB617A877A4} + WinExe + Properties + FeedCenter + FeedCenter + v4.5 + + + 512 + {60dc8134-eba5-43b8-bcc9-bb4bc16c2548};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC} + 4 + false + SAK + SAK + SAK + SAK + \\server\d\FeedCenter\ + true + Unc + false + Foreground + 7 + Days + false + false + true + Feed Center + Feed Center + true + Publish.html + false + 208 + 0.1.0.%2a + false + true + true + + + x86 + true + full + false + bin\Debug\ + DEBUG;TRACE + prompt + 4 + false + + + AnyCPU + pdbonly + true + bin\Release\ + TRACE + prompt + 4 + false + + + + + + + true + + + FeedCenter_TemporaryKey.pfx + + + Resources\Application.ico + + + LocalIntranet + + + true + + + Properties\app.manifest + + + true + + + BC151B601A9608463CB7A5371944A97EDEE60B1A + + + FeedCenter_1_TemporaryKey.pfx + + + true + bin\Debug\ + DEBUG;TRACE + full + AnyCPU + bin\Debug\FeedCenter.exe.CodeAnalysisLog.xml + true + GlobalSuppressions.cs + prompt + MinimumRecommendedRules.ruleset + ;C:\Program Files (x86)\Microsoft Visual Studio 10.0\Team Tools\Static Analysis Tools\\Rule Sets + false + ;C:\Program Files (x86)\Microsoft Visual Studio 10.0\Team Tools\Static Analysis Tools\FxCop\\Rules + false + false + true + false + + + bin\Release\ + TRACE + true + pdbonly + AnyCPU + bin\Release\FeedCenter.exe.CodeAnalysisLog.xml + true + GlobalSuppressions.cs + prompt + MinimumRecommendedRules.ruleset + ;C:\Program Files (x86)\Microsoft Visual Studio 10.0\Team Tools\Static Analysis Tools\\Rule Sets + ;C:\Program Files (x86)\Microsoft Visual Studio 10.0\Team Tools\Static Analysis Tools\FxCop\\Rules + false + + + + ..\Common.Wpf.MarkupExtensions\bin\Release\Common.Wpf.MarkupExtensions.dll + + + + + + + False + bin\Debug\System.Data.SqlServerCe.dll + + + False + bin\Debug\System.Data.SqlServerCe.Entity.dll + + + + + + + + + + + + + + 4.0 + + + + + + + + MSBuild:Compile + Designer + + + + + + FeedErrorWindow.xaml + + + + True + True + Model.edmx + + + + AboutOptionsPanel.xaml + + + BulkFeedWindow.xaml + + + CategoryWindow.xaml + + + DisplayOptionsPanel.xaml + + + FeedsOptionsPanel.xaml + + + FeedWindow.xaml + + + GeneralOptionsPanel.xaml + + + + + OptionsWindow.xaml + + + ReadingOptionsPanel.xaml + + + UpdateOptionsPanel.xaml + + + + SplashWindow.xaml + + + + Designer + MSBuild:Compile + + + MSBuild:Compile + Designer + + + App.xaml + Code + + + + + + + + + + + MainWindow.xaml + Code + + + Designer + MSBuild:Compile + + + Designer + MSBuild:Compile + + + Designer + MSBuild:Compile + + + Designer + MSBuild:Compile + + + Designer + MSBuild:Compile + + + Designer + MSBuild:Compile + + + MSBuild:Compile + Designer + + + Designer + MSBuild:Compile + + + Designer + MSBuild:Compile + + + MSBuild:Compile + Designer + + + Designer + MSBuild:Compile + + + Designer + MSBuild:Compile + + + + + Code + + + True + True + Resources.resx + + + True + Settings.settings + True + + + PublicResXFileCodeGenerator + Resources.Designer.cs + Designer + + + Designer + + + amd64\Microsoft.VC90.CRT\Microsoft.VC90.CRT.manifest + Always + + + x86\Microsoft.VC90.CRT\Microsoft.VC90.CRT.manifest + Always + + + EntityModelCodeGenerator + Model.Designer.cs + + + + + + + SettingsSingleFileGenerator + Settings.Designer.cs + + + + + + + + + + + + + + + + + + False + Microsoft .NET Framework 4.5 %28x86 and x64%29 + true + + + False + .NET Framework 3.5 SP1 Client Profile + false + + + False + .NET Framework 3.5 SP1 + false + + + False + Windows Installer 4.5 + true + + + + + {ED1C07A1-54F5-4796-8B06-2A0BB1960D84} + Common.Native + + + {0074C983-550E-4094-9E8C-F566FB669297} + Common.Wpf + + + {17864D82-457D-4A0A-BC10-1D07F2B3A5D6} + Common + + + + + amd64\Microsoft.VC90.CRT\msvcr90.dll + Always + + + amd64\sqlceca40.dll + Always + + + amd64\sqlcecompact40.dll + Always + + + amd64\sqlceer40EN.dll + Always + + + amd64\sqlceme40.dll + Always + + + amd64\sqlceqp40.dll + Always + + + amd64\sqlcese40.dll + Always + + + + + + + + + + Libraries\System.Data.SqlServerCe.dll + Always + + + Libraries\System.Data.SqlServerCe.Entity.dll + Always + + + x86\Microsoft.VC90.CRT\msvcr90.dll + Always + + + x86\sqlceca40.dll + Always + + + x86\sqlcecompact40.dll + Always + + + x86\sqlceer40EN.dll + Always + + + x86\sqlceme40.dll + Always + + + x86\sqlceqp40.dll + Always + + + x86\sqlcese40.dll + Always + + + + + + + + + + \ No newline at end of file diff --git a/FeedCenter.csproj.DotSettings b/FeedCenter.csproj.DotSettings new file mode 100644 index 0000000..2a8adce --- /dev/null +++ b/FeedCenter.csproj.DotSettings @@ -0,0 +1,2 @@ + + True \ No newline at end of file diff --git a/FeedCenter.sln b/FeedCenter.sln new file mode 100644 index 0000000..bab9c72 --- /dev/null +++ b/FeedCenter.sln @@ -0,0 +1,91 @@ +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio 2013 +VisualStudioVersion = 12.0.21005.1 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "FeedCenter", "FeedCenter.csproj", "{BD3D12F2-DE23-4466-83B1-1EB617A877A4}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Common", "..\Common\Common.csproj", "{17864D82-457D-4A0A-BC10-1D07F2B3A5D6}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Common.Wpf", "..\Common.Wpf\Common.Wpf.csproj", "{0074C983-550E-4094-9E8C-F566FB669297}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Common.Native", "..\Common.Native\Common.Native.csproj", "{ED1C07A1-54F5-4796-8B06-2A0BB1960D84}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Any CPU = Debug|Any CPU + Debug|Mixed Platforms = Debug|Mixed Platforms + Debug|x64 = Debug|x64 + Debug|x86 = Debug|x86 + Release|Any CPU = Release|Any CPU + Release|Mixed Platforms = Release|Mixed Platforms + Release|x64 = Release|x64 + Release|x86 = Release|x86 + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {BD3D12F2-DE23-4466-83B1-1EB617A877A4}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {BD3D12F2-DE23-4466-83B1-1EB617A877A4}.Debug|Any CPU.Build.0 = Debug|Any CPU + {BD3D12F2-DE23-4466-83B1-1EB617A877A4}.Debug|Mixed Platforms.ActiveCfg = Debug|x86 + {BD3D12F2-DE23-4466-83B1-1EB617A877A4}.Debug|Mixed Platforms.Build.0 = Debug|x86 + {BD3D12F2-DE23-4466-83B1-1EB617A877A4}.Debug|x64.ActiveCfg = Debug|x86 + {BD3D12F2-DE23-4466-83B1-1EB617A877A4}.Debug|x86.ActiveCfg = Debug|x86 + {BD3D12F2-DE23-4466-83B1-1EB617A877A4}.Debug|x86.Build.0 = Debug|x86 + {BD3D12F2-DE23-4466-83B1-1EB617A877A4}.Release|Any CPU.ActiveCfg = Release|Any CPU + {BD3D12F2-DE23-4466-83B1-1EB617A877A4}.Release|Any CPU.Build.0 = Release|Any CPU + {BD3D12F2-DE23-4466-83B1-1EB617A877A4}.Release|Mixed Platforms.ActiveCfg = Release|x86 + {BD3D12F2-DE23-4466-83B1-1EB617A877A4}.Release|Mixed Platforms.Build.0 = Release|x86 + {BD3D12F2-DE23-4466-83B1-1EB617A877A4}.Release|x64.ActiveCfg = Release|x86 + {BD3D12F2-DE23-4466-83B1-1EB617A877A4}.Release|x86.ActiveCfg = Release|x86 + {BD3D12F2-DE23-4466-83B1-1EB617A877A4}.Release|x86.Build.0 = Release|x86 + {17864D82-457D-4A0A-BC10-1D07F2B3A5D6}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {17864D82-457D-4A0A-BC10-1D07F2B3A5D6}.Debug|Any CPU.Build.0 = Debug|Any CPU + {17864D82-457D-4A0A-BC10-1D07F2B3A5D6}.Debug|Mixed Platforms.ActiveCfg = Debug|x86 + {17864D82-457D-4A0A-BC10-1D07F2B3A5D6}.Debug|Mixed Platforms.Build.0 = Debug|x86 + {17864D82-457D-4A0A-BC10-1D07F2B3A5D6}.Debug|x64.ActiveCfg = Debug|x64 + {17864D82-457D-4A0A-BC10-1D07F2B3A5D6}.Debug|x64.Build.0 = Debug|x64 + {17864D82-457D-4A0A-BC10-1D07F2B3A5D6}.Debug|x86.ActiveCfg = Debug|x86 + {17864D82-457D-4A0A-BC10-1D07F2B3A5D6}.Debug|x86.Build.0 = Debug|x86 + {17864D82-457D-4A0A-BC10-1D07F2B3A5D6}.Release|Any CPU.ActiveCfg = Release|Any CPU + {17864D82-457D-4A0A-BC10-1D07F2B3A5D6}.Release|Any CPU.Build.0 = Release|Any CPU + {17864D82-457D-4A0A-BC10-1D07F2B3A5D6}.Release|Mixed Platforms.ActiveCfg = Release|x86 + {17864D82-457D-4A0A-BC10-1D07F2B3A5D6}.Release|Mixed Platforms.Build.0 = Release|x86 + {17864D82-457D-4A0A-BC10-1D07F2B3A5D6}.Release|x64.ActiveCfg = Release|x64 + {17864D82-457D-4A0A-BC10-1D07F2B3A5D6}.Release|x64.Build.0 = Release|x64 + {17864D82-457D-4A0A-BC10-1D07F2B3A5D6}.Release|x86.ActiveCfg = Release|x86 + {17864D82-457D-4A0A-BC10-1D07F2B3A5D6}.Release|x86.Build.0 = Release|x86 + {0074C983-550E-4094-9E8C-F566FB669297}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {0074C983-550E-4094-9E8C-F566FB669297}.Debug|Any CPU.Build.0 = Debug|Any CPU + {0074C983-550E-4094-9E8C-F566FB669297}.Debug|Mixed Platforms.ActiveCfg = Debug|x86 + {0074C983-550E-4094-9E8C-F566FB669297}.Debug|Mixed Platforms.Build.0 = Debug|x86 + {0074C983-550E-4094-9E8C-F566FB669297}.Debug|x64.ActiveCfg = Debug|x64 + {0074C983-550E-4094-9E8C-F566FB669297}.Debug|x64.Build.0 = Debug|x64 + {0074C983-550E-4094-9E8C-F566FB669297}.Debug|x86.ActiveCfg = Debug|x86 + {0074C983-550E-4094-9E8C-F566FB669297}.Debug|x86.Build.0 = Debug|x86 + {0074C983-550E-4094-9E8C-F566FB669297}.Release|Any CPU.ActiveCfg = Release|Any CPU + {0074C983-550E-4094-9E8C-F566FB669297}.Release|Any CPU.Build.0 = Release|Any CPU + {0074C983-550E-4094-9E8C-F566FB669297}.Release|Mixed Platforms.ActiveCfg = Release|x86 + {0074C983-550E-4094-9E8C-F566FB669297}.Release|Mixed Platforms.Build.0 = Release|x86 + {0074C983-550E-4094-9E8C-F566FB669297}.Release|x64.ActiveCfg = Release|x64 + {0074C983-550E-4094-9E8C-F566FB669297}.Release|x64.Build.0 = Release|x64 + {0074C983-550E-4094-9E8C-F566FB669297}.Release|x86.ActiveCfg = Release|x86 + {0074C983-550E-4094-9E8C-F566FB669297}.Release|x86.Build.0 = Release|x86 + {ED1C07A1-54F5-4796-8B06-2A0BB1960D84}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {ED1C07A1-54F5-4796-8B06-2A0BB1960D84}.Debug|Any CPU.Build.0 = Debug|Any CPU + {ED1C07A1-54F5-4796-8B06-2A0BB1960D84}.Debug|Mixed Platforms.ActiveCfg = Debug|x86 + {ED1C07A1-54F5-4796-8B06-2A0BB1960D84}.Debug|Mixed Platforms.Build.0 = Debug|x86 + {ED1C07A1-54F5-4796-8B06-2A0BB1960D84}.Debug|x64.ActiveCfg = Debug|x64 + {ED1C07A1-54F5-4796-8B06-2A0BB1960D84}.Debug|x64.Build.0 = Debug|x64 + {ED1C07A1-54F5-4796-8B06-2A0BB1960D84}.Debug|x86.ActiveCfg = Debug|x86 + {ED1C07A1-54F5-4796-8B06-2A0BB1960D84}.Debug|x86.Build.0 = Debug|x86 + {ED1C07A1-54F5-4796-8B06-2A0BB1960D84}.Release|Any CPU.ActiveCfg = Release|Any CPU + {ED1C07A1-54F5-4796-8B06-2A0BB1960D84}.Release|Any CPU.Build.0 = Release|Any CPU + {ED1C07A1-54F5-4796-8B06-2A0BB1960D84}.Release|Mixed Platforms.ActiveCfg = Release|x86 + {ED1C07A1-54F5-4796-8B06-2A0BB1960D84}.Release|Mixed Platforms.Build.0 = Release|x86 + {ED1C07A1-54F5-4796-8B06-2A0BB1960D84}.Release|x64.ActiveCfg = Release|x64 + {ED1C07A1-54F5-4796-8B06-2A0BB1960D84}.Release|x64.Build.0 = Release|x64 + {ED1C07A1-54F5-4796-8B06-2A0BB1960D84}.Release|x86.ActiveCfg = Release|x86 + {ED1C07A1-54F5-4796-8B06-2A0BB1960D84}.Release|x86.Build.0 = Release|x86 + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection +EndGlobal diff --git a/FeedCenterEntities.datasource b/FeedCenterEntities.datasource new file mode 100644 index 0000000..c919ef6 --- /dev/null +++ b/FeedCenterEntities.datasource @@ -0,0 +1,10 @@ + + + + FeedCenter.FeedCenterEntities, Model.Designer.cs, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null + \ No newline at end of file diff --git a/FeedCenterEntities1.datasource b/FeedCenterEntities1.datasource new file mode 100644 index 0000000..c919ef6 --- /dev/null +++ b/FeedCenterEntities1.datasource @@ -0,0 +1,10 @@ + + + + FeedCenter.FeedCenterEntities, Model.Designer.cs, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null + \ No newline at end of file diff --git a/FeedCenterEntities2.datasource b/FeedCenterEntities2.datasource new file mode 100644 index 0000000..c919ef6 --- /dev/null +++ b/FeedCenterEntities2.datasource @@ -0,0 +1,10 @@ + + + + FeedCenter.FeedCenterEntities, Model.Designer.cs, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null + \ No newline at end of file diff --git a/FeedCenter_1_TemporaryKey.pfx b/FeedCenter_1_TemporaryKey.pfx new file mode 100644 index 0000000..cf47975 Binary files /dev/null and b/FeedCenter_1_TemporaryKey.pfx differ diff --git a/FeedCenter_TemporaryKey.pfx b/FeedCenter_TemporaryKey.pfx new file mode 100644 index 0000000..41fcdac Binary files /dev/null and b/FeedCenter_TemporaryKey.pfx differ diff --git a/FeedErrorWindow.xaml b/FeedErrorWindow.xaml new file mode 100644 index 0000000..b0b52a0 --- /dev/null +++ b/FeedErrorWindow.xaml @@ -0,0 +1,112 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +