public RenameWindow(Author author) : this() { _renameType = RenameType.RenameAuthor; Title = "Переименовать автора"; ResultNewName = author.Name; NewName.Text = author.Name; }
/// <summary> /// Перестраивает окно /// </summary> /// <param name="author">Автор</param> /// <param name="rect">Положение относительно формы</param> public void ReBuild(Author author, Rect rect) { _author = author; authorPanel.Build(author, _setting.GetAdvancedWindowSetting(author).HeightComment); _desiredRect = rect; // присваиваем вручную, _manualChange нужно, чтобы Window_SizeChanged // не изменил желаемые размеры окна, установленные мышью _manualChange = true; Width = _setting.GetAdvancedWindowSetting(author).Size.Width; Height = _setting.GetAdvancedWindowSetting(author).Size.Height; _manualChange = false; Resize(); }
/// <summary> /// Пытается добавить текст автора в очередь закачки. /// Если уже есть в кеше, то не добавляет, а возвращает из кеша. /// </summary> /// <param name="author">Автор</param> /// <param name="text">Текст</param> /// <returns>Элемент очереди, либо из кеша</returns> public static DownloadTextItem Add(Author author, AuthorText text) { foreach (DownloadTextItem downloadTextItem in DownloadTextItems) { if (downloadTextItem.GetHashCode() == (new DownloadTextItem(author, text)).GetHashCode()) return downloadTextItem; } DownloadTextItem item = new DownloadTextItem(author, text) {Logger = _logger}; if (item.Text == null) DownloadTextItems.Add(item); ChangeVisibility(); return item; }
public AuthorUpdates(Author author, Setting setting, Logger logger) { InitializeComponent(); _author = author; _setting = setting; AuthorWindowSetting authorWindowSetting = _setting.GetAuthorWindowSetting(author); Width = authorWindowSetting.Size.Width; Height = authorWindowSetting.Size.Height; Left = authorWindowSetting.Location.X; Top = authorWindowSetting.Location.Y; SizeChanged += AuthorUpdatesSizeChanged; LocationChanged += AuthorUpdatesLocationChanged; authorPanel.SetSetting(setting, logger); authorPanel.Build(author, authorWindowSetting.HeightComment); authorPanel.SplitterChanged += AuthorPanelSplitterChanged; Title = author.Name; AuthorUpdateDate.Content = "Состояние текстов автора на дату: " + author.UpdateDate.ToShortDateString(); }
public AuthorWindowSetting GetAuthorWindowSetting(Author author) { return (author != null) && (AuthorWindowSettingDictionary.ContainsKey(author.URL)) ? AuthorWindowSettingDictionary[author.URL] : AuthorWindowSettingDictionary["Default"]; }
internal UpdateTextParam(Author author, string page, int index, int count) { Author = author; Page = page; Index = index; Count = count; }
/// <summary> /// Конвертация автора в xml /// </summary> /// <param name="author"></param> /// <returns></returns> private string Author2Xml(Author author) { var xs = new XmlSerializer(typeof(Author)); var sb = new StringBuilder(); var w = new StringWriter(sb, CultureInfo.InvariantCulture); xs.Serialize(w, author, new XmlSerializerNamespaces(new[] { new XmlQualifiedName(string.Empty) })); return sb.ToString(); }
/// <summary> /// Сохранение автора в БД в отдельном потоке, например при удалении автора, чтобы не тормозил интерфейс /// </summary> /// <param name="author"></param> public void SaveAuthorThreaded(Author author) { Task.Factory.StartNew(() => SaveAuthor(author)); }
/// <summary> /// Получает путь к файлу различий с предыдущей версией для книги /// </summary> /// <param name="author">Автор книги</param> /// <returns>Путь на диске</returns> public string GetDiffFileName(Author author) { return GetCachedFileName(author).Replace(".shtml", "_diff.shtml"); }
/// <summary> /// Обновляет признак наличия файла отличий книги /// </summary> /// <param name="author">Автор - для создания правильного пути к файлу в кеше</param> public void UpdateHasDiff(Author author) { HasDiff = File.Exists(GetDiffFileName(author)); }
/// <summary> /// Обновляет список произведений автора /// </summary> /// <param name="page">Страница автора со списком произведений</param> /// <param name="context">Контекст синхронизации для обновления GUI</param> /// <returns>true - автор обновился</returns> public bool UpdateAuthorInfo(string page, SynchronizationContext context) { lock (_lockObj) { bool retValue = false; Author authorTemp = new Author { UpdateDate = UpdateDate }; // проанализируем данные на страничке. если раньше их не загружали, то в любом случае не показываем, что есть обновления, просто заполняем данные MatchCollection matches = Regex.Matches(page, "<DL><DT><li>(?:<font.*?>.*?</font>)?\\s*(<b>(?<Authors>.*?)\\s*</b>\\s*)?<A HREF=(?<LinkToText>.*?)><b>\\s*(?<NameOfText>.*?)\\s*</b></A>.*?<b>(?<SizeOfText>\\d+)k</b>.*?<small>(?:Оценка:<b>(?<DescriptionOfRating>(?<rating>\\d+(?:\\.\\d+)?).*?)</b>.*?)?\\s*\"(?<Section>.*?)\"\\s*(?<Genres>.*?)?\\s*(?:<A HREF=\"(?<LinkToComments>.*?)\">Комментарии:\\s*(?<CommentsDescription>(?<CommentCount>\\d+).*?)</A>\\s*)?</small>.*?(?:<br><DD>(?<Description>.*?))?</DL>"); if (matches.Count > 0) { int cnt = 0; foreach (Match m in matches) { var item = new AuthorText { Description = NormalizeHTML(m.Groups["Description"].Value).Trim(), Genres = NormalizeHTML(m.Groups["Genres"].Value), Link = m.Groups["LinkToText"].Value, Name = NormalizeHTML(m.Groups["NameOfText"].Value), Order = cnt, SectionName = NormalizeHTML(m.Groups["Section"].Value).Replace("@", ""), Size = int.Parse(m.Groups["SizeOfText"].Value) }; authorTemp.Texts.Add(item); cnt++; } } if (Texts.Count > 0) // если раньше загружали автора, то проводим сравнение { foreach (AuthorText txt in authorTemp.Texts) { bool bFound = false; int OldSize = 0; // стрый размер текста foreach (AuthorText t in Texts) { if (txt.Link == t.Link) { txt.Cached = t.Cached; OldSize = t.Size;// запоминаем старый размер, чтобы запомнить его в новом тексте } if (txt.Description == t.Description && txt.Name == t.Name && txt.Size == t.Size) { bFound = true; // переносим значение isNew в новый массив, чтобы не потерять непрочитанные новые тексты txt.IsNew = t.IsNew; txt.UpdateDate = t.UpdateDate; break; } } if (!bFound) { retValue = true; authorTemp.IsNew = true; txt.IsNew = true; txt.UpdateDate = DateTime.Now; txt.SizeOld = OldSize; // да, автор обновился authorTemp.UpdateDate = DateTime.Now; } } // доп проверка по количеству произведений if (authorTemp.Texts.Count != Texts.Count) { retValue = true; authorTemp.UpdateDate = DateTime.Now; } } context.Post(SyncRun, new RunContent {Renewed = this, New = authorTemp}); return retValue; } // lock }
/// <summary> /// Конструктор (при нахождении файла в кеше устанавливается свойство Text /// </summary> /// <param name="author">Автор</param> /// <param name="text">Текст</param> public DownloadTextItem(Author author, AuthorText text) { _author = author; AuthorText = text; string fileName = GetCachedFileName(); if (File.Exists(fileName)) Text = File.ReadAllText(fileName, Encoding.GetEncoding(1251)); BytesReceived = 0; }
private void AuthorPanelSplitterChanged(Author author, double heightcomment) { _setting.SetAuthorWindowHeightCommentSetting(_author, heightcomment); }
public static AuthorUpdates FindWindow(Author author) { foreach (AuthorUpdates au in OpenedWindows) if (au.authorPanel.Author == author) return au; return null; }
/// <summary> /// Добавляет в RSS ленту новые произведения автора /// </summary> /// <param name="author">Автор</param> public void Add(Author author) { foreach (AuthorText authorText in author.Texts) { if (authorText.IsNew) { RssItem item = new RssItem { Title = author.Name + " | " + authorText.Name, Link = authorText.GetFullLink(author), PubDate = DateTime.Now, Author = author.Name, Category = author.Category }; StringBuilder sb = new StringBuilder(); sb.AppendFormat(@"<a href=""{0}""><font size=""+1"" color=TEAL>{1}</font></a>. Категория: {2}.", author.URL, author.Name, author.Category); sb.AppendLine("<br>"); sb.AppendFormat(@"<a href=""{0}""><font size=""+1"" color=TEAL>{1}</font></a>. Размер: {2} кб.", authorText.GetFullLink(author), authorText.Name, authorText.Size); sb.AppendLine("<br>"); sb.AppendFormat(@"{0} -> {1}", authorText.Genres, authorText.SectionName); sb.AppendLine("<br>"); sb.AppendFormat(@"{0}", authorText.Description); item.Description = sb.ToString(); item.Guid = (item.Title.GetHashCode() ^ item.Link.GetHashCode() ^ item.Author.GetHashCode() ^ item.Category.GetHashCode() ^ item.Description.GetHashCode()).ToString(); if (!_dictRssItem.ContainsKey(item.Guid)) { _dictRssItem.Add(item.Guid, item); _articles.Insert(0, item); } } } }
/// <summary> /// Обновляет признак кешированности книги /// </summary> /// <param name="author">Автор - для создания правильного пути к файлу в кеше</param> public void UpdateIsCached(Author author) { IsCached = File.Exists(GetCachedFileName(author)); }
public void SetAdvancedWindowHeightCommentSetting(Author author, double heightComment) { if (author == null) return; if (heightComment == AdvancedWindowSettingDictionary["Default"].HeightComment) return; if (Keyboard.Modifiers == (ModifierKeys.Control ^ ModifierKeys.Shift)) { foreach (AdvancedWindowSetting advancedWindowSetting in AdvancedWindowSettingDictionary.Values) { advancedWindowSetting.HeightComment = heightComment; } return; } if (Keyboard.Modifiers == ModifierKeys.Control) { AdvancedWindowSettingDictionary["Default"].HeightComment = heightComment; return; } if (AdvancedWindowSettingDictionary.ContainsKey(author.URL)) AdvancedWindowSettingDictionary[author.URL].HeightComment = heightComment; else { AdvancedWindowSetting newSetting = new AdvancedWindowSetting { Size = AdvancedWindowSettingDictionary["Default"].Size, HeightComment = heightComment }; AdvancedWindowSettingDictionary.Add(author.URL, newSetting); } }
private void AuthorPanelSplitterChanged(Author author, double heightComment) { if (!_manualChange) { _setting.SetAdvancedWindowHeightCommentSetting(_author, heightComment); } }
public void SetAuthorWindowSizeSetting(Author author, Size size) { if (author == null) return; if (size == AuthorWindowSettingDictionary["Default"].Size) return; if (Keyboard.Modifiers == (ModifierKeys.Control ^ ModifierKeys.Shift)) { foreach (AuthorWindowSetting authorWindowSetting in AuthorWindowSettingDictionary.Values) { authorWindowSetting.Size = size; } return; } if (Keyboard.Modifiers == ModifierKeys.Control) { AuthorWindowSettingDictionary["Default"].Size = size; return; } if (AuthorWindowSettingDictionary.ContainsKey(author.URL)) AuthorWindowSettingDictionary[author.URL].Size = size; else { AuthorWindowSetting newSetting = new AuthorWindowSetting { Size = size, Location = AuthorWindowSettingDictionary["Default"].Location, HeightComment = AuthorWindowSettingDictionary["Default"].HeightComment }; AuthorWindowSettingDictionary.Add(author.URL, newSetting); } }
public static void DeleteAuthor(Author author) { AuthorUpdates au = AuthorUpdates.FindWindow(author); if (au != null) au.Close(); author.IsDeleted = true;// помечаем, что удален if (MainWindow.GetSettings().UseDatabase) MainWindow.MainForm.GetDatabaseManager().SaveAuthorThreaded(author); // сохраняем удаленный статус асинхронно //Authors.Remove(author); Refresh();// перерисовывем списко авторов }
/// <summary> /// Сохранение автора в БД /// </summary> /// <param name="author"></param> public void SaveAuthor(Author author) { lock (_locker) { if (string.IsNullOrEmpty(author.Id)) //author.Id = Guid.NewGuid().ToString(); author.CheckID(); //author.timeStamp = DateTime.Now.ToUniversalTime(); string author_xml = Author2Xml(author); if (!string.IsNullOrEmpty(author_xml)) { // проверим, есть ли такой автор в БД using (SQLiteCommand cmd = new SQLiteCommand("", conn)) { string sql = ""; sql = string.Format("select * from authors where id='{0}'", author.Id); cmd.CommandText = sql; int cnt = cmd.ExecuteNonQuery(); //long timeStamp = author.timeStamp.ToBinary(); if (ds != null) ds.Dispose(); ds = new DataSet(); da = new SQLiteDataAdapter(); da.SelectCommand = cmd; var cb = new System.Data.SQLite.SQLiteCommandBuilder(da); da.Fill(ds, "author"); if (ds.Tables["author"].Rows.Count == 0) { DataRow dr = ds.Tables["author"].NewRow(); dr["id"] = author.Id; ds.Tables["author"].Rows.Add(dr); } ds.Tables["author"].Rows[0]["author_xml"] = author_xml; //ds.Tables["author"].Rows[0]["stamp"] = timeStamp; da.Update(ds.Tables["author"]); //if (cnt > 0) // sql = string.Format("update authors set author_xml='{0}', stamp={1} where id='{1}'", author_xml, timeStamp, author.Id); //else // sql = string.Format("insert into authors (id, author_xml, stamp) ('{0}','{1}',{2})", author.Id, author_xml, timeStamp); //cmd.CommandText = sql; //cmd.ExecuteNonQuery(); } } } }
/// <summary> /// Конструирует правильный url книги из абсолютного адреса автора и относительного книги /// </summary> /// <param name="author">Автор</param> /// <returns>URL</returns> public string GetFullLink(Author author) { string url = author.URL; if (url.EndsWith("indexdate.shtml")) url = url.Replace("indexdate.shtml", Link); else url = (url.EndsWith("/")) ? url + Link : url + "/" + Link; return url; }
public static Author AddAuthor(string url) { _logger.Add("Добавление автора..."); // Перевести URL на samlib.ru url = url.ToLowerInvariant().Replace("zhurnal.lib.ru", "samlib.ru"); // аналог DoEvents в WPF, иначе "Добавление автора..." вообще не появляется, т.к. метод синхронный Application.Current.Dispatcher.Invoke(DispatcherPriority.Background, new ThreadStart(delegate { })); if (!url.StartsWith("http://")) url = "http://" + url; // Если URL заканчивается на index.shtml, преобразовать его в нужный) if (url.EndsWith("index.shtml")) url = url.Replace("index.shtml", "indexdate.shtml"); if (!url.EndsWith("indexdate.shtml")) url = (url.EndsWith("/")) ? url + "indexdate.shtml" : url + "/indexdate.shtml"; Author author = Authors.FindAuthor(url); if (author != null) { _logger.Add("Этот автор уже присутствует в списке", true, true); return author; } try { string pageContent = WEB.DownloadPageSilent(url); if (pageContent == null) { _logger.Add("Не удалось открыть страницу автора", true, true); return null; } int index = pageContent.IndexOf('.', pageContent.IndexOf("<title>")) + 1; string authorName = pageContent.Substring(index, pageContent.IndexOf('.', index) - index); DateTime updateDate = GetUpdateDate(pageContent); if (updateDate == DateTime.MinValue) { _logger.Add("Не удалось получить дату со страницы автора", true, true); return null; } if (authorName.Trim() == "") { _logger.Add("Не удалось получить имя автора", true, true); return null; } author = new Author {Name = authorName, IsNew = false, UpdateDate = updateDate, URL = url}; author.CheckID();// генерим id Authors.Add(author); author.UpdateAuthorInfo(pageContent, SynchronizationContext.Current); _logger.Add("Добавлен: " + author.Name); author.Changed = true; } catch (Exception ex) { _logger.Add(ex.StackTrace, false, true); _logger.Add(ex.Message, false, true); _logger.Add("Необработанная ошибка при добавлении автора", true, true); } return author; }
/// <summary> /// Сохранение автора в БД /// </summary> /// <param name="author"></param> public void SaveAuthor(Author author) { if (server == null) return; try { using (IObjectContainer documentStore = server.OpenClient()) { var _author = documentStore .Query<AuthorDb4o>(x => x != null && x.Id == author.Id) .FirstOrDefault(); if (_author != null) { _author.author = author; documentStore.Delete(_author); _author.author.URL = _author.author.URL.Replace("zhurnal.lib.ru", "samlib.ru"); documentStore.Store(_author); }else documentStore.Store(new AuthorDb4o { Id = author.Id, author = author }); documentStore.Commit(); } } catch (Exception ex) { MessageBox.Show("Ошибка сохранения данных автора в БД." + ex.Message, "Ошибка", MessageBoxButton.OK, MessageBoxImage.Error); } }
// обновить данные автора из скачанного с гугла public static void UpdateAuthorContent(Author author) { foreach (Author _author in Authors) { if (author.Id == _author.Id) { //_author.Cached = author.Cached; //_author.Category = author.Category; //_author.Comment = author.Comment; //_author.IsIgnored = author.IsIgnored; //_author.Name = author.Name; //_author.Texts = new BindingList<AuthorText>(); //foreach (AuthorText authorText in author.Texts) // _author.Texts.Add(authorText); //_author.IsNew = author.IsNew; //_author.timeStamp = GoogleTime; //_author.UpdateDate = author.UpdateDate; //_author.Changed = true;// говорим, что данные изменились (для хаписи в БД) //_author.ChangedGoogle = false;// говорим, что синхронизировать с гуглом не надо Authors.Remove(_author); Authors.Add(author); break; } } }
/// <summary> /// Получает путь к файлу кеша для книги /// </summary> /// <param name="author">Автор книги</param> /// <returns>Путь на диске</returns> public string GetCachedFileName(Author author) { string urlWithoutHTTP = author.URL.Replace(@"http://", ""); if (urlWithoutHTTP.EndsWith("/indexdate.shtml")) urlWithoutHTTP = urlWithoutHTTP.Replace("/indexdate.shtml", ""); string endPath = urlWithoutHTTP.Substring(urlWithoutHTTP.IndexOf("/") + 1).Replace("/", @"\"); string booksCachedPath = DownloadTextHelper.BooksPath(); booksCachedPath = Path.Combine(booksCachedPath, endPath); string sectionName = SectionName; foreach (char c in Path.GetInvalidFileNameChars()) { sectionName = sectionName.Replace(c, '_'); } booksCachedPath = Path.Combine(booksCachedPath, sectionName); string fileName = Path.Combine(booksCachedPath, Link); string ext = Path.GetExtension(fileName); fileName = fileName.Substring(0, fileName.LastIndexOf(ext)) + "." + UpdateDate.Ticks + ext; return fileName; }