Итак 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]);
// конец кода
Дальше просматриваем списки Жанров, Автором и Переводчиков и выводим оттуда информацию (если она там есть).
Т.е. проверяем все заполненные поля форм описывающих книгу и выводим информацию в соответствующие секции заголовка книги.
Будем считать, что с Description - покончили.
Осталось только
// начало кода
procedure SaveEndnotes;
var
S: string;
i: integer;
begin
if Form1.EndNotesList.Items.Count = 0 then exit;
OutList.Add('<body name="notes"><title>
Примечания
</title>');
for i:= 0 to Form1.EndNotesList.Items.Count - 1 do
begin
S:= Form1.EndNotesList.Items[i];
OutList.Add('<section id="n_'+IntToStr(i+1)+'"><title>
'+IntToStr(i+1)+'
');
OutList.Add('</title>
'+S+'
');
OutList.Add('</section>');
end;
OutList.Add('</body>');
end;
// конец кода
Согласитесь, что здесь все просто, просматриваем список сносок и соблюдаем формат FB2. Но остается один маленький вопрос, а что если нам нужно будет вывести многострочную (точнее много абзачную) сноску. Да, возникает вопрос, приходят и варианты решения…
Ладно, кое-что в коде я пропустил. Но основные недостатки программы, я кажется описал. Правда, наверняка есть ляпы, которые я не заметил…
Наконец файл книги в формате FB2 создан.
На этом все? Ну нет, сейчас все авторы заканчивают книги словами "Продолжение следует". И я замыслил по крайней мере одно продолжение. Мне кажется оно просто необходимо.
Программа должна уметь не только создавать, но и читать файл FB2. Тогда можно растягивать удовольствие изготовления книги на несколько дней, и не потребуется каждый раз заново: читать текстовый файл, расставлять стили, форматировать строки и т. д. и все это с одной и той же книгой - ужас.
Но, как известно из математики, обратная задача всегда сложнее прямой. И т. к. я считаю, что на сегодня уже достаточно утомил Вас. Давайте рассказ о второй версии программы отложим.
Связаться со мной Вы сможете по адресу [email protected] (обратите внимание, 2 подчеркивания, т. к. [email protected] оказался уже занят). Предупреждаю сразу, я ленив, почту смотрю не каждый день, да и отвечать всем может и не смогу (я же не знаю сколько найдется желающих мне написать). Второе, эту почту я специально завел для этой программки, и если Вы, друзья мои завалите ее спамом или матом, я просто забуду туда дорогу.
Лицензионные условия таковы, пользуйтесь на здоровье, копируйте, переделывайте, если сможете заработать на этом деньги, буду только рад.
Карпов Юрий.
Кохтла-Ярве.
2010.
Итак.
Продолжение следует…
Исходный код программы.
Выложил исходник на один сайт, но боюсь, что там ему и потерянному быть…
Поэтому, не буду ждать милости, справимся и сами.
Для начала, извлечем исходник из этого файла.
«Нет таких задач, которые не могли бы решить комму… (извиняюсь) программисты!»
Сделаем копию этого файла. Переименуем его как текст. В этом тексте найдем слово «Приложение». Удалим все до этого слова, да и немного далее, до начала исходного текста.
Теперь заменим все
и
на пустое место.
Еще заменим:
<empty-line/> на пустое место.
& на &
< на <
> на >
«Цели определены, задачи поставлены, за работу товарищи…»
Программа состоит из 4 форм и 6 файлов pas, всего около 50 кбайт.
Далее, последует инструкция, как сделать программку.
Если Delphi 5 и выше то все просто.
Получившийся пирожок, нужно разрезать на отдельные файлы и назвать так как они подписаны
И запустить проект.
Иначе придется повозится.
В новой папочке создайте пустой проект Delphi.
На форме кликните правой кнопкой мыши и выберите View as Text
Скопируйте код формы из книги (не захватывая слова "начало кода" и "конец кода"). Вставьте его в открытое окно. Нажмите правую кнопку мыши и выберите View as Form. Если все сделано правильно Вы увидите форму.
Скопируйте код соответствующего unit. Замените им код в окне Code.
Хорошо, одна форма сделана.
Теперь создайте новую форму File - New - Form
И повторите предыдущие операции
Форм и соответствующих им Юнитов нужно сделать 4:
Unit1.dfm, genres.dfm, EditStr.dfm, authors.dfm
Unit1.pas, genres.pas, EditStr.pas, authors.pas
Файлы UmFB2.pas и dm.pas форм не имеют т.е. просто сделайте их из текстовых.
Итак, начали.
// начало кода
object Form1: TForm1
Left = 187
Top = 98
Width = 722
Height = 463
Caption = 'Form1'
Color = clBtnFace
Font.Charset = DEFAULT_CHARSET
Font.Color = clWindowText
Font.Height = -11
Font.Name = 'MS Sans Serif'
Font.Style = []
Menu = MainMenu1
OldCreateOrder = False
OnCreate = FormCreate
PixelsPerInch = 96
TextHeight = 13
object PageControl1: TPageControl
Left = 0
Top = 0
Width = 714
Height = 417
ActivePage = TabSheet2
Align = alClient
TabIndex = 3
TabOrder = 0
object TabSheet1: TTabSheet
Caption = 'title-info'
object Annotation: TMemo
Left = 0
Top = 273
Width = 706
Height = 116
Align = alClient
ScrollBars = ssVertical
TabOrder = 0
WordWrap = False
end
object Panel3: TPanel
Left = 0
Top = 0
Width = 706
Height = 273
Align = alTop
BevelOuter = bvNone
TabOrder = 1
object Lbook_title: TLabel
Left = 8
Top = 64
Width = 43
Height = 13
Caption = 'book-title'
end
object LProject: TLabel
Left = 8
Top = 8
Width = 36
Height = 13
Caption = 'Project:'
end
object LAnnotation: TLabel
Left = 16
Top = 240
Width = 51
Height = 13
Caption = 'Annotation'
end
object Lsequence: TLabel
Left = 16
Top = 176
Width = 49
Height = 13
Caption = 'Sequence'
end
object LLang: TLabel
Left = 376
Top = 176
Width = 27
Height = 13
Caption = 'Lang.'
end
object Lsrc_lang: TLabel
Left = 456