// Very simple: just parse the EventLists out of the album front page HTML. // No need to get the event list names (usually years) from the HTML, as these // names should be embedded in the EventLists. public Album ReadAlbum(string masterFilename, out string aDiagnostic) { aDiagnostic = null; string xmlFilename = GetDirectory(masterFilename) + "Album.xml"; Album album = new Album(xmlFilename); string html = ReadFile(masterFilename); if (html == null) { aDiagnostic = "ReadAlbum: bad HTML Album file " + masterFilename; return(null); } else { // Determine the master directory string masterDirectory = GetDirectory(masterFilename); //Console.WriteLine("HtmlReader: parsing " + masterFilename); ParseHTML parse = new ParseHTML(); parse.Source = html; while (!parse.Eof()) { char ch = parse.Parse(); if (ch == 0) { AttributeList tag = parse.GetTag(); if (tag["href"] != null) { string href = tag["href"].Value.Replace('/', '\\'); //Console.WriteLine("HtmlReader: add year " + href + " to master XML file"); // Process child events file EventList events = ReadEvents(masterDirectory + href, out aDiagnostic); if (events == null) { return(null); } else { album.Add(events); } } } } return(album); } }
public void LoadEvents(string aWorkingFolder, string aXmlFile) { // Load a new events list, discarding any previous one this.Text = aXmlFile; iWorkingFolder = aWorkingFolder; string fullPath = iWorkingFolder + "\\" + aXmlFile; iEventList = new EventList(fullPath); iEventList.Load(); // Populate the listbox from the events list iEventList.Reset(); while (iEventList.NextEvent()) { listBoxEvents.Items.Add(iEventList.Name); } }
// Load the events from an XML document public bool Load() { // Start with empty EventsList iEventList = new List <Event>(); if (!File.Exists(iFilePath)) { MessageBox.Show("Cannot load " + iFilePath + " - no such file", "EventList"); return(false); } XmlSerializer s = new XmlSerializer(typeof(EventList)); TextReader r = new StreamReader(iFilePath); // Wanted to say "this = s.Deserialize(r)", but it is illegal. // Instead load EventList into "loaded" and transcribe to "this". EventList loaded = s.Deserialize(r) as EventList; iTitle = loaded.Title; iEventList = loaded.Events; iCurrent = -1; r.Close(); // Loaded the event list. Recurse to load each slide show. foreach (Event happening in iEventList) { if (happening.Path != null) { SlideShow slideShow = new SlideShow(); slideShow.Load(happening.Path); } } iLoaded = true; return(true); }
void convertMenuItem_Click(object sender, EventArgs e) { // It should only be possible to invoke the Convert menu item for an HTML // file, but we will check to make sure ListView.SelectedListViewItemCollection selectedItems = this.listView.SelectedItems; if (selectedItems.Count == 1) { string filename = selectedItems[0].Text; if (IsHtml(new FileInfo(filename))) { // Parse HTML file string currentDirectory = TreePath(treeView.SelectedNode); string htmlPath = currentDirectory + "\\" + filename; HtmlReader htmlReader = new HtmlReader(); string diagnostic = null; string baseFilename = Path.GetFileNameWithoutExtension(filename); string xmlFilename = Path.Combine(currentDirectory, baseFilename + ".xml"); if (baseFilename.Equals("yearframe", StringComparison.CurrentCultureIgnoreCase)) { // Create album from parsing Album album = htmlReader.ReadAlbum(htmlPath, out diagnostic); if (album == null) { MessageBox.Show("Failed to read HTML file\n" + diagnostic, "PhotoStudio"); } else { // Save album to XML file xmlFilename = currentDirectory + "\\album.xml"; album.Save(xmlFilename); MessageBox.Show("Album converted", "PhotoStudio"); } } else if (baseFilename.Equals("events", StringComparison.CurrentCultureIgnoreCase)) { // Create event list from parsing EventList events = htmlReader.ReadEvents(htmlPath, out diagnostic); if (events == null) { MessageBox.Show("Failed to read HTML file\n" + diagnostic, "PhotoStudio"); } else { // Save event list to XML file events.Save(true); MessageBox.Show("Events converted", "PhotoStudio"); } } else { // Create slide show from parsing SlideShow slideShow = htmlReader.ReadSlideShow(htmlPath, out diagnostic); if (slideShow == null) { MessageBox.Show("Failed to read HTML file\n" + diagnostic, "PhotoStudio"); } else { // Save slide show to XML file slideShow.Save(xmlFilename); MessageBox.Show("SlideShow converted", "PhotoStudio"); } } // Refresh display (should be a new XML file) ListFolderContents(new DirectoryInfo(currentDirectory)); } } }
/// <summary> /// Need pre-validation - for any image files which are not catalogued, and any catalogued images that do not exist /// </summary> void ApplyPropertiesMenuItem_Click(object sender, EventArgs e) { // It should only be possible to invoke the Apply Properties menu item for an XML // file, but we will check to make sure ListView.SelectedListViewItemCollection selectedItems = this.listView.SelectedItems; if (selectedItems.Count == 1) { string filename = selectedItems[0].Text; if (IsXml(new FileInfo(filename))) { string currentDirectory = TreePath(treeView.SelectedNode); string filetype = Path.GetFileNameWithoutExtension(filename); if (filetype.Equals("album", StringComparison.CurrentCultureIgnoreCase)) { Album album = new Album(Path.Combine(currentDirectory, filename)); album.Load(); Application.DoEvents(); foreach (Year year in album.Events) { iLabelYear.Text = year.Name; iLabelYear.Visible = true; EventList catalogue = new EventList(year.Path); if (catalogue.Load()) { iProgressBar.Maximum = catalogue.Events.Count; iProgressBar.Value = 0; iProgressBar.Visible = true; foreach (Event happening in catalogue.Events) { // Title events have no slideshow if (happening.SlideShow != null) { ApplyPropertiesToSlideshow(happening.Path); } iProgressBar.Value++; Application.DoEvents(); } } else { MessageBox.Show("Failed to load events for " + year.Name, "Year"); } } } else if (filetype.Equals("events", StringComparison.CurrentCultureIgnoreCase)) { EventList catalogue = new EventList(Path.Combine(currentDirectory, filename)); if (catalogue.Load()) { iProgressBar.Maximum = catalogue.Events.Count; iProgressBar.Value = 0; iProgressBar.Visible = true; iLabelYear.Text = catalogue.Title; iLabelYear.Visible = true; foreach (Event happening in catalogue.Events) { // Title events have no slideshow if (happening.SlideShow != null) { ApplyPropertiesToSlideshow(happening.Path); } iProgressBar.Value++; Application.DoEvents(); } } else { MessageBox.Show("Failed to load events for " + catalogue.Name, "Events"); } } else { ApplyPropertiesToSlideshow(Path.Combine(filename, currentDirectory)); } } iLabelYear.Visible = false; iProgressBar.Visible = false; } }
/// <summary> /// Verify that all catalogued images exist, and report on any non-catalogued images /// </summary> void validateToolStripMenuItem_Click(object sender, EventArgs e) { // All images recorded in the album List <string> cataloguedImages = new List <string>(); // Images recorded in the album but not physically present List <string> unpresentImages = new List <string>(); // Images physically present but not recorded in the album List <string> uncataloguedImages = new List <string>(); // It should only be possible to invoke the Apply Properties menu item for an XML // file, but we will check to make sure ListView.SelectedListViewItemCollection selectedItems = this.listView.SelectedItems; if (selectedItems.Count == 1) { string filename = selectedItems[0].Text; if (IsXml(new FileInfo(filename))) { string currentDirectory = TreePath(treeView.SelectedNode); string filetype = Path.GetFileNameWithoutExtension(filename); if (filetype.Equals("album", StringComparison.CurrentCultureIgnoreCase)) { Album album = new Album(Path.Combine(currentDirectory, filename)); album.Load(); foreach (Year year in album.Events) { EventList catalogue = new EventList(year.Path); if (catalogue.Load()) { string yearFolder = Path.GetDirectoryName(year.Path); foreach (Event happening in catalogue.Events) { // Title events have no slideshow if (happening.SlideShow != null) { string eventFolder = Path.GetDirectoryName(happening.Path); foreach (var slide in happening.SlideShow.Slides) { string fullPath = Path.Combine(eventFolder, slide.Path); cataloguedImages.Add(fullPath.ToLower()); if (!File.Exists(fullPath)) { unpresentImages.Add(fullPath); } } } } } else { MessageBox.Show("Failed to load events for " + year.Name, "Year"); } } foreach (string presentImage in Directory.GetFiles(currentDirectory, "*.jpg", SearchOption.AllDirectories)) { if (!cataloguedImages.Contains(presentImage.ToLower())) { uncataloguedImages.Add(presentImage); } } if ((unpresentImages.Count == 0) && (uncataloguedImages.Count == 0)) { MessageBox.Show("Validated"); } else { ValidationForm problems = new ValidationForm(unpresentImages, uncataloguedImages); problems.Show(); } } } } }
// Read one HTML page and return an Event list public EventList ReadEvents(string aEventsFile, out string aDiagnostic) { aDiagnostic = null; string xmlFilePath = aEventsFile.Replace(".htm", ".xml"); EventList events = new EventList(xmlFilePath); string html = ReadFile(aEventsFile); if (html == null) { aDiagnostic = "ReadEvents: bad HTML Events file " + aEventsFile; return(null); } else { // Determine the events directory string eventsDirectory = GetDirectory(aEventsFile); //Console.WriteLine(" HtmlReader ReadEvents: parsing " + aEventsFile); ParseHTML parse = new ParseHTML(); parse.Source = html; HtmlPreprocess htmlPreprocess = new HtmlPreprocess(); string name = ""; // Collect stream of characters in HTML source int indent = 0; SlideShow slideShow = null; // Collect slide show from href while (!parse.Eof()) { char ch = parse.Parse(); if (ch == 0) { AttributeList tag = parse.GetTag(); if (tag.Name.Equals("h2", StringComparison.CurrentCultureIgnoreCase)) { // Start collecting title name = ""; indent = 0; } else if (tag.Name.Equals("/h2", StringComparison.CurrentCultureIgnoreCase)) { // Title is now complete events.Title = name.Trim(); name = ""; indent = 0; } else if ((tag.Name.Equals("p", StringComparison.CurrentCultureIgnoreCase)) || (tag.Name.Equals("br", StringComparison.CurrentCultureIgnoreCase)) || (tag.Name.Equals("hr", StringComparison.CurrentCultureIgnoreCase))) { // End of line, check whether we have an event if (name.Length > 0) { // Use indent as the level for now events.Add(indent, name.Trim(), slideShow); } // Reset for next event name = ""; indent = 0; slideShow = null; } else if (tag["href"] != null) { string href = tag["href"].Value.Replace('/', '\\'); //Console.WriteLine(" + HtmlReader ReadEvents: add event " + href + " to events XML file"); // Strip any anchor: we cannot handle it if (href.Contains('#')) { href = href.Remove(href.IndexOf('#')); } // Process child events file slideShow = ReadSlideShow(eventsDirectory + href, out aDiagnostic); if (slideShow == null) { return(null); } } // Preprocessing of regular character stream starts with clean sheet after tag htmlPreprocess.Reset(); } else { // Preprocess ch = htmlPreprocess.Add(ch); if (ch == HtmlPreprocess.NullChar) { // Nothing to do continue; } else if (ch.Equals(' ')) { if (name.Length == 0) { // Leading space: count the indent indent++; } else { // Count all non-leading spaces returned by the preprocessor name += ch; } } else if (ch.Equals('+')) { if (name.Length == 0) { // Initial plus marks a subevent - count it in the indent indent++; } else { // Transcribe other plus symbols into the event name name += ch; } } else { // Add regular character name += ch; } } } // End of event list, check for any outstanding event if (name.Length > 0) { events.Add(indent, name.Trim(), slideShow); } // The event levels were arbitrarily set as a measure of the indentation // of each event name in the HTML. Reassign sequential levels. events.Relevel(); return(events); } }
// Constructor: start with an empty year public Year() { iEvents = new EventList(); }
// Add a new year to the album public void Add(EventList aEvents) { iYear.Add(new Year(aEvents)); iYear.Sort(); }
void TabControlSelected(object sender, TabControlEventArgs e) { // Before populating the newly selected tab, check whether the event list // for the previously selected tab was changed CheckEventListEdits(); // Populate the selected tab with the controls common to all tabs TabPage yearTab = yearTabControl.TabPages[e.TabPageIndex]; foreach (Control control in iTabControls) { yearTab.Controls.Add(control); } // Populate the listbox from the chosen events list eventsListBox.Items.Clear(); if (yearTab.Text == "New") { // It's a new events list string newYearName = CreateNewYear(); if (newYearName == null) { // User declined to create a new year: switch tabs yearTabControl.SelectedIndex--; return; } else { // Create the events list for the new year string newYearFolder = Path.Combine(iWorkingFolder, newYearName); string newYearFile = Path.Combine(newYearFolder, "Events.xml"); iEventList = new EventList(newYearFile); iEventList.Title = newYearName; // Problem: the Add method inserts the iEventList into order, // but the tab remains in its same position iAlbum.Add(iEventList); yearTab.Text = newYearName; iAlbumChanged = true; // Remember that a new tab has been added eventLabel.Text = "No events"; // Clear details from previous tab albumPictureBox.Image = null; editButton.Enabled = false; // No events - can't edit playButton.Enabled = false; } } else { iEventList = iAlbum.GetYear(e.TabPageIndex); } if (iEventList != null) { // Also populate the label above the picture box yearLabel.Text = iEventList.Title; PopulateEventsListBox(false); } }