Beispiel #1
0
        /// <summary>
        /// Adds a column with the given column name and value pair.
        /// </summary>
        /// <param name="columnName"></param>
        /// <param name="columnValue"></param>
        protected void AddColumn(string columnName, decimal?columnValue)
        {
            ColumnTuple columnTuple = new ColumnTuple();

            columnTuple.Name      = columnName;
            columnTuple.ValueType = typeof(decimal?);
            columnTuple.Value     = columnValue;
            RegisteredColumns.Add(columnTuple);
        }
Beispiel #2
0
        /// <summary>
        /// Adds a column with the given column name and value pair.
        /// </summary>
        /// <param name="columnName"></param>
        /// <param name="columnValue"></param>
        protected void AddColumn(string columnName, SqlBoolean columnValue)
        {
            ColumnTuple columnTuple = new ColumnTuple();

            columnTuple.Name      = columnName;
            columnTuple.ValueType = typeof(SqlBoolean);
            columnTuple.Value     = columnValue;
            RegisteredColumns.Add(columnTuple);
        }
        /// <summary>
        /// If there are missing folders, search for possible matches and raise a dialog box asking the user to locate them
        /// </summary>
        /// <param name="owner"></param>
        /// <param name="fileDatabase"></param>
        /// <param name="missingFolders"></param>
        /// <returns>whether any folder are actually missing </returns>
        private static bool?CorrectForMissingFolders(Window owner, FileDatabase fileDatabase, List <string> missingRelativePaths)
        {
            // Abort if the arguments for null
            if (null == fileDatabase)
            {
                return(null);
            }
            if (null == missingRelativePaths)
            {
                return(null);
            }

            // We know that at least one or more folders are missing.
            // For each missing folder path, try to find all folders with the same name under the root folder.
            Dictionary <string, List <string> > matchingFolderNames = Util.FilesFolders.TryGetMissingFolders(fileDatabase.FolderPath, missingRelativePaths);
            Dictionary <string, string>         finalFileLocations;

            // We want to show the normal cursor when we display dialog boxes, so save the current cursor so we can store it.
            Cursor cursor = Mouse.OverrideCursor;

            bool?result;

            if (matchingFolderNames != null)
            {
                Mouse.OverrideCursor = null;
                // Present a dialog box that asks the user to locate the missing folders. It will show possible locations for each folder (if any).
                // The user can then confirm correct locations, manually set the locaton of those folders, or cancel altogether.
                MissingFoldersLocateAllFolders dialog = new MissingFoldersLocateAllFolders(owner, fileDatabase.FolderPath, matchingFolderNames);
                result = dialog.ShowDialog();

                if (result == true)
                {
                    // Get the updated folder locations and update the database
                    finalFileLocations = dialog.FinalFolderLocations;
                    foreach (string key in finalFileLocations.Keys)
                    {
                        ColumnTuple           columnToUpdate          = new ColumnTuple(Constant.DatabaseColumn.RelativePath, finalFileLocations[key]);
                        ColumnTuplesWithWhere columnToUpdateWithWhere = new ColumnTuplesWithWhere(columnToUpdate, key);
                        fileDatabase.UpdateFiles(columnToUpdateWithWhere);
                    }
                    Mouse.OverrideCursor = cursor;
                    return(true);
                }
            }
            Mouse.OverrideCursor = cursor;
            return(null); // Operaton aborted
        }
        // Get the root folder name from the database, and check to see if its the same as the actual root folder.
        // If not, ask the user if he/she wants to update the database.
        private void CheckAndCorrectRootFolder(FileDatabase fileDatabase)
        {
            // Check the arguments for null
            if (fileDatabase == null)
            {
                // this should not happen
                // System.Diagnostics.Debug.Print("The fielDatabase was null and it shouldn't be");
                TracePrint.PrintStackTrace(1);
                // No-op
                return;
            }
            List <object> allRootFolderPaths = fileDatabase.GetDistinctValuesInColumn(Constant.DBTables.FileData, Constant.DatabaseColumn.Folder);

            if (allRootFolderPaths.Count < 1)
            {
                // System.Diagnostics.Debug.Print("Checking the root folder name in the database, but no entries were found. Perhaps the database is empty?");
                return;
            }

            // retrieve and compare the db and actual root folder path names. While there really should be only one entry in the allRootFolderPaths,
            // we still do a check in case there is more than one. If even one entry doesn't match, we use that entry to ask the user if he/she
            // wants to update the root folder to match the actual location of the root folder containing the template, data and image files.
            string actualRootFolderName = fileDatabase.FolderPath.Split(Path.DirectorySeparatorChar).Last();

            foreach (string databaseRootFolderName in allRootFolderPaths)
            {
                if (databaseRootFolderName.Equals(actualRootFolderName))
                {
                    continue;
                }
                else
                {
                    // We have at least one entry where there is a mismatch between the actual root folder and the stored root folder
                    // Consequently, ask the user if he/she wants to update the db entry
                    Dialog.UpdateRootFolder renameRootFolderDialog;
                    renameRootFolderDialog = new Dialog.UpdateRootFolder(this, databaseRootFolderName, actualRootFolderName);
                    bool?result = renameRootFolderDialog.ShowDialog();
                    if (result == true)
                    {
                        ColumnTuple columnToUpdate = new ColumnTuple(Constant.DatabaseColumn.Folder, actualRootFolderName);
                        fileDatabase.UpdateFiles(columnToUpdate);
                    }
                    return;
                }
            }
        }
Beispiel #5
0
        // Reads all the data from the old ImageData.xml files into the imageData structure from the XML file in the filepath.
        // Note that we need to know the code controls,as we have to associate any points read in with a particular counter control
        public static Tuple <int, int> Read(string filePath, FileDatabase imageDatabase)
        {
            // XML Preparation - follows CA3075  pattern for loading
            XmlDocument xmlDoc = new XmlDocument()
            {
                XmlResolver = null
            };

            System.IO.StringReader sreader = new System.IO.StringReader(File.ReadAllText(filePath));
            XmlReader reader = XmlReader.Create(sreader, new XmlReaderSettings()
            {
                XmlResolver = null
            });

            xmlDoc.Load(reader);

            // Import the old log (if any)
            XmlNodeList logNodes = xmlDoc.SelectNodes(Constant.ImageXml.Images + Constant.ImageXml.Slash + Constant.DatabaseColumn.Log);

            if (logNodes.Count > 0)
            {
                XmlNode logNode = logNodes[0];
                imageDatabase.ImageSet.Log = logNode.InnerText;
                imageDatabase.UpdateSyncImageSetToDatabase();
            }

            // Create three lists, each one representing the datalabels (in order found in the template) of notes, counters and choices
            // We will use these to find the matching ones in the xml data table.
            List <string> noteControlNames    = new List <string>();
            List <string> counterControlNames = new List <string>();
            List <string> choiceControlNames  = new List <string>();

            foreach (ControlRow control in imageDatabase.Controls)
            {
                // Note that code should be modified to  deal with flag controls
                switch (control.Type)
                {
                case Constant.Control.Counter:
                    counterControlNames.Add(control.DataLabel);
                    break;

                case Constant.Control.FixedChoice:
                    choiceControlNames.Add(control.DataLabel);
                    break;

                case Constant.Control.Note:
                    noteControlNames.Add(control.DataLabel);
                    break;

                default:

                    break;
                }
            }

            XmlNodeList  nodeList         = xmlDoc.SelectNodes(Constant.ImageXml.Images + Constant.ImageXml.Slash + Constant.DatabaseColumn.Image);
            int          imageID          = 0;
            TimeZoneInfo imageSetTimeZone = imageDatabase.ImageSet.GetSystemTimeZone();
            List <ColumnTuplesWithWhere> imagesToUpdate  = new List <ColumnTuplesWithWhere>();
            List <ColumnTuplesWithWhere> markersToUpdate = new List <ColumnTuplesWithWhere>();
            List <Tuple <string, List <ColumnTuple> > > fileNamesMarkersList = new List <Tuple <string, List <ColumnTuple> > >();

            int successCounter = 0;
            int skippedCounter = 0;

            foreach (XmlNode node in nodeList)
            {
                imageID++;

                // We ignore:
                // - Folder and Relative path, as the new template will have the correct values
                // - ImageQuality, as the new Timelapse version probably has a better determination of it
                // - DeleteFlag, as the old-style xml templates didn't have them
                // - Flags as the old-style xml templates didn't have them

                List <ColumnTuple> columnsToUpdate = new List <ColumnTuple>(); // Populate the data
                // File Field - We use the file name as a key into a particular database row. We don't change the database field as it is our key.
                string imageFileName = node[Constant.ImageXml.File].InnerText;

                // If the Folder Path differs from where we had previously loaded it,
                // warn the user that the new path will be substituted in its place
                // This gets the folderName in the Xml file, but we still ahve to get the folderName as it currently exists.
                // string folderName = node[Constant.ImageXml.Folder].InnerText;

                // Date - We use the original date, as the analyst may have adjusted them
                string date = node[Constant.ImageXml.Date].InnerText;
                columnsToUpdate.Add(new ColumnTuple(Constant.DatabaseColumn.Date, date));

                // Date - We use the original time, although its almost certainly identical
                string time = node[Constant.ImageXml.Time].InnerText;
                columnsToUpdate.Add(new ColumnTuple(Constant.DatabaseColumn.Time, time));

                // DateTime
                if (DateTimeHandler.TryParseLegacyDateTime(date, time, imageSetTimeZone, out DateTimeOffset dateTime))
                {
                    columnsToUpdate.Add(new ColumnTuple(Constant.DatabaseColumn.DateTime, dateTime.UtcDateTime));
                    columnsToUpdate.Add(new ColumnTuple(Constant.DatabaseColumn.UtcOffset, dateTime.Offset));
                }

                // Notes: Iterate through
                int         innerNodeIndex = 0;
                XmlNodeList innerNodeList  = node.SelectNodes(Constant.Control.Note);
                foreach (XmlNode innerNode in innerNodeList)
                {
                    // System.Diagnostics.Debug.Print("Note: " + noteControlNames[innerNodeIndex] + " | " + innerNode.InnerText);
                    columnsToUpdate.Add(new ColumnTuple(noteControlNames[innerNodeIndex++], innerNode.InnerText));
                }

                // Choices: Iterate through
                innerNodeIndex = 0;
                innerNodeList  = node.SelectNodes(Constant.Control.FixedChoice);
                foreach (XmlNode innerNode in innerNodeList)
                {
                    // System.Diagnostics.Debug.Print("Choice: " + choiceControlNames[innerNodeIndex] + " | " + innerNode.InnerText);
                    columnsToUpdate.Add(new ColumnTuple(choiceControlNames[innerNodeIndex++], innerNode.InnerText));
                }

                // Counters: Iterate through
                List <ColumnTuple> counterCoordinates = new List <ColumnTuple>();
                innerNodeIndex = 0;
                innerNodeList  = node.SelectNodes(Constant.Control.Counter);
                foreach (XmlNode innerNode in innerNodeList)
                {
                    // Add the value of each counter to the dataline
                    XmlNodeList dataNode = innerNode.SelectNodes(Constant.DatabaseColumn.Data);
                    // System.Diagnostics.Debug.Print("Counter: " + counterControlNames[innerNodeIndex] + " | " + dataNode[0].InnerText);
                    columnsToUpdate.Add(new ColumnTuple(counterControlNames[innerNodeIndex], dataNode[0].InnerText));

                    // For each counter, find the points associated with it and compose them together as x1,y1|x2,y2|...|xn,yn
                    XmlNodeList pointNodeList = innerNode.SelectNodes(Constant.DatabaseColumn.Point);
                    string      countercoord  = String.Empty;
                    foreach (XmlNode pointNode in pointNodeList)
                    {
                        String x = pointNode.SelectSingleNode(Constant.DatabaseColumn.X).InnerText;
                        if (x.Length > 5)
                        {
                            x = x.Substring(0, 5);
                        }
                        String y = pointNode.SelectSingleNode(Constant.DatabaseColumn.Y).InnerText;
                        if (y.Length > 5)
                        {
                            y = y.Substring(0, 5);
                        }
                        countercoord += x + "," + y + "|";
                    }

                    // Remove the last "|" from the point list
                    if (!String.IsNullOrEmpty(countercoord))
                    {
                        countercoord = countercoord.Remove(countercoord.Length - 1); // Remove the last "|"
                    }

                    // Countercoords will have a list of points (possibly empty) with each list entry representing a control
                    counterCoordinates.Add(new ColumnTuple(counterControlNames[innerNodeIndex], countercoord));
                    innerNodeIndex++;
                }

                // add this image's updates to the update lists
                ColumnTuplesWithWhere imageToUpdate = new ColumnTuplesWithWhere(columnsToUpdate);
                // Since Timelapse1 didn't have relative paths, we only need to set Where using the image filename
                // imageToUpdate.SetWhere(currentFolderName, null, imageFileName); //<- replaced by the simpler SetWhere form below
                if (File.Exists(Path.Combine(Path.GetDirectoryName(filePath), imageFileName)))
                {
                    imageToUpdate.SetWhere(imageFileName);
                    imagesToUpdate.Add(imageToUpdate);
                    ColumnTuple ColumnTupleFileName = new ColumnTuple(Constant.DatabaseColumn.File, imageFileName);

                    // We have to do the markers later, as we need to get the ID of the matching filename from the data table,
                    // and use that to set the markers.
                    Tuple <string, List <ColumnTuple> > filenameMarkerTuple = new Tuple <string, List <ColumnTuple> >(imageFileName, counterCoordinates);
                    fileNamesMarkersList.Add(filenameMarkerTuple);
                    successCounter++;
                }
                else
                {
                    skippedCounter++;
                }
            }

            // batch update the data table
            imageDatabase.UpdateFiles(imagesToUpdate);

            // Now that we have updated the data table, we can update the markers.
            // We retrieve the ID of the filename associated with the markers from the data table,
            // and use that to set the correct row in the marker table.
            foreach (Tuple <string, List <ColumnTuple> > tuple in fileNamesMarkersList)
            {
                long id = imageDatabase.GetIDFromDataTableByFileName(tuple.Item1);
                ColumnTuplesWithWhere markerToUpdate = new ColumnTuplesWithWhere(tuple.Item2, id);
                markersToUpdate.Add(markerToUpdate);
                imageDatabase.UpdateMarkers(markersToUpdate);
            }

            if (reader != null)
            {
                reader.Dispose();
            }
            return(new Tuple <int, int>(successCounter, skippedCounter));
        }