Пример #1
0
        public Metadata Read(MetadataBrokerType broker, string fullFilePath)
        {
            int serialNumber;

            if (string.IsNullOrWhiteSpace(fullFilePath))
            {
                return(null);
            }

            string driverLetter = fullFilePath.Substring(0, 2);

            if (dictionarySerialToDriveToId.ContainsKey(driverLetter))
            {
                serialNumber = dictionarySerialToDriveToId[driverLetter];
            }
            else
            {
                serialNumber = convertSerialToDriveToId(driverLetter);
                dictionarySerialToDriveToId.Add(driverLetter, serialNumber);
            }

            return(ReadMetadata(broker,
                                Path.GetFileName(fullFilePath),
                                Path.GetDirectoryName(fullFilePath).Substring(2),
                                Path.GetDirectoryName(fullFilePath), serialNumber));
        }
 public FileEntryBroker GetFileEntryBroker(MetadataBrokerType metadataBrokerType)
 {
     if (FileEntryVersion == FileEntryVersion.Error)
     {
         return(new FileEntryBroker((FileEntry)this, metadataBrokerType | MetadataBrokerType.ExifToolWriteError));
     }
     return(new FileEntryBroker((FileEntry)this, metadataBrokerType));
 }
Пример #3
0
        public override int GetHashCode()
        {
            int hashCode = -793585214;

            hashCode = hashCode * -1521134295 + MetadataBrokerType.GetHashCode();
            hashCode = hashCode * -1521134295 + DateTimeFrom.GetHashCode();
            hashCode = hashCode * -1521134295 + DateTimeTo.GetHashCode();
            return(hashCode);
        }
        public override int GetHashCode()
        {
            int hashCode = 677046786;

            hashCode = hashCode * -1521134295 + MetadataBrokerType.GetHashCode();
            hashCode = hashCode * -1521134295 + SwitchState.GetHashCode();
            hashCode = hashCode * -1521134295 + CellReadOnly.GetHashCode();
            return(hashCode);
        }
        public Metadata Read(MetadataBrokerType broker, string fullFilePath)
        {
            if (errorHasOccurdDoNotReconnect)
            {
                return(null);
            }
            if (checkIfWindowLivePhotoGalleryExists)
            {
                checkIfWindowLivePhotoGalleryExists = false; //Check only once
                string sourceFile = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData), "Microsoft\\Windows Live Photo Gallery\\Pictures.pd6");
                try
                {
                    doesWindowLivePhotoGalleryExists = File.Exists(sourceFile);
                }
                catch { }
            }
            if (!doesWindowLivePhotoGalleryExists)
            {
                return(null);
            }

            Stopwatch stopWatch = new Stopwatch();

            ErrorMessageReset();

            bool retryConnect = false;

            do
            {
                PipeClientForceDisconnectAfterError(ref pipeClientProcessErrorOccurred, ref pipeClientDiconnected, ref consoleProcessDisconnected);

                #region Start PipeClient, if "HANGING" Console process exist, kill that first
                if (pipeClient == null)
                {
                    //Chech if Console Procss running after crash
                    if (IsConsoleProcessRunning())
                    {
                        try
                        {
                            consoleProcessWaitEventServerExited.Reset();

                            if (process != null)
                            {
                                process.CloseMainWindow();
                            }
                            else
                            {
                                Logger.Warn("[Windows Live Photo Gallery | Console Process] Console Server running, but lost process connection with it. Can't close it.");
                            }
                            consoleProcessWaitEventServerExited.WaitOne(2000);
                        }
                        catch (Exception ex)
                        {
                            Logger.Error(ex, "[Windows Live Photo Gallery | Console Process] Close process was not preformed. ");
                        }
                    }

                    if (IsConsoleProcessRunning())
                    {
                        try
                        {
                            if (process != null)
                            {
                                process.Kill();
                            }
                            else
                            {
                                Logger.Warn("[Windows Live Photo Gallery | Console Process] Console Server running, but lost process connection with it. Can't kill it.");
                            }
                        }
                        catch (Exception ex)
                        {
                            Logger.Error(ex, "[Windows Live Photo Gallery | Console Process] Kill process was not preformed. ");
                        }
                    }

                    PipeClient_Start_WithoutConnect();
                }
                #endregion

                if (!pipeClientDiconnected || !pipeClientProcessErrorOccurred || pipeClient != null)
                {
                    ConsoleProcessStart();
                }

                #region PipeMessageCommand
                if (!pipeClientProcessErrorOccurred && !consoleProcessErrorOccurred)
                {
                    metadataReadFromPipe = null;

                    stopWatch.Restart();
                    PipeMessageCommand pipeMessageCommand = new PipeMessageCommand();
                    pipeMessageCommand.FullFileName = fullFilePath;
                    pipeMessageCommand.Command      = "File";
                    pipeMessageCommand.Message      = "File:" + fullFilePath;

                    if (pipeClient != null)
                    {
                        try
                        {
                            pipeClientEventWaitPipeCommandReturn.Reset(); //Clear in case of timeout
                            pipeClient.PushMessage(pipeMessageCommand);
                        } catch (Exception ex)
                        {
                            Logger.Error(ex, "Metadata Read - Pipe Client");
                        }
                    }
                    Logger.Trace("[Windows Live Photo Gallery | Pipe Client] Push message: Request File {0}ms...", stopWatch.ElapsedMilliseconds);

                    stopWatch.Restart();

                    #region Retry timeout
                    bool retryWait;
                    do
                    {
                        retryWait = false;

                        Application.DoEvents();

                        if (pipeClientEventWaitPipeCommandReturn.WaitOne(20000))
                        {
                            Logger.Trace("[Windows Live Photo Gallery | Console Process] Push message: Wait answer {0}ms...", stopWatch.ElapsedMilliseconds);
                            return(metadataReadFromPipe);
                        }
                        else
                        {
                            Logger.Trace("[Windows Live Photo Gallery | Console Process] Push message: Wait answer failed {0}ms...", stopWatch.ElapsedMilliseconds);
                            lock (_ErrorHandlingLock)
                            {
                                pipeClientProcessErrorOccurred = true;
                                globalErrorMessageHandler     += (globalErrorMessageHandler == "" ? "" : "\r\n") + "[Windows Live Photo Gallery | Pipe Client] No response from server. Wait message timeout...";
                            }
                            Logger.Error(globalErrorMessageHandler);

                            if (!pipeClientDiconnected && !pipeClientProcessErrorOccurred && !consoleProcessDisconnected)
                            {
                                switch (MessageBox.Show(
                                            "Retry - and wait more.\r\n" +
                                            "Ignor - and continue trying.\r\n" +
                                            "Abort - and stop loading data from Windows Live Photo Gallery",
                                            "Waiting answer from server timeouted...", MessageBoxButtons.AbortRetryIgnore))
                                {
                                case DialogResult.Retry:
                                    retryWait = true;
                                    break;

                                case DialogResult.Ignore:
                                    retryWait = false;
                                    break;

                                case DialogResult.Abort:
                                    errorHasOccurdDoNotReconnect = true;
                                    return(null);
                                }
                            }
                        }
                    } while (retryWait);
                    #endregion
                }
                #endregion

                #region MessageBox - retry
                bool   errorOccured;
                string errorMessage;

                lock (_ErrorHandlingLock)
                {
                    errorOccured = (pipeClientProcessErrorOccurred || consoleProcessErrorOccurred || !string.IsNullOrWhiteSpace(globalErrorMessageHandler));
                    errorMessage = globalErrorMessageHandler;
                    globalErrorMessageHandler = "";
                }

                if (errorOccured)
                {
                    switch (MessageBox.Show(
                                "Error occured:\r\n" + errorMessage + "\r\n\r\n\r\n" +
                                "Retry - and try again.\r\n" +
                                "Ignor - and continue trying later.\r\n" +
                                "Abort - and stop loading data from Windows Live Photo Gallery",
                                "Error from Windows Live Photo Gallery background process", MessageBoxButtons.AbortRetryIgnore))
                    {
                    case DialogResult.Retry:
                        retryConnect = true;
                        break;

                    case DialogResult.Ignore:
                        retryConnect = false;
                        break;

                    case DialogResult.Abort:
                        retryConnect = false;
                        errorHasOccurdDoNotReconnect = true;
                        break;
                    }
                }
                else
                {
                    retryConnect = false;
                }
                #endregion
            } while (retryConnect);
            return(null);
        }
        private static void PopulateKeywords(DataGridView dataGridView, Metadata metadata, int columnIndex, MetadataBrokerType metadataBrokerType, FileEntryAttribute fileEntryAttribute)
        {
            foreach (KeywordTag tag in metadata.PersonalKeywordTags)
            {
                if (tag.Confidence >= MediaAiTagConfidence)
                {
                    int rowIndex = AddRowKeywords(dataGridView, columnIndex,
                                                  new DataGridViewGenericRow(headerKeywords, tag.Keyword, ReadWriteAccess.ForceCellToReadOnly),
                                                  tag.Keyword,
                                                  new DataGridViewGenericCellStatus(MetadataBrokerType.Empty, SwitchStates.Undefine, true), true);

                    List <KeywordTag> keywordTags = new List <KeywordTag>();
                    keywordTags.Add(new KeywordTag(tag.Keyword));

                    List <string> newKeywords = AutoKeywordHandler.NewKeywords(AutoKeywordConvertions, null, null, null, null, null, keywordTags);
                    DataGridViewHandler.SetCellToolTipText(dataGridView, columnIndex, rowIndex, "Running AutoCorrect will add these keywords", newKeywords);

                    //Updated default cell status with new staus
                    DataGridViewGenericCellStatus dataGridViewGenericCellStatus = new DataGridViewGenericCellStatus(DataGridViewHandler.GetCellStatus(dataGridView, columnIndex, rowIndex));

                    dataGridViewGenericCellStatus.MetadataBrokerType |= metadataBrokerType;
                    if (fileEntryAttribute.FileEntryVersion != FileEntryVersion.CompatibilityFixedAndAutoUpdated &&
                        fileEntryAttribute.FileEntryVersion != FileEntryVersion.MetadataToSave)
                    {
                        if (dataGridViewGenericCellStatus.SwitchState == SwitchStates.Undefine)
                        {
                            dataGridViewGenericCellStatus.SwitchState = (dataGridViewGenericCellStatus.MetadataBrokerType & MetadataBrokerType.ExifTool) == MetadataBrokerType.ExifTool ? SwitchStates.On : SwitchStates.Off;
                        }
                    }
                    else
                    {
                        dataGridViewGenericCellStatus.SwitchState = (dataGridViewGenericCellStatus.MetadataBrokerType & MetadataBrokerType.ExifTool) == MetadataBrokerType.ExifTool ? SwitchStates.On : SwitchStates.Off;
                        DataGridViewGenericRow dataGridViewGenericRow = DataGridViewHandler.GetRowDataGridViewGenericRow(dataGridView, rowIndex);

                        if (dataGridViewGenericRow != null && dataGridViewGenericRow.ReadWriteAccess == ReadWriteAccess.AllowCellReadAndWrite)
                        {
                            dataGridViewGenericRow.ReadWriteAccess = ReadWriteAccess.ForceCellToReadOnly;
                            for (int columnIndexUpdate = 0; columnIndexUpdate < DataGridViewHandler.GetColumnCount(dataGridView); columnIndexUpdate++)
                            {
                                DataGridViewHandler.SetCellReadOnlyDependingOfStatus(dataGridView, columnIndexUpdate, rowIndex, dataGridViewGenericCellStatus);
                            }
                        }
                    }
                    DataGridViewHandler.SetCellStatus(dataGridView, columnIndex, rowIndex, dataGridViewGenericCellStatus, false);
                }
            }

            //If updated, check if any keyword are removed from the list
            int keywordsStarts = DataGridViewHandler.GetRowHeaderItemStarts(dataGridView, headerKeywords);
            int keywordsEnds   = DataGridViewHandler.GetRowHeaderItemsEnds(dataGridView, headerKeywords);

            for (int rowIndex = keywordsStarts; rowIndex <= keywordsEnds; rowIndex++)
            {
                DataGridViewGenericCellStatus dataGridViewGenericCellStatus = DataGridViewHandler.GetCellStatus(dataGridView, columnIndex, rowIndex);
                if ((dataGridViewGenericCellStatus.MetadataBrokerType & metadataBrokerType) == metadataBrokerType)
                {
                    DataGridViewGenericRow dataGridViewGenericRow = DataGridViewHandler.GetRowDataGridViewGenericRow(dataGridView, rowIndex);

                    if (!metadata.PersonalKeywordTags.Contains(new KeywordTag(dataGridViewGenericRow.RowName)))
                    {
                        if ((dataGridViewGenericCellStatus.MetadataBrokerType & metadataBrokerType) == MetadataBrokerType.ExifTool && dataGridViewGenericCellStatus.SwitchState == SwitchStates.On)
                        {
                            dataGridViewGenericCellStatus.SwitchState = SwitchStates.Undefine;
                        }

                        dataGridViewGenericCellStatus.MetadataBrokerType &= ~metadataBrokerType; //Remove flag if line deleted
                        DataGridViewHandler.SetCellStatus(dataGridView, columnIndex, rowIndex, dataGridViewGenericCellStatus, false);
                    }
                }
            }
        }
Пример #7
0
 public MetadataRegionNameKey(MetadataBrokerType metadataBrokerType, DateTime dateTimeFrom, DateTime dateTimeTo)
 {
     MetadataBrokerType = metadataBrokerType;
     DateTimeFrom       = dateTimeFrom;
     DateTimeTo         = dateTimeTo;
 }
Пример #8
0
 public FileBroker(MetadataBrokerType broker, string fullFilePath)
 {
     FullFilePath = fullFilePath;
     Broker       = broker;
 }
        private static int AddRowRegion(DataGridView dataGridView, MetadataBrokerType metadataBrokerType, Metadata metadata, int columnIndex, DataGridViewGenericRow dataGridViewGenericRow, RegionStructure regionStructureToAdd, DataGridViewGenericCellStatus dataGridViewGenericCellStatusDefaults)
        {
            #region Find Row to Edit or Where to add
            bool rowFound           = false;
            int  lastHeaderRowFound = -1;

            bool rowBlankFound    = false;
            int  firstBlankFound  = -1;
            int  rowIndexRowFound = -1;

            int startSearchRow = 0;
            for (int rowIndex = startSearchRow; rowIndex < DataGridViewHandler.GetRowCountWithoutEditRow(dataGridView); rowIndex++)
            {
                DataGridViewGenericRow dataGridViewGenericRowCheck = DataGridViewHandler.GetRowDataGridViewGenericRow(dataGridView, rowIndex);


                if (!dataGridViewGenericRowCheck.IsHeader &&
                    !dataGridViewGenericRow.IsHeader &&     //Is row
                    dataGridViewGenericRowCheck.HeaderName == dataGridViewGenericRow.HeaderName &&
                    dataGridViewGenericRowCheck.RowName == dataGridViewGenericRow.RowName)
                {
                    //Check if region match
                    RegionStructure regionStructureInCell = DataGridViewHandler.GetCellValue(dataGridView, columnIndex, rowIndex) as RegionStructure;

                    if (regionStructureToAdd != null && regionStructureInCell != null)
                    {
                        if (metadata != null && metadata.MediaHeight != null && metadata.MediaWidth != null)
                        {
                            Size      imageSize           = new Size((int)metadata.MediaWidth, (int)metadata.MediaHeight);
                            Rectangle mediaRectangleToAdd = regionStructureToAdd.GetImageRegionPixelRectangle(imageSize);
                            Rectangle mediaRectangleCell  = regionStructureInCell.GetImageRegionPixelRectangle(imageSize);

                            if (RegionStructure.RectangleEqual(mediaRectangleToAdd, mediaRectangleCell))
                            {
                                rowFound         = true;
                                rowIndexRowFound = rowIndex;
                                break; // return rowIndex;
                            }
                        }
                    }

                    if (regionStructureInCell == null)
                    {
                        rowBlankFound = true;
                        if (firstBlankFound == -1)
                        {
                            firstBlankFound = rowIndex;
                        }
                    }
                }

                #region Sorting
                if (dataGridViewGenericRow.IsHeader && //A normal row is add (not header)
                                                       //dataGridViewGenericRowCheck.IsHeader &&  //If header, then check if same header name
                    dataGridViewGenericRow.HeaderName.CompareTo(dataGridViewGenericRowCheck.HeaderName) >= 0)
                {
                    lastHeaderRowFound = rowIndex; //Remember head row found
                }
                //Add sorted
                if (!dataGridViewGenericRow.IsHeader &&     //A normal row is add (not header)
                    dataGridViewGenericRowCheck.IsHeader && //If header, then check if same header name
                    dataGridViewGenericRowCheck.HeaderName == dataGridViewGenericRow.HeaderName)
                {
                    lastHeaderRowFound = rowIndex;           //Remember head row found
                }
                if (!dataGridViewGenericRow.IsHeader &&      //A normal row is add (not header)
                    !dataGridViewGenericRowCheck.IsHeader && //If header, then check if same header name
                    dataGridViewGenericRowCheck.HeaderName == dataGridViewGenericRow.HeaderName &&
                    dataGridViewGenericRow.RowName.CompareTo(dataGridViewGenericRowCheck.RowName) >= 0)
                {
                    lastHeaderRowFound = rowIndex; //If lower or eaual, remeber last
                }
                #endregion
            }
            #endregion

            #region Update row or Add
            int rowIndexUsed;
            if (rowFound) //Found row and cell with correct region
            {
                rowIndexUsed = rowIndexRowFound;
                RegionStructure regionStructureInCell = DataGridViewHandler.GetCellRegionStructure(dataGridView, columnIndex, rowIndexUsed);
                if (regionStructureInCell == null || regionStructureInCell?.Thumbnail == null || (metadata.Broker == MetadataBrokerType.ExifTool && regionStructureToAdd.Thumbnail != null))
                {
                    DataGridViewHandler.SetCellValue(dataGridView, columnIndex, rowIndexUsed, regionStructureToAdd, false); //Prioritize ExifTool
                }
            }
            else if (rowBlankFound) //Found row and but no cell with correct region
            {
                rowIndexUsed = firstBlankFound;
                RegionStructure regionStructureInCell = DataGridViewHandler.GetCellRegionStructure(dataGridView, columnIndex, rowIndexUsed);
                if (regionStructureInCell == null || regionStructureInCell?.Thumbnail == null || (metadata.Broker == MetadataBrokerType.ExifTool && regionStructureToAdd.Thumbnail != null))
                {
                    DataGridViewHandler.SetCellValue(dataGridView, columnIndex, rowIndexUsed, regionStructureToAdd, false); //Prioritize ExifTool
                }
            }
            else //No postion found, add on sorted location
            {
                //lastHeaderRowFound
                rowIndexUsed = DataGridViewHandler.AddRow(dataGridView, columnIndex, dataGridViewGenericRow,
                                                          DataGridViewHandler.GetFavoriteList(dataGridView), regionStructureToAdd, dataGridViewGenericCellStatusDefaults, lastHeaderRowFound, true, true, true);
            }
            #endregion

            SetCellDefault(dataGridView, metadataBrokerType, columnIndex, rowIndexUsed); //No DirtyFlagSet

            DataGridViewHandler.SetCellRowHeight(dataGridView, rowIndexUsed, DataGridViewHandler.GetCellRowHeight(dataGridView));

            #region Delete from suggestion
            DataGridViewHandler.DeleteRow(dataGridView, headerPeopleSuggestion, regionStructureToAdd.Name);
            DataGridViewHandler.DeleteRow(dataGridView, headerPeopleMostUsed, regionStructureToAdd.Name);
            #endregion

            return(rowIndexUsed);
        }
 public static void SetCellDefault(DataGridView dataGridView, MetadataBrokerType metadataBrokerType, int columnIndex, int rowIndexUsed)
 {
     DataGridViewHandler.SetCellDefaultAfterUpdated(dataGridView, metadataBrokerType, columnIndex, rowIndexUsed);
 }
        private static void PopulatePeople(DataGridView dataGridView, Metadata metadata, int columnIndex, MetadataBrokerType metadataBrokerType) //, ref List<string> regionNames)
        {
            foreach (RegionStructure region in metadata.PersonalRegionList)
            {
                DataGridViewGenericRow dataGridViewGenericRow = new DataGridViewGenericRow(headerPeople, region.Name, ReadWriteAccess.AllowCellReadAndWrite);

                AddRowRegion(dataGridView, metadataBrokerType, metadata, columnIndex, dataGridViewGenericRow,
                             new RegionStructure(region),                                                               //DataGridViewHandler.DeepCopy(region),
                             new DataGridViewGenericCellStatus(MetadataBrokerType.Empty, SwitchStates.Undefine, true)); //Other cell for this row will by default be Empty and disabled
            }
        }
Пример #12
0
        private Metadata ReadMetadata(MetadataBrokerType broker, string filename, string windowsLivePhotoGalleryDirectory, string directory, int serialNumber)
        {
            Metadata metadata = null;

            var errors   = new StringBuilder();
            var messages = new StringBuilder();

            string sql = "SELECT tblVolume.Label, tblPath.Path, tblObject.Filename, tblObject.FileSize, " +
                         "tblLocation.LocationName, tblLocation.LocationLat, tblLocation.LocationLong, tblObject.Latitude, tblObject.Longitude, " +
                         "tblObject.DateModified, tblObject.Title, tblObject.\"Desc\" as Desciption, tblObject.DateTaken, tblObject.Rating, tblObject.Author, tblObject.LabelCount, " +
                         "tblObject.ResolutionX, tblObject.ResolutionY, tblObject.CameraMake, tblObject.CameraModel, " +
                         "tblObject.CameraShutterSpeed, tblObject.CameraFocalLength, tblObject.CameraAperture, tblObject.CameraISO, " +
                         "tblObject.VideoBitrate, tblObject.VideoFramerate, tblObject.MediaDuration " +
                         "FROM tblObject " +
                         "INNER JOIN tblPath ON tblObject.FilePathId = tblPath.PathId " +
                         "INNER JOIN tblVolume ON tblPath.VolumeId = tblVolume.VolumeId " +
                         "LEFT OUTER JOIN tblocationUsage ON tblocationUsage.ObjectID = tblObject.ObjectID " +
                         "LEFT OUTER JOIN tblLocation ON tblocationUsage.LocationId = tblLocation.LocationID " +
                         "WHERE " +
                         "tblObject.Filename = '" + filename + "' " +
                         "AND tblPath.Path = '" + windowsLivePhotoGalleryDirectory + "' " +
                         "AND tblVolume.SerialNo = " + serialNumber.ToString(CultureInfo.InvariantCulture);



            int resultCount;
            var result = database.ExecuteQuery(sql, errors, messages, out resultCount) as DataSet;

            if (result == null)
            {
                return(metadata);                //No point to contine, when header of information missing.
            }
            foreach (DataTable table in result.Tables)
            {
                if (table.Rows.Count > 0)
                {
                    metadata = new Metadata(broker);

                    //File
                    metadata.FileName = table.Rows[0].Field <String>("Filename");
                    //metadata.FileDirectory = table.Rows[0].Field<String>("Path");
                    metadata.FileDirectory = directory; //Override path from database, it's not a complete folder path, missing root path
                    metadata.FileSize      = table.Rows[0].Field <Int64>("FileSize");

                    DateTime newDateTime = new DateTime(new DateTime(1600, 12, 31, 23, 59, 59, 0, DateTimeKind.Utc).AddSeconds(1).Ticks + table.Rows[0].Field <long>("DateModified"));
                    metadata.FileDateModified = newDateTime.ToLocalTime();

                    string fullFilePath = Path.Combine(metadata.FileDirectory, metadata.FileName);
                    if (File.Exists(Path.Combine(metadata.FileDirectory, metadata.FileName)))
                    {
                        metadata.FileDateModified = File.GetLastWriteTime(fullFilePath);
                        metadata.FileDateCreated  = File.GetCreationTime(fullFilePath);
                        metadata.FileDateAccessed = File.GetLastAccessTime(fullFilePath);
                    }

                    //Personal
                    metadata.PersonalTitle       = table.Rows[0].Field <String>("Title");
                    metadata.PersonalDescription = table.Rows[0].Field <String>("Desciption");
                    metadata.PersonalRating      = table.Rows[0].Field <Byte?>("Rating");
                    metadata.PersonalAuthor      = table.Rows[0].Field <String>("Author");

                    //Media
                    metadata.MediaWidth     = table.Rows[0].Field <Int32?>("ResolutionX");
                    metadata.MediaHeight    = table.Rows[0].Field <Int32?>("ResolutionY");
                    metadata.MediaDateTaken = table.Rows[0].Field <DateTime?>("DateTaken");

                    //Camera
                    metadata.CameraMake  = table.Rows[0].Field <String>("CameraMake");
                    metadata.CameraModel = table.Rows[0].Field <String>("CameraModel");

                    //Location
                    metadata.LocationName      = table.Rows[0].Field <String>("LocationName");
                    metadata.LocationLatitude  = (float?)table.Rows[0].Field <double?>("LocationLat");  //Fixed address location, tagged location in map
                    metadata.LocationLongitude = (float?)table.Rows[0].Field <double?>("LocationLong"); //Fixed address location, tagged location in map
                    //If -999, GPS location missiong, use tagged location
                    if (table.Rows[0].Field <double?>("Latitude") != -999)
                    {
                        metadata.LocationLatitude = (float?)table.Rows[0].Field <double?>("Latitude");                                                        //Real GPS location
                    }
                    if (table.Rows[0].Field <double?>("Longitude") != -999)
                    {
                        metadata.LocationLongitude = (float?)table.Rows[0].Field <double?>("Longitude");                                                       //Real GPS location
                    }
                }
            }

            if (metadata == null)
            {
                return(metadata);
            }

            #region Region Name and Size
            sql = "SELECT tblVolume.Label, tblPath.Path, tblObject.Filename, tblPerson.Name,  tblRegion.\"Top\", tblRegion.\"Left\"," +
                  "tblRegion.Width, tblRegion.Height " +
                  "FROM tblObject " +
                  "INNER JOIN tblPath ON tblObject.FilePathId = tblPath.PathId " +
                  "INNER JOIN tblVolume ON tblPath.VolumeId = tblVolume.VolumeId " +
                  "INNER JOIN tblRegion ON tblRegion.ObjectID = tblObject.ObjectId " +
                  "INNER JOIN tblPerson ON tblRegion.PersonID = tblPerson.PersonId " +
                  "WHERE " +
                  "tblObject.Filename = '" + filename + "' " +
                  "AND tblPath.Path = '" + windowsLivePhotoGalleryDirectory + "' " +
                  "AND tblVolume.SerialNo = " + serialNumber.ToString();

            result = database.ExecuteQuery(sql, errors, messages, out resultCount) as DataSet;

            if (result != null)
            {
                foreach (DataTable table in result.Tables)
                {
                    if (table.Rows.Count > 0)
                    {
                        foreach (DataRow row in table.Rows)
                        {
                            RegionStructure region = new RegionStructure();

                            region.Name                = (String)row["Name"];
                            region.AreaX               = (float)Math.Round((double)row["Left"], 5);
                            region.AreaY               = (float)Math.Round((double)row["Top"], 5);
                            region.AreaWidth           = (float)Math.Round((double)row["Width"], 5);
                            region.AreaHeight          = (float)Math.Round((double)row["Height"], 5);
                            region.Type                = "Face";
                            region.RegionStructureType = RegionStructureTypes.WindowsLivePhotoGalleryDatabase;
                            metadata.PersonalRegionListAddIfNotExists(region);
                        }
                    }
                }
            }
            #endregion

            #region Keywrods tags
            sql = "SELECT tblVolume.Label, tblPath.Path, tblObject.Filename, LabelName " +
                  "FROM tblObject " +
                  "INNER JOIN tblPath ON tblObject.FilePathId = tblPath.PathId " +
                  "INNER JOIN tblVolume ON tblPath.VolumeId = tblVolume.VolumeId " +
                  "INNER JOIN tblLabelUsage ON tblLabelUsage.ObjectID = tblObject.ObjectId " +
                  "INNER JOIN tblLabel ON tblLabel.LabelID = tblLabelUsage.LabelId " +
                  "WHERE " +
                  "tblObject.Filename = '" + filename + "' " +
                  "AND tblPath.Path = '" + windowsLivePhotoGalleryDirectory + "' " +
                  "AND tblVolume.SerialNo = " + serialNumber.ToString();

            result = database.ExecuteQuery(sql, errors, messages, out resultCount) as DataSet;

            if (result != null)
            {
                foreach (DataTable table in result.Tables)
                {
                    if (table.Rows.Count > 0)
                    {
                        foreach (DataRow row in table.Rows)
                        {
                            metadata.PersonalKeywordTagsAddIfNotExists(new KeywordTag((String)row["LabelName"]));
                        }
                    }
                }
            }
            #endregion

            return(metadata);
        }
        public Metadata Read(MetadataBrokerType broker, string fullFilePath)
        {
            Metadata metadata      = null;
            string   fileDirectory = Path.GetDirectoryName(fullFilePath);
            string   fileName      = Path.GetFileName(fullFilePath);

            #region SELECT
            String query = "SELECT(WITH RECURSIVE " +
                           "under_alice(folderid, folderlevel, foldername) AS( " +
                           "VALUES(Item_ParentFolderId, 0, NULL) " +
                           "UNION ALL " +
                           "SELECT Folder_ParentFolderId, under_alice.folderlevel + 1 AS folderlevel, Folder_DisplayName " +
                           "FROM Folder JOIN under_alice ON Folder.Folder_Id = under_alice.folderid " +
                           "), path_from_root AS( " +
                           "SELECT folderlevel, foldername, folderid " +
                           "FROM under_alice " +
                           "ORDER BY folderlevel DESC " +
                           ") " +
                           "SELECT  group_concat(foldername, '/') " +
                           "FROM path_from_root " +
                           "ORDER BY folderlevel DESC) " +
                           "AS ItemPath, " +
                           "Item_Filename, Item_ParentFolderId, " +
                           "Item_Filename, Item_FileSize, " +
                           "Location.Location_Name, LocationCountry.LocationCountry_Name,  " +
                           "LocationDistrict.LocationDistrict_Name, LocationRegion.LocationRegion_Name,  " +
                           "Item_DateTaken, Item_DateCreated, Item_DateModified, Item_Caption, Album.Album_Name, Item_SimpleRating,  " +
                           "Item_Width, Item_Height,  " +
                           "CameraManufacturer.CameraManufacturer_Text, CameraModel.CameraModel_Text,  " +
                           "Item_Latitude, Item_Longitude FROM Item " +
                           "INNER JOIN Folder ON Folder.Folder_Id = Item.Item_ParentFolderId " +
                           "LEFT OUTER JOIN Location ON Item.Item_LocationId = Location.Location_Id " +
                           "LEFT OUTER JOIN LocationCountry ON Location.Location_LocationCountryId = LocationCountry.LocationCountry_Id " +
                           "LEFT OUTER JOIN LocationDistrict ON Location.Location_LocationDistrictId = LocationDistrict.LocationDistrict_Id " +
                           "LEFT OUTER JOIN LocationRegion ON Location.Location_LocationRegionId = LocationRegion.LocationRegion_Id " +
                           "LEFT OUTER JOIN CameraManufacturer ON Item.Item_CameraManufacturerId = CameraManufacturer.CameraManufacturer_Id " +
                           "LEFT OUTER JOIN CameraModel ON Item.Item_CameraModelId = CameraModel.CameraModel_Id " +
                           "LEFT OUTER JOIN AlbumItemLink ON AlbumItemLink.AlbumItemLink_ItemId = Item.Item_Id " +
                           "LEFT OUTER JOIN Album ON Album.Album_Id = AlbumItemLink.AlbumItemLink_AlbumId " +
                           "WHERE Item_Filename LIKE @FileName";
            //"WHERE Item_Filename = '" + fullFilePath + "'";
            //"AND ItemPath = '" + path + "%'";

            using (CommonSqliteCommand commandDatabase = new CommonSqliteCommand(query, dbToolsMicrosoftReader.ConnectionDatabase))
            {
                commandDatabase.Parameters.AddWithValue("@FileName", fileName);

                using (CommonSqliteDataReader reader = commandDatabase.ExecuteReader())
                {
                    while (reader.Read())
                    {
                        String itemPath = dbToolsMicrosoftReader.ConvertFromDBValString(reader["ItemPath"]);
                        itemPath = itemPath.Replace("/", "\\");
                        if (fileDirectory.EndsWith(itemPath, StringComparison.InvariantCulture) == true)
                        {
                            //File
                            metadata          = new Metadata(broker);
                            metadata.FileName = dbToolsMicrosoftReader.ConvertFromDBValString(reader["Item_Filename"]);
                            //metadata.FileDirectory = dbTools.ConvertFromDBValString(reader["ItemPath"]);
                            metadata.FileDirectory    = fileDirectory; //Override path from database, it's not a complete folder path, missing root path
                            metadata.FileSize         = dbToolsMicrosoftReader.ConvertFromDBValLong(reader["Item_FileSize"]);
                            metadata.FileDateCreated  = dbToolsMicrosoftReader.ConvertSecoundsSince1600ToDateTime(reader["Item_DateCreated"], DateTimeKind.Utc);
                            metadata.FileDateModified = dbToolsMicrosoftReader.ConvertSecoundsSince1600ToDateTime(reader["Item_DateModified"], DateTimeKind.Utc);

                            if (metadata.FileDateCreated == null ||
                                metadata.FileDateModified == null ||
                                metadata.FileDateAccessed == null ||
                                File.Exists(fullFilePath))
                            {
                                try
                                {
                                    //Due to sometimes NULL in Microsoft Database, I always use current file attributes.
                                    FileInfo fileInfo = new FileInfo(fullFilePath);
                                    metadata.FileDateCreated  = fileInfo.CreationTime;   //File.GetCreationTime(fullFilePath);
                                    metadata.FileDateModified = fileInfo.LastWriteTime;  //File.GetLastWriteTime(fullFilePath);
                                    metadata.FileDateAccessed = fileInfo.LastAccessTime; //File.GetLastAccessTime(fullFilePath);
                                } catch (Exception ex)
                                {
                                    Logger.Error(ex);
                                    metadata.FileDateCreated  = DateTime.Now;
                                    metadata.FileDateModified = metadata.FileDateCreated; //File.GetLastWriteTime(fullFilePath);
                                    metadata.FileDateAccessed = metadata.FileDateCreated; //File.GetLastAccessTime(fullFilePath);
                                }
                            }

                            //Personal
                            metadata.PersonalTitle = dbToolsMicrosoftReader.ConvertFromDBValString(reader["Item_Caption"]);
                            //metaData.PersonalDescription = dbTools.ConvertFromDBValString(reader["Item_Caption"]);
                            metadata.PersonalRating = dbToolsMicrosoftReader.ConvertFromDBValByte(reader["Item_SimpleRating"]);
                            //metaData.PersonalAuthor = dbTools.ConvertFromDBValString(reader["Unknown"]);
                            metadata.PersonalAlbum = dbToolsMicrosoftReader.ConvertFromDBValString(reader["Album_Name"]);

                            //Media
                            metadata.MediaWidth     = dbToolsMicrosoftReader.ConvertFromDBValInt(reader["Item_Width"]);
                            metadata.MediaHeight    = dbToolsMicrosoftReader.ConvertFromDBValInt(reader["Item_Height"]);
                            metadata.MediaDateTaken = dbToolsMicrosoftReader.ConvertSecoundsSince1600ToDateTime(reader["Item_DateTaken"], DateTimeKind.Local);

                            //Camera
                            metadata.CameraMake  = dbToolsMicrosoftReader.ConvertFromDBValString(reader["CameraManufacturer_Text"]);
                            metadata.CameraModel = dbToolsMicrosoftReader.ConvertFromDBValString(reader["CameraModel_Text"]);

                            //Location
                            metadata.LocationName    = dbToolsMicrosoftReader.ConvertFromDBValString(reader["Location_Name"]);
                            metadata.LocationCountry = dbToolsMicrosoftReader.ConvertFromDBValString(reader["LocationCountry_Name"]);
                            metadata.LocationCity    = dbToolsMicrosoftReader.ConvertFromDBValString(reader["LocationDistrict_Name"]);
                            metadata.LocationState   = dbToolsMicrosoftReader.ConvertFromDBValString(reader["LocationRegion_Name"]);

                            metadata.LocationLatitude  = dbToolsMicrosoftReader.ConvertFromDBValFloat(reader["Item_Latitude"]);
                            metadata.LocationLongitude = dbToolsMicrosoftReader.ConvertFromDBValFloat(reader["Item_Longitude"]);

                            if (metadata.LocationLatitude == 0 && metadata.LocationLongitude == 0) //Due to bug in Microsoft Photos Gallery
                            {
                                metadata.LocationLatitude  = null;
                                metadata.LocationLongitude = null;
                            }
                            break;
                        }
                    }
                }
            }
            #endregion
            if (metadata == null)
            {
                return(null);
            }

            #region SELECT
            query = "SELECT(WITH RECURSIVE " +
                    "under_alice(folderid, folderlevel, foldername) AS( " +
                    "VALUES(Item_ParentFolderId, 0, NULL) " +
                    "UNION ALL " +
                    "SELECT Folder_ParentFolderId, under_alice.folderlevel + 1 AS folderlevel, Folder_DisplayName " +
                    "FROM Folder JOIN under_alice ON Folder.Folder_Id = under_alice.folderid " +
                    "), path_from_root AS( " +
                    "SELECT folderlevel, foldername, folderid " +
                    "FROM under_alice " +
                    "ORDER BY folderlevel DESC " +
                    ") " +
                    "SELECT  group_concat(foldername, '/') " +
                    "FROM path_from_root " +
                    "ORDER BY folderlevel DESC) " +
                    "AS ItemPath, Item_Filename, Item_FileSize, " +
                    "Person_Name, Face_Rect_Left, Face_Rect_Top, Face_Rect_Width, Face_Rect_Height " +
                    "FROM Item " +
                    "INNER JOIN Folder ON Folder.Folder_Id = Item.Item_ParentFolderId " +
                    "INNER JOIN Face ON Face.Face_ItemId = Item.Item_Id " +
                    "INNER JOIN Person ON Person.Person_Id = Face_PersonId " +
                    "WHERE " +
                    "Item.Item_Filename LIKE @FileName";

            using (CommonSqliteCommand commandDatabase = new CommonSqliteCommand(query, dbToolsMicrosoftReader.ConnectionDatabase))
            {
                commandDatabase.Parameters.AddWithValue("@FileName", fileName);

                using (CommonSqliteDataReader reader = commandDatabase.ExecuteReader())
                {
                    while (reader.Read())
                    {
                        String itemPath = dbToolsMicrosoftReader.ConvertFromDBValString(reader["ItemPath"]);
                        itemPath = itemPath.Replace("/", "\\");
                        if (fileDirectory.EndsWith(itemPath, StringComparison.InvariantCulture) == true)
                        {
                            RegionStructure region = new RegionStructure();
                            region.Name                = dbToolsMicrosoftReader.ConvertFromDBValString(reader["Person_Name"]);
                            region.AreaX               = (float)dbToolsMicrosoftReader.ConvertFromDBValFloat(reader["Face_Rect_Left"]);
                            region.AreaY               = (float)dbToolsMicrosoftReader.ConvertFromDBValFloat(reader["Face_Rect_Top"]);
                            region.AreaWidth           = (float)dbToolsMicrosoftReader.ConvertFromDBValFloat(reader["Face_Rect_Width"]);
                            region.AreaHeight          = (float)dbToolsMicrosoftReader.ConvertFromDBValFloat(reader["Face_Rect_Height"]);
                            region.Type                = "Face";
                            region.RegionStructureType = RegionStructureTypes.MicrosoftPhotosDatabase;
                            metadata.PersonalRegionListAddIfNotExists(region);
                        }
                    }
                }
            }
            #endregion

            #region SELECT
            query = "SELECT (WITH RECURSIVE under_alice(folderid, folderlevel, foldername) AS(VALUES(Item_ParentFolderId, 0, NULL) " +
                    "UNION ALL SELECT Folder_ParentFolderId, under_alice.folderlevel + 1 AS folderlevel, Folder_DisplayName " +
                    "FROM Folder JOIN under_alice " +
                    "ON Folder.Folder_Id = under_alice.folderid), path_from_root AS " +
                    "(SELECT folderlevel, foldername, folderid FROM under_alice ORDER BY folderlevel DESC) " +
                    "SELECT group_concat(foldername, '/') FROM path_from_root ORDER BY folderlevel DESC) AS ItemPath, " +
                    "Item_Filename, Item_FileSize, Item.Item_DateModified, Item.Item_DateCreated " +
                    ", Item.Item_Id " +
                    ", ItemTags1.ItemTags_TagId " +
                    //Workaround, I have now clue why, when ItemTags_Confidence not selected this way, then indexes wasn't used
                    ", (SELECT ItemTags_Confidence FROM ItemTags AS ItemTags2 Where ItemTags2.ItemTags_TagId = ItemTags1.ItemTags_TagId ) AS ItemTags_Confidence " +
                    ", (SELECT TagVariant_Text FROM TagVariant Where TagVariant.TagVariant_TagResourceId = Tag.Tag_ResourceId ) AS TagVariant_Text " +
                    "FROM Item " +
                    "INNER JOIN Folder ON Folder.Folder_Id = Item.Item_ParentFolderId " +
                    "INNER JOIN ItemTags AS ItemTags1 ON ItemTags1.ItemTags_ItemId = Item.Item_Id " +
                    "INNER JOIN Tag ON ItemTags1.ItemTags_TagId = Tag.Tag_Id " +
                    "WHERE Item.Item_Filename LIKE @FileName";

            using (CommonSqliteCommand commandDatabase = new CommonSqliteCommand(query, dbToolsMicrosoftReader.ConnectionDatabase))
            {
                commandDatabase.Parameters.AddWithValue("@FileName", fileName);

                using (CommonSqliteDataReader reader = commandDatabase.ExecuteReader())
                {
                    while (reader.Read())
                    {
                        String itemPath = dbToolsMicrosoftReader.ConvertFromDBValString(reader["ItemPath"]);
                        itemPath = itemPath.Replace("/", "\\");
                        if (fileDirectory.EndsWith(itemPath, StringComparison.InvariantCulture) == true)
                        {
                            KeywordTag keywordTag = new KeywordTag(
                                dbToolsMicrosoftReader.ConvertFromDBValString(reader["TagVariant_Text"]),
                                (float)dbToolsMicrosoftReader.ConvertFromDBValFloat(reader["ItemTags_Confidence"])
                                );
                            metadata.PersonalKeywordTagsAddIfNotExists(keywordTag);
                        }
                    }
                }
            }
            #endregion

            return(metadata);
        }
 public DataGridViewGenericCellStatus(MetadataBrokerType metadataBrokerTypes, SwitchStates switchStates, bool cellReadOnly)
 {
     MetadataBrokerType = metadataBrokerTypes;
     SwitchState        = switchStates;
     CellReadOnly       = cellReadOnly;
 }