/Source/HydroDesktop.MainPlugin/ProjectManager.cs

# · C# · 353 lines · 237 code · 48 blank · 68 comment · 31 complexity · c563dc37d93e8c284f730f3328b33b51 MD5 · raw file

  1. using System;
  2. using System.IO;
  3. using System.Windows.Forms;
  4. using DotSpatial.Data;
  5. using DotSpatial.Controls;
  6. using DotSpatial.Projections;
  7. using HydroDesktop.Configuration;
  8. using HydroDesktop.Database;
  9. using DotSpatial.Topology;
  10. using DotSpatial.Symbology;
  11. using Hydrodesktop.Common;
  12. namespace HydroDesktop.Main
  13. {
  14. public class ProjectManager
  15. {
  16. /// <summary>
  17. /// The main app manager
  18. /// </summary>
  19. public AppManager App { get; private set; }
  20. /// <summary>
  21. /// Creates a new instance of the project manager
  22. /// </summary>
  23. /// <param name="mainApp"></param>
  24. public ProjectManager(AppManager mainApp)
  25. {
  26. App = mainApp;
  27. }
  28. public static ProjectionInfo DefaultProjection { get { return KnownCoordinateSystems.Projected.World.WebMercator; } }
  29. //sets the map extent to continental U.S
  30. private void SetDefaultMapExtents()
  31. {
  32. App.Map.ViewExtents = DefaultMapExtents().ToExtent();
  33. }
  34. public static Envelope DefaultMapExtents()
  35. {
  36. Envelope _defaultMapExtent = new Envelope(-130, -60, 10, 55);
  37. double[] xy = new double[4];
  38. xy[0] = _defaultMapExtent.Minimum.X;
  39. xy[1] = _defaultMapExtent.Minimum.Y;
  40. xy[2] = _defaultMapExtent.Maximum.X;
  41. xy[3] = _defaultMapExtent.Maximum.Y;
  42. double[] z = new double[] { 0, 0 };
  43. ProjectionInfo wgs84 = KnownCoordinateSystems.Geographic.World.WGS1984;
  44. Reproject.ReprojectPoints(xy, z, wgs84, DefaultProjection, 0, 2);
  45. return new Envelope(xy[0], xy[2], xy[1], xy[3]);
  46. }
  47. private static void CopyStream(Stream input, Stream output)
  48. {
  49. byte[] buffer = new byte[8192];
  50. int bytesRead;
  51. while ((bytesRead = input.Read(buffer, 0, buffer.Length)) > 0)
  52. {
  53. output.Write(buffer, 0, bytesRead);
  54. }
  55. }
  56. /// <summary>
  57. /// Check if the path is a valid SQLite database
  58. /// This function returns false, if the SQLite db
  59. /// file doesn't exist or if the file size is 0 Bytes
  60. /// </summary>
  61. public static bool DatabaseExists(string dbPath)
  62. {
  63. return SQLiteHelper.DatabaseExists(dbPath);
  64. }
  65. /// <summary>
  66. /// To get the SQLite database path given the SQLite connection string
  67. /// </summary>
  68. public static string GetSQLiteFileName(string sqliteConnString)
  69. {
  70. return SQLiteHelper.GetSQLiteFileName(sqliteConnString);
  71. }
  72. /// <summary>
  73. /// To get the full SQLite connection string given the SQLite database path
  74. /// </summary>
  75. public static string GetSQLiteConnectionString(string dbFileName)
  76. {
  77. return SQLiteHelper.GetSQLiteConnectionString(dbFileName);
  78. }
  79. /// <summary>
  80. /// Create the default .SQLITE database in the user-specified path
  81. /// </summary>
  82. /// <returns>true if database was created, false otherwise</returns>
  83. public static Boolean CreateNewDatabase(string dbPath)
  84. {
  85. //to create the default.sqlite database file using the SQLiteHelper method
  86. return SQLiteHelper.CreateSQLiteDatabase(dbPath);
  87. }
  88. /// <summary>
  89. /// Checks if the two paths are on the same drive.
  90. /// </summary>
  91. /// <param name="path1">the first path</param>
  92. /// <param name="path2">the second path</param>
  93. /// <returns>true if the two paths are on same drive</returns>
  94. private static Boolean IsSameDrive(string path1, string path2)
  95. {
  96. if (Path.IsPathRooted(path1) && Path.IsPathRooted(path2) && !path1.StartsWith("\\\\") && !path2.StartsWith("\\\\"))
  97. {
  98. if (Path.GetPathRoot(path1) == Path.GetPathRoot(path2))
  99. {
  100. return true;
  101. }
  102. }
  103. return false;
  104. }
  105. /// <summary>
  106. /// Opens a project and updates the maps
  107. /// </summary>
  108. public void OpenProject(string projectFileName)
  109. {
  110. App.ProgressHandler.Progress("Opening Project", 0, "Opening Project");
  111. App.SerializationManager.OpenProject(projectFileName);
  112. App.ProgressHandler.Progress("Project opened", 0, "");
  113. //disable excessive progress reporting (no longer needed with new DS)
  114. //DisableProgressReportingForLayers();
  115. }
  116. private void DisableProgressReportingForLayers()
  117. {
  118. foreach (IMapLayer layer in App.Map.MapFrame.GetAllLayers())
  119. {
  120. layer.ProgressHandler = null;
  121. MapPolygonLayer polyLay = layer as MapPolygonLayer;
  122. if (polyLay != null)
  123. {
  124. polyLay.ProgressReportingEnabled = false;
  125. }
  126. }
  127. App.Map.ProgressHandler = null;
  128. }
  129. public void OpeningProject()
  130. {
  131. if (App.SerializationManager.CurrentProjectFile == null) return;
  132. //todo: change the configuration settings paths
  133. string projectFile = App.SerializationManager.CurrentProjectFile;
  134. Settings.Instance.CurrentProjectFile = App.SerializationManager.CurrentProjectFile;
  135. //also need to set-up the DB
  136. string dbFileName = Path.ChangeExtension(projectFile, "sqlite");
  137. string cacheDbFileName = dbFileName.Replace(".sqlite", "_cache.sqlite");
  138. if (!ValidateDatabase(dbFileName, DatabaseType.DefaulDatabase))
  139. {
  140. SQLiteHelper.CreateSQLiteDatabase(dbFileName);
  141. }
  142. if (!ValidateDatabase(cacheDbFileName, DatabaseType.MetadataCacheDatabase))
  143. {
  144. SQLiteHelper.CreateMetadataCacheDb(cacheDbFileName);
  145. }
  146. Settings.Instance.DataRepositoryConnectionString = SQLiteHelper.GetSQLiteConnectionString(dbFileName);
  147. Settings.Instance.MetadataCacheConnectionString = SQLiteHelper.GetSQLiteConnectionString(cacheDbFileName);
  148. }
  149. //checks if the db exists. Also checks the db schema
  150. private bool ValidateDatabase(string dbFileName, DatabaseType dbType)
  151. {
  152. //check if db exists
  153. if (SQLiteHelper.DatabaseExists(dbFileName))
  154. {
  155. return true;
  156. }
  157. else
  158. {
  159. return false;
  160. }
  161. }
  162. /// <summary>
  163. /// Creates a new project, using a predefined project template to load the base maps.
  164. /// </summary>
  165. /// <param name="templateName">The project template name</param>
  166. public void CreateNewProject(string templateName, AppManager appManager, Map map)
  167. {
  168. switch (templateName)
  169. {
  170. case "North America":
  171. NorthAmericaProjectTemplate.LoadBaseMaps(appManager, map);
  172. break;
  173. case "World":
  174. //foreach (Extension ext in App.Extensions)
  175. //{
  176. // if (ext.AssemblyQualifiedName.ToLower().Contains("webmap"))
  177. // ext.Deactivate();
  178. //}
  179. WorldProjectTemplate.LoadBaseMaps(appManager, map);
  180. App.SerializationManager.SetCustomSetting("world_template", "true");
  181. App.SerializationManager.SetCustomSetting("FetchBasemap_BasemapName", "Bing Aerial Map");
  182. App.SerializationManager.SetCustomSetting("FetchBasemap_Opacity", "50");
  183. App.SerializationManager.OnDeserializing(new SerializingEventArgs());
  184. App.Map.MapFrame.ResetExtents();
  185. break;
  186. default:
  187. NorthAmericaProjectTemplate.LoadBaseMaps(appManager, map);
  188. break;
  189. }
  190. }
  191. /// <summary>
  192. /// Creates a new 'empty' project
  193. /// </summary>
  194. public void CreateEmptyProject()
  195. {
  196. App.Map.Layers.Clear();
  197. }
  198. //saves the current HydroDesktop project file to the user specified location
  199. public void SavingProject()
  200. {
  201. string projectFileName = App.SerializationManager.CurrentProjectFile;
  202. Settings.Instance.AddFileToRecentFiles(projectFileName);
  203. string newProjectDirectory = Path.GetDirectoryName(projectFileName);
  204. App.ProgressHandler.Progress("Saving Project " + projectFileName, 0, "");
  205. Application.DoEvents();
  206. //are we saving or are we doing 'save as' ?
  207. if (projectFileName != Settings.Instance.CurrentProjectFile)
  208. {
  209. //also create a copy of the .sqlite database
  210. string newDbPath = Path.ChangeExtension(projectFileName, ".sqlite");
  211. //current database path
  212. string currentDbPath = SQLiteHelper.GetSQLiteFileName(Settings.Instance.DataRepositoryConnectionString);
  213. //copy db to new path. If no db exists, create new db in the new location
  214. if (SQLiteHelper.DatabaseExists(currentDbPath))
  215. {
  216. File.Copy(currentDbPath, newDbPath, true);
  217. }
  218. else
  219. {
  220. CreateNewDatabase(newDbPath);
  221. }
  222. //create a copy of the metadata cache (_cache.sqlite) database
  223. string newCachePath = projectFileName.Replace(".dspx", "_cache.sqlite");
  224. //current database path
  225. string currentCachePath = SQLiteHelper.GetSQLiteFileName(Settings.Instance.MetadataCacheConnectionString);
  226. //copy db to new path. If no db exists, create new db in the new location
  227. if (SQLiteHelper.DatabaseExists(currentCachePath))
  228. {
  229. File.Copy(currentCachePath, newCachePath, true);
  230. }
  231. else
  232. {
  233. SQLiteHelper.CreateMetadataCacheDb(newCachePath);
  234. }
  235. //TODO: need to trigger a DatabaseChanged event (Settings.Instance.DatabaseChanged..)
  236. //update application level database configuration settings
  237. Settings.Instance.DataRepositoryConnectionString = SQLiteHelper.GetSQLiteConnectionString(newDbPath);
  238. Settings.Instance.MetadataCacheConnectionString = SQLiteHelper.GetSQLiteConnectionString(newCachePath);
  239. Settings.Instance.CurrentProjectFile = App.SerializationManager.CurrentProjectFile;
  240. //Also save the files of all map layers
  241. IMapGroup dataSitesGroup = FindGroupByName(LayerConstants.SearchGroupName);
  242. string projDir = App.SerializationManager.CurrentProjectDirectory;
  243. foreach (IMapLayer layer in App.Map.MapFrame.GetAllLayers())
  244. {
  245. IMapFeatureLayer fl = layer as IMapFeatureLayer;
  246. if (fl != null)
  247. {
  248. if (!String.IsNullOrEmpty(fl.DataSet.Filename))
  249. {
  250. fl.DataSet.SaveAs(Path.Combine(projDir, Path.GetFileName(fl.DataSet.Filename)), true);
  251. }
  252. }
  253. IMapRasterLayer rl = layer as IMapRasterLayer;
  254. if (rl != null)
  255. {
  256. rl.DataSet.SaveAs(Path.Combine(projDir, Path.GetFileName(rl.DataSet.Filename)));
  257. }
  258. }
  259. }
  260. App.ProgressHandler.Progress(String.Empty, 0, String.Empty);
  261. }
  262. /// <summary>
  263. /// Finds the map group with the specific name
  264. /// </summary>
  265. /// <param name="map">the map to search</param>
  266. /// <param name="groupLegendText">the legend text of the map group</param>
  267. /// <returns></returns>
  268. private IMapGroup FindGroupByName(string groupLegendText)
  269. {
  270. foreach (LegendItem item in App.Map.Layers)
  271. {
  272. if (item is IMapGroup && item.LegendText.ToLower() == groupLegendText.ToLower())
  273. {
  274. return (IMapGroup)item;
  275. }
  276. }
  277. return null;
  278. }
  279. public static string GetMapDirectory()
  280. {
  281. string binariesDirectory = AppDomain.CurrentDomain.BaseDirectory;
  282. if (binariesDirectory.EndsWith(@"\")) binariesDirectory =
  283. binariesDirectory.Substring(0, binariesDirectory.Length - 1);
  284. DirectoryInfo baseDirInfo = Directory.GetParent(binariesDirectory);
  285. string baseDirectory = baseDirInfo.FullName;
  286. string baseMapFolder1 = baseDirectory + Path.DirectorySeparatorChar +
  287. @"Maps\BaseData-MercatorSphere";
  288. string baseMapFolder2 = Path.Combine(binariesDirectory, @"Maps\BaseData-MercatorSphere");
  289. if (Directory.Exists(baseMapFolder1))
  290. {
  291. return baseMapFolder1;
  292. }
  293. else if (Directory.Exists(baseMapFolder2))
  294. {
  295. return baseMapFolder2;
  296. }
  297. else
  298. {
  299. MessageBox.Show("error loading base map data. The directory " +
  300. baseMapFolder2 + " does not exist.");
  301. return "";
  302. }
  303. }
  304. }
  305. }