Exemple #1
0
        // 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);
        }