private void CloseProject()
		{
			UpdateTimer.Stop();

			BuildList.Items.Clear();
			BuildList.Groups.Clear();

			SelectedFileName = null;
			SelectedProjectIdentifier = null;
			BranchDirectoryName = null;
			EditorTargetName = null;

			if(NotificationWindow != null)
			{
				NotificationWindow.Dispose();
				NotificationWindow = null;
			}
			if(PerforceMonitor != null)
			{
				PerforceMonitor.Dispose();
				PerforceMonitor = null;
			}
			if(Workspace != null)
			{
				Workspace.Dispose();
				Workspace = null;
			}
			if(EventMonitor != null)
			{
				EventMonitor.Dispose();
				EventMonitor = null;
			}

			ListIndexToChangeIndex = new List<int>();
			SortedChangeNumbers = new List<int>();
			NumChanges = 0;
			ContextMenuChange = null;
			HoverItem = -1;
			PendingSelectedChangeNumber = -1;
			NotifiedBuildTypeToChangeNumber = new Dictionary<string,int>();

			SyncLog.CloseFile();
			SyncLog.Clear();

			UpdateBuildSteps();

			StatusPanel.SetProjectLogo(null);
			UpdateStatusPanel();

			Taskbar.SetState(Handle, TaskbarState.NoProgress);
		}
		private bool OpenProject(string NewSelectedFileName)
		{
			if(String.IsNullOrWhiteSpace(NewSelectedFileName))
			{
				Log.WriteLine("Trying to open empty project path - closing instead");
				return TryCloseProject();
			}

			Log.WriteLine("Trying to open project {0}", NewSelectedFileName);
			if(!File.Exists(NewSelectedFileName))
			{
				ShowErrorDialog("{0} does not exist.", NewSelectedFileName);
				return false;
			}

			// Detect the project settings in a background thread
			using(DetectProjectSettingsTask DetectSettings = new DetectProjectSettingsTask(NewSelectedFileName, Log))
			{
				string ErrorMessage;
				if(!ModalTaskWindow.Execute(DetectSettings, "Opening Project", "Opening project, please wait...", out ErrorMessage))
				{
					if(!String.IsNullOrEmpty(ErrorMessage))
					{
						ShowErrorDialog("{0}", ErrorMessage);
					}
					return false;
				}

				// Now that we've done everything that can fail, perform the final switch over
				if(!TryCloseProject())
				{
					return false;
				}

				// Set the project logo on the status panel and notification window
				NotificationWindow = new NotificationWindow(Properties.Resources.DefaultNotificationLogo);
				StatusPanel.SetProjectLogo(DetectSettings.ProjectLogo);
				DetectSettings.ProjectLogo = null;

				// Update the user settings for the new project
				Settings.OpenProject(DetectSettings.BranchClientPath, DetectSettings.NewSelectedClientFileName);

				// Commit all the new project info
				PerforceConnection PerforceClient = DetectSettings.PerforceClient;
				SelectedFileName = NewSelectedFileName;
				SelectedProjectIdentifier = DetectSettings.NewSelectedProjectIdentifier;
				EditorTargetName = DetectSettings.NewProjectEditorTarget;
				BranchDirectoryName = Path.GetFullPath(Path.Combine(Path.GetDirectoryName(DetectSettings.BaseEditorTargetPath), "..", ".."));
				StreamName = DetectSettings.StreamName;
				ServerTimeZone = DetectSettings.ServerTimeZone;

				// Check if we've the project we've got open in this workspace is the one we're actually synced to
				int CurrentChangeNumber = -1;
				if(String.Compare(Settings.CurrentWorkspace.CurrentProjectIdentifier, SelectedProjectIdentifier, true) == 0)
				{
					CurrentChangeNumber = Settings.CurrentWorkspace.CurrentChangeNumber;
				}

				string ProjectLogBaseName = Path.Combine(DataFolder, String.Format("{0}@{1}", PerforceClient.ClientName, DetectSettings.BranchClientPath.Replace("//" + PerforceClient.ClientName + "/", "").Trim('/').Replace("/", "$")));

				string TelemetryProjectIdentifier = PerforceUtils.GetClientOrDepotDirectoryName(DetectSettings.NewSelectedProjectIdentifier);

				Workspace = new Workspace(PerforceClient, BranchDirectoryName, SelectedFileName, DetectSettings.BranchClientPath, DetectSettings.NewSelectedClientFileName, CurrentChangeNumber, Settings.CurrentWorkspace.LastBuiltChangeNumber, TelemetryProjectIdentifier, new LogControlTextWriter(SyncLog));
				Workspace.OnUpdateComplete += UpdateCompleteCallback;

				PerforceMonitor = new PerforceMonitor(PerforceClient, DetectSettings.BranchClientPath, DetectSettings.NewSelectedClientFileName, SelectedProjectIdentifier, ProjectLogBaseName + ".p4.log");
				PerforceMonitor.OnUpdate += UpdateBuildListCallback;
				PerforceMonitor.OnUpdateMetadata += UpdateBuildMetadataCallback;
				PerforceMonitor.OnStreamChange += StreamChangedCallbackAsync;

				EventMonitor = new EventMonitor(SqlConnectionString, PerforceUtils.GetClientOrDepotDirectoryName(SelectedProjectIdentifier), DetectSettings.PerforceClient.UserName, ProjectLogBaseName + ".review.log");
				EventMonitor.OnUpdatesReady += UpdateReviewsCallback;

				string LogFileName = Path.Combine(DataFolder, ProjectLogBaseName + ".sync.log");
				SyncLog.OpenFile(LogFileName);

				ProjectList.Text = NewSelectedFileName;
				UpdateProjectList();

				Settings.LastProjectFileName = SelectedFileName;
				Settings.Save();

				BuildList.Items.Clear();
				UpdateBuildList();
				UpdateBuildSteps();
				UpdateSyncActionCheckboxes();
				UpdateStatusPanel();

				if(CurrentChangeNumber != -1)
				{
					SelectChange(CurrentChangeNumber);
				}
			}
			return true;
		}