1 /** Copyright (C) 2010, J.M.Reneau
2  **
3  **  This program is free software; you can redistribute it and/or modify
4  **  it under the terms of the GNU General Public License as published by
5  **  the Free Software Foundation; either version 2 of the License, or
6  **  (at your option) any later version.
7  **
8  **  This program is distributed in the hope that it will be useful,
9  **  but WITHOUT ANY WARRANTY; without even the implied warranty of
10  **  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
11  **  GNU General Public License for more details.
12  **
13  **  You should have received a copy of the GNU General Public License along
14  **  with this program; if not, write to the Free Software Foundation, Inc.,
15  **  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
16  **/
17 
18 #include <iostream>
19 
20 
21 
22 #include "PreferencesWin.h"
23 #include "Settings.h"
24 #include "MainWindow.h"
25 #include "md5.h"
26 
27 #ifdef ESPEAK
28 	#include <speak_lib.h>
29 #endif
30 
PreferencesWin(QWidget * parent,bool showAdvanced)31 PreferencesWin::PreferencesWin (QWidget * parent, bool showAdvanced)
32 	:QDialog(parent) {
33 
34 	settingsbrowser = NULL;
35 
36 	int r=0, i;
37 	SETTINGS;
38 
39 	// *******************************************************************************************
40 	// build the advanced tab
41 	if (showAdvanced) {
42 		advancedtablayout = new QGridLayout(this);
43 		advancedtabwidget = new QWidget(this);
44 		advancedtabwidget->setLayout(advancedtablayout);
45 		r=0;
46 		//
47 		passwordlabel = new QLabel(tr("Advanced Preferences Password:"),this);
48 		passwordinput = new QLineEdit(QString(),this);
49 		passwordinput->setText(settings.value(SETTINGSPREFPASSWORD, "").toString());
50 		passwordinput->setMaxLength(32);
51 		passwordinput->setEchoMode(QLineEdit::Password);
52 		advancedtablayout->addWidget(passwordlabel,r,1,1,1);
53 		advancedtablayout->addWidget(passwordinput,r,2,1,2);
54 		//
55 		r++;
56 		allowsystemlabel = new QLabel(tr("Allow SYSTEM statement:"), this);
57 		advancedtablayout->addWidget(allowsystemlabel,r,1,1,1);
58 		allowsystemcombo = new QComboBox(this);
59 		//allowsystemcombo->addItem(tr("Ignore"), -1);
60 		allowsystemcombo->addItem(tr("Do not allow"), 0);
61 		allowsystemcombo->addItem(tr("Ask confirmation from user"), 1);
62 		allowsystemcombo->addItem(tr("Allow"), 2);
63 		int s = settings.value(SETTINGSALLOWSYSTEM, SETTINGSALLOWSYSTEMDEFAULT).toInt();
64 		int system = allowsystemcombo->findData(s);
65 		if (system != -1) allowsystemcombo->setCurrentIndex(system);
66 		advancedtablayout->addWidget(allowsystemcombo,r,2,1,2);
67 		//
68 #ifdef WIN32
69 #ifndef WIN32PORTABLE
70 		r++;
71 		allowportlabel = new QLabel(tr("Allow PORTIN/PORTOUT statements:"), this);
72 		advancedtablayout->addWidget(allowportlabel,r,1,1,1);
73 		allowportcombo = new QComboBox(this);
74 		//allowportcombo->addItem(tr("Ignore"), -1);
75 		allowportcombo->addItem(tr("Do not allow"), 0);
76 		allowportcombo->addItem(tr("Ask confirmation from user"), 1);
77 		allowportcombo->addItem(tr("Allow"), 2);
78 		int p = settings.value(SETTINGSALLOWPORT, SETTINGSALLOWPORTDEFAULT).toInt();
79 		int port = allowportcombo->findData(p);
80 		if (port != -1) allowportcombo->setCurrentIndex(port);
81 		advancedtablayout->addWidget(allowportcombo,r,2,1,2);
82 #endif
83 #endif
84 		//
85 		/*
86 		r++;
87 		QFrame *separator = new QFrame;
88 		separator->setFrameShape(QFrame::HLine);
89 		separator->setFrameShadow(QFrame::Sunken);
90 		advancedtablayout->addWidget(separator,r,1,1,3);
91 		*/
92 		//
93 		r++;
94 		settingsaccesslabel = new QLabel(tr("GETSETTING/SETSETTING access level:"), this);
95 		advancedtablayout->addWidget(settingsaccesslabel,r,1,1,1);
96 		settingsaccesscombo = new QComboBox(this);
97 		settingsaccesscombo->addItem(tr("Get / set only owned settings"), 0);
98 		settingsaccesscombo->addItem(tr("Get any settings / set only owned settings"), 1);
99 		settingsaccesscombo->addItem(tr("Full access (get/set) to settings"), 2);
100 		int l = settings.value(SETTINGSSETTINGSACCESS, SETTINGSSETTINGSACCESSDEFAULT).toInt();
101 		int index = settingsaccesscombo->findData(l);
102 		if (index != -1) settingsaccesscombo->setCurrentIndex(index);
103 		advancedtablayout->addWidget(settingsaccesscombo,r,2,1,2);
104 		//
105 		r++;
106 		settingcheckbox = new QCheckBox(tr("Allow programs to use persistent settings (SETSETTING statement)"),this);
107 		settingcheckbox->setChecked(settings.value(SETTINGSALLOWSETTING, SETTINGSALLOWSETTINGDEFAULT).toBool());
108 		advancedtablayout->addWidget(settingcheckbox,r,2,1,2);
109 		//
110 		r++;
111 		browsesaveddata = new QPushButton(tr("Browse persistent settings"), this);
112 		connect(browsesaveddata, SIGNAL(clicked()), this, SLOT (clickBrowseSavedData()));
113 		advancedtablayout->addWidget(browsesaveddata,r,2,1,1);
114 		clearsaveddata = new QPushButton(tr("Clear all persistent settings"), this);
115 		connect(clearsaveddata, SIGNAL(clicked()), this, SLOT (clickClearSavedData()));
116 		advancedtablayout->addWidget(clearsaveddata,r,3,1,1);
117 		//
118 		r++;
119 		settingsmaxlabel = new QLabel(tr("Max number of settings for each program:"), this);
120 		advancedtablayout->addWidget(settingsmaxlabel,r,1,1,1);
121 		settingsmaxcombo = new QComboBox(this);
122 		settingsmaxcombo->addItem(tr("No limit"), 0);
123 		settingsmaxcombo->addItem(tr("50 keys"), 50);
124 		settingsmaxcombo->addItem(tr("100 keys"), 100);
125 		settingsmaxcombo->addItem(tr("200 keys"), 200);
126 		int m = settings.value(SETTINGSSETTINGSMAX, SETTINGSSETTINGSMAXDEFAULT).toInt();
127 		int max = settingsmaxcombo->findData(m);
128 		if (max != -1) settingsmaxcombo->setCurrentIndex(max);
129 		advancedtablayout->addWidget(settingsmaxcombo,r,2,1,2);
130 
131 	}
132 
133 
134 	// *******************************************************************************************
135 	// build the user tab
136 	usertablayout = new QGridLayout(this);
137 	usertabwidget = new QWidget(this);
138 	usertabwidget->setLayout(usertablayout);
139 	r=0;
140 	// Startup - restore last windows position on start or check for update
141 	r++;
142 	startuplabel = new QLabel(tr("Startup"),this);
143 	usertablayout->addWidget(startuplabel,r,1,1,1);
144 	windowsrestorecheckbox = new QCheckBox(tr("Restore last windows position on start"),this);
145 	windowsrestorecheckbox->setChecked(settings.value(SETTINGSWINDOWSRESTORE, SETTINGSWINDOWSRESTOREDEFAULT).toBool());
146 	usertablayout->addWidget(windowsrestorecheckbox,r,2,1,1);
147 	r++;
148 	checkupdatecheckbox = new QCheckBox(tr("Check for an update on start"),this);
149 	checkupdatecheckbox->setChecked(settings.value(SETTINGSCHECKFORUPDATE, SETTINGSCHECKFORUPDATEDEFAULT).toBool());
150 	usertablayout->addWidget(checkupdatecheckbox,r,2,1,2);
151 	//
152 	r++;
153 	{
154 		int settypeconv;
155 		typeconvlabel = new QLabel(tr("Runtime handling of bad type conversions:"), this);
156 		usertablayout->addWidget(typeconvlabel,r,1,1,1);
157 		typeconvcombo = new QComboBox(this);
158 		typeconvcombo->addItem(tr("Ignore"), SETTINGSERRORNONE);
159 		typeconvcombo->addItem(tr("Warn"), SETTINGSERRORWARN);
160 		typeconvcombo->addItem(tr("Error"), SETTINGSERROR);
161 		// set setting and select
162 		settypeconv = settings.value(SETTINGSTYPECONV, SETTINGSTYPECONVDEFAULT).toInt();
163 		int index = typeconvcombo->findData(settypeconv);
164 		if ( index != -1 ) { // -1 for not found
165 			typeconvcombo->setCurrentIndex(index);
166 		}
167 		// add to layout
168 		usertablayout->addWidget(typeconvcombo,r,2,1,2);
169 	}
170 	//
171 	r++;
172 	{
173 		int setvarnotassigned;
174 		varnotassignedlabel = new QLabel(tr("Runtime handling of unassigned variables:"), this);
175 		usertablayout->addWidget(varnotassignedlabel,r,1,1,1);
176 		varnotassignedcombo = new QComboBox(this);
177 		varnotassignedcombo->addItem(tr("Ignore"), SETTINGSERRORNONE);
178 		varnotassignedcombo->addItem(tr("Warn"), SETTINGSERRORWARN);
179 		varnotassignedcombo->addItem(tr("Error"), SETTINGSERROR);
180 		// set setting and select
181 		setvarnotassigned = settings.value(SETTINGSVARNOTASSIGNED, SETTINGSVARNOTASSIGNEDDEFAULT).toInt();
182 		int index = varnotassignedcombo->findData(setvarnotassigned);
183 		if ( index != -1 ) { // -1 for not found
184 			varnotassignedcombo->setCurrentIndex(index);
185 		}
186 		// add to layout
187 		usertablayout->addWidget(varnotassignedcombo,r,2,1,2);
188 	}
189 	//
190 	r++;
191 	saveonruncheckbox = new QCheckBox(tr("Automatically save program when it is successfully run"),this);
192 	saveonruncheckbox->setChecked(settings.value(SETTINGSIDESAVEONRUN, SETTINGSIDESAVEONRUNDEFAULT).toBool());
193 	usertablayout->addWidget(saveonruncheckbox,r,2,1,2);
194 	//
195 	// decimal digits slider
196 	r++;
197 	decdigslabel = new QLabel(tr("Number of digits to print numbers:"),this);
198 	decdigsvalue = new QLabel("",this);
199 	QHBoxLayout * decdigslabellayout = new QHBoxLayout();
200 	decdigslabellayout->addWidget(decdigslabel);
201 	decdigslabellayout->addWidget(decdigsvalue);
202 	decdigslabellayout->addStretch();
203 
204 	decdigsslider = new QSlider(Qt::Horizontal, this);
205 	decdigsslider->setMinimum(SETTINGSDECDIGSMIN);
206 	decdigsslider->setMaximum(SETTINGSDECDIGSMAX);
207 	decdigsslider->setSingleStep(1);
208 	decdigsslider->setPageStep(1);
209 	QLabel *decdigsbefore = new QLabel(QString::number(SETTINGSDECDIGSMIN),this);
210 	QLabel *decdigsafter = new QLabel(QString::number(SETTINGSDECDIGSMAX),this);
211 	connect(decdigsslider, SIGNAL(valueChanged(int)), this, SLOT(setDigitsValue(int)));
212 	QHBoxLayout * decdigssliderlayout = new QHBoxLayout();
213 	decdigssliderlayout->addWidget(decdigsbefore);
214 	decdigssliderlayout->addWidget(decdigsslider);
215 	decdigssliderlayout->addWidget(decdigsafter);
216 	usertablayout->addLayout(decdigslabellayout,r,1,1,1);
217 	usertablayout->addLayout(decdigssliderlayout,r,2,1,2);
218 	i = settings.value(SETTINGSDECDIGS, SETTINGSDECDIGSDEFAULT).toInt();
219 	decdigsslider->setValue(i);
220 	setDigitsValue(i);
221 	decdigsvalue->setText(decdigsvalue->text() + "        "); //ensure space for label to grow without resizing window
222 	// show trailing .0 on floatingpoint numbers (python style numbers)
223 	r++;
224 	floatlocalecheckbox = new QCheckBox(tr("Use localized decimal point on floating point numbers"),this);
225 	floatlocalecheckbox->setChecked(settings.value(SETTINGSFLOATLOCALE, SETTINGSFLOATLOCALEDEFAULT).toBool());
226 	usertablayout->addWidget(floatlocalecheckbox,r,2,1,2);
227 	r++;
228 	floattailcheckbox = new QCheckBox(tr("Always show decimal point on floating point numbers"),this);
229 	floattailcheckbox->setChecked(settings.value(SETTINGSFLOATTAIL, SETTINGSFLOATTAILDEFAULT).toBool());
230 	usertablayout->addWidget(floattailcheckbox,r,2,1,2);
231 
232 	//
233 	// speed of next statement in run to breakpoint
234 	r++;
235 	debugspeedlabel = new QLabel(tr("Debugging Speed:"),this);
236 	debugspeedvalue = new QLabel("",this);
237 	QHBoxLayout * debugspeedlabellayout = new QHBoxLayout();
238 	debugspeedlabellayout->addWidget(debugspeedlabel);
239 	debugspeedlabellayout->addWidget(debugspeedvalue);
240 	debugspeedlabellayout->addStretch();
241 
242 	debugspeedslider = new QSlider(Qt::Horizontal, this);
243 	debugspeedslider->setMinimum(SETTINGSDEBUGSPEEDMIN);
244 	debugspeedslider->setMaximum(SETTINGSDEBUGSPEEDMAX);
245 	QLabel *debugspeedbefore = new QLabel(tr("Fast"),this);
246 	QLabel *debugspeedafter = new QLabel(tr("Slow"),this);
247 	connect(debugspeedslider, SIGNAL(valueChanged(int)), this, SLOT(setDebugSpeedValue(int)));
248 	QHBoxLayout * debugspeedsliderlayout = new QHBoxLayout();
249 	debugspeedsliderlayout->addWidget(debugspeedbefore);
250 	debugspeedsliderlayout->addWidget(debugspeedslider);
251 	debugspeedsliderlayout->addWidget(debugspeedafter);
252 	usertablayout->addLayout(debugspeedlabellayout,r,1,1,1);
253 	usertablayout->addLayout(debugspeedsliderlayout,r,2,1,2);
254 	i = settings.value(SETTINGSDEBUGSPEED, SETTINGSDEBUGSPEEDDEFAULT).toInt();
255 	debugspeedslider->setValue(i);
256 	setDebugSpeedValue(i);
257 	debugspeedvalue->setText(debugspeedvalue->text() + "        "); //ensure space for label to grow without resizing window
258 
259 	//
260 	// *******************************************************************************************
261 	// build the sound tab
262 	soundtablayout = new QGridLayout();
263 	soundtabwidget = new QWidget(this);
264 	soundtabwidget->setLayout(soundtablayout);
265 	r=0;
266 
267 
268 
269 
270 	// sound volume slider
271 	r++;
272 	soundvolumelabel = new QLabel(tr("Volume:"),this);
273 	soundvolumevalue = new QLabel("",this);
274 	QHBoxLayout * soundvolumelabellayout = new QHBoxLayout();
275 	soundvolumelabellayout->addWidget(soundvolumelabel);
276 	soundvolumelabellayout->addWidget(soundvolumevalue);
277 	soundvolumelabellayout->addStretch();
278 	soundvolumeslider = new QSlider(Qt::Horizontal,this);
279 	soundvolumeslider->setMinimum(SETTINGSSOUNDVOLUMEMIN);
280 	soundvolumeslider->setMaximum(SETTINGSSOUNDVOLUMEMAX);
281 	soundvolumeslider->setSingleStep(1);
282 	soundvolumeslider->setPageStep(1);
283 	QLabel *soundvolumebefore = new QLabel(QString::number(SETTINGSSOUNDVOLUMEMIN),this);
284 	QLabel *soundvolumeafter = new QLabel(QString::number(SETTINGSSOUNDVOLUMEMAX),this);
285 	connect(soundvolumeslider, SIGNAL(valueChanged(int)), this, SLOT(setVolumeValue(int)));
286 	QHBoxLayout * soundvolumesliderlayout = new QHBoxLayout();
287 	soundvolumesliderlayout->addWidget(soundvolumebefore);
288 	soundvolumesliderlayout->addWidget(soundvolumeslider);
289 	soundvolumesliderlayout->addWidget(soundvolumeafter);
290 	soundtablayout->addLayout(soundvolumelabellayout,r,1,1,1);
291 	soundtablayout->addLayout(soundvolumesliderlayout,r,2,1,2);
292 	i = settings.value(SETTINGSSOUNDVOLUME, SETTINGSSOUNDVOLUMEDEFAULT).toInt();
293 	soundvolumeslider->setValue(i);
294 	setVolumeValue(i);
295 	soundvolumevalue->setText(soundvolumevalue->text() + "        "); //ensure space for label to grow without resizing window
296 
297 
298 
299 	// sample rate
300 	r++;
301 	{
302 		int setsoundsamplerate;
303 		soundsampleratelabel = new QLabel(tr("Sound sample rate:"),this);
304 		soundtablayout->addWidget(soundsampleratelabel,r,1,1,1);
305 		soundsampleratecombo = new QComboBox(this);
306 		soundsampleratecombo->addItem(tr("44100 Hz"), 44100);
307 		soundsampleratecombo->addItem(tr("32000 Hz"), 32000);
308 		soundsampleratecombo->addItem(tr("22050 Hz"), 22050);
309 		soundsampleratecombo->addItem(tr("16000 Hz"), 16000);
310 		soundsampleratecombo->addItem(tr("11025 Hz"), 11025);
311 		soundsampleratecombo->addItem(tr("8000 Hz"), 8000);
312 		soundsampleratecombo->addItem(tr("4400 Hz"), 4400);
313 		// set setting and select
314 		setsoundsamplerate = settings.value(SETTINGSSOUNDSAMPLERATE, SETTINGSSOUNDSAMPLERATEDEFAULT).toInt();
315 		int index = soundsampleratecombo->findData(setsoundsamplerate);
316 		if ( index != -1 ) { // -1 for not found
317 			soundsampleratecombo->setCurrentIndex(index);
318 		}
319 		// add to layout
320 		soundtablayout->addWidget(soundsampleratecombo,r,2,1,2);
321 	}
322 
323 
324 
325 	// sound normalize slider
326 	r++;
327 	soundnormalizelabel = new QLabel(tr("Min. period to normalize louder sounds:"),this);
328 	soundnormalizevalue = new QLabel("",this);
329 	QHBoxLayout * soundnormalizelabellayout = new QHBoxLayout();
330 	soundnormalizelabellayout->addWidget(soundnormalizelabel);
331 	soundnormalizelabellayout->addWidget(soundnormalizevalue);
332 	soundnormalizelabellayout->addStretch();
333 	soundnormalizeslider = new QSlider(Qt::Horizontal, this);
334 	soundnormalizeslider->setMinimum(SETTINGSSOUNDNORMALIZEMIN/10);
335 	soundnormalizeslider->setMaximum(SETTINGSSOUNDNORMALIZEMAX/10);
336 	soundnormalizeslider->setSingleStep(1);
337 	soundnormalizeslider->setPageStep(10);
338 	QLabel *soundnormalizebefore = new QLabel(QString::number(SETTINGSSOUNDNORMALIZEMIN),this);
339 	QLabel *soundnormalizeafter = new QLabel(QString::number(SETTINGSSOUNDNORMALIZEMAX),this);
340 	connect(soundnormalizeslider, SIGNAL(valueChanged(int)), this, SLOT(setNormalizeValue(int)));
341 	QHBoxLayout * soundnormalizesliderlayout = new QHBoxLayout();
342 	soundnormalizesliderlayout->addWidget(soundnormalizebefore);
343 	soundnormalizesliderlayout->addWidget(soundnormalizeslider);
344 	soundnormalizesliderlayout->addWidget(soundnormalizeafter);
345 	soundtablayout->addLayout(soundnormalizelabellayout,r,1,1,1);
346 	soundtablayout->addLayout(soundnormalizesliderlayout,r,2,1,2);
347 	i = settings.value(SETTINGSSOUNDNORMALIZE, SETTINGSSOUNDNORMALIZEDEFAULT).toInt()/10;
348 	soundnormalizeslider->setValue(i);
349 	setNormalizeValue(i);
350 	soundnormalizevalue->setText(soundnormalizevalue->text() + "        "); //ensure space for label to grow without resizing window
351 
352 
353 
354 
355 
356 
357 	// sound volume restore slider
358 	r++;
359 	soundvolumerestorelabel = new QLabel(tr("Period to restore volume after louder sound:"),this);
360 	soundvolumerestorevalue = new QLabel("",this);
361 	QHBoxLayout * soundvolumerestorelabellayout = new QHBoxLayout();
362 	soundvolumerestorelabellayout->addWidget(soundvolumerestorelabel);
363 	soundvolumerestorelabellayout->addWidget(soundvolumerestorevalue);
364 	soundvolumerestorelabellayout->addStretch();
365 	soundvolumerestoreslider = new QSlider(Qt::Horizontal,this);
366 	soundvolumerestoreslider->setMinimum(SETTINGSSOUNDVOLUMERESTOREMIN/10);
367 	soundvolumerestoreslider->setMaximum(SETTINGSSOUNDVOLUMERESTOREMAX/10);
368 	soundvolumerestoreslider->setSingleStep(1);
369 	soundvolumerestoreslider->setPageStep(10);
370 	QLabel *soundvolumerestorebefore = new QLabel(QString::number(SETTINGSSOUNDVOLUMERESTOREMIN),this);
371 	QLabel *soundvolumerestoreafter = new QLabel(QString::number(SETTINGSSOUNDVOLUMERESTOREMAX),this);
372 	connect(soundvolumerestoreslider, SIGNAL(valueChanged(int)), this, SLOT(setVolumeRestoreValue(int)));
373 	QHBoxLayout * soundvolumerestoresliderlayout = new QHBoxLayout();
374 	soundvolumerestoresliderlayout->addWidget(soundvolumerestorebefore);
375 	soundvolumerestoresliderlayout->addWidget(soundvolumerestoreslider);
376 	soundvolumerestoresliderlayout->addWidget(soundvolumerestoreafter);
377 	soundtablayout->addLayout(soundvolumerestorelabellayout,r,1,1,1);
378 	soundtablayout->addLayout(soundvolumerestoresliderlayout,r,2,1,2);
379 	i = settings.value(SETTINGSSOUNDVOLUMERESTORE, SETTINGSSOUNDVOLUMERESTOREDEFAULT).toInt()/10;
380 	soundvolumerestoreslider->setValue(i);
381 	setVolumeRestoreValue(i);
382 	soundvolumerestorevalue->setText(soundvolumerestorevalue->text() + "        "); //ensure space for label to grow without resizing wind
383 
384 
385 #ifdef ESPEAK
386 	r++;
387 	{
388 #ifdef WIN32
389 		// use program install folder
390 		espeak_Initialize(AUDIO_OUTPUT_SYNCH_PLAYBACK,0,(char *) QFileInfo(QCoreApplication::applicationFilePath()).absolutePath().toUtf8().data(),0);
391 #else
392 		// use default path for espeak-data
393 		espeak_Initialize(AUDIO_OUTPUT_SYNCH_PLAYBACK,0,NULL,0);
394 #endif
395 
396 		QString setvoice;
397 		voicelabel = new QLabel(tr("SAY Voice:"),this);
398 		soundtablayout->addWidget(voicelabel,r,1,1,1);
399 		voicecombo = new QComboBox(this);
400 
401 		const espeak_VOICE **voices;
402 		voices = espeak_ListVoices(NULL);
403 
404 		voicecombo->addItem(QString("default"),	QString("default"));
405 		for(int i=0; voices[i] != NULL; i++) {
406 			QString name = voices[i]->name;
407 			QString lang = (voices[i]->languages + 1);
408 			voicecombo->addItem( lang + " (" + name + ")",	name);
409 		}
410 
411 		// set setting and select
412 		setvoice = settings.value(SETTINGSESPEAKVOICE, SETTINGSESPEAKVOICEDEFAULT).toString();
413 		int index = voicecombo->findData(setvoice);
414 		if ( index != -1 ) { // -1 for not found
415 			voicecombo->setCurrentIndex(index);
416 		}
417 		// add to layout
418 		soundtablayout->addWidget(voicecombo,r,2,1,2);
419 	}
420 #endif
421 
422 #ifdef ESPEAK_EXECUTE
423 	r++;
424 	{
425 		// set statement to speak words
426 		speakstmtlabel = new QLabel(tr("PDF File Name:"),this);
427 		speakstmtinput = new QLineEdit(QString(),this);
428 		speakstmtinput->setText(settings.value(SETTINGSESPEAKSTATEMENT, SETTINGSESPEAKSTATEMENTDEFAULT).toString());
429 		speakstmtinput->setMaxLength(96);
430 		soundtablayout->addWidget(speakstmtlabel,r,1,1,1);
431 		soundtablayout->addWidget(speakstmtinput,r,2,1,2);
432 	}
433 #endif
434 
435 	// *******************************************************************************************
436 	// build the printer tab
437 	printertablayout = new QGridLayout();
438 	printertabwidget = new QWidget(this);
439 	printertabwidget->setLayout(printertablayout);
440 	r=0;
441 	{
442 		int dflt = -1;
443 		int setprinter;
444 		printerslabel = new QLabel(tr("Printer:"),this);
445 		printertablayout->addWidget(printerslabel,r,1,1,1);
446 		printerscombo = new QComboBox(this);
447 		// build list of printers
448 		QList<QPrinterInfo> printerList=QPrinterInfo::availablePrinters();
449 		for (int i=0; i< printerList.count(); i++) {
450 			printerscombo->addItem(printerList[i].printerName(),i);
451 			if (printerList[i].isDefault()) dflt = i;
452 		}
453 		printerscombo->addItem(tr("PDF File Output"),-1);
454 		// set setting and select
455 		setprinter = settings.value(SETTINGSPRINTERPRINTER, dflt).toInt();
456 		if (setprinter<-1||setprinter>=printerList.count()) setprinter = dflt;
457 		int index = printerscombo->findData(setprinter);
458 		if ( index != -1 ) { // -1 for not found
459 			printerscombo->setCurrentIndex(index);
460 		}
461 		// add to layout
462 		printertablayout->addWidget(printerscombo,r,2,1,2);
463 	}
464 	//
465 	r++;
466 	{
467 		int setpaper;
468 		paperlabel = new QLabel(tr("Paper:"),this);
469 		printertablayout->addWidget(paperlabel,r,1,1,1);
470 		papercombo = new QComboBox(this);
471 		papercombo->addItem("A0 (841 x 1189 mm)",	QPrinter::A0);
472 		papercombo->addItem("A1 (594 x 841 mm)", QPrinter::A1);
473 		papercombo->addItem("A2 (420 x 594 mm", QPrinter::A2);
474 		papercombo->addItem("A3 (297 x 420 mm", QPrinter::A3);
475 		papercombo->addItem("A4 (210 x 297 mm, 8.26 x 11.69 inches", QPrinter::A4);
476 		papercombo->addItem("A5 (148 x 210 mm", QPrinter::A5);
477 		papercombo->addItem("A6 (105 x 148 mm", QPrinter::A6);
478 		papercombo->addItem("A7 (74 x 105 mm", QPrinter::A7);
479 		papercombo->addItem("A9 (52 x 74 mm", QPrinter::A8);
480 		papercombo->addItem("A9 (37 x 52 mm", QPrinter::A9);
481 		papercombo->addItem("B0 (1000 x 1414 mm", QPrinter::B0);
482 		papercombo->addItem("B1 (707 x 1000 mm", QPrinter::B1);
483 		papercombo->addItem("B2 (500 x 707 mm", QPrinter::B2);
484 		papercombo->addItem("B3 (353 x 500 mm", QPrinter::B3);
485 		papercombo->addItem("B4 (250 x 353 mm", QPrinter::B4);
486 		papercombo->addItem("B5 (176 x 250 mm, 6.93 x 9.84 inches", QPrinter::B5);
487 		papercombo->addItem("B6 (125 x 176 mm", QPrinter::B6);
488 		papercombo->addItem("B7 (88 x 125 mm", QPrinter::B7);
489 		papercombo->addItem("B8 (62 x 88 mm", QPrinter::B8);
490 		papercombo->addItem("B9 (33 x 62 mm", QPrinter::B9);
491 		papercombo->addItem("B10 (31 x 44 mm", QPrinter::B10);
492 		papercombo->addItem("#5 Envelope (163 x 229 mm", QPrinter::C5E);
493 		papercombo->addItem("#10 Envelope (105 x 241 mm", QPrinter::Comm10E);
494 		papercombo->addItem("DLE (110 x 220 mm", QPrinter::DLE);
495 		papercombo->addItem("Executive (7.5 x 10 inches, 190.5 x 254 mm", QPrinter::Executive);
496 		papercombo->addItem("Folio (210 x 330 mm", QPrinter::Folio);
497 		papercombo->addItem("Ledger (431.8 x 279.4 mm", QPrinter::Ledger);
498 		papercombo->addItem("Legal (8.5 x 14 inches, 215.9 x 355.6 mm", QPrinter::Legal);
499 		papercombo->addItem("Letter (8.5 x 11 inches, 215.9 x 279.4 mm", QPrinter::Letter);
500 		papercombo->addItem("Tabloid (279.4 x 431.8 mm", QPrinter::Tabloid);
501 		// set setting and select
502 		setpaper = settings.value(SETTINGSPRINTERPAPER, SETTINGSPRINTERPAPERDEFAULT).toInt();
503 		int index = papercombo->findData(setpaper);
504 		if ( index != -1 ) { // -1 for not found
505 			papercombo->setCurrentIndex(index);
506 		}
507 		// add to layout
508 		printertablayout->addWidget(papercombo,r,2,1,2);
509 	}
510 	//
511 	r++;
512 	{
513 		pdffilelabel = new QLabel(tr("PDF File Name:"),this);
514 		pdffileinput = new QLineEdit(QString(),this);
515 		pdffileinput->setText(settings.value(SETTINGSPRINTERPDFFILE, "").toString());
516 		pdffileinput->setMaxLength(96);
517 		printertablayout->addWidget(pdffilelabel,r,1,1,1);
518 		printertablayout->addWidget(pdffileinput,r,2,1,2);
519 	}
520 	//
521 	r++;
522 	{
523 		resolutiongroup = new QGroupBox(tr("Printer Resolution:"),this);
524 		resolutionhigh = new QRadioButton(tr("High"),this);
525 		resolutionscreen = new QRadioButton(tr("Screen"),this);
526 		QVBoxLayout *resolutionbox = new QVBoxLayout;
527 		resolutionbox->addWidget(resolutionhigh);
528 		resolutionbox->addWidget(resolutionscreen);
529 		resolutiongroup->setLayout(resolutionbox);
530 		printertablayout->addWidget(resolutiongroup,r,2,1,2);
531 		resolutionhigh->setChecked(settings.value(SETTINGSPRINTERRESOLUTION, SETTINGSPRINTERRESOLUTIONDEFAULT)==QPrinter::HighResolution);
532 		resolutionscreen->setChecked(settings.value(SETTINGSPRINTERRESOLUTION, SETTINGSPRINTERRESOLUTIONDEFAULT)==QPrinter::ScreenResolution);
533 	}
534 	//
535 	r++;
536 	{
537 		orientgroup = new QGroupBox(tr("Orientation:"),this);
538 		orientportrait = new QRadioButton(tr("Portrait"),this);
539 		orientlandscape = new QRadioButton(tr("Landscape"),this);
540 		QVBoxLayout *orientbox = new QVBoxLayout;
541 		orientbox->addWidget(orientportrait);
542 		orientbox->addWidget(orientlandscape);
543 		orientgroup->setLayout(orientbox);
544 		printertablayout->addWidget(orientgroup,r,2,1,2);
545 		orientportrait->setChecked(settings.value(SETTINGSPRINTERORIENT, SETTINGSPRINTERORIENTDEFAULT)==QPrinter::Portrait);
546 		orientlandscape->setChecked(settings.value(SETTINGSPRINTERORIENT, SETTINGSPRINTERORIENTDEFAULT)==QPrinter::Landscape);
547 	}
548 
549 
550 	// *******************************************************************************************
551 	// *******************************************************************************************
552 	// *******************************************************************************************
553 	// now that we have the tab layouts built - make the main window
554 	QTabWidget * tabs = new QTabWidget(this);
555 	tabs->addTab(usertabwidget,tr("User"));
556 	tabs->addTab(soundtabwidget,tr("Sound"));
557 	tabs->addTab(printertabwidget,tr("Printing"));
558 	if (showAdvanced) tabs->addTab(advancedtabwidget,tr("Advanced"));
559 
560 	QGridLayout * mainlayout = new QGridLayout();
561 	mainlayout->addWidget(tabs,0,1,1,3);
562 
563 	cancelbutton = new QPushButton(tr("Cancel"), this);
564 	connect(cancelbutton, SIGNAL(clicked()), this, SLOT (clickCancelButton()));
565 	savebutton = new QPushButton(tr("Save"), this);
566 	connect(savebutton, SIGNAL(clicked()), this, SLOT (clickSaveButton()));
567 	mainlayout->addWidget(cancelbutton,1,2,1,1);
568 	mainlayout->addWidget(savebutton,1,3,1,1);
569 	savebutton->setDefault(true);
570 
571 	this->setLayout(mainlayout);
572 
573 	move(settings.value(SETTINGSPREFPOS, QPoint(200, 200)).toPoint());
574 	setWindowTitle(tr("BASIC-256 Preferences and Settings"));
575 }
576 
clickCancelButton()577 void PreferencesWin::clickCancelButton() {
578 	close();
579 }
580 
clickSaveButton()581 void PreferencesWin::clickSaveButton() {
582 	bool validate = true;
583 
584 	SETTINGS;
585 
586 	// validate file name if PDF
587 	if (printerscombo->itemData(printerscombo->currentIndex())==-1 && pdffileinput->text()=="") {
588 		//
589 		QMessageBox::information(this, tr(SETTINGSAPP), tr("File name required for PDF output."),QMessageBox::Ok, QMessageBox::Ok);
590 		validate = false;
591 	}
592 	// add other validation here
593 
594 	if(validate) {
595 
596 		// *******************************************************************************************
597 		// advanced settings
598 		if(advancedtabwidget) {
599 			// only changed advanced settings if they are  shown
600 			//
601 			// if password has changed - digest and save
602 			QString currentpw = settings.value(SETTINGSPREFPASSWORD, "").toString();
603 			if(QString::compare(currentpw,passwordinput->text())!=0) {
604 				QString pw("");
605 				if(passwordinput->text().length()!=0) {
606 					pw = MD5(passwordinput->text().toUtf8().data()).hexdigest();
607 				}
608 				settings.setValue(SETTINGSPREFPASSWORD, pw);
609 			}
610 			//
611 			settings.setValue(SETTINGSALLOWSYSTEM, allowsystemcombo->itemData(allowsystemcombo->currentIndex()));
612 			settings.setValue(SETTINGSALLOWSETTING, settingcheckbox->isChecked());
613 			settings.setValue(SETTINGSSETTINGSACCESS, settingsaccesscombo->itemData(settingsaccesscombo->currentIndex()));
614 			settings.setValue(SETTINGSSETTINGSMAX, settingsmaxcombo->itemData(settingsmaxcombo->currentIndex()));
615 #ifdef WIN32
616 #ifndef WIN32PORTABLE
617 			settings.setValue(SETTINGSALLOWPORT, allowportcombo->itemData(allowportcombo->currentIndex()));
618 			//settings.setValue(SETTINGSALLOWPORT, portcheckbox->isChecked());
619 #endif
620 #endif
621 		}
622 
623 
624 		// *******************************************************************************************
625 		// user settings
626 		settings.setValue(SETTINGSIDESAVEONRUN, saveonruncheckbox->isChecked());
627 		if (typeconvcombo->currentIndex()!=-1) {
628 			settings.setValue(SETTINGSTYPECONV, typeconvcombo->itemData(typeconvcombo->currentIndex()));
629 		}
630 		if (varnotassignedcombo->currentIndex()!=-1) {
631 			settings.setValue(SETTINGSVARNOTASSIGNED, varnotassignedcombo->itemData(varnotassignedcombo->currentIndex()));
632 		}
633 		settings.setValue(SETTINGSDECDIGS, decdigsslider->value());
634 		settings.setValue(SETTINGSDEBUGSPEED, debugspeedslider->value());
635 		settings.setValue(SETTINGSFLOATTAIL, floattailcheckbox->isChecked());
636 		settings.setValue(SETTINGSFLOATLOCALE, floatlocalecheckbox->isChecked());
637 		settings.setValue(SETTINGSWINDOWSRESTORE, windowsrestorecheckbox->isChecked());
638 		settings.setValue(SETTINGSCHECKFORUPDATE, checkupdatecheckbox->isChecked());
639 
640 		// *******************************************************************************************
641 		// sound settings
642 		settings.setValue(SETTINGSSOUNDVOLUME, soundvolumeslider->value());
643 		settings.setValue(SETTINGSSOUNDNORMALIZE, soundnormalizeslider->value()*10);
644 		settings.setValue(SETTINGSSOUNDVOLUMERESTORE, soundvolumerestoreslider->value()*10);
645 		if (soundsampleratecombo->currentIndex()!=-1) {
646 			settings.setValue(SETTINGSSOUNDSAMPLERATE, soundsampleratecombo->itemData(soundsampleratecombo->currentIndex()));
647 		}
648 #ifdef ESPEAK
649 		//
650 		if (voicecombo->currentIndex()!=-1) {
651 			settings.setValue(SETTINGSESPEAKVOICE, voicecombo->itemData(voicecombo->currentIndex()));
652 		}
653 #endif
654 #ifdef ESPEAK_EXECUTE
655 		//
656 		settings.setValue(SETTINGSESPEAKSTATEMENT, speakstmtinput->text());
657 #endif
658 
659 		// *******************************************************************************************
660 		// printer settings
661 		if (printerscombo->currentIndex()!=-1) {
662 			settings.setValue(SETTINGSPRINTERPRINTER, printerscombo->itemData(printerscombo->currentIndex()));
663 		}
664 		//
665 		if (papercombo->currentIndex()!=-1) {
666 			settings.setValue(SETTINGSPRINTERPAPER, papercombo->itemData(papercombo->currentIndex()));
667 		}
668 		//
669 		settings.setValue(SETTINGSPRINTERPDFFILE, pdffileinput->text());
670 		//
671 		if (resolutionhigh->isChecked()) settings.setValue(SETTINGSPRINTERRESOLUTION, QPrinter::HighResolution);
672 		if (resolutionscreen->isChecked()) settings.setValue(SETTINGSPRINTERRESOLUTION, QPrinter::ScreenResolution);
673 		//
674 		if (orientportrait->isChecked()) settings.setValue(SETTINGSPRINTERORIENT, QPrinter::Portrait);
675 		if (orientlandscape->isChecked()) settings.setValue(SETTINGSPRINTERORIENT, QPrinter::Landscape);
676 
677 
678 		// *******************************************************************************************
679 		// all done
680 		QMessageBox::information(this, tr(SETTINGSAPP), tr("Preferences and settings have been saved."),QMessageBox::Ok, QMessageBox::Ok);
681 		//
682 		close();
683 	}
684 }
685 
closeEvent(QCloseEvent * e)686 void PreferencesWin::closeEvent(QCloseEvent *e) {
687 	(void) e;
688 	// save current screen posision
689 	SETTINGS;
690 	//settings.setValue(SETTINGSPREFSIZE, size());
691 	settings.setValue(SETTINGSPREFPOS, pos());
692 }
693 
setDigitsValue(int i)694 void PreferencesWin::setDigitsValue(int i){
695 	QString t = QString::number(i) + " " + tr("digits");
696 	QToolTip::showText(QCursor::pos(), t);
697 	decdigsvalue->setText(t);
698 	decdigsslider->setToolTip(t);
699 }
700 
setDebugSpeedValue(int i)701 void PreferencesWin::setDebugSpeedValue(int i){
702 	QString t = tr("pause") + " " + QString::number(i) + " " + tr("ms");
703 	QToolTip::showText(QCursor::pos(),t);
704 	debugspeedvalue->setText(t);
705 	debugspeedslider->setToolTip(t);
706 }
707 
setVolumeValue(int i)708 void PreferencesWin::setVolumeValue(int i){
709 	QString t = QString::number(i);
710 	QToolTip::showText(QCursor::pos(), t);
711 	soundvolumevalue->setText(t);
712 	soundvolumeslider->setToolTip(t);
713 }
714 
setNormalizeValue(int i)715 void PreferencesWin::setNormalizeValue(int i){
716 	QString t = QString::number(i*10) + " " + tr("ms");
717 	QToolTip::showText(QCursor::pos(), t);
718 	soundnormalizevalue->setText(t);
719 	soundnormalizeslider->setToolTip(t);
720 }
721 
setVolumeRestoreValue(int i)722 void PreferencesWin::setVolumeRestoreValue(int i){
723 	QString t = QString::number(i*10) + " " + tr("ms");
724 	QToolTip::showText(QCursor::pos(), t);
725 	soundvolumerestorevalue->setText(t);
726 	soundvolumerestoreslider->setToolTip(t);
727 }
728 
clickClearSavedData()729 void PreferencesWin::clickClearSavedData() {
730 	if(QMessageBox::Yes == QMessageBox::question(this, tr("Delete persistent settings"), tr("Do you really want to delete persistent settings for all programs?"), QMessageBox::Yes|QMessageBox::No, QMessageBox::No)){
731 		SETTINGS;
732 		settings.beginGroup(SETTINGSGROUPUSER);
733 		settings.remove("");
734 		settings.endGroup();
735 	}
736 }
737 
clickBrowseSavedData()738 void PreferencesWin::clickBrowseSavedData() {
739 	settingsbrowser = new SettingsBrowser(this);
740 	settingsbrowser->exec();
741 	delete settingsbrowser;
742 }
743 
744 
745 
746 
SettingsBrowser(QWidget * parent)747 SettingsBrowser::SettingsBrowser (QWidget * parent):QDialog(parent) {
748 	setWindowTitle(tr("BASIC-256 Persistent settings"));
749 	QGridLayout *layout = new QGridLayout(this);
750 	setLayout(layout);
751 	QFileIconProvider iconProvider;
752 	treeWidgetSettings = new QTreeWidget(this);
753 	treeWidgetSettings->setColumnCount(2);
754 	treeWidgetSettings->setHeaderLabels(QStringList() << tr("Program/Key") << tr("Value"));
755 	QList<QTreeWidgetItem *> items;
756 
757 	SETTINGS;
758 	settings.beginGroup(SETTINGSGROUPUSER);
759 	QStringList applications = settings.childGroups();
760 
761 	for (int p = 0; p < applications.size(); p++){
762 		QString app(applications.at(p));
763 		settings.beginGroup(app);
764 		QStringList keys = settings.childKeys();
765 		QTreeWidgetItem *item = new QTreeWidgetItem(treeWidgetSettings, (QStringList() << app << QString::number(keys.count())) );
766 		item->setFlags(item->flags() | Qt::ItemIsTristate | Qt::ItemIsUserCheckable);
767 		item->setCheckState(0, Qt::Unchecked);
768 		item->setIcon(0,iconProvider.icon(QFileIconProvider::Folder));
769 		for (int k = 0; k < keys.size(); k++){
770 			QString key(keys.at(k));
771 			QTreeWidgetItem *i = new QTreeWidgetItem(item, QStringList() << key << settings.value(key, "").toString());
772 			i->setCheckState(0, Qt::Unchecked);
773 			item->addChild(i);
774 		}
775 		settings.endGroup();
776 		items.append(item);
777 	}
778 	settings.endGroup();
779 	treeWidgetSettings->insertTopLevelItems(0, items);
780 	treeWidgetSettings->setSortingEnabled(true);
781 	treeWidgetSettings->sortItems(0, Qt::AscendingOrder);
782 	treeWidgetSettings->resizeColumnToContents(0);
783 	layout->addWidget(treeWidgetSettings, 1, 1, 1, 2);
784 
785 	deleteselectedsettings = new QPushButton(tr("Delete selected settings"), this);
786 	deleteselectedsettings->setEnabled(false);
787 	connect(deleteselectedsettings, SIGNAL(clicked()), this, SLOT (clickDeleteButton()));
788 	layout->addWidget(deleteselectedsettings, 2, 1);
789 
790 	canceldeletesettings = new QPushButton(tr("Cancel"), this);
791 	canceldeletesettings->setDefault(true);
792 	connect(canceldeletesettings, SIGNAL(clicked()), this, SLOT (reject()));
793 	layout->addWidget(canceldeletesettings,2,2);
794 
795 	connect(treeWidgetSettings, SIGNAL(itemChanged(QTreeWidgetItem*, int)), this, SLOT (treeWidgetCheckboxChanged()));
796 }
797 
treeWidgetCheckboxChanged()798 void SettingsBrowser::treeWidgetCheckboxChanged() {
799 	QTreeWidgetItemIterator it(treeWidgetSettings);
800 	while (*it) {
801 		if ((*it)->checkState(0) != Qt::Unchecked){
802 			deleteselectedsettings->setEnabled(true);
803 			return;
804 		}
805 		++it;
806 	}
807 	deleteselectedsettings->setEnabled(false);
808 }
809 
clickDeleteButton()810 void SettingsBrowser::clickDeleteButton() {
811 	if(QMessageBox::Yes == QMessageBox::question(this, tr("Delete selected settings"), tr("Do you really want to delete selected persistent settings?"), QMessageBox::Yes|QMessageBox::No, QMessageBox::No)){
812 		SETTINGS;
813 		settings.beginGroup(SETTINGSGROUPUSER);
814 
815 		deleteselectedsettings->setEnabled(false);
816 		int top=treeWidgetSettings->topLevelItemCount()-1;
817 		while(top>=0){
818 			QTreeWidgetItem *topitem = treeWidgetSettings->topLevelItem(top);
819 			if(topitem->checkState(0) == Qt::Checked){
820 				settings.remove(topitem->text(0));
821 				delete topitem;
822 			}
823 			top--;
824 		}
825 
826 		QTreeWidgetItemIterator it(treeWidgetSettings);
827 		while (*it) {
828 			QTreeWidgetItem * item = (*it);
829 			++it;
830 			if (item->checkState(0) == Qt::Checked){
831 					settings.remove(item->parent()->text(0) + QString("/") + item->text(0));
832 					delete item;
833 			}
834 		}
835 		settings.endGroup();
836 	}
837 }
838 
839