//private int noteCount = 0; //private int fixedchoiceCount = 0; //private int counterCount = 0; public OptionsWindow(TimelapseWindow mainWindow, Timelapse.MarkableImageCanvas mcanvas) { InitializeComponent(); this.Topmost = true; this.markableCanvas = mcanvas; this.mainProgram = mainWindow; //// The Max Zoom Value sldrMaxZoom.Value = markableCanvas.MaxZoom; sldrMaxZoom.ToolTip = markableCanvas.MaxZoom; sldrMaxZoom.Maximum = markableCanvas.MaxZoomUpperBound; sldrMaxZoom.Minimum = 1; //// Image Differencing Thresholds sldrDifferenceThreshold.Value = mainProgram.differenceThreshold; sldrDifferenceThreshold.ToolTip = mainProgram.differenceThreshold; sldrDifferenceThreshold.Maximum = mainProgram.differenceThresholdMax; sldrDifferenceThreshold.Minimum = mainProgram.differenceThresholdMin; //// For swapping data within notes, fixed choices, or counters: //// Get the counts of each type of code control, as we only need to do this once, //// then generate the contents of the listboxes //this.noteCount = this.mainProgram.codeControls.notes.Length; //this.fixedchoiceCount = this.mainProgram.codeControls.fixedChoice.Length; //this.counterCount = this.mainProgram.codeControls.counters.Length; //GenerateLists(); }
// Find missing folders private async void MenuItemEditFindMissingFolder_Click(object sender, RoutedEventArgs e) { bool?result = TimelapseWindow.GetAndCorrectForMissingFolders(this, this.DataHandler.FileDatabase); if (true == result) { await this.FilesSelectAndShowAsync().ConfigureAwait(true); return; } if (result != null && false == result.Value) { Dialogs.MenuEditNoFoldersAreMissing(this); } // if result is null, it means that the operation was aborted for some reason, or the folders were missing but not updated. }
// Load the specified database template and then the associated images. // templateDatabasePath is the Fully qualified path to the template database file. // Returns true only if both the template and image database file are loaded (regardless of whether any images were loaded) , false otherwise private async Task <bool> TryOpenTemplateAndBeginLoadFoldersAsync(string templateDatabasePath) { // Try to create or open the template database // First, check the file path length and notify the user the template couldn't be loaded because its path is too long if (IsCondition.IsPathLengthTooLong(templateDatabasePath)) { Mouse.OverrideCursor = null; Dialogs.TemplatePathTooLongDialog(this, templateDatabasePath); return(false); } // Second, check to see if we can actually open it. // As we can't have out parameters in an async method, we return the state and the desired templateDatabase as a tuple Tuple <bool, TemplateDatabase> tupleResult = await TemplateDatabase.TryCreateOrOpenAsync(templateDatabasePath).ConfigureAwait(true); this.templateDatabase = tupleResult.Item2; if (!tupleResult.Item1) { // Notify the user the template couldn't be loaded rather than silently doing nothing Mouse.OverrideCursor = null; Dialogs.TemplateFileNotLoadedAsCorruptDialog(this, templateDatabasePath); return(false); } // The .tdb templateDatabase should now be loaded // Try to get the image database file path // importImages will be true if its a new image database file, (meaning we should later ask the user to try to import some images) if (this.TrySelectDatabaseFile(templateDatabasePath, out string fileDatabaseFilePath, out bool importImages) == false) { // No image database file was selected return(false); } // Check the file path length of the .ddb file and notify the user the ddb couldn't be loaded because its path is too long if (IsCondition.IsPathLengthTooLong(fileDatabaseFilePath)) { Mouse.OverrideCursor = null; Dialogs.DatabasePathTooLongDialog(this, fileDatabaseFilePath); return(false); } // Check the expected file path length of the backup files, and warn the user if backups may not be made because thier path is too long if (IsCondition.IsBackupPathLengthTooLong(templateDatabasePath) || IsCondition.IsBackupPathLengthTooLong(fileDatabaseFilePath)) { Mouse.OverrideCursor = null; Dialogs.BackupPathTooLongDialog(this); } // Before fully loading an existing image database, // - upgrade the template tables if needed for backwards compatability (done automatically) // - compare the controls in the .tdb and .ddb template tables to see if there are any added or missing controls TemplateSyncResults templateSyncResults = new Database.TemplateSyncResults(); bool backUpJustMade = false; using (FileDatabase fileDB = await FileDatabase.UpgradeDatabasesAndCompareTemplates(fileDatabaseFilePath, this.templateDatabase, templateSyncResults).ConfigureAwait(true)) { // A file database was available to open if (fileDB != null) { if (templateSyncResults.ControlSynchronizationErrors.Count > 0 || (templateSyncResults.ControlSynchronizationWarnings.Count > 0 && templateSyncResults.SyncRequiredAsDataLabelsDiffer == false)) { // There are unresolvable syncronization issues. Report them now as we cannot use this template. // Depending on the user response, we either abort Timelapse or use the template found in the ddb file Mouse.OverrideCursor = null; Dialog.TemplateSynchronization templatesNotCompatibleDialog; templatesNotCompatibleDialog = new Dialog.TemplateSynchronization(templateSyncResults.ControlSynchronizationErrors, templateSyncResults.ControlSynchronizationWarnings, this); bool?result = templatesNotCompatibleDialog.ShowDialog(); if (result == false) { // user indicates exiting rather than continuing. Application.Current.Shutdown(); return(false); } else { templateSyncResults.UseTemplateDBTemplate = templatesNotCompatibleDialog.UseNewTemplate; templateSyncResults.SyncRequiredAsChoiceMenusDiffer = templateSyncResults.ControlSynchronizationWarnings.Count > 0; } } else if (templateSyncResults.SyncRequiredAsDataLabelsDiffer) { // If there are any new or missing columns, report them now // Depending on the user response, set the useTemplateDBTemplate to signal whether we should: // - update the template and image data columns in the image database // - use the old template Mouse.OverrideCursor = null; TemplateChangedAndUpdate templateChangedAndUpdate = new TemplateChangedAndUpdate(templateSyncResults, this); bool?result1 = templateChangedAndUpdate.ShowDialog(); templateSyncResults.UseTemplateDBTemplate = result1 == true; } else if (templateSyncResults.SyncRequiredAsNonCriticalFieldsDiffer) { // Non critical differences in template, so these don't need reporting templateSyncResults.UseTemplateDBTemplate = true; } backUpJustMade = fileDB.mostRecentBackup != DateTime.MinValue; } else if (File.Exists(fileDatabaseFilePath) == true) { // The .ddb file (which exists) is for some reason unreadable. // It is likely due to an empty or corrupt or otherwise unreadable database in the file. // Raise an error message bool isEmpty = File.Exists(fileDatabaseFilePath) && new FileInfo(fileDatabaseFilePath).Length == 0; Mouse.OverrideCursor = null; Dialogs.DatabaseFileNotLoadedAsCorruptDialog(this, fileDatabaseFilePath, isEmpty); return(false); } ; } // At this point: // - for backwards compatability, all old databases will have been updated (if needed) to the current version standard // - we should have a valid template and image database loaded // - we know if the user wants to use the old or the new template // So lets load the database for real. The useTemplateDBTemplate signals whether to use the template stored in the DDB, or to use the TDB template. FileDatabase fileDatabase = await FileDatabase.CreateOrOpenAsync(fileDatabaseFilePath, this.templateDatabase, this.State.CustomSelectionTermCombiningOperator, templateSyncResults, backUpJustMade).ConfigureAwait(true); // The next test is to test and syncronize (if needed) the default values stored in the fileDB table schema to those stored in the template Dictionary <string, string> columndefaultdict = fileDatabase.SchemaGetColumnsAndDefaultValues(Constant.DBTables.FileData); char[] quote = { '\'' }; foreach (KeyValuePair <string, string> pair in columndefaultdict) { ControlRow row = this.templateDatabase.GetControlFromTemplateTable(pair.Key); if (row != null && pair.Value.Trim(quote) != row.DefaultValue) { // If even one default is different between the schema default and the template default, update the entire file table. fileDatabase.UpgradeFileDBSchemaDefaultsFromTemplate(); break; } } // Check to see if the root folder stored in the database is the same as the actual root folder. If not, ask the user if it should be changed. this.CheckAndCorrectRootFolder(fileDatabase); // Check to see if there are any missing folders as specified by the relative paths. For those missing, ask the user to try to locate those folders. int missingFoldersCount = TimelapseWindow.GetMissingFolders(fileDatabase).Count; if (missingFoldersCount > 0) { Dialogs.MissingFoldersInformationDialog(this, missingFoldersCount); } // Generate and render the data entry controls, regardless of whether there are actually any files in the files database. this.DataHandler = new DataEntryHandler(fileDatabase); this.DataEntryControls.CreateControls(fileDatabase, this.DataHandler); this.SetUserInterfaceCallbacks(); this.MarkableCanvas.DataEntryControls = this.DataEntryControls; // so the markable canvas can access the controls this.DataHandler.ThumbnailGrid = this.MarkableCanvas.ThumbnailGrid; this.DataHandler.MarkableCanvas = this.MarkableCanvas; this.Title = Constant.Defaults.MainWindowBaseTitle + " (" + Path.GetFileName(fileDatabase.FilePath) + ")"; this.State.MostRecentImageSets.SetMostRecent(templateDatabasePath); this.RecentFileSets_Refresh(); // Record the version number of the currently executing version of Timelapse only if its greater than the one already stored in the ImageSet Table. // This will indicate the latest timelapse version that is compatable with the database structure. string currentVersionNumberAsString = VersionChecks.GetTimelapseCurrentVersionNumber().ToString(); if (VersionChecks.IsVersion1GreaterThanVersion2(currentVersionNumberAsString, this.DataHandler.FileDatabase.ImageSet.VersionCompatability)) { this.DataHandler.FileDatabase.ImageSet.VersionCompatability = currentVersionNumberAsString; this.DataHandler.FileDatabase.UpdateSyncImageSetToDatabase(); } // Create an index on RelativePath, File,and RelativePath/File if it doesn't already exist // This is really just a version check in case old databases don't have the index created, // Newer databases (from 2.2.4.4 onwards) will have these indexes created and updated whenever images are loaded or added for the first time. // If the index exists, this is a very cheap operation so there really is no need to do it by a version number check. this.DataHandler.FileDatabase.IndexCreateForFileAndRelativePathIfNotExists(); // If this is a new image database, try to load images (if any) from the folder... if (importImages) { this.TryBeginImageFolderLoad(this.FolderPath, this.FolderPath); } else { await this.OnFolderLoadingCompleteAsync(false).ConfigureAwait(true); } return(true); }