source: psi/trunk/src/xdata_widget.cpp@ 150

Last change on this file since 150 was 2, checked in by dmik, 19 years ago

Imported original Psi 0.10 sources from Affinix

File size: 11.3 KB
Line 
1/*
2 * xdata_widget.cpp - a class for displaying jabber:x:data forms
3 * Copyright (C) 2003-2004 Michail Pishchagin
4 *
5 * This program is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU General Public License
7 * as published by the Free Software Foundation; either version 2
8 * of the License, or (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this library; if not, write to the Free Software
17 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
18 *
19 */
20
21#include "xdata_widget.h"
22
23#include <qlayout.h>
24#include <qlabel.h>
25#include <qcheckbox.h>
26#include <qcombobox.h>
27#include <qlistbox.h>
28#include <qlineedit.h>
29#include <qptrlist.h>
30#include <qobjectlist.h>
31#include <qtooltip.h>
32#include <qtextedit.h>
33
34//----------------------------------------------------------------------------
35// XDataField
36//----------------------------------------------------------------------------
37class XDataField
38{
39public:
40 XDataField(XData::Field f)
41 {
42 _field = f;
43 }
44 virtual ~XDataField()
45 {
46 }
47
48 virtual XData::Field field() const
49 {
50 return _field;
51 }
52
53 QString labelText() const
54 {
55 QString text = _field.label();
56 if ( text.isEmpty() )
57 text = _field.var();
58 return text + ": ";
59 }
60
61 QString reqText() const
62 {
63 QString req;
64 if ( _field.required() )
65 req = "*";
66 if ( !_field.desc().isEmpty() ) {
67 if ( !req.isEmpty() )
68 req += " ";
69 req += "(?)";
70 }
71 return req;
72 }
73
74 virtual bool isValid() const
75 {
76 return field().isValid();
77 }
78
79private:
80 XData::Field _field;
81};
82
83////////////////////////////////////////
84
85class XDataField_Hidden : public XDataField
86{
87public:
88 XDataField_Hidden(XData::Field f)
89 : XDataField(f)
90 {
91 }
92};
93
94////////////////////////////////////////
95
96class XDataField_Boolean : public XDataField
97{
98public:
99 XDataField_Boolean(XData::Field f, QGridLayout *grid, int row, QWidget *parent)
100 : XDataField(f)
101 {
102 bool checked = false;
103 if ( f.value().count() ) {
104 QString s = f.value().first();
105 if ( s == "1" || s == "true" || s == "yes" )
106 checked = true;
107 }
108
109 QLabel *label = new QLabel(labelText(), parent);
110 grid->addWidget(label, row, 0);
111
112 check = new QCheckBox(parent);
113 check->setChecked(checked);
114 grid->addWidget(check, row, 1);
115
116 QLabel *req = new QLabel(reqText(), parent);
117 grid->addWidget(req, row, 2);
118
119 if ( !f.desc().isEmpty() ) {
120 QToolTip::add(label, f.desc());
121 QToolTip::add(check, f.desc());
122 QToolTip::add(req, f.desc());
123 }
124 }
125
126 XData::Field field() const
127 {
128 XData::Field f = XDataField::field();
129 QStringList val;
130 val << QString( check->isChecked() ? "1" : "0" );
131 f.setValue(val);
132 return f;
133 }
134
135private:
136 QCheckBox *check;
137};
138
139////////////////////////////////////////
140
141class XDataField_Fixed : public XDataField
142{
143public:
144 XDataField_Fixed(XData::Field f, QGridLayout *grid, int row, QWidget *parent)
145 : XDataField(f)
146 {
147 QString text;
148 QStringList val = f.value();
149 QStringList::Iterator it = val.begin();
150 for ( ; it != val.end(); ++it) {
151 if ( !text.isEmpty() )
152 text += "<br>";
153 text += *it;
154 }
155
156 QLabel *fixed = new QLabel("<qt>" + text + "</qt>", parent);
157 grid->addMultiCellWidget(fixed, row, row, 0, 2);
158
159 if ( !f.desc().isEmpty() ) {
160 QToolTip::add(fixed, f.desc());
161 }
162 }
163};
164
165////////////////////////////////////////
166
167class XDataField_TextSingle : public XDataField
168{
169public:
170 XDataField_TextSingle(XData::Field f, QGridLayout *grid, int row, QWidget *parent)
171 : XDataField(f)
172 {
173 QString text;
174 if ( f.value().count() )
175 text = f.value().first();
176
177 QLabel *label = new QLabel(labelText(), parent);
178 grid->addWidget(label, row, 0);
179
180 edit = new QLineEdit(parent);
181 edit->setText(text);
182 grid->addWidget(edit, row, 1);
183
184 QLabel *req = new QLabel(reqText(), parent);
185 grid->addWidget(req, row, 2);
186
187 if ( !f.desc().isEmpty() ) {
188 QToolTip::add(label, f.desc());
189 QToolTip::add(edit, f.desc());
190 QToolTip::add(req, f.desc());
191 }
192 }
193
194 XData::Field field() const
195 {
196 XData::Field f = XDataField::field();
197 QStringList val;
198 val << edit->text();
199 f.setValue(val);
200 return f;
201 }
202
203protected:
204 QLineEdit *edit;
205};
206
207////////////////////////////////////////
208
209class XDataField_TextPrivate : public XDataField_TextSingle
210{
211public:
212 XDataField_TextPrivate(XData::Field f, QGridLayout *grid, int row, QWidget *parent)
213 : XDataField_TextSingle(f, grid, row, parent)
214 {
215 edit->setEchoMode(QLineEdit::Password);
216 }
217};
218
219////////////////////////////////////////
220
221class XDataField_JidSingle : public XDataField_TextSingle
222{
223public:
224 XDataField_JidSingle(XData::Field f, QGridLayout *grid, int row, QWidget *parent)
225 : XDataField_TextSingle(f, grid, row, parent)
226 {
227 // TODO: add proper validation
228 }
229};
230
231////////////////////////////////////////
232
233class XDataField_ListSingle : public XDataField
234{
235public:
236 XDataField_ListSingle(XData::Field f, QGridLayout *grid, int row, QWidget *parent)
237 : XDataField(f)
238 {
239 QLabel *label = new QLabel(labelText(), parent);
240 grid->addWidget(label, row, 0);
241
242 combo = new QComboBox(parent);
243 grid->addWidget(combo, row, 1);
244 combo->setInsertionPolicy(QComboBox::NoInsertion);
245
246 QString sel;
247 if ( !f.value().isEmpty() )
248 sel = f.value().first();
249
250 XData::Field::OptionList opts = f.options();
251 XData::Field::OptionList::Iterator it = opts.begin();
252 for ( ; it != opts.end(); ++it) {
253 QString lbl = (*it).label;
254 if ( lbl.isEmpty() )
255 lbl = (*it).value;
256
257 combo->insertItem(lbl);
258 if ( (*it).value == sel )
259 combo->setCurrentText( lbl );
260 }
261
262 QLabel *req = new QLabel(reqText(), parent);
263 grid->addWidget(req, row, 2);
264
265 if ( !f.desc().isEmpty() ) {
266 QToolTip::add(label, f.desc());
267 QToolTip::add(combo, f.desc());
268 QToolTip::add(req, f.desc());
269 }
270 }
271
272 XData::Field field() const
273 {
274 QString lbl = combo->currentText();
275
276 XData::Field f = XDataField::field();
277 QStringList val;
278
279 XData::Field::OptionList opts = f.options();
280 XData::Field::OptionList::Iterator it = opts.begin();
281 for ( ; it != opts.end(); ++it) {
282 if ( (*it).label == lbl || (*it).value == lbl ) {
283 val << (*it).value;
284 break;
285 }
286 }
287
288 f.setValue(val);
289 return f;
290 }
291
292private:
293 QComboBox *combo;
294};
295
296////////////////////////////////////////
297
298class XDataField_ListMulti : public XDataField
299{
300public:
301 XDataField_ListMulti(XData::Field f, QGridLayout *grid, int row, QWidget *parent)
302 : XDataField(f)
303 {
304 QLabel *label = new QLabel(labelText(), parent);
305 grid->addWidget(label, row, 0);
306
307 list = new QListBox(parent);
308 grid->addWidget(list, row, 1);
309 list->setSelectionMode(QListBox::Multi);
310
311 QListBoxText *last = 0;
312 XData::Field::OptionList opts = f.options();
313 XData::Field::OptionList::Iterator it = opts.begin();
314 for ( ; it != opts.end(); ++it) {
315 QString lbl = (*it).label;
316 if ( lbl.isEmpty() )
317 lbl = (*it).value;
318
319 QListBoxText *item = new QListBoxText(list, lbl, last);
320
321 QStringList val = f.value();
322 QStringList::Iterator sit = val.begin();
323 for ( ; sit != val.end(); ++sit)
324 if ( (*it).label == *sit || (*it).value == *sit )
325 list->setSelected(item, true);
326
327 last = item;
328 }
329
330 QLabel *req = new QLabel(reqText(), parent);
331 grid->addWidget(req, row, 2);
332
333 if ( !f.desc().isEmpty() ) {
334 QToolTip::add(label, f.desc());
335 QToolTip::add(list, f.desc());
336 QToolTip::add(req, f.desc());
337 }
338 }
339
340 XData::Field field() const
341 {
342 XData::Field f = XDataField::field();
343 QStringList val;
344
345 QListBoxItem *item = list->firstItem();
346 while ( item ) {
347 if ( item->isSelected() ) {
348 QString lbl = item->text();
349 XData::Field::OptionList opts = f.options();
350 XData::Field::OptionList::Iterator it = opts.begin();
351 for ( ; it != opts.end(); ++it) {
352 if ( (*it).label == lbl || (*it).value == lbl ) {
353 val << (*it).value;
354 break;
355 }
356 }
357 }
358
359 item = item->next();
360 }
361
362 f.setValue(val);
363 return f;
364 }
365
366private:
367 QListBox *list;
368};
369
370////////////////////////////////////////
371
372class XDataField_TextMulti : public XDataField
373{
374public:
375 XDataField_TextMulti(XData::Field f, QGridLayout *grid, int row, QWidget *parent)
376 : XDataField(f)
377 {
378 QLabel *label = new QLabel(labelText(), parent);
379 grid->addWidget(label, row, 0);
380
381 edit = new QTextEdit(parent);
382 grid->addWidget(edit, row, 1);
383
384 QString text;
385 QStringList val = f.value();
386 QStringList::Iterator it = val.begin();
387 for ( ; it != val.end(); ++it) {
388 if ( !text.isEmpty() )
389 text += "\n";
390 text += *it;
391 }
392 edit->setText(text);
393
394 QLabel *req = new QLabel(reqText(), parent);
395 grid->addWidget(req, row, 2);
396
397 if ( !f.desc().isEmpty() ) {
398 QToolTip::add(label, f.desc());
399 QToolTip::add(edit, f.desc());
400 QToolTip::add(req, f.desc());
401 }
402 }
403
404 XData::Field field() const
405 {
406 XData::Field f = XDataField::field();
407 f.setValue( QStringList::split("\n", edit->text(), true) );
408 return f;
409 }
410
411private:
412 QTextEdit *edit;
413};
414
415////////////////////////////////////////
416
417class XDataField_JidMulti : public XDataField_TextMulti
418{
419public:
420 XDataField_JidMulti(XData::Field f, QGridLayout *grid, int row, QWidget *parent)
421 : XDataField_TextMulti(f, grid, row, parent)
422 {
423 // TODO: improve validation
424 }
425};
426
427//----------------------------------------------------------------------------
428// XDataWidget
429//----------------------------------------------------------------------------
430class XDataWidget::Private
431{
432public:
433 Private() {
434 fields.setAutoDelete(true);
435 }
436
437 typedef QPtrList<XDataField> XDataFieldList;
438 XDataFieldList fields;
439};
440
441XDataWidget::XDataWidget(QWidget *parent, const char *name)
442: QWidget(parent, name)
443{
444 d = new Private;
445}
446
447XDataWidget::~XDataWidget()
448{
449 delete d;
450}
451
452XData::FieldList XDataWidget::fields() const
453{
454 XData::FieldList f;
455
456 QPtrListIterator<XDataField> it (d->fields);
457 XDataField *field;
458 for ( ; (field = it.current()); ++it)
459 f.append( field->field() );
460
461 return f;
462}
463
464void XDataWidget::setFields(const XData::FieldList &f)
465{
466 d->fields.clear();
467
468 // delete all child widgets
469 QObjectList *objlist = queryList();
470 objlist->setAutoDelete(true);
471 delete objlist;
472
473 if ( f.count() ) {
474 QGridLayout *grid = new QGridLayout(this, 3, f.count(), 0, 3);
475
476 int row = 0;
477 XData::FieldList::ConstIterator it = f.begin();
478 for ( ; it != f.end(); ++it, ++row) {
479 XDataField *f;
480 switch ( (*it).type() ) {
481 case XData::Field::Field_Boolean:
482 f = new XDataField_Boolean(*it, grid, row, this);
483 break;
484 case XData::Field::Field_Fixed:
485 f = new XDataField_Fixed(*it, grid, row, this);
486 break;
487 case XData::Field::Field_Hidden:
488 f = new XDataField_Hidden(*it);
489 break;
490 case XData::Field::Field_JidSingle:
491 f = new XDataField_JidSingle(*it, grid, row, this);
492 break;
493 case XData::Field::Field_ListMulti:
494 f = new XDataField_ListMulti(*it, grid, row, this);
495 break;
496 case XData::Field::Field_ListSingle:
497 f = new XDataField_ListSingle(*it, grid, row, this);
498 break;
499 case XData::Field::Field_TextMulti:
500 f = new XDataField_TextMulti(*it, grid, row, this);
501 break;
502 case XData::Field::Field_JidMulti:
503 f = new XDataField_JidMulti(*it, grid, row, this);
504 break;
505 case XData::Field::Field_TextPrivate:
506 f = new XDataField_TextPrivate(*it, grid, row, this);
507 break;
508
509 default:
510 f = new XDataField_TextSingle(*it, grid, row, this);
511 }
512 d->fields.append(f);
513 }
514 }
515}
Note: See TracBrowser for help on using the repository browser.