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     begin                : Jun 2005
9     copyright            : (C) 2005 by Craig Bradney
10     email                : cbradney@zip.com.au
11  ***************************************************************************/
12 
13 /***************************************************************************
14  *                                                                         *
15  *   This program is free software; you can redistribute it and/or modify  *
16  *   it under the terms of the GNU General Public License as published by  *
17  *   the Free Software Foundation; either version 2 of the License, or     *
18  *   (at your option) any later version.                                   *
19  *                                                                         *
20  ***************************************************************************/
21 #include "tocgenerator.h"
22 
23 #include <QMap>
24 #include <QString>
25 
26 #include "gtframestyle.h"
27 #include "gtparagraphstyle.h"
28 #include "gtwriter.h"
29 #include "pageitem.h"
30 #include "pageitemiterator.h"
31 #include "pagestructs.h"
32 #include "scpage.h"
33 #include "scribusdoc.h"
34 
TOCGenerator(QObject * parent,ScribusDoc * doc)35 TOCGenerator::TOCGenerator(QObject *parent, ScribusDoc *doc) : QObject(parent)
36 {
37 	m_doc = doc;
38 }
39 
setDoc(ScribusDoc * doc)40 void TOCGenerator::setDoc(ScribusDoc *doc)
41 {
42 	m_doc = doc;
43 }
44 
findTargetFrame(const QString & targetFrameName)45 PageItem* TOCGenerator::findTargetFrame(const QString &targetFrameName)
46 {
47 	PageItem* targetFrame=nullptr;
48 	if (m_doc != nullptr)
49 	{
50 		for (int d = 0; d < m_doc->DocItems.count(); ++d)
51 		{
52 			if (m_doc->DocItems.at(d) != nullptr)
53 			{
54 				if (m_doc->DocItems.at(d)->itemType()==PageItem::TextFrame && m_doc->DocItems.at(d)->itemName()==targetFrameName)
55 				{
56 					targetFrame=m_doc->DocItems.at(d);
57 					break;
58 				}
59 			}
60 		}
61 	}
62 	return targetFrame;
63 }
64 
generateDefault()65 void TOCGenerator::generateDefault()
66 {
67 	if (m_doc == nullptr)
68 		return;
69 	Q_ASSERT(!m_doc->masterPageMode());
70 
71 	const ToCSetupVector& topSetups = m_doc->tocSetups();
72 	for (auto tocSetupIt = topSetups.cbegin(); tocSetupIt != topSetups.cend(); ++tocSetupIt)
73 	{
74 		PageItem* tocFrame = findTargetFrame(tocSetupIt->frameName);
75 		if (tocFrame == nullptr)
76 			continue;
77 
78 		PageItem *currentDocItem;
79 		QMap<QString, QString> tocMap;
80 
81 		int *pageCounter = new int[m_doc->DocPages.count()];
82 		if (pageCounter == nullptr)
83 			return;
84 		int pageNumberWidth = QString("%1").arg(m_doc->DocPages.count()).length();
85 		for (int i = 0; i < m_doc->DocPages.count(); ++i)
86 			pageCounter[i] = 0;
87 
88 		for (PageItemIterator itemIter(m_doc->DocItems); *itemIter; ++itemIter)
89 		{
90 			currentDocItem = itemIter.current();
91 			if (currentDocItem == nullptr)
92 				continue;
93 			//Item not on a page, continue
94 			if (currentDocItem->OwnPage == -1)
95 				continue;
96 			//If we don't want to list non printing frames and this one is set to not print, continue
97 			if (!tocSetupIt->listNonPrintingFrames && !currentDocItem->printEnabled())
98 				continue;
99 
100 			ObjectAttribute objAttr;
101 			QList<ObjectAttribute> objAttrs = currentDocItem->getObjectAttributes(tocSetupIt->itemAttrName);
102 			if (objAttrs.count() <= 0)
103 				continue;
104 
105 			QString pageID = QString("%1").arg(currentDocItem->OwnPage + m_doc->FirstPnum, pageNumberWidth);
106 			QString sectionID = m_doc->getSectionPageNumberForPageIndex(currentDocItem->OwnPage);
107 
108 			for (int i = 0; i < objAttrs.count(); ++i)
109 			{
110 				objAttr = objAttrs.at(i);
111 				if (objAttr.name.isNull())
112 					continue;
113 
114 				//The key is generated to produce a sequence of numbers for the page numbers
115 				//First is the page of the item
116 				//Second is an incremented counter for the item so multiple per page works
117 				//Third is the section based page number which is actually used in the TOC.
118 				QString tocID = QString("%1").arg(pageCounter[currentDocItem->OwnPage]++, 3 , 10, QChar('0'));
119 				QString key = QString("%1,%2,%3").arg(pageID, tocID, sectionID);
120 				tocMap.insert(key, objAttr.value);
121 			}
122 		}
123 
124 		//Set up the gtWriter instance with the selected paragraph style
125 		gtWriter writer(false, tocFrame);
126 		writer.setUpdateParagraphStyles(false);
127 		writer.setOverridePStyleFont(false);
128 		gtFrameStyle* fstyle = writer.getDefaultStyle();
129 		gtParagraphStyle* pstyle = new gtParagraphStyle(*fstyle);
130 		pstyle->setName(tocSetupIt->textStyle);
131 		writer.setParagraphStyle(pstyle);
132 
133 		QString oldTocPage;
134 		for (QMap<QString, QString>::Iterator tocIt=tocMap.begin(); tocIt != tocMap.end();++tocIt)
135 		{
136 			QString tocPage(tocIt.key().section( ',', 2, 2 ).trimmed());
137 			QString tocLine;
138 			//Start with text or numbers
139 			if (tocSetupIt->pageLocation == End || tocSetupIt->pageLocation == NotShown)
140 				tocLine = tocIt.value();
141 			if (tocSetupIt->pageLocation == Beginning && oldTocPage != tocPage)
142 				tocLine = tocPage;
143 			//Add in the tab for the leaders
144 			tocLine += "\t";
145 			//End with text or numbers
146 			if (tocSetupIt->pageLocation == Beginning)
147 				tocLine += tocIt.value();
148 			if (tocSetupIt->pageLocation == End && oldTocPage != tocPage)
149 				tocLine += tocPage;
150 			tocLine += "\n";
151 			writer.append(tocLine);
152 		}
153 
154 		delete[] pageCounter;
155 	}
156 }
157