1
#include "optionsdlg.h"
2
#include "optionstab.h"
5
#include "fancylabel.h"
6
#include "iconwidget.h"
10
#include <qlistview.h>
11
#include <qwidgetstack.h>
13
#include <qobjectlist.h>
18
#include "opt_application.h"
20
#include "opt_events.h"
21
#include "opt_status.h"
22
#include "opt_appearance.h"
23
#include "opt_iconset.h"
24
#include "opt_groupchat.h"
25
#include "opt_sound.h"
26
#include "opt_advanced.h"
28
#include "opt_lookfeel.h"
30
//----------------------------------------------------------------------------
32
//----------------------------------------------------------------------------
34
class FancyItem : public QListViewItem
37
FancyItem(QListView *, QListViewItem *after);
40
int width(const QFontMetrics &, const QListView *lv, int c) const;
41
void paintFocus(QPainter *, const QColorGroup &, const QRect &);
42
void paintCell(QPainter *p, const QColorGroup &, int c, int width, int align);
45
FancyItem::FancyItem(QListView *lv, QListViewItem *after)
46
: QListViewItem(lv, after)
50
void FancyItem::setup()
52
QListView *lv = listView();
54
for(int i = 0; i < lv->columns(); ++i) {
56
ph = QMAX(ph, pixmap(i)->height());
58
int y = QMAX(ph, lv->fontMetrics().height());
63
int FancyItem::width(const QFontMetrics &fm, const QListView *, int c) const
66
const QPixmap *pix = pixmap(c);
72
x += fm.width(text(c));
77
void FancyItem::paintFocus(QPainter *, const QColorGroup &, const QRect &)
79
// re-implimented to do nothing. selection is enough of a focus
82
void FancyItem::paintCell(QPainter *p, const QColorGroup &cg, int c, int w, int)
85
QFontMetrics fm(p->font());
87
p->fillRect(0, 0, w, h-1, cg.highlight());
89
p->fillRect(0, 0, w, h, cg.base());
92
const QPixmap *pix = pixmap(c);
94
p->drawPixmap(4, (h - pix->height()) / 2, *pix);
100
int y = ((h - fm.height()) / 2) + fm.ascent();
101
p->setPen(isSelected() ? cg.highlightedText() : cg.text());
102
p->drawText(x, y, text(c));
104
p->setPen(QPen(QColor(0xE0, 0xE0, 0xE0), 0, DotLine));
105
p->drawLine(0, h-1, w-1, h-1);
108
//----------------------------------------------------------------------------
110
//----------------------------------------------------------------------------
112
class OptionsTabBase : public OptionsTab
116
OptionsTabBase(QObject *parent, QCString id, QCString parentId, QString iconName, QString name, QString desc)
117
: OptionsTab(parent, id, parentId, name, desc, iconName)
120
QGridLayout *layout = new QGridLayout(w, 0, 2, 0, 5);
121
layout->setAutoAdd(true);
128
QWidget *widget() { return w; }
131
void tabAdded(OptionsTab *tab);
137
void OptionsTabBase::tabAdded(OptionsTab *tab)
139
//qWarning("OptionsTabBase::tabAdded(): id = %s, tab_id = %s", (const char *)id(), (const char *)tab->id());
140
QLabel *name = new QLabel(w);
141
name->setText("<b>" + tab->name() + "</b>");
142
name->setSizePolicy(QSizePolicy::Maximum, QSizePolicy::Preferred);
144
IconLabel *desc = new IconLabel(w);
145
desc->setText(tab->desc());
146
desc->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Preferred);
149
//----------------------------------------------------------------------------
150
// OptionsDlg::Private
151
//----------------------------------------------------------------------------
153
class OptionsDlg::Private : public QObject
157
Private(OptionsDlg *dlg, PsiCon *_psi, const Options &_opt);
163
void itemSelected(QListViewItem *);
164
void openTab(QString id);
166
void noDirtySlot(bool);
168
void createChangedMap();
170
void addWidgetChangedSignal(QString widgetName, QCString signal);
171
void connectDataChanged(QWidget *);
178
QDict<QWidget> id2widget;
179
QPtrList<OptionsTab> tabs;
181
QMap<QString, QCString> changedMap;
184
OptionsDlg::Private::Private(OptionsDlg *d, PsiCon *_psi, const Options &_opt)
188
opt = _opt; // option
191
dlg->lb_pageTitle->setScaledContents(32, 32);
193
dlg->lv_tabs->setSorting( -1 );
194
dlg->lv_tabs->header()->hide();
195
connect(dlg->lv_tabs, SIGNAL(selectionChanged(QListViewItem *)), SLOT(itemSelected(QListViewItem *)));
200
// fill the QListView
201
QPtrListIterator<OptionsTab> it ( tabs );
203
for ( ; it.current(); ++it) {
204
opttab = it.current();
205
//qWarning("Adding tab %s...", (const char *)opttab->id());
206
opttab->setData(psi, dlg);
207
connect(opttab, SIGNAL(dataChanged()), SLOT(dataChanged()));
208
connect(opttab, SIGNAL(addWidgetChangedSignal(QString, QCString)), SLOT(addWidgetChangedSignal(QString, QCString)));
209
connect(opttab, SIGNAL(noDirty(bool)), SLOT(noDirtySlot(bool)));
210
connect(opttab, SIGNAL(connectDataChanged(QWidget *)), SLOT(connectDataChanged(QWidget *)));
213
QListViewItem *parent = 0, *prev = 0;
214
QString parentId = opttab->parentId();
215
if ( !parentId.isEmpty() ) {
216
QListViewItemIterator it2( dlg->lv_tabs );
217
for ( ; it2.current(); ++it2) {
218
//qWarning("Searching the QListView %s...", it2.current()->text(1).latin1());
219
if ( it2.current()->text(1) == parentId ) {
220
//qWarning("...done");
221
parent = it2.current();
223
// notify the parent about the child
224
QPtrListIterator<OptionsTab> it3 ( tabs );
226
for ( ; it3.current(); ++it3) {
227
opttab2 = it3.current();
228
//qWarning("Searching tabs %s...", (const char *)opttab2->id());
229
if ( opttab2->id() == opttab->parentId() ) {
230
//qWarning("...done");
231
opttab2->tabAdded( opttab );
236
parent->setOpen( true );
241
//qWarning("****************");
243
// search for previous item
246
top = parent->firstChild();
248
top = dlg->lv_tabs->firstChild();
251
if ( !prev->nextSibling() )
253
prev = prev->nextSibling();
256
if ( opttab->id().isEmpty() )
262
// item = new FancyItem(parent, prev);
264
item = new FancyItem(dlg->lv_tabs, prev);
266
item->setText(0, opttab->tabName());
267
if ( opttab->tabIcon() )
268
item->setPixmap(0, opttab->tabIcon()->impix().pixmap());
269
item->setText(1, opttab->id());
273
// new ListItemSeparator(dlg->lv_tabs, item);
277
// fix the width of the listview based on the largest item
278
int largestWidth = 0;
279
QFontMetrics fm(dlg->lv_tabs->font());
280
for(QListViewItem *i = dlg->lv_tabs->firstChild(); i; i = i->nextSibling())
281
largestWidth = QMAX(largestWidth, i->width(fm, dlg->lv_tabs, 0));
282
dlg->lv_tabs->setFixedWidth(largestWidth + 32);
284
openTab( "application" );
287
dlg->pb_apply->setEnabled(false);
290
void OptionsDlg::Private::createTabs()
293
/*tabs.append( new OptionsTabGeneral(this) );
294
//tabs.append( new OptionsTabBase(this, "general", "", "psi/psi16", tr("General"), tr("General preferences list")) );
295
tabs.append( new OptionsTabEvents(this) );
296
//tabs.append( new OptionsTabBase(this, "events", "", "psi/system", tr("Events"), tr("Change the events behaviour")) );
297
tabs.append( new OptionsTabPresence(this) );
298
//tabs.append( new OptionsTabBase(this, "presence", "", "status/online", tr("Presence"), tr("Presence configuration")) );
299
tabs.append( new OptionsTabLookFeel(this) );
300
tabs.append( new OptionsTabIconset(this) );
301
//tabs.append( new OptionsTabBase(this, "lookfeel", "", "psi/smile", tr("Look and Feel"), tr("Change the Psi's Look and Feel")) );
302
tabs.append( new OptionsTabSound(this) );
303
//tabs.append( new OptionsTabBase(this, "sound", "", "psi/playSounds", tr("Sound"), tr("Configure how Psi sounds")) );
306
tabs.append( new OptionsTabApplication(this) );
307
tabs.append( new OptionsTabChat(this) );
308
tabs.append( new OptionsTabEvents(this) );
309
tabs.append( new OptionsTabStatus(this) );
310
tabs.append( new OptionsTabAppearance(this) );
311
tabs.append( new OptionsTabIconsetSystem(this) );
312
tabs.append( new OptionsTabIconsetRoster(this) );
313
tabs.append( new OptionsTabIconsetEmoticons(this) );
314
tabs.append( new OptionsTabGroupchat(this) );
315
tabs.append( new OptionsTabSound(this) );
316
tabs.append( new OptionsTabAdvanced(this) );
318
tabs.append( new OptionsTabLookFeelToolbars(this) ); // it needs to be there, otherwise toolbar options would not be saved correctly in all cases
321
/*tabs.append( new OptionsTabGeneralRoster(this) );
322
tabs.append( new OptionsTabGeneralDocking(this) );
323
tabs.append( new OptionsTabGeneralNotifications(this) );
324
tabs.append( new OptionsTabGeneralGroupchat(this) );
325
tabs.append( new OptionsTabGeneralMisc(this) );*/
328
/*tabs.append( new OptionsTabEventsReceive(this) );
329
tabs.append( new OptionsTabEventsMisc(this) );*/
332
/*tabs.append( new OptionsTabPresenceAuto(this) );
333
tabs.append( new OptionsTabPresencePresets(this) );
334
tabs.append( new OptionsTabPresenceMisc(this) );*/
336
// tabs - look and feel
337
/*tabs.append( new OptionsTabLookFeelColors(this) );
338
tabs.append( new OptionsTabLookFeelFonts(this) );
339
tabs.append( new OptionsTabIconsetSystem(this) );
340
tabs.append( new OptionsTabIconsetEmoticons(this) );
341
tabs.append( new OptionsTabIconsetRoster(this) );
342
tabs.append( new OptionsTabLookFeelToolbars(this) );
343
tabs.append( new OptionsTabLookFeelMisc(this) );*/
346
/*tabs.append( new OptionsTabSoundPrefs(this) );
347
tabs.append( new OptionsTabSoundEvents(this) );*/
350
void OptionsDlg::Private::createChangedMap()
352
// NOTE about commented out signals:
353
// Do NOT call addWidgetChangedSignal() for them.
354
// Instead, connect the widget's signal to your tab own dataChaged() signal
355
changedMap.insert("QButton", SIGNAL(stateChanged(int)));
356
changedMap.insert("QCheckBox", SIGNAL(stateChanged(int)));
357
changedMap.insert("QPushButton", SIGNAL(stateChanged(int)));
358
changedMap.insert("QRadioButton", SIGNAL(stateChanged(int)));
359
changedMap.insert("QComboBox", SIGNAL(activated (int)));
360
//changedMap.insert("QComboBox", SIGNAL(textChanged(const QString &)));
361
changedMap.insert("QDateEdit", SIGNAL(valueChanged(const QDate &)));
362
changedMap.insert("QDateTimeEdit", SIGNAL(valueChanged(const QDateTime &)));
363
changedMap.insert("QDial", SIGNAL(valueChanged (int)));
364
changedMap.insert("QLineEdit", SIGNAL(textChanged(const QString &)));
365
changedMap.insert("QSlider", SIGNAL(valueChanged(int)));
366
changedMap.insert("QSpinBox", SIGNAL(valueChanged(int)));
367
changedMap.insert("QTimeEdit", SIGNAL(valueChanged(const QTime &)));
368
changedMap.insert("QTextEdit", SIGNAL(textChanged()));
369
changedMap.insert("QTextBrowser", SIGNAL(sourceChanged(const QString &)));
370
changedMap.insert("QMultiLineEdit", SIGNAL(textChanged()));
371
//changedMap.insert("QListBox", SIGNAL(selectionChanged()));
372
//changedMap.insert("QTabWidget", SIGNAL(currentChanged(QWidget *)));
375
void OptionsDlg::Private::addWidgetChangedSignal(QString widgetName, QCString signal)
377
changedMap.insert(widgetName, signal);
380
void OptionsDlg::Private::openTab(QString id)
385
QWidget *tab = id2widget[id];
388
QPtrListIterator<OptionsTab> it ( tabs );
390
for ( ; it.current(); ++it) {
391
opttab = it.current();
393
if ( opttab->id() == id.latin1() ) {
394
tab = opttab->widget(); // create the widget
398
// TODO: how about QScrollView for large tabs?
399
// idea: maybe do it only for those, whose sizeHint is bigger than ws_tabs'
400
QWidget *w = new QWidget(dlg->ws_tabs, "QWidgetStack/tab");
401
QVBoxLayout *vbox = new QVBoxLayout(w);
403
/*FancyLabel *toplbl = new FancyLabel(w, "QWidgetStack/tab/FancyLabel");
404
toplbl->setText( opttab->name() );
405
toplbl->setHelp( opttab->desc() );
406
toplbl->setIcon( opttab->icon() );
407
vbox->addWidget( toplbl );
408
vbox->addSpacing( 5 );*/
410
tab->reparent(w, 0, QPoint(0, 0));
411
vbox->addWidget(tab);
412
if ( !opttab->stretchable() )
415
dlg->ws_tabs->addWidget(w);
416
id2widget.insert( id, w );
417
connectDataChanged( tab ); // no need to connect to dataChanged() slot by hands anymore
421
opttab->restoreOptions( &opt ); // initialize widgets' values
424
dlg->pb_apply->setEnabled( dirty );
433
qWarning("OptionsDlg::Private::itemSelected(): could not create widget for id '%s'", id.latin1());
439
QPtrListIterator<OptionsTab> it ( tabs );
441
for ( ; it.current(); ++it) {
442
opttab = it.current();
444
if ( opttab->id() == id.latin1() ) {
445
dlg->lb_pageTitle->setText( opttab->name() );
446
dlg->lb_pageTitle->setHelp( opttab->desc() );
447
dlg->lb_pageTitle->setIcon( opttab->icon() );
454
dlg->ws_tabs->raiseWidget( tab );
456
// and select item in lv_tabs...
457
QListViewItemIterator it( dlg->lv_tabs );
458
while ( it.current() ) {
459
it.current()->setSelected( it.current()->text(1) == id );
464
void OptionsDlg::Private::connectDataChanged(QWidget *widget)
466
QObjectList *l = widget->queryList( "QWidget", 0, false, true ); // search for all QWidget children of widget
467
QObjectListIterator it( *l );
469
for ( ; it.current(); ++it) {
470
QWidget *w = (QWidget *)it.current();
472
QMap<QString, QCString>::Iterator it2 = changedMap.find( w->className() );
473
if ( it2 != changedMap.end() ) {
474
disconnect(w, changedMap[w->className()], this, SLOT(dataChanged()));
475
connect(w, changedMap[w->className()], SLOT(dataChanged()));
482
void OptionsDlg::Private::itemSelected(QListViewItem *item)
487
openTab( item->text(1) );
490
void OptionsDlg::Private::dataChanged()
497
dlg->pb_apply->setEnabled(true);
501
void OptionsDlg::Private::noDirtySlot(bool d)
506
void OptionsDlg::Private::doApply()
511
QPtrListIterator<OptionsTab> it ( tabs );
513
for ( ; it.current(); ++it) {
514
opttab = it.current();
516
opttab->applyOptions( &opt );
519
emit dlg->applyOptions( opt );
522
dlg->pb_apply->setEnabled(false);
525
//----------------------------------------------------------------------------
527
//----------------------------------------------------------------------------
529
OptionsDlg::OptionsDlg(PsiCon *psi, const Options &opt, QWidget *parent, const char *name)
530
: OptionsUI(parent, name, false, WDestructiveClose)
532
d = new Private(this, psi, opt);
533
d->psi->dialogRegister(this);
535
setCaption(CAP(caption()));
539
OptionsDlg::~OptionsDlg()
541
d->psi->dialogUnregister(this);
545
void OptionsDlg::doOk()
551
void OptionsDlg::doApply()
556
#include "optionsdlg.moc"