public DateTimeRereadFromFiles(FileDatabase database, Window owner)
 {
     this.InitializeComponent();
     Utilities.TryFitWindowInWorkingArea(this);
     this.database = database;
     this.Owner = owner;
 }
        public DateCorrectAmbiguous(FileDatabase database, Window owner)
        {
            this.InitializeComponent();
            this.ambiguousDatesList = new List<AmbiguousDate>();
            this.database = database;
            this.displayingPreview = false;
            this.Owner = owner;

            // set callbacks in code behind to avoid invoking callbacks when the dialog is created
            this.OriginalDate.Checked += this.DateBox_Checked;
            this.SwappedDate.Checked += this.DateBox_Checked;

            // find the ambiguous dates in the current selection
            if (this.FindAllAmbiguousDatesInSelectedImages() == true)
            {
                this.Abort = false;
            }
            else
            {
                this.Abort = true;
            }

            // Start displaying from the first ambiguous date.
            this.ambiguousDatesListIndex = 0;
        }
 public DataEntryHandler(FileDatabase fileDatabase)
 {
     this.disposed = false;
     this.ImageCache = new ImageCache(fileDatabase);
     this.FileDatabase = fileDatabase;
     this.IsProgrammaticControlUpdate = false;
 }
        public AdvancedImageSetOptions(FileDatabase database, Window owner)
        {
            this.InitializeComponent();
            this.Owner = owner;
            this.database = database;

            this.currentImageSetTimeZone = database.ImageSet.GetTimeZone();
            this.TimeZones.SelectTimeZone(this.currentImageSetTimeZone);
        }
 public ImageCache(FileDatabase fileDatabase) :
     base(fileDatabase)
 {
     this.CurrentDifferenceState = ImageDifference.Unaltered;
     this.differenceBitmapCache = new Dictionary<ImageDifference, BitmapSource>();
     this.mostRecentlyUsedIDs = new MostRecentlyUsedList<long>(Constant.Images.BitmapCacheSize);
     this.prefetechesByID = new ConcurrentDictionary<long, Task>();
     this.unalteredBitmapsByID = new ConcurrentDictionary<long, BitmapSource>();
 }
        public DarkImagesThreshold(FileDatabase database, int currentImageIndex, CarnassialUserRegistrySettings state, Window owner)
        {
            this.InitializeComponent();
            this.Owner = owner;

            this.database = database;
            this.imageEnumerator = new FileTableEnumerator(database, currentImageIndex);
            this.darkPixelThreshold = state.DarkPixelThreshold;
            this.darkPixelRatio = state.DarkPixelRatioThreshold;
            this.darkPixelRatioFound = 0;
            this.disposed = false;
            this.isColor = false;
            this.updateImageQualityForAllSelectedImagesStarted = false;
            this.stop = false;
            this.userSettings = state;
        }
        public DateTimeFixedCorrection(FileDatabase fileDatabase, ImageRow fileToDisplay, Window owner)
        {
            this.InitializeComponent();
            this.displayingPreview = false;
            this.fileDatabase = fileDatabase;
            this.fileToDisplay = fileToDisplay;
            this.Owner = owner;

            // get the image filename and display it
            this.FileName.Content = fileToDisplay.FileName;
            this.FileName.ToolTip = this.FileName.Content;

            // configure datetime picker
            this.initialDateTime = fileToDisplay.GetDateTime();
            this.OriginalDate.Content = DateTimeHandler.ToDisplayDateTimeString(this.initialDateTime);
            this.DateTimePicker.Value = this.initialDateTime;
            this.DateTimePicker.ValueChanged += this.DateTimePicker_ValueChanged;
        }
        public DateTimeSetTimeZone(FileDatabase fileDatabase, ImageRow fileToDisplay, Window owner)
        {
            this.InitializeComponent();
            this.displayingPreview = false;
            this.fileDatabase = fileDatabase;
            this.fileToDisplay = fileToDisplay;
            this.Owner = owner;

            // get the file's current time
            DateTimeOffset currentDateTime = fileToDisplay.GetDateTime();
            this.OriginalDate.Content = DateTimeHandler.ToDisplayDateTimeUtcOffsetString(currentDateTime);

            // get the filename and display it
            this.FileName.Content = fileToDisplay.FileName;

            // configure timezone picker
            this.TimeZones.SelectTimeZone(this.fileDatabase.ImageSet.GetTimeZone());
            this.TimeZones.SelectionChanged += this.TimeZones_SelectionChanged;
        }
        public void CreateControls(FileDatabase database, DataEntryHandler dataEntryPropagator)
        {
            // Depending on how the user interacts with the file import process image set loading can be aborted after controls are generated and then
            // another image set loaded.  Any existing controls therefore need to be cleared.
            this.ControlGrid.Children.Clear();
            this.Controls.Clear();
            this.ControlsByDataLabel.Clear();

            DataEntryDateTime dateTimeControl = null;
            DataEntryUtcOffset utcOffsetControl = null;
            List<DataEntryControl> visibleControls = new List<DataEntryControl>();
            foreach (ControlRow control in database.Controls)
            {
                // no point in generating a control if it doesn't render in the UX
                if (control.Visible == false)
                {
                    continue;
                }

                if (control.Type == Constant.DatabaseColumn.DateTime)
                {
                    dateTimeControl = new DataEntryDateTime(control, this);
                    visibleControls.Add(dateTimeControl);
                }
                else if (control.Type == Constant.DatabaseColumn.File ||
                         control.Type == Constant.DatabaseColumn.RelativePath ||
                         control.Type == Constant.Control.Note)
                {
                    // standard controls rendering as notes aren't editable by the user
                    List<string> autocompletions = null;
                    bool readOnly = control.Type != Constant.Control.Note;
                    if (readOnly == false)
                    {
                        autocompletions = new List<string>(database.GetDistinctValuesInFileDataColumn(control.DataLabel));
                    }
                    DataEntryNote noteControl = new DataEntryNote(control, autocompletions, this);
                    noteControl.ContentReadOnly = readOnly;
                    visibleControls.Add(noteControl);
                }
                else if (control.Type == Constant.Control.Flag || control.Type == Constant.DatabaseColumn.DeleteFlag)
                {
                    DataEntryFlag flagControl = new DataEntryFlag(control, this);
                    visibleControls.Add(flagControl);
                }
                else if (control.Type == Constant.Control.Counter)
                {
                    DataEntryCounter counterControl = new DataEntryCounter(control, this);
                    visibleControls.Add(counterControl);
                }
                else if (control.Type == Constant.Control.FixedChoice || control.Type == Constant.DatabaseColumn.ImageQuality)
                {
                    DataEntryChoice choiceControl = new DataEntryChoice(control, this);
                    visibleControls.Add(choiceControl);
                }
                else if (control.Type == Constant.DatabaseColumn.UtcOffset)
                {
                    utcOffsetControl = new DataEntryUtcOffset(control, this);
                    visibleControls.Add(utcOffsetControl);
                }
                else
                {
                    Debug.Fail(String.Format("Unhandled control type {0}.", control.Type));
                    continue;
                }
            }

            if ((dateTimeControl != null) && (utcOffsetControl != null))
            {
                dateTimeControl.ShowUtcOffset();
                visibleControls.Remove(utcOffsetControl);
            }

            foreach (DataEntryControl control in visibleControls)
            {
                this.ControlGrid.Children.Add(control.Container);
                this.Controls.Add(control);
                this.ControlsByDataLabel.Add(control.DataLabel, control);
            }

            dataEntryPropagator.SetDataEntryCallbacks(this.ControlsByDataLabel);
        }
        private async Task CheckDifferenceResult(ImageDifferenceResult result, ImageCache cache, FileDatabase fileDatabase)
        {
            BitmapSource currentBitmap = cache.GetCurrentImage();
            switch (result)
            {
                case ImageDifferenceResult.CurrentImageNotAvailable:
                case ImageDifferenceResult.NextImageNotAvailable:
                case ImageDifferenceResult.PreviousImageNotAvailable:
                    if (cache.CurrentDifferenceState == ImageDifference.Unaltered)
                    {
                        Assert.IsNotNull(currentBitmap);
                    }
                    else
                    {
                        Assert.IsNull(currentBitmap);
                    }
                    break;
                case ImageDifferenceResult.NotCalculable:
                    bool expectNullBitmap = false;
                    int previousNextImageRow = -1;
                    int otherImageRowForCombined = -1;
                    switch (cache.CurrentDifferenceState)
                    {
                        // as a default assume images are matched and expect differences to be calculable if the necessary images are available
                        case ImageDifference.Combined:
                            expectNullBitmap = (cache.CurrentRow == 0) || (cache.CurrentRow == fileDatabase.CurrentlySelectedFileCount - 1);
                            previousNextImageRow = cache.CurrentRow - 1;
                            otherImageRowForCombined = cache.CurrentRow + 1;
                            break;
                        case ImageDifference.Next:
                            expectNullBitmap = cache.CurrentRow == fileDatabase.CurrentlySelectedFileCount - 1;
                            previousNextImageRow = cache.CurrentRow + 1;
                            break;
                        case ImageDifference.Previous:
                            expectNullBitmap = cache.CurrentRow == 0;
                            previousNextImageRow = cache.CurrentRow - 1;
                            break;
                        case ImageDifference.Unaltered:
                            // result should be NotCalculable on Unaltered
                            expectNullBitmap = true;
                            return;
                    }

                    // check if the image to diff against is matched
                    if (fileDatabase.IsFileRowInRange(previousNextImageRow))
                    {
                        WriteableBitmap unalteredBitmap = (await cache.Current.LoadBitmapAsync(fileDatabase.FolderPath)).AsWriteable();
                        ImageRow previousNextImage = fileDatabase.Files[previousNextImageRow];
                        WriteableBitmap previousNextBitmap = (await previousNextImage.LoadBitmapAsync(fileDatabase.FolderPath)).AsWriteable();
                        bool mismatched = WriteableBitmapExtensions.BitmapsMismatchedOrNot24BitRgb(unalteredBitmap, previousNextBitmap);

                        if (fileDatabase.IsFileRowInRange(otherImageRowForCombined))
                        {
                            ImageRow otherImageForCombined = fileDatabase.Files[otherImageRowForCombined];
                            WriteableBitmap otherBitmapForCombined = (await otherImageForCombined.LoadBitmapAsync(fileDatabase.FolderPath)).AsWriteable();
                            mismatched |= WriteableBitmapExtensions.BitmapsMismatchedOrNot24BitRgb(unalteredBitmap, otherBitmapForCombined);
                        }

                        expectNullBitmap |= mismatched;
                    }

                    if (expectNullBitmap)
                    {
                        Assert.IsNull(currentBitmap, "Expected a null bitmap for difference result {0} and state {1}.", result, cache.CurrentDifferenceState);
                    }
                    else
                    {
                        Assert.IsNotNull(currentBitmap, "Expected a bitmap for difference result {0} and state {1}.", result, cache.CurrentDifferenceState);
                    }
                    break;
                case ImageDifferenceResult.Success:
                    Assert.IsNotNull(currentBitmap);
                    break;
                default:
                    throw new NotSupportedException(String.Format("Unhandled result {0}.", result));
            }
        }
        public DateTimeLinearCorrection(FileDatabase fileDatabase, Window owner)
        {
            this.InitializeComponent();
            this.Abort = false;
            this.Owner = owner;

            this.displayingPreview = false;
            this.earliestFileDateTimeUncorrected = DateTime.MaxValue.ToUniversalTime();
            this.latestFileDateTimeUncorrected = DateTime.MinValue.ToUniversalTime();
            this.fileDatabase = fileDatabase;

            this.earliestFile = null;
            this.latestFile = null;
            bool foundEarliest = false;
            bool foundLatest = false;
            foreach (ImageRow file in fileDatabase.Files)
            {
                DateTimeOffset fileDateTime = file.GetDateTime();

                if (fileDateTime >= this.latestFileDateTimeUncorrected)
                {
                    this.latestFile = file;
                    this.latestFileDateTimeUncorrected = fileDateTime;
                    foundLatest = true;
                }

                if (fileDateTime <= this.earliestFileDateTimeUncorrected)
                {
                    this.earliestFile = file;
                    this.earliestFileDateTimeUncorrected = fileDateTime;
                    foundEarliest = true;
                }
            }

            if ((foundEarliest == false) || (foundLatest == false))
            {
                this.Abort = true;
                return;
            }

            // configure earliest and latest images
            // Images proper are loaded in Window_Loaded().
            this.EarliestImageFileName.Content = this.earliestFile.FileName;
            this.EarliestImageFileName.ToolTip = this.EarliestImageFileName.Content;

            this.LatestImageFileName.Content = this.latestFile.FileName;
            this.LatestImageFileName.ToolTip = this.LatestImageFileName.Content;

            // configure interval
            this.ClockLastCorrect.Maximum = this.earliestFileDateTimeUncorrected;
            this.ClockLastCorrect.Value = this.earliestFileDateTimeUncorrected;
            this.ClockLastCorrect.ValueChanged += this.Interval_ValueChanged;

            this.ClockDriftMeasured.Minimum = this.latestFileDateTimeUncorrected;
            this.ClockDriftMeasured.Value = this.latestFileDateTimeUncorrected;
            this.ClockDriftMeasured.ValueChanged += this.Interval_ValueChanged;

            // configure adjustment
            this.ClockDrift.Value = this.ClockDrift.Value;
            this.ClockDrift.ValueChanged += this.ClockDrift_ValueChanged;

            // show image times
            this.RefreshImageTimes();
        }
 protected Dictionary<string, string> LoadMetadata(FileDatabase fileDatabase, FileExpectations fileExpectation)
 {
     string filePath = Path.Combine(this.WorkingDirectory, fileExpectation.RelativePath, fileExpectation.FileName);
     Dictionary<string, string> metadata = Utilities.LoadMetadata(filePath);
     Assert.IsTrue(metadata.Count > 40, "Expected at least 40 metadata fields to be retrieved from {0}", filePath);
     // example information returned from ExifTool
     // field name                   Bushnell                                    Reconyx
     // --- fields of likely interest for image analysis ---
     // Create Date                  2016.02.24 04:59:46                         [Bushnell only]
     // Date/Time Original           2016.02.24 04:59:46                         2015.01.28 11:17:34 [but located in Makernote rather than the standard EXIF field!]
     // Modify Date                  2016.02.24 04:59:46                         [Bushnell only]
     // --- fields possibly of interest interest for image analysis ---
     // Exposure Time                0                                           1/84
     // Shutter Speed                0                                           1/84
     // Software                     BS683BWYx05209                              [Bushnell only]
     // Firmware Version             [Reconyx only]                              3.3.0
     // Trigger Mode                 [Reconyx only]                              Motion Detection
     // Sequence                     [Reconyx only]                              1 of 5
     // Ambient Temperature          [Reconyx only]                              0 C
     // Serial Number                [Reconyx only]                              H500DE01120343
     // Infrared Illuminator         [Reconyx only]                              Off
     // User Label                   [Reconyx only]                              CCPF DS02
     // --- fields of little interest (Bushnell often uses placeholder values which don't change) ---
     // ExifTool Version Number      10.14                                       10.14
     // File Name                    BushnellTrophyHD-119677C-20160224-056.JPG   Reconyx-HC500-20150128-201.JPG
     // Directory                    Carnassial/UnitTests/bin/Debug               Carnassial/UnitTests/bin/Debug/CarnivoreTestImages
     // File Size                    731 kB                                      336 kB
     // File Modification Date/Time  <file time from last build>                 <file time from last build>
     // File Access Date/Time        <file time from last build>                 <file time from last build>
     // File Creation Date/Time      <file time from last build>                 <file time from last build>
     // File Permissions             rw-rw-rw-                                   rw-rw-rw-
     // File Type                    JPEG                                        JPEG
     // File Type Extension          jpg                                         jpg
     // MIME Type                    image/jpeg                                  image/jpeg
     // Exif Byte Order              Little-endian(Intel, II)                    Little-endian(Intel, II)
     // Image Description            M2E6L0-0R350B362                            [Bushnell only]
     // Make                         [blank]                                     [Bushnell only]
     // Camera Model Name            [blank]                                     [Bushnell only]
     // Orientation                  Horizontal(normal)                          [Bushnell only]
     // X Resolution                 96                                          72
     // Y Resolution                 96                                          72
     // Resolution Unit              inches                                      inches
     // Y Cb Cr Positioning          Co-sited                                    Co-sited
     // Copyright                    Copyright 2002                              [Bushnell only]
     // F Number                     2.8                                         [Bushnell only]
     // Exposure Program             Aperture-priority AE                        [Bushnell only]
     // ISO                          100                                         50
     // Exif Version                 0210                                        0220
     // Components Configuration     Y, Cb, Cr, -                                Y, Cb, Cr, -
     // Compressed Bits Per Pixel    0.7419992711                                [Bushnell only]
     // Shutter Speed Value          1                                           [Bushnell only]
     // Aperture Value               2.6                                         [Bushnell only]
     // Exposure Compensation        +2                                          [Bushnell only]
     // Max Aperture Value           2.6                                         [Bushnell only]
     // Metering Mode                Average                                     [Bushnell only]
     // Light Source                 Daylight                                    [Bushnell only]
     // Flash                        No Flash                                    [Bushnell only]
     // Warning                      [minor]Unrecognized MakerNotes              [Bushnell only]
     // Flashpix Version             0100                                        0100
     // Color Space                  sRGB                                        sRGB
     // Exif Image Width             3264                                        2048
     // Exif Image Height            2448                                        1536
     // Related Sound File           RelatedSound                                [Bushnell only]
     // Interoperability Index       R98 - DCF basic file(sRGB)                  [Bushnell only]
     // Interoperability Version     0100                                        [Bushnell only]
     // Exposure Index               1                                           [Bushnell only]
     // Sensing Method               One-chip color area                         [Bushnell only]
     // File Source                  Digital Camera                              [Bushnell only]
     // Scene Type                   Directly photographed                       [Bushnell only]
     // Compression                  JPEG(old - style)                           [Bushnell only]
     // Thumbnail Offset             1312                                        [Bushnell only]
     // Thumbnail Length             5768                                        [Bushnell only]
     // Image Width                  3264                                        2048
     // Image Height                 2448                                        1536
     // Encoding Process             Baseline DCT, Huffman coding                Baseline DCT, Huffman coding
     // Bits Per Sample              8                                           8
     // Color Components             3                                           3
     // Y Cb Cr Sub Sampling         YCbCr4:2:2 (2 1)                            YCbCr4:2:2 (2 1)
     // Aperture                     2.8                                         [Bushnell only]
     // Image Size                   3264x2448                                   2048x1536
     // Megapixels                   8.0                                         3.1
     // Thumbnail Image              <binary data>                               [Bushnell only]
     // Ambient Temperature Fahrenheit [Reconyx only]                            31 F
     // Battery Voltage              [Reconyx only]                              8.65 V
     // Contrast                     [Reconyx only]                              142
     // Brightness                   [Reconyx only]                              238
     // Event Number                 [Reconyx only]                              39
     // Firmware Date                [Reconyx only]                              2011:01:10
     // Maker Note Version           [Reconyx only]                              0xf101
     // Moon Phase                   [Reconyx only]                              First Quarter
     // Motion Sensitivity           [Reconyx only]                              100
     // Sharpness                    [Reconyx only]                              64
     // Saturation                   [Reconyx only]                              144
     return metadata;
 }
        protected List<FileExpectations> PopulateDefaultDatabase(FileDatabase fileDatabase, bool excludeSubfolderFiles)
        {
            TimeZoneInfo imageSetTimeZone = fileDatabase.ImageSet.GetTimeZone();

            // files in same folder as .tdb and .ddb
            DateTimeAdjustment martenDateTimeAdjustment;
            ImageRow martenImage = this.CreateFile(fileDatabase, imageSetTimeZone, TestConstant.FileExpectation.InfraredMarten, out martenDateTimeAdjustment);
            Assert.IsTrue(martenDateTimeAdjustment.HasFlag(DateTimeAdjustment.MetadataDate) &&
                          martenDateTimeAdjustment.HasFlag(DateTimeAdjustment.MetadataTime));

            DateTimeAdjustment bobcatDatetimeAdjustment;
            ImageRow bobcatImage = this.CreateFile(fileDatabase, imageSetTimeZone, TestConstant.FileExpectation.DaylightBobcat, out bobcatDatetimeAdjustment);
            Assert.IsTrue(bobcatDatetimeAdjustment.HasFlag(DateTimeAdjustment.MetadataDate) &&
                          bobcatDatetimeAdjustment.HasFlag(DateTimeAdjustment.MetadataTime));

            fileDatabase.AddFiles(new List<ImageRow>() { martenImage, bobcatImage }, null);
            fileDatabase.SelectFiles(FileSelection.All);

            FileTableEnumerator fileEnumerator = new FileTableEnumerator(fileDatabase);
            Assert.IsTrue(fileEnumerator.TryMoveToFile(0));
            Assert.IsTrue(fileEnumerator.MoveNext());

            ColumnTuplesWithWhere bobcatUpdate = new ColumnTuplesWithWhere();
            bobcatUpdate.Columns.Add(new ColumnTuple(TestConstant.DefaultDatabaseColumn.Choice0, "choice b"));
            bobcatUpdate.Columns.Add(new ColumnTuple(TestConstant.DefaultDatabaseColumn.Counter0, 1.ToString()));
            bobcatUpdate.Columns.Add(new ColumnTuple(TestConstant.DefaultDatabaseColumn.FlagNotVisible, true));
            bobcatUpdate.Columns.Add(new ColumnTuple(TestConstant.DefaultDatabaseColumn.Note3, "bobcat"));
            bobcatUpdate.Columns.Add(new ColumnTuple(TestConstant.DefaultDatabaseColumn.NoteNotVisible, "adult"));
            bobcatUpdate.SetWhere(fileEnumerator.Current.ID);
            fileDatabase.UpdateFiles(new List<ColumnTuplesWithWhere>() { bobcatUpdate });

            long martenImageID = fileDatabase.Files[0].ID;
            fileDatabase.UpdateFile(martenImageID, TestConstant.DefaultDatabaseColumn.Choice0, "choice b");
            fileDatabase.UpdateFile(martenImageID, TestConstant.DefaultDatabaseColumn.Counter0, 1.ToString());
            fileDatabase.UpdateFile(martenImageID, TestConstant.DefaultDatabaseColumn.FlagNotVisible, Boolean.TrueString);
            fileDatabase.UpdateFile(martenImageID, TestConstant.DefaultDatabaseColumn.Note3, "American marten");
            fileDatabase.UpdateFile(martenImageID, TestConstant.DefaultDatabaseColumn.NoteNotVisible, "adult");

            // generate expectations
            List<FileExpectations> fileExpectations = new List<FileExpectations>()
            {
                new FileExpectations(TestConstant.FileExpectation.InfraredMarten),
                new FileExpectations(TestConstant.FileExpectation.DaylightBobcat),
            };

            // files in subfolder
            if (excludeSubfolderFiles == false)
            {
                DateTimeAdjustment martenPairDateTimeAdjustment;
                ImageRow martenPairImage = this.CreateFile(fileDatabase, imageSetTimeZone, TestConstant.FileExpectation.DaylightMartenPair, out martenPairDateTimeAdjustment);
                Assert.IsTrue(martenPairDateTimeAdjustment.HasFlag(DateTimeAdjustment.MetadataDate) &&
                              martenPairDateTimeAdjustment.HasFlag(DateTimeAdjustment.MetadataTime));

                DateTimeAdjustment coyoteDatetimeAdjustment;
                ImageRow coyoteImage = this.CreateFile(fileDatabase, imageSetTimeZone, TestConstant.FileExpectation.DaylightCoyote, out coyoteDatetimeAdjustment);
                Assert.IsTrue(coyoteDatetimeAdjustment.HasFlag(DateTimeAdjustment.MetadataDate) &&
                              coyoteDatetimeAdjustment.HasFlag(DateTimeAdjustment.MetadataTime));

                fileDatabase.AddFiles(new List<ImageRow>() { martenPairImage, coyoteImage }, null);
                fileDatabase.SelectFiles(FileSelection.All);

                ColumnTuplesWithWhere coyoteImageUpdate = new ColumnTuplesWithWhere();
                coyoteImageUpdate.Columns.Add(new ColumnTuple(TestConstant.DefaultDatabaseColumn.Note3, "coyote"));
                coyoteImageUpdate.Columns.Add(new ColumnTuple(TestConstant.DefaultDatabaseColumn.NoteNotVisible, "adult"));
                coyoteImageUpdate.Columns.Add(new ColumnTuple(TestConstant.DefaultDatabaseColumn.NoteWithCustomDataLabel, String.Empty));
                coyoteImageUpdate.Columns.Add(new ColumnTuple(TestConstant.DefaultDatabaseColumn.Note0, "escaped field, because a comma is present"));
                coyoteImageUpdate.SetWhere(fileEnumerator.Current.ID);
                fileDatabase.UpdateFiles(new List<ColumnTuplesWithWhere>() { coyoteImageUpdate });

                long martenPairImageID = fileDatabase.Files[3].ID;
                fileDatabase.UpdateFile(martenPairImageID, TestConstant.DefaultDatabaseColumn.Note3, "American marten");
                fileDatabase.UpdateFile(martenPairImageID, TestConstant.DefaultDatabaseColumn.NoteNotVisible, "adult");
                fileDatabase.UpdateFile(martenPairImageID, TestConstant.DefaultDatabaseColumn.NoteWithCustomDataLabel, String.Empty);
                fileDatabase.UpdateFile(martenPairImageID, TestConstant.DefaultDatabaseColumn.Note0, "escaped field due to presence of \",\"");

                fileExpectations.Add(new FileExpectations(TestConstant.FileExpectation.DaylightMartenPair));
                fileExpectations.Add(new FileExpectations(TestConstant.FileExpectation.DaylightCoyote));
            }

            // pull the file data table again so the updates are visible to .csv export
            fileDatabase.SelectFiles(FileSelection.All);

            // complete setting expectations
            for (int fileIndex = 0; fileIndex < fileDatabase.Files.RowCount; ++fileIndex)
            {
                FileExpectations fileExpectation = fileExpectations[fileIndex];
                fileExpectation.ID = fileIndex + 1;
            }
            return fileExpectations;
        }
 private void VerifyDefaultImageSet(FileDatabase fileDatabase)
 {
     // InitialFolderName - current directory case occurs when the test creates a new file database, UnitTests case when the default .ddb is cloned
     Assert.IsTrue(fileDatabase.ImageSet.FileSelection == FileSelection.All);
     Assert.IsTrue((fileDatabase.ImageSet.InitialFolderName == Path.GetFileName(Environment.CurrentDirectory)) ||
                   (fileDatabase.ImageSet.InitialFolderName == "UnitTests"));
     Assert.IsTrue(fileDatabase.ImageSet.MostRecentFileID == Constant.Database.DefaultFileID);
     Assert.IsTrue(fileDatabase.ImageSet.Log == Constant.Database.ImageSetDefaultLog);
     Assert.IsFalse(fileDatabase.ImageSet.Options.HasFlag(ImageSetOptions.Magnifier));
     Assert.IsTrue(fileDatabase.ImageSet.TimeZone == TimeZoneInfo.Local.Id);
 }
        public ImageRow GetFileData(FileDatabase fileDatabase)
        {
            string imageFilePath;
            if (String.IsNullOrEmpty(this.RelativePath))
            {
                imageFilePath = Path.Combine(fileDatabase.FolderPath, this.FileName);
            }
            else
            {
                imageFilePath = Path.Combine(fileDatabase.FolderPath, this.RelativePath, this.FileName);
            }

            TimeZoneInfo imageSetTimeZone = fileDatabase.ImageSet.GetTimeZone();
            ImageRow imageProperties;
            fileDatabase.GetOrCreateFile(new FileInfo(imageFilePath), imageSetTimeZone, out imageProperties);
            // imageProperties.Date is defaulted by constructor
            // imageProperties.DateTime is defaulted by constructor
            // imageProperties.FileName is set by constructor
            // imageProperties.ID is set when images are refreshed after being added to the database
            // imageProperties.ImageQuality is defaulted by constructor
            // imageProperties.ImageTaken is set by constructor
            // imageProperties.InitialRootFolderName is set by constructor
            // imageProperties.RelativePath is set by constructor
            // imageProperties.Time is defaulted by constructor
            return imageProperties;
        }
        /// <summary>
        /// Ask the user if he/she wants to delete one or more files and (depending on whether deleteData is set) the data associated with those files.
        /// Other parameters indicate various specifics of how the deletion was specified, which also determines what is displayed in the interface:
        /// </summary>
        public DeleteFiles(FileDatabase database, List<ImageRow> filesToDelete, bool deleteFileAndData, bool deleteCurrentFileOnly, Window owner)
        {
            this.InitializeComponent();
            this.deleteFileAndData = deleteFileAndData;
            this.fileDatabase = database;
            this.filesToDelete = filesToDelete;
            this.Owner = owner;
            this.ThumbnailList.ItemsSource = this.filesToDelete;
            this.ThumbnailList.View = this.GetFileGridView();

            if (this.deleteFileAndData)
            {
                this.OkButton.IsEnabled = false;
            }
            else
            {
                this.OkButton.IsEnabled = true;
                this.Confirm.Visibility = Visibility.Collapsed;
            }

            // construct the dialog's text based on the state of the flags
            if (deleteCurrentFileOnly)
            {
                string imageOrVideo = filesToDelete[0].IsVideo ? "video" : "image";
                if (deleteFileAndData == false)
                {
                    // Case 1: Delete the current image, but not its data.
                    this.Message.Title = String.Format("Delete the current {0} but not its data?", imageOrVideo);
                    this.Message.What = String.Format("Deletes the current {0} (shown below) but not its data.", imageOrVideo);
                    this.Message.Result = String.Format("\u2022 The deleted {0} will be backed up in a sub-folder named {1}.{2}", imageOrVideo, Constant.File.DeletedFilesFolder, Environment.NewLine);
                    this.Message.Result += String.Format("\u2022 A placeholder {0} will be shown when you try to view a deleted {0}.", imageOrVideo);
                    this.Message.Hint = String.Format("\u2022 Restore the deleted {0} by manually moving it back to its original location, or{1}", imageOrVideo, Environment.NewLine);
                    this.Message.Hint += String.Format("\u2022 Permanently delete the {0} by deleting it from the {1} folder.", imageOrVideo, Constant.File.DeletedFilesFolder);
                }
                else
                {
                    // Case 2: Delete the current image and its data
                    this.Message.Title = String.Format("Delete the current {0} and its data", imageOrVideo);
                    this.Message.What = String.Format("Deletes the current {0} (shown below) and the data associated with that {0}.", imageOrVideo);
                    this.Message.Result = String.Format("\u2022 The deleted {0} will be backed up in a sub-folder named {1}.{2}", imageOrVideo, Constant.File.DeletedFilesFolder, Environment.NewLine);
                    this.Message.Result += String.Format("\u2022 However, the data associated with that {0} will be permanently deleted.", imageOrVideo);
                    this.Message.Hint = String.Format("You can permanently delete the {0} by deleting it from the {1} folder.", imageOrVideo, Constant.File.DeletedFilesFolder);
                }
            }
            else
            {
                int numberOfFilesToDelete = this.filesToDelete.Count;
                this.Message.Title = "Delete " + numberOfFilesToDelete.ToString() + " images and videos marked for deletion in this selection?";
                this.Message.Result = String.Empty;
                if (numberOfFilesToDelete > Constant.Images.LargeNumberOfDeletedImages)
                {
                    this.Message.Result += "Deleting " + numberOfFilesToDelete.ToString() + " files will take a few moments. Please be patient." + Environment.NewLine;
                }
                this.Message.Result += String.Format("\u2022 The deleted files will be backed up in a sub-folder named {0}.{1}", Constant.File.DeletedFilesFolder, Environment.NewLine);

                if (deleteFileAndData == false)
                {
                    // Case 3: Delete files which the delete flag set but not their data
                    this.Message.What = "Deletes " + numberOfFilesToDelete.ToString() + " images and videos marked for deletion (shown below) in this selection, but not the data entered for them.";
                    this.Message.Result += "\u2022 A placeholder image will be shown when you view a deleted file.";
                    this.Message.Hint = "\u2022 Restore deleted files by manually copying or moving them back to their original location, or" + Environment.NewLine;
                    this.Message.Hint += String.Format("\u2022 Permanently delete the files by deleting them from the {0} folder", Constant.File.DeletedFilesFolder);
                }
                else
                {
                    // Case 4: Delete files which have the delete flag set and their data
                    this.Message.Title = "Delete " + numberOfFilesToDelete.ToString() + " images and videos marked for deletion";
                    this.Message.What = "Deletes images and videos marked for deletion (shown below), along with the data entered for them.";
                    this.Message.Result += "\u2022 The data for these files will be permanently deleted.";
                    this.Message.Hint = String.Format("You can permanently delete the files by deleting the {0} folder.", Constant.File.DeletedFilesFolder);
                }
            }
            this.Title = this.Message.Title;
        }
 /// <summary>
 /// Creates a data row from the specified FileExpectation.  Verifies the file isn't already in the database and does not add it to the database.
 /// </summary>
 protected ImageRow CreateFile(FileDatabase fileDatabase, TimeZoneInfo imageSetTimeZone, FileExpectations fileExpectation, out DateTimeAdjustment dateTimeAdjustment)
 {
     FileInfo fileInfo = new FileInfo(Path.Combine(this.WorkingDirectory, fileExpectation.RelativePath, fileExpectation.FileName));
     ImageRow file;
     Assert.IsFalse(fileDatabase.GetOrCreateFile(fileInfo, imageSetTimeZone, out file));
     dateTimeAdjustment = file.TryReadDateTimeOriginalFromMetadata(fileDatabase.FolderPath, imageSetTimeZone);
     return file;
 }
        public static bool TryCreateOrOpen(string filePath, TemplateDatabase templateDatabase, bool orderFilesByDate, CustomSelectionOperator customSelectionTermCombiningOperator, out FileDatabase fileDatabase)
        {
            // check for an existing database before instantiating the databse as SQL wrapper instantiation creates the database file
            bool populateDatabase = !File.Exists(filePath);

            fileDatabase = new FileDatabase(filePath);
            if (populateDatabase)
            {
                // initialize the database if it's newly created
                fileDatabase.OnDatabaseCreated(templateDatabase);
            }
            else
            {
                // if it's an existing database check if it needs updating to current structure and load data tables
                if (fileDatabase.OnExistingDatabaseOpened(templateDatabase) == false)
                {
                    return false;
                }
            }

            // ensure all tables have been loaded from the database
            if (fileDatabase.ImageSet == null)
            {
                fileDatabase.GetImageSet();
            }
            if (fileDatabase.Markers == null)
            {
                fileDatabase.GetMarkers();
            }

            fileDatabase.CustomSelection = new CustomSelection(fileDatabase.Controls, customSelectionTermCombiningOperator);
            fileDatabase.OrderFilesByDateTime = orderFilesByDate;
            fileDatabase.PopulateDataLabelMaps();
            return true;
        }
        private void VerifyDefaultMarkerTableContent(FileDatabase fileDatabase, int filesExpected)
        {
            DataTable markers = fileDatabase.Markers.ExtractDataTable();

            List<string> expectedColumns = new List<string>() { Constant.DatabaseColumn.ID };
            foreach (ControlRow control in fileDatabase.Controls)
            {
                if (control.Type == Constant.Control.Counter)
                {
                    expectedColumns.Add(control.DataLabel);
                }
            }

            Assert.IsTrue(markers.Columns.Count == expectedColumns.Count);
            for (int column = 0; column < expectedColumns.Count; ++column)
            {
                Assert.IsTrue(expectedColumns[column] == markers.Columns[column].ColumnName, "Expected column named '{0}' but found '{1}'.", expectedColumns[column], markers.Columns[column].ColumnName);
            }
            if (expectedColumns.Count == TestConstant.DefaultMarkerColumns.Count)
            {
                for (int column = 0; column < expectedColumns.Count; ++column)
                {
                    Assert.IsTrue(expectedColumns[column] == TestConstant.DefaultMarkerColumns[column], "Expected column named '{0}' but found '{1}'.", expectedColumns[column], TestConstant.DefaultMarkerColumns[column]);
                }
            }

            // marker rows aren't populated if no counters are present in the database
            if (expectedColumns.Count == 1)
            {
                Assert.IsTrue(fileDatabase.Markers.RowCount == 0);
            }
            else
            {
                Assert.IsTrue(fileDatabase.Markers.RowCount == filesExpected);
            }
        }
 private void VerifyFiles(FileDatabase fileDatabase, List<FileExpectations> imageExpectations, TimeZoneInfo initialImageSetTimeZone, int initialImageCount, TimeZoneInfo secondImageSetTimeZone)
 {
     for (int image = 0; image < imageExpectations.Count; ++image)
     {
         TimeZoneInfo expectedTimeZone = image >= initialImageCount ? secondImageSetTimeZone : initialImageSetTimeZone;
         FileExpectations imageExpectation = imageExpectations[image];
         imageExpectation.Verify(fileDatabase.Files[image], expectedTimeZone);
     }
 }
 protected List<FileExpectations> PopulateDefaultDatabase(FileDatabase fileDatabase)
 {
     return this.PopulateDefaultDatabase(fileDatabase, false);
 }