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 #include "tfdia.h"
8 
9 #include <QApplication>
10 #include <QComboBox>
11 #include <QDesktopWidget>
12 #include <QFrame>
13 #include <QLineEdit>
14 #include <QPushButton>
15 #include <QScrollArea>
16 #include <QBoxLayout>
17 #include <QHBoxLayout>
18 #include <QVBoxLayout>
19 #include <QToolTip>
20 #include <QPixmap>
21 #include <QRect>
22 
23 #include "prefsmanager.h"
24 #include "prefsfile.h"
25 #include <prefstable.h>
26 
27 #include "commonstrings.h"
28 #include "iconmanager.h"
29 #include "util.h"
30 
tfDia()31 tfDia::tfDia()
32 {
33 	setModal(true);
34 	setWindowIcon(QIcon(IconManager::instance().loadIcon("AppIcon.png")));
35 	setWindowTitle( tr("Create filter"));
36 	setMinimumWidth(524);
37 	prefs = PrefsManager::instance().prefsFile->getPluginContext("TextFilter");
38 
39 	//Get last window geometry values
40 	int vleft   = qMax(0, prefs->getInt("x", 10));
41 #if defined(Q_OS_MAC) || defined(_WIN32)
42 	int vtop    = qMax(64, prefs->getInt("y", 10));
43 #else
44 	int vtop    = qMax(0, prefs->getInt("y", 10));
45 #endif
46 	int vwidth  = qMax(400, prefs->getInt("width", 400));
47 	int vheight = qMax(300, prefs->getInt("height", 300));
48 	// Check values against current available space
49 	QRect scr = QApplication::desktop()->availableGeometry(this);
50 	if ( vleft >= scr.width() )
51 		vleft = 0;
52 	if ( vtop >= scr.height() )
53 		vtop = 64;
54 	if ( vwidth >= scr.width() )
55 		vwidth = qMax( 0, scr.width() - vleft );
56 	if ( vheight >= scr.height() )
57 		vheight = qMax( 0, scr.height() - vtop );
58 
59 	setGeometry(vleft, vtop, vwidth, vheight);
60    	createLayout();
61    	resize(width() + 10, height() + 10);
62 }
63 
createLayout()64 void tfDia::createLayout()
65 {
66 	currentFilter = "tf_lastUsed";
67 	currentIndex = 0;
68 
69 	layout = new QVBoxLayout(this);
70 	layout->setContentsMargins(9, 9, 9, 9);
71 	layout->setSpacing(6);
72 
73 	QBoxLayout* layout1 = new QHBoxLayout;
74 	layout1->setContentsMargins(0, 0, 0, 0);
75 	layout1->setSpacing(6);
76 	clearButton = new QPushButton( tr("C&lear"), this);
77 	layout1->addWidget(clearButton);
78 	layout1->addStretch(10);
79 	deleteButton = new QPushButton( tr("&Delete"), this);
80 	deleteButton->setEnabled(false);
81 	layout1->addWidget(deleteButton);
82 	filtersCombo = new QComboBox(this);
83 	filtersCombo->setMinimumSize(QSize(150, 0));
84 	filtersCombo->setEditable(false);
85 	filtersCombo->setDuplicatesEnabled(false);
86 	filtersCombo->setToolTip( tr("Choose a previously saved filter"));
87 	PrefsTable* filterNames = prefs->getTable("tf_Filters");
88 	filtersCombo->addItem("");
89 	for (int i = 0; i < filterNames->height(); ++i)
90 	{
91 		QString fname = filterNames->get(i, 0, "");
92 		fname = fname.right(fname.length() - 3);
93 		filtersCombo->addItem(fname);
94 	}
95 	layout1->addWidget(filtersCombo);
96 	layout->addLayout(layout1);
97 
98 	QBoxLayout* flayout = new QHBoxLayout;
99 	flayout->setContentsMargins(0, 0, 0, 0);
100 	flayout->setSpacing(6);
101 	QFrame* f = new QFrame(this);
102 	f->setFrameStyle(QFrame::HLine | QFrame::Sunken);
103 	flayout->addWidget(f);
104 	layout->addLayout(flayout);
105 
106 
107 	qsv = new QScrollArea(this);
108 	QVBoxLayout *a1layout = new QVBoxLayout;
109 	a1layout->setContentsMargins(0, 0, 0, 0);
110 	a1layout->setSpacing(6);
111 	vbox = new QFrame(this);
112 	vbox->setFixedWidth(qsv->viewport()->width());
113 	qsv->viewport()->resize(width() - 12, vbox->height());
114 	a1layout->addWidget(qsv);
115 	qsv->setWidget(vbox);
116 	layout->addLayout(a1layout);
117 
118 	alayout = new QVBoxLayout(vbox);
119 	alayout->setContentsMargins(9, 9, 9, 9);
120 	alayout->setSpacing(6);
121 
122 	createFilter(prefs->getTable("tf_lastUsed"));
123 	filters[0]->setRemovable((filters.size() >= 2));
124 
125 	QBoxLayout* flayout2 = new QHBoxLayout;
126 	flayout2->setContentsMargins(0, 0, 0, 0);
127 	flayout2->setSpacing(6);
128 	QFrame* f2 = new QFrame(this);
129 	f2->setFrameStyle(QFrame::HLine | QFrame::Sunken);
130 	flayout2->addWidget(f2);
131 	layout->addLayout(flayout2);
132 
133 	QBoxLayout* layout2 = new QHBoxLayout;
134 	layout2->setContentsMargins(0, 0, 0, 0);
135 	layout2->setSpacing(6);
136 	saveEdit = new QLineEdit(this);
137 	saveEdit->setToolTip( tr("Give a name to this filter for saving"));
138 	layout2->addWidget(saveEdit, 10);
139 	if (prefs->getBool("save_hint", true))
140 	{
141 		saveEdit->setText( tr("Give a name for saving"));
142 		prefs->set("save_hint", false);
143 	}
144 	layout2->addSpacing(20);
145 	okButton = new QPushButton(CommonStrings::tr_OK, this);
146 	layout2->addWidget(okButton, 0);
147 	cancelButton = new QPushButton(CommonStrings::tr_Cancel, this);
148 	layout2->addWidget(cancelButton, 0);
149 	layout->addLayout(layout2);
150 
151 
152 	connect(filtersCombo, SIGNAL(activated(const QString&)), this, SLOT(loadFilter(const QString&)));
153 	connect(clearButton, SIGNAL(clicked()), this, SLOT(clearClicked()));
154 	connect(deleteButton, SIGNAL(clicked()), this, SLOT(deleteClicked()));
155 	connect(okButton, SIGNAL(clicked()), this, SLOT(okClicked()));
156 	connect(cancelButton, SIGNAL(clicked()), this, SLOT(cancelClicked()));
157 	connect(saveEdit, SIGNAL(textChanged(const QString&)), this, SLOT(saveTextChanged(const QString&)));
158 }
159 
createFilterRow(tfFilter * after)160 void tfDia::createFilterRow(tfFilter* after)
161 {
162 	tfFilter* tmp = new tfFilter(vbox, "tfFilter");
163 	if (after == nullptr)
164 	{
165 		filters.push_back(tmp);
166 		alayout->addWidget(tmp);
167 	}
168 	else
169 	{
170 		std::vector<tfFilter*>::iterator it = filters.begin();
171 		uint i = 0;
172 		for (i= 0; i < filters.size(); ++i, ++it)
173 		{
174 			if (filters[i] == after)
175 			{
176 				++it;
177 				++i;
178 				break;
179 			}
180 		}
181 		filters.insert(it, tmp);
182 		alayout->insertWidget(static_cast<int>(i), tmp);
183 	}
184 	tmp->show();
185 	vbox->adjustSize();
186 	if (filters.size() == 2)
187 		filters[0]->setRemovable(true);
188 	else if (filters.size() == 1)
189 		filters[0]->setRemovable(false);
190 
191 	connect(tmp, SIGNAL(actionChanged(tfFilter*)), this, SLOT(adjustVBoxSize()));
192 	connect(tmp, SIGNAL(addClicked(tfFilter*)), this, SLOT(createFilterRow(tfFilter*)));
193 	connect(tmp, SIGNAL(removeClicked(tfFilter*)), SLOT(removeRow(tfFilter*)));
194 }
195 
createFilter(PrefsTable * table)196 void tfDia::createFilter(PrefsTable* table)
197 {
198 	if (table->width() != 10)
199 		createFilterRow(nullptr);
200 	else
201 	{
202 		for (uint i = 0; i < static_cast<uint>(table->height()); ++i)
203 		{
204 			tfFilter* tmp = new tfFilter(vbox, "tfFilter",
205 										 table->getInt(i, 0, 0),
206 										 table->get(i, 1, ""),
207 										 table->get(i, 2, ""),
208 										 table->get(i, 3, ""),
209 										 table->getInt(i, 4, 0),
210 										 table->getInt(i, 5, 0),
211 										 table->getInt(i, 6, 0),
212 										 table->getBool(i, 7, true),
213 										 table->getBool(i, 8, true),
214 										 table->getBool(i, 9, false));
215 			filters.push_back(tmp);
216 			alayout->addWidget(tmp);
217 			tmp->show();
218 			vbox->adjustSize();
219 			if (filters.size() == 2)
220 				filters[0]->setRemovable(true);
221 			connect(tmp, SIGNAL(actionChanged(tfFilter*)), this, SLOT(adjustVBoxSize()));
222 			connect(tmp, SIGNAL(addClicked(tfFilter*)), this, SLOT(createFilterRow(tfFilter*)));
223 			connect(tmp, SIGNAL(removeClicked(tfFilter*)), this, SLOT(removeRow(tfFilter*)));
224 		}
225 	}
226 }
227 
removeRow(tfFilter * tff)228 void tfDia::removeRow(tfFilter* tff)
229 {
230 	std::vector<tfFilter*>::iterator it = filters.begin();
231 	for (uint i = 0; i < filters.size(); ++i)
232 	{
233 		if (filters[i] == tff)
234 		{
235 			filters[i]->hide();
236 			delete filters[i];
237 			it = filters.erase(it);
238 		}
239 		else
240 		{
241 			++it;
242 		}
243 	}
244 	vbox->adjustSize();
245 	if (filters.size() == 1)
246 		filters[0]->setRemovable(false);
247 }
248 
adjustVBoxSize()249 void tfDia::adjustVBoxSize()
250 {
251 	vbox->adjustSize();
252 }
253 
saveTextChanged(const QString & text)254 void tfDia::saveTextChanged(const QString& text)
255 {
256 	setCurrentComboItem(filtersCombo, text);
257 }
258 
clearClicked()259 void tfDia::clearClicked()
260 {
261 	clear();
262 	createFilterRow(nullptr);
263 }
264 
clear()265 void tfDia::clear()
266 {
267 	for (uint i = 0; i < filters.size(); ++i)
268 	{
269 		filters[i]->hide();
270 		delete filters[i];
271 	}
272 	filters.clear();
273 }
274 
okClicked()275 void tfDia::okClicked()
276 {
277 	storeLastFilter();
278 	if ((!saveEdit->text().isEmpty()) && (saveEdit->text() != tr("Give a name to this filter for saving")))
279 	{
280 		PrefsTable* savedFilters = prefs->getTable("tf_Filters");
281 		if (savedFilters->find(0, QString("tf_" + saveEdit->text())) == -1)
282 			savedFilters->set(savedFilters->height(), 0, QString("tf_" + saveEdit->text()));
283 		prefs->removeTable("tf_" + saveEdit->text());
284 		PrefsTable* newFilter = prefs->getTable("tf_" + saveEdit->text());
285 		for (uint i = 0; i < filters.size(); ++i)
286 		{
287 			writeFilterRow(newFilter, i, filters[i]);
288 		}
289 	}
290 	accept();
291 }
292 
cancelClicked()293 void tfDia::cancelClicked()
294 {
295 	storeLastFilter();
296 	reject();
297 }
298 
writeFilterRow(PrefsTable * table,int row,tfFilter * filter)299 void tfDia::writeFilterRow(PrefsTable* table, int row, tfFilter* filter)
300 {
301 	table->set(row, 0, filter->getAction());
302 	table->set(row, 1, filter->regExp());
303 	table->set(row, 2, filter->replaceWith());
304 	table->set(row, 3, filter->getPStyleName());
305 	table->set(row, 4, filter->getLessThan());
306 	table->set(row, 5, filter->getMoreThan());
307 	table->set(row, 6, filter->getStyle());
308 	table->set(row, 7, filter->removeMatch());
309 	table->set(row, 8, filter->isEnabled());
310 	table->set(row, 9, filter->isRegExp());
311 }
312 
loadFilter(const QString & name)313 void tfDia::loadFilter(const QString& name)
314 {
315 	if (currentFilter == "tf_lastUsed")
316 		storeLastFilter();
317 	if (filtersCombo->currentIndex() == 0)
318 	{
319 		deleteButton->setEnabled(false);
320 		clear();
321 		createFilter(prefs->getTable("tf_lastUsed"));
322 		currentFilter = "tf_lastUsed";
323 		currentIndex = 0;
324 	}
325 	else if (prefs->containsTable("tf_" + name))
326 	{
327 		deleteButton->setEnabled(true);
328 		clear();
329 		createFilter(prefs->getTable("tf_"+name));
330 		currentFilter = "tf_" + name;
331 		currentIndex = filtersCombo->currentIndex();
332 	}
333 	saveEdit->setText(name);
334 }
335 
deleteClicked()336 void tfDia::deleteClicked()
337 {
338 	if (currentIndex != 0)
339 	{
340 		PrefsTable* t = prefs->getTable("tf_Filters");
341 		t->removeRow(0, currentFilter);
342 		prefs->removeTable(currentFilter);
343 		filtersCombo->removeItem(currentIndex);
344 		filtersCombo->setCurrentIndex(0);
345 		clear();
346 		saveEdit->setText("");
347 		deleteButton->setEnabled(false);
348 		createFilter(prefs->getTable("tf_lastUsed"));
349 		currentIndex = 0;
350 		currentFilter = "tf_lastUsed";
351 	}
352 }
353 
storeLastFilter()354 void tfDia::storeLastFilter()
355 {
356 	prefs->removeTable("tf_lastUsed");
357 	PrefsTable* lastUsed = prefs->getTable("tf_lastUsed");
358 	for (uint i = 0; i < filters.size(); ++i)
359 	{
360 		writeFilterRow(lastUsed, i, filters[i]);
361 	}
362 }
363 
resizeEvent(QResizeEvent *)364 void tfDia::resizeEvent(QResizeEvent*)
365 {
366 	vbox->setFixedWidth(qsv->viewport()->width());
367 }
368 
~tfDia()369 tfDia::~tfDia()
370 {
371 	for (uint i = 0; i < filters.size(); ++i)
372 		delete filters[i];
373 	QRect r = geometry();
374 	prefs->set("x", r.x());
375 	prefs->set("y", r.y());
376 	prefs->set("width", width());
377 	prefs->set("height", height());
378 }
379