Subversion Repositories Scribus

Rev

Rev 23992 | Rev 24743 | Go to most recent revision | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
23992 craig 1
/*
2
For general Scribus (>=1.3.2) copyright and licensing information please refer
3
to the COPYING file provided with the program. Following this notice may exist
4
a copyright and/or license notice that predates the release of Scribus 1.3.2
5
for which a new license (GPL+exception) is in place.
6
*/
7
/***************************************************************************
8
                                                         -------------------
9
        begin                : Wed Aug 19 2020
10
        copyright            : (C) 2020 by Craig Bradney
11
        email                : cbradney@scribus.info
12
 ***************************************************************************/
13
#include "markdownim.h"
14
 
15
#include <QApplication>
16
#include <QByteArray>
17
#include <QTextBlock>
18
#include <QTextBlockFormat>
19
#include <QTextCharFormat>
20
#include <QTextDocument>
21
#include <QTextFrameFormat>
23996 craig 22
#include <QTextList>
23992 craig 23
#include <QTextListFormat>
24
 
25
#include "prefsmanager.h"
26
#include "scribus.h"
27
#include "scribusdoc.h"
28
#include "styles/charstyle.h"
29
#include "styles/paragraphstyle.h"
30
 
31
QString FileFormatName()
32
{
33
        return QObject::tr("MarkDown Document");
34
}
35
 
36
QStringList FileExtensions()
37
{
38
        return QStringList("md");
39
}
40
 
41
void GetText2(const QString& filename, const QString& encoding, bool textOnly, bool prefix, bool append, PageItem *textItem)
42
{
43
        MarkDownIm* markdownim = new MarkDownIm(filename, textItem, textOnly, prefix, append);
44
        delete markdownim;
45
}
46
 
47
MarkDownIm::MarkDownIm(const QString& fileName, PageItem *textItem, bool textOnly, bool prefix, bool append)
48
{
49
        m_Doc = textItem->doc();
50
        m_item = textItem;
51
        m_textOnly = textOnly;
52
        m_prefixName = prefix;
53
        m_append = append;
54
 
55
        QFile f(fileName);
56
        if (!f.open(QIODevice::ReadOnly))
57
                return;
58
 
59
        QByteArray data = f.readAll();
60
        f.close();
61
 
62
        m_importedText.setMarkdown(data, QTextDocument::MarkdownDialectGitHub);
63
        if (!append)
64
        {
65
                QString defaultParagraphStyle = CommonStrings::DefaultParagraphStyle;
66
                ParagraphStyle newStyle;
67
                newStyle.setDefaultStyle(false);
68
                newStyle.setParent(defaultParagraphStyle);
69
                m_item->itemText.clear();
70
                m_item->itemText.setDefaultStyle(newStyle);
71
        }
72
        parseMarkDown();
73
        m_item->itemText.trim();
74
        m_item->itemText.invalidateLayout();
75
}
76
 
77
void MarkDownIm::parseMarkDown()
78
{
79
        struct styleStruct
80
        {
81
                int start;
82
                int length;
83
                QString styleName;
84
        };
85
        QList<styleStruct> styleApplicationList;
86
 
87
        StyleSet<ParagraphStyle> newParaStyleSet;
88
        StyleSet<CharStyle> newCharStyleSet;
89
        defaultParagraphStyle.setParent(CommonStrings::DefaultParagraphStyle);
90
        defaultParagraphStyle.charStyle().setParent(CommonStrings::DefaultCharacterStyle);
91
        defaultParagraphStyle.setLineSpacingMode(ParagraphStyle::AutomaticLineSpacing);
92
        m_item->itemText.clear();
93
        m_item->itemText.setDefaultStyle(defaultParagraphStyle);
94
 
23996 craig 95
        int listStyleCount=1;
96
        int listCounter=1;
23992 craig 97
        int blockCount = m_importedText.blockCount();
23996 craig 98
        QString listStyleName;
23992 craig 99
        for (int i = 0; i < blockCount; i++)
100
        {
101
                QTextBlock curblk = m_importedText.findBlockByNumber(i);
102
                if (!curblk.isValid())
103
                        continue;
23996 craig 104
                QTextBlockFormat tbf = curblk.blockFormat();
23992 craig 105
                styleApplicationList.clear();
106
                currentParagraphStyle = defaultParagraphStyle;
107
                if (!m_textOnly)
108
                {
23996 craig 109
                        //Headings, find and then create styles
23992 craig 110
                        int headingLevel = curblk.blockFormat().headingLevel();
111
                        if (headingLevel > 0)
112
                        {
23996 craig 113
                                QString headingStyleName=QString("Heading %1").arg(headingLevel);
114
                                if (!newParaStyleSet.contains(headingStyleName))
23992 craig 115
                                {
116
                                        ParagraphStyle newParaStyle;
117
                                        newParaStyle.setParent(CommonStrings::DefaultParagraphStyle);
118
                                        newParaStyle.setLineSpacingMode(ParagraphStyle::AutomaticLineSpacing);
119
                                        newParaStyle.setContext(m_item->itemText.defaultStyle().context());
120
                                        newParaStyle.charStyle().setFontSize(20 * (7-headingLevel) + newParaStyle.charStyle().fontSize());
121
                                        QString styleName;
122
                                        if (m_prefixName)
123
                                                styleName=m_item->itemName() + "_";
23996 craig 124
                                        styleName+=headingStyleName;
23992 craig 125
                                        newParaStyle.setName(styleName);
126
                                        newParaStyleSet.create(newParaStyle);
127
                                        currentParagraphStyle = newParaStyle;
128
                                }
129
                                else
23996 craig 130
                                        currentParagraphStyle = newParaStyleSet.get(headingStyleName);
23992 craig 131
                        }
132
 
23996 craig 133
                        //List items
134
                        if (curblk.textList()!=nullptr)
135
                        {
136
                                QTextListFormat tlf = curblk.textList()->format();
137
                                if (listCounter==1)
138
                                {
139
                                        listStyleName=QString("List %1").arg(listStyleCount);
140
                                        if (tlf.style() == QTextListFormat::ListDecimal)
141
                                                listStyleName.prepend("Numbered ");
142
                                        if (!newParaStyleSet.contains(listStyleName))
143
                                        {
144
                                                listStyleCount++;
145
                                                ParagraphStyle newParaStyle;
146
                                                newParaStyle.setParent(CommonStrings::DefaultParagraphStyle);
147
                                                newParaStyle.setLineSpacingMode(ParagraphStyle::AutomaticLineSpacing);
148
                                                newParaStyle.setContext(m_item->itemText.defaultStyle().context());
149
                                                switch (tlf.style())
150
                                                {
151
                                                        case QTextListFormat::ListDisc:
152
                                                                newParaStyle.setBulletStr(QChar(0x2022));
153
                                                                newParaStyle.setHasBullet(true);
154
                                                                break;
155
                                                        case QTextListFormat::ListCircle:
156
                                                                newParaStyle.setBulletStr(QChar(0x2022));
157
                                                                newParaStyle.setHasBullet(true);
158
                                                                break;
159
                                                        case QTextListFormat::ListSquare:
160
                                                                newParaStyle.setBulletStr(QChar(0x25A0));
161
                                                                newParaStyle.setHasBullet(true);
162
                                                                break;
163
                                                        case QTextListFormat::ListDecimal:
164
                                                                newParaStyle.setHasNum(true);
165
                                                                break;
166
                                                        case QTextListFormat::ListLowerAlpha:
167
                                                        case QTextListFormat::ListUpperAlpha:
168
                                                        case QTextListFormat::ListLowerRoman:
169
                                                        case QTextListFormat::ListUpperRoman:
170
                                                        case QTextListFormat::ListStyleUndefined:
171
                                                                break;
172
                                                }
173
                                                QString styleName;
174
                                                if (m_prefixName)
175
                                                        styleName=m_item->itemName() + "_";
176
                                                styleName+=listStyleName;
177
                                                newParaStyle.setName(styleName);
178
                                                newParaStyleSet.create(newParaStyle);
179
                                                currentParagraphStyle = newParaStyle;
180
                                        }
181
                                }
182
                                else
183
                                        currentParagraphStyle = newParaStyleSet.get(listStyleName);
184
                                if (listCounter++==curblk.textList()->count())
185
                                        listCounter=1;
186
                        }
187
                        //Process all fragments of the text block to find different formats within. Create a structure
188
                        //of where and what style was applied
189
                        //Strikethrough
190
                        //Bold
191
                        //Italic
23992 craig 192
                        for (QTextBlock::iterator it = curblk.begin(); !(it.atEnd()); ++it)
193
                        {
194
                                QTextFragment currentFragment = it.fragment();
195
                                if (currentFragment.isValid())
196
                                {
197
                                        if (currentFragment.charFormat().isValid())
198
                                        {
199
                                                QTextCharFormat cf = currentFragment.charFormat();
200
                                                bool charFormatFound = false;
201
                                                CharStyle cs;
202
                                                cs.setParent(CommonStrings::DefaultCharacterStyle);
203
                                                cs.setContext(m_item->itemText.defaultStyle().context());
204
                                                QString styleName;
205
                                                if (m_prefixName)
206
                                                        styleName=m_item->itemName() + "_";
23996 craig 207
 
208
                                                //Strikethrough
23992 craig 209
                                                if (cf.fontStrikeOut())
210
                                                {
23996 craig 211
                                                        StyleFlag s(cs.effects());
23992 craig 212
                                                        charFormatFound = true;
213
                                                        styleName+="Strikethrough";
214
                                                        cs.setName(styleName);
215
                                                        s |= ScStyle_Strikethrough;
216
                                                        cs.setFeatures(s.featureList());
217
                                                }
23996 craig 218
 
23992 craig 219
                                                //Bold and Italic
220
                                                bool isBold = cf.fontWeight() == QFont::Bold;
221
                                                bool isItalic = cf.fontItalic();
222
                                                if ((isBold && headingLevel == 0) || isItalic)
223
                                                {
224
                                                        charFormatFound = true;
225
                                                        if (isBold)
226
                                                                styleName+="Bold";
227
                                                        if (isItalic)
228
                                                                styleName+="Italic";
229
                                                        cs.setName(styleName);
230
                                                        QString family(m_item->itemText.charStyle(m_item->itemText.length()).font().family());
231
                                                        if (!family.isEmpty())
232
                                                        {
233
                                                                QStringList slist = PrefsManager::instance().appPrefs.fontPrefs.AvailFonts.fontMap[family];
23996 craig 234
                                                                if (isBold && isItalic && slist.contains("Bold Italic"))
235
                                                                        cs.setFont(PrefsManager::instance().appPrefs.fontPrefs.AvailFonts[family + " Bold Italic"]);
236
                                                                if (isBold && !isItalic && slist.contains("Bold"))
237
                                                                        cs.setFont(PrefsManager::instance().appPrefs.fontPrefs.AvailFonts[family + " Bold"]);
238
                                                                if (!isBold && isItalic && slist.contains("Italic"))
239
                                                                        cs.setFont(PrefsManager::instance().appPrefs.fontPrefs.AvailFonts[family + " Italic"]);
240
//                                                              if (!isBold && !isItalic && slist.contains("Regular"))
241
//                                                                      cs.setFont(PrefsManager::instance().appPrefs.fontPrefs.AvailFonts[family + " Regular"]);
23992 craig 242
                                                        }
243
                                                }
23996 craig 244
 
245
 
246
                                                //If we found a character formatted then record the generated character style
23992 craig 247
                                                if (charFormatFound)
248
                                                {
249
                                                        newCharStyleSet.create(cs);
250
                                                        styleStruct ss;
251
                                                        ss.start = currentFragment.position();
252
                                                        ss.length = currentFragment.length();
253
                                                        ss.styleName = cs.name();
254
                                                        styleApplicationList.append(ss);
255
                                                }
256
                                        }
257
                                }
258
                        }
259
                }
23996 craig 260
                //Insert our text and a paragraph separator
23992 craig 261
                m_item->itemText.insertChars(m_item->itemText.length(), curblk.text());
262
                m_item->itemText.insertChars(m_item->itemText.length(), SpecialChars::PARSEP);
23996 craig 263
                //If we are not just inserting the text, apply a paragraph style and the character styles based on the positions we recorded earlier
23992 craig 264
                if (!m_textOnly)
265
                {
23996 craig 266
                        ParagraphStyle paraStyle;
267
                        paraStyle.setParent(currentParagraphStyle.name());
23992 craig 268
                        m_item->itemText.applyStyle(m_item->itemText.length() - 1, paraStyle);
269
                        for (int i = 0; i < styleApplicationList.size(); ++i)
270
                        {
271
                                CharStyle charStyle;
272
                                charStyle.setParent(styleApplicationList.at(i).styleName);
273
                                m_item->itemText.applyCharStyle(styleApplicationList.at(i).start, styleApplicationList.at(i).length, charStyle);
274
                        }
275
                }
276
        }
277
        if (!m_textOnly)
278
        {
279
                m_Doc->redefineStyles(newParaStyleSet, false);
280
                m_Doc->redefineCharStyles(newCharStyleSet, false);
281
        }
282
}
283
 
284