- 1
- 2
- 3
- 4
- 5
- . . .
- последняя (9) »
случае эта структура - дерево. В корне(в первой строчке), я предлагаю писать название книги, а дальше части, главы или что там есть.
Программе для обработки структуры понадобится стек (напомню, стек - это список с правилом "последний пришел - первый вышел")
Полученный код FB2, как эталоном, я проверяю программой "FictionBook Editor". Так вот, экзаменатору не нравится такая структура:
// начало примера H1 | Кальман Миксат. ОСАДА БЕСТЕРЦЕ S| (История одного чудака) H2 | ВВЕДЕНИЕ // конец примера
Т.е. между секциями не должно быть ничего лишнего… А вот так будет все нормально:
// начало примера H1 | Кальман Миксат. ОСАДА БЕСТЕРЦЕ H1 | (История одного чудака) H2 | ВВЕДЕНИЕ // конец примера
Итак, когда при обработке списка ListBox1 встречается строка с типом от H1 до H5 вызывается процедура StyleStucture; // начало кода procedure StyleStucture; begin if CurStyle <> oldStyle then begin // пока предположим, что предыдущий стиль был не заголовок if SytleStack.Count = 0 then // если стек пуст begin // записываем стиль в стек SytleStack.Add(TObject(CurStyle)) end else // если в стеке что-то есть begin // значит надо проверить последний из заголовков LastStyle:= TmyStyle(SytleStack.Last); // считываем последний стиль case SubStyle(CurStyle, LastStyle) of // вычисляем разность текущий стиль минус последний 0: OutList.Add('</section>'); // стили равны, ничего особенного делать не надо 1: SytleStack.Add(TObject(CurStyle)); // новый стиль больше, добавляем его в стек // предыдущая секция не закончилась, т. к. новая будет в ее входить как матрешка else // иначе, считаем что разность меньше нуля begin OutList.Add('</section>'); while CurStyle <>LastStyle do begin SytleStack.Delete(SytleStack.Count-1); // уменьшаем стек OutList.Add('</section>'); // завершаем секции до тех пор пока LastStyle:= TmyStyle(SytleStack.Last); // текущий стиль и стиль в стеке не сравняются. end; end; end;// case end; OutList.Add('<section>'); // начинаем новую секцию OutList.Add('<title>'); end; OutList.Add('<p>'+s+'</p>'); // записываем заголовок секции end; // StyleStucture; // конец кода
Пожалуй, это самый тяжелый код в данном манускрипте, но он вроде работает, хотя я вижу в нем по крайней мере две неувязки, но что это, не скажу…
Ну вот с обработкой книги почти закончили, мелкие подробности увидите в исходнике.
Нажимаем пункт меню File - Save as FB2. И - ничего не получается. Запланированная шутка. Вылезла надпись "Заполнить поля" и фокус перенаправлен на начальную закладку. Напоминаю FB2 - это не только легкоусвояемый (легкоусваиваемый) текст, но и очень нужный и полезный заголовок книги. Давайте посмотрим, все таки, что происходит при выборе пункта Save as FB2 // начало кода procedure TForm1.SaveasFB21Click(Sender: TObject); begin if not BookHaveName then // проверяем, все ли в порядке в заголовке begin // если нет, то происходит все то что Вы видели PageControl1.ActivePageIndex:= 0; ShowMessage('Fill the form.'); exit; end; SaveDialog1.FileName:= form1.FB2_file.Text; if SaveDialog1.Execute then Make_fb2(SaveDialog1.FileName); end; // конец кода
Посмотрим на процедуру BookHaveName // начало кода function BookHaveName: boolean; begin with Form1 do result:= (book_title.Text <> '') and (FB2_file.Text <> '') and (GenresBox.Count > 0); end; // конец кода Ничего особенного в этой функции нет. Единственно из-за чего я ее вытащил, это сказать, что Вы можете и скорее даже будете вынуждены, как-то изменить ее, чтобы контроль заполнения заголовка книги был более разумным.
А я пока вернусь к заполнению заголовка. В программе Вы видите три закладки Title-info, Document-info и Publish-info. В формате FB2 есть еще кое-что, но я пока это игнорировал. Предоставляю Вам такую возможность. Код Вам в руки…
Итак Title-info Поле Project - само заполнится при открытии текстового файла. При желании, Вы можете изменить, имя сохраняемого fb2 файла.
Поле book-title действительно обязательно надо заполнить
Теперь Genre - Жанр. Ага, тут немного интереснее, есть о чем погуторить. Нажимаем кнопку с тремя точками. И открывается окошко Жанры. Наша цель добавить один или несколько жанров в левый ListBox. Выберите подходящий жанр в правом ListBoxсике и нажмите кнопку Add В навигации по жанрам поможет верхний ComboBox О коде в этом unit мне говорить лень, ничего особенного, рутина. Интереснее, вот, что, информация для загрузки в эти Боксики находится в unit dm Посмотрите на нее, и поругайте мою лень. Дело в том, что я не уверен, что этот список жанров правилен. Второе, этот список, очевидно, не окончателен. А значит он не должен быть жестко зафиксирован в программе. Значит, так. Вам задание - переписать прогу, чтобы эти списки грузились или из текстового файла или из INI файла.
Вернемся к заполнению заголовка Нам надо ввести данные об авторе / авторах и переводчике / переводчиках Так же нажимаем на соответствующую кнопочку с троеточием и работаем в открывшемся окне.
Вы уже наверно заметили, что мне прискучило очень уж подробно расписывать код. Но в данном unit тоже ничего особенного, единственно, пришлось ввести структуру TPerson, я думаю Вы легко разберетесь зачем она мне нужна. Мне интереснее, совершенствование программы. Представьте ситуацию, Вы делаете 10 книг (или 100) одного автора и каждый раз делая новую книгу, заполняете опять и опять данные об этом человеке. Мне было бы лень. Ваши предложения?…
Ну хорошо мы заполнили и Title-info и Document-info и Publish-info.
Давайте-ка глянем, что там в коде записи файла FB2.
// начало кода Procedure Make_fb2(S: string); begin // if Form1.ListBox1.Items.Count = 0 then exit; SytleStack.Clear; // подготовка стека стилей OutList.Clear; // подготовка выходного списка SaveDescription; SaveBodyFB2; // это мы уже в общем рассмотрели SaveEndnotes; OutList.Add('</FictionBook>'); // закрываем книгу OutList.SaveToFile(S); // Запись в файл showMessage('Done.'); // Сообщаем об удачном завершении end; // конец кода
Как видите мы еще не рассмотрели две процедуры.
// начало кода procedure SaveDescription; const max = 5; // может я захочу изменить число строк в массиве, тогда я изменю только одну цифру mas: array[1.. max] of string = (// массив для заголовочной части FB2 файла '<?xml version="1.0" encoding="windows-1251"?>', // как видите я делаю файл в кодировке Win // я не вижу смысла в применении юникода, но если речь идет не о русском языке, // то сделайте здесь изменение. '<FictionBook xmlns="http://www.gribuser.ru/xml/fictionbook/2.0"', ' xmlns: l="http://www.w3.org/1999/xlink">', ' <description>', ' <title-info>' ); var i: byte; begin // Выводим в выходной файл начало FB2 файла for i:= 1 to max do OutList.Add(Mas[i]); // конец кода Дальше просматриваем списки Жанров, Автором и Переводчиков и выводим оттуда информацию (если она там есть). Т.е. проверяем все заполненные поля
Полученный код FB2, как эталоном, я проверяю программой "FictionBook Editor". Так вот, экзаменатору не нравится такая структура:
// начало примера H1 | Кальман Миксат. ОСАДА БЕСТЕРЦЕ S| (История одного чудака) H2 | ВВЕДЕНИЕ // конец примера
Т.е. между секциями не должно быть ничего лишнего… А вот так будет все нормально:
// начало примера H1 | Кальман Миксат. ОСАДА БЕСТЕРЦЕ H1 | (История одного чудака) H2 | ВВЕДЕНИЕ // конец примера
Итак, когда при обработке списка ListBox1 встречается строка с типом от H1 до H5 вызывается процедура StyleStucture; // начало кода procedure StyleStucture; begin if CurStyle <> oldStyle then begin // пока предположим, что предыдущий стиль был не заголовок if SytleStack.Count = 0 then // если стек пуст begin // записываем стиль в стек SytleStack.Add(TObject(CurStyle)) end else // если в стеке что-то есть begin // значит надо проверить последний из заголовков LastStyle:= TmyStyle(SytleStack.Last); // считываем последний стиль case SubStyle(CurStyle, LastStyle) of // вычисляем разность текущий стиль минус последний 0: OutList.Add('</section>'); // стили равны, ничего особенного делать не надо 1: SytleStack.Add(TObject(CurStyle)); // новый стиль больше, добавляем его в стек // предыдущая секция не закончилась, т. к. новая будет в ее входить как матрешка else // иначе, считаем что разность меньше нуля begin OutList.Add('</section>'); while CurStyle <>LastStyle do begin SytleStack.Delete(SytleStack.Count-1); // уменьшаем стек OutList.Add('</section>'); // завершаем секции до тех пор пока LastStyle:= TmyStyle(SytleStack.Last); // текущий стиль и стиль в стеке не сравняются. end; end; end;// case end; OutList.Add('<section>'); // начинаем новую секцию OutList.Add('<title>'); end; OutList.Add('<p>'+s+'</p>'); // записываем заголовок секции end; // StyleStucture; // конец кода
Пожалуй, это самый тяжелый код в данном манускрипте, но он вроде работает, хотя я вижу в нем по крайней мере две неувязки, но что это, не скажу…
Ну вот с обработкой книги почти закончили, мелкие подробности увидите в исходнике.
Нажимаем пункт меню File - Save as FB2. И - ничего не получается. Запланированная шутка. Вылезла надпись "Заполнить поля" и фокус перенаправлен на начальную закладку. Напоминаю FB2 - это не только легкоусвояемый (легкоусваиваемый) текст, но и очень нужный и полезный заголовок книги. Давайте посмотрим, все таки, что происходит при выборе пункта Save as FB2 // начало кода procedure TForm1.SaveasFB21Click(Sender: TObject); begin if not BookHaveName then // проверяем, все ли в порядке в заголовке begin // если нет, то происходит все то что Вы видели PageControl1.ActivePageIndex:= 0; ShowMessage('Fill the form.'); exit; end; SaveDialog1.FileName:= form1.FB2_file.Text; if SaveDialog1.Execute then Make_fb2(SaveDialog1.FileName); end; // конец кода
Посмотрим на процедуру BookHaveName // начало кода function BookHaveName: boolean; begin with Form1 do result:= (book_title.Text <> '') and (FB2_file.Text <> '') and (GenresBox.Count > 0); end; // конец кода Ничего особенного в этой функции нет. Единственно из-за чего я ее вытащил, это сказать, что Вы можете и скорее даже будете вынуждены, как-то изменить ее, чтобы контроль заполнения заголовка книги был более разумным.
А я пока вернусь к заполнению заголовка. В программе Вы видите три закладки Title-info, Document-info и Publish-info. В формате FB2 есть еще кое-что, но я пока это игнорировал. Предоставляю Вам такую возможность. Код Вам в руки…
Итак Title-info Поле Project - само заполнится при открытии текстового файла. При желании, Вы можете изменить, имя сохраняемого fb2 файла.
Поле book-title действительно обязательно надо заполнить
Теперь Genre - Жанр. Ага, тут немного интереснее, есть о чем погуторить. Нажимаем кнопку с тремя точками. И открывается окошко Жанры. Наша цель добавить один или несколько жанров в левый ListBox. Выберите подходящий жанр в правом ListBoxсике и нажмите кнопку Add В навигации по жанрам поможет верхний ComboBox О коде в этом unit мне говорить лень, ничего особенного, рутина. Интереснее, вот, что, информация для загрузки в эти Боксики находится в unit dm Посмотрите на нее, и поругайте мою лень. Дело в том, что я не уверен, что этот список жанров правилен. Второе, этот список, очевидно, не окончателен. А значит он не должен быть жестко зафиксирован в программе. Значит, так. Вам задание - переписать прогу, чтобы эти списки грузились или из текстового файла или из INI файла.
Вернемся к заполнению заголовка Нам надо ввести данные об авторе / авторах и переводчике / переводчиках Так же нажимаем на соответствующую кнопочку с троеточием и работаем в открывшемся окне.
Вы уже наверно заметили, что мне прискучило очень уж подробно расписывать код. Но в данном unit тоже ничего особенного, единственно, пришлось ввести структуру TPerson, я думаю Вы легко разберетесь зачем она мне нужна. Мне интереснее, совершенствование программы. Представьте ситуацию, Вы делаете 10 книг (или 100) одного автора и каждый раз делая новую книгу, заполняете опять и опять данные об этом человеке. Мне было бы лень. Ваши предложения?…
Ну хорошо мы заполнили и Title-info и Document-info и Publish-info.
Давайте-ка глянем, что там в коде записи файла FB2.
// начало кода Procedure Make_fb2(S: string); begin // if Form1.ListBox1.Items.Count = 0 then exit; SytleStack.Clear; // подготовка стека стилей OutList.Clear; // подготовка выходного списка SaveDescription; SaveBodyFB2; // это мы уже в общем рассмотрели SaveEndnotes; OutList.Add('</FictionBook>'); // закрываем книгу OutList.SaveToFile(S); // Запись в файл showMessage('Done.'); // Сообщаем об удачном завершении end; // конец кода
Как видите мы еще не рассмотрели две процедуры.
// начало кода procedure SaveDescription; const max = 5; // может я захочу изменить число строк в массиве, тогда я изменю только одну цифру mas: array[1.. max] of string = (// массив для заголовочной части FB2 файла '<?xml version="1.0" encoding="windows-1251"?>', // как видите я делаю файл в кодировке Win // я не вижу смысла в применении юникода, но если речь идет не о русском языке, // то сделайте здесь изменение. '<FictionBook xmlns="http://www.gribuser.ru/xml/fictionbook/2.0"', ' xmlns: l="http://www.w3.org/1999/xlink">', ' <description>', ' <title-info>' ); var i: byte; begin // Выводим в выходной файл начало FB2 файла for i:= 1 to max do OutList.Add(Mas[i]); // конец кода Дальше просматриваем списки Жанров, Автором и Переводчиков и выводим оттуда информацию (если она там есть). Т.е. проверяем все заполненные поля
- 1
- 2
- 3
- 4
- 5
- . . .
- последняя (9) »