acpi: Select proper one shot timer based on CPUs' C3 state.
[dragonfly.git] / contrib / bsdinstaller-1.1.6 / src / frontends / qt / src / form.cpp
1 /*
2  * Copyright (c) 2004 The DragonFly Project.  All rights reserved.
3  *
4  * This code is derived from software contributed to The DragonFly Project
5  * by Shawn R. Walker <adonijah@gmail.com>
6  *
7  * Redistribution and use in source and binary forms, with or without
8  * modification, are permitted provided that the following conditions
9  * are met:
10  *
11  * 1. Redistributions of source code must retain the above copyright
12  *    notice, this list of conditions and the following disclaimer.
13  * 2. Redistributions in binary form must reproduce the above copyright
14  *    notice, this list of conditions and the following disclaimer in
15  *    the documentation and/or other materials provided with the
16  *    distribution.
17  * 3. Neither the name of The DragonFly Project nor the names of its
18  *    contributors may be used to endorse or promote products derived
19  *    from this software without specific, prior written permission.
20  *
21  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
22  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
23  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
24  * FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE
25  * COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
26  * INCIDENTAL, SPECIAL, EXEMPLARY OR CONSEQUENTIAL DAMAGES (INCLUDING,
27  * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
28  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
29  * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
30  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
31  * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
32  * SUCH DAMAGE.
33  *
34  * $Id: form.cpp,v 1.24 2005/02/07 06:49:10 cpressey Exp $
35  * $DragonFly: src/contrib/bsdinstaller-1.1.6/src/frontends/qt/src/form.cpp,v 1.1.1.1 2008/03/12 22:15:53 dave Exp $
36  */
37
38 #include "form.h"
39
40 Form::Form(QWidget *parent, const char *name, struct dfui_connection *c)
41     : QScrollView(parent, name)
42 {
43         extensible = false;
44         multiple = false;
45         processing = false;
46         cancelled = false;
47         connection = c;
48         pbar = NULL;
49 }
50
51 bool Form::buildProgress(struct dfui_progress *payload)
52 {
53         QWidget *main;
54         QTextEdit *long_text;
55
56         main = new QWidget(viewport(), "main");
57         addChild(main);
58
59         QVBoxLayout *layout = new QVBoxLayout(main); // Overall
60         layout->setMargin(10);
61         layout->setSpacing(5);
62
63         QVBoxLayout *tLayout = new QVBoxLayout(layout); // Top
64         QVBoxLayout *bLayout = new QVBoxLayout(layout); // Bottom
65
66         // Set our title
67         setCaption("Processing...");
68
69         // Add description
70         long_text = new QTextEdit(main);
71         long_text->setReadOnly(true);
72         long_text->setText(
73             tr(dfui_info_get_short_desc(dfui_progress_get_info(payload))));
74         tLayout->addWidget(long_text);
75         long_text = NULL;
76
77         // Add Progress bar
78         pbar = new QProgressBar(main);
79         if (dfui_progress_get_streaming(payload))
80                 pbar->setTotalSteps(0);
81         else
82                 pbar->setTotalSteps(100);
83
84         pbar->setProgress(0);
85         tLayout->addWidget(pbar);
86
87         // Add Cancel
88         QPushButton *button = new QPushButton(tr("Cancel"), main, "actProgress");
89         connect(button, SIGNAL(clicked()), this, SLOT(actProgress()));
90         bLayout->addWidget(button);
91
92         // Add Progress Text (for streaming case)
93         if (dfui_progress_get_streaming(payload)) {
94                 long_text = new QTextEdit(main, "progress_text");
95                 long_text->setReadOnly(true);
96                 long_text->setText("");
97                 bLayout->addWidget(long_text);
98                 long_text = NULL;
99         }
100
101         multiple = false;
102         cancelled = false;
103         main->setMinimumWidth(viewport()->width() -
104             verticalScrollBar()->width());
105         main->setMinimumHeight(viewport()->height());
106         main->show();
107
108         return true;
109 }
110
111 void Form::actProgress()
112 {
113         const QObject *wid = QObject::sender();
114         const QString text = ((QPushButton *)wid)->text();
115
116         if (text == "Cancel") {
117                 cancelled = true;
118         } else if (text == "Ok") {
119                 processing = false;
120                 close();
121                 child("main")->deleteLater();
122         }
123 }
124
125 void Form::setProgress(int amount)
126 {
127         if (pbar && amount == -1) {
128                 pbar->setProgress(pbar->totalSteps());
129                 if (pbar->totalSteps() == 0) {
130                         QObject *widget = child("main")->child("actProgress");
131                         ((QPushButton *)widget)->setText("Ok");
132
133                         // Trick the event loop into waiting for the user
134                         // to acknowledge the streaming message output
135                         processing = true;
136                 } else {
137                         close();
138                         child("main")->deleteLater();
139                 }
140         } else if (pbar) {
141                 pbar->setProgress(amount);
142         } else {
143                 cancelled = true;
144         }
145 }
146
147 void Form::updateProgressText(const char *text)
148 {
149         QObject *progressText = NULL;
150         if (child("main"))
151                 progressText = child("main")->child("progress_text");
152
153         if (progressText)
154                 ((QTextEdit *)progressText)->append(tr(text));
155 }
156
157 QObject *Form::buildWidget(QWidget *pwidget,
158                            struct dfui_celldata *cd,
159                            struct dfui_field *field)
160 {
161         QObject *widget;
162         struct dfui_option *option;
163         const char *desc = dfui_info_get_short_desc(dfui_field_get_info(field));
164         const char *name = dfui_field_get_id(field);
165         const char *value;
166
167         if (cd)
168                 value = dfui_celldata_get_value(cd);
169         else
170                 value = "";
171
172         if (dfui_field_property_is(field, "control", "checkbox")) {
173                 widget = new QCheckBox("", pwidget, name);
174
175                 if (strcmp(value, "Y") == 0)
176                         ((QCheckBox *)widget)->setDown(true);
177
178         } else if ((option = dfui_field_option_get_first(field)) != NULL) {
179                 widget = new QComboBox(pwidget, name);
180
181                 if (dfui_field_property_is(field, "editable", "false"))
182                         ((QComboBox *)widget)->setEditable(false);
183
184                 for (option = dfui_field_option_get_first(field);
185                     option != NULL; option = dfui_option_get_next(option)) {
186                         QString optval = tr(dfui_option_get_value(option));
187                         ((QComboBox *)widget)->insertItem(optval);
188                         if (strcmp(optval.ascii(), value) == 0)
189                                 ((QComboBox *)widget)->setCurrentText(
190                                     optval);
191         
192                 }
193         } else {
194                 widget = new QLineEdit(value, pwidget, name);
195
196                 if (dfui_field_property_is(field, "editable", "false"))
197                         ((QLineEdit *)widget)->setReadOnly(true);
198
199                 if (dfui_field_property_is(field, "obscured","true")) {
200                         ((QLineEdit *)widget)->setEchoMode(
201                             QLineEdit::Password);
202                 }
203         }
204
205         QToolTip::add((QWidget *)widget, tr(desc));
206         return widget;
207 }
208
209 QPushButton *Form::buildActWidget(QWidget *pwidget, struct dfui_action *action)
210 {
211         QPushButton *button;
212         const char *name, *value;
213         
214         name = dfui_action_get_id(action);
215         value = dfui_info_get_name(dfui_action_get_info(action));
216         
217         button = new QPushButton(tr(value), pwidget, name);
218         connect(button, SIGNAL(clicked()), this, SLOT(actButton()));
219         return button;
220 }
221
222 bool Form::buildSingle()
223 {
224         struct dfui_action *action;
225         struct dfui_dataset *ds;
226         struct dfui_field *field;
227         QWidget *main;
228         QTextEdit *long_text;
229         int row;
230
231         main = new QWidget(viewport(), "main");
232         addChild(main);
233
234         QVBoxLayout *layout = new QVBoxLayout(main); // Overall
235         layout->setMargin(10);
236         layout->setSpacing(5);
237
238         QVBoxLayout *tLayout = new QVBoxLayout(layout); // Top
239         QGridLayout *mLayout = new QGridLayout(layout); // Middle
240         QVBoxLayout *bLayout = new QVBoxLayout(layout); // Bottom
241
242         // Set our identifier for response later
243         setName(dfui_form_get_id(data));
244
245         // Set our title
246         setCaption(tr(dfui_info_get_name(dfui_form_get_info(data))));
247
248         // Add description
249         long_text = new QTextEdit(main);
250         long_text->setReadOnly(true);
251         long_text->setText(tr(dfui_info_get_short_desc(dfui_form_get_info(data))));
252         tLayout->addWidget(long_text);
253         long_text = NULL;
254
255         // Grab the dataset so we can get values from it during field generation
256         ds = dfui_form_dataset_get_first(data);
257
258         row = 0;
259         for (field = dfui_form_field_get_first(data); field != NULL;
260             field = dfui_field_get_next(field)) {
261                 QLabel *wlabel;
262                 QObject *widget;
263                 struct dfui_celldata *cd;
264                 const char *label;
265
266                 // Grab the incoming dataset celldata
267                 cd = dfui_dataset_celldata_find(ds, dfui_field_get_id(field));
268
269                 label = dfui_info_get_name(dfui_field_get_info(field));
270                 wlabel = new QLabel(tr(label), main);
271                 mLayout->addWidget(wlabel, row, 0);
272
273                 widget = buildWidget(main, cd, field);
274                 mLayout->addWidget((QWidget *)widget, row++, 1);
275         }
276
277         for (action = dfui_form_action_get_first(data); action != NULL;
278             action = dfui_action_get_next(action)) {
279                 QPushButton *button = buildActWidget(main, action);
280                 bLayout->addWidget(button);
281         }
282
283         multiple = false;
284         main->setMinimumWidth(viewport()->width() -
285             verticalScrollBar()->width());
286         main->setMinimumHeight(viewport()->height());
287         main->show();
288
289         return true;
290 }
291
292 void Form::buildRow(int row, QWidget *pwidget, QTable *mLayout, struct dfui_dataset *ds)
293 {
294         int col = 0;
295         for (struct dfui_field *field = dfui_form_field_get_first(data);
296             field != NULL; field = dfui_field_get_next(field)) {
297                 struct dfui_celldata *cd = NULL;
298         
299                 // Grab the incoming dataset celldata
300                 if (ds)
301                         cd = dfui_dataset_celldata_find(ds, dfui_field_get_id(field));
302         
303                 QObject *widget = buildWidget(pwidget, cd, field);
304                 mLayout->setCellWidget(row, col++, (QWidget *)widget);
305         }
306         
307         if (extensible) {
308                 QString row_id;
309                 row_id.setNum(row);
310         
311                 QPushButton *ins = new QPushButton(tr("Insert"), pwidget,
312                     row_id);
313                 QPushButton *del = new QPushButton(tr("Delete"), pwidget,
314                     row_id);
315         
316                 mLayout->setCellWidget(row, col, ins);
317                 connect(ins, SIGNAL(clicked()), this, SLOT(actInsertRow()));
318         
319                 mLayout->setCellWidget(row, col + 1, del);
320                 connect(del, SIGNAL(clicked()), this, SLOT(actDeleteRow()));
321         }
322 }
323
324 bool Form::buildMultiple()
325 {
326         QWidget *main;
327         QTextEdit *long_text;
328         int col, row;
329
330         main = new QWidget(viewport(), "main");
331         addChild(main);
332
333         QVBoxLayout *layout = new QVBoxLayout(main); // Overall
334         layout->setMargin(10);
335         layout->setSpacing(5);
336
337         QVBoxLayout *tLayout = new QVBoxLayout(layout); // Top
338         QTable *mLayout = new QTable(main, "table"); // Middle
339         layout->addWidget(mLayout);
340
341         QVBoxLayout *bLayout = new QVBoxLayout(layout); // Bottom
342
343         // Set our identifier for response later
344         setName(dfui_form_get_id(data));
345
346         // Set our title
347         setCaption(tr(dfui_info_get_name(dfui_form_get_info(data))));
348
349         // Add description
350         long_text = new QTextEdit(main);
351         long_text->setReadOnly(true);
352         long_text->setText(tr(dfui_info_get_short_desc(dfui_form_get_info(data))));
353         tLayout->addWidget(long_text);
354         long_text = NULL;
355
356         col = 0;
357         for (struct dfui_field *field = dfui_form_field_get_first(data); field != NULL;
358             field = dfui_field_get_next(field)) {
359                 const char *label = dfui_info_get_name(dfui_field_get_info(field));
360
361                 mLayout->insertColumns(col);
362                 mLayout->horizontalHeader()->setLabel(col++, tr(label));
363         }
364
365         if (dfui_form_is_extensible(data)) {
366                 extensible = true;
367                 for (int i = 0; i < 2; i++) {
368                         mLayout->insertColumns(col, 1); // Needed for Ins, Del, Add
369                         mLayout->horizontalHeader()->setLabel(col++, tr(""));
370                 }
371         }
372
373         row = 0;
374         for (struct dfui_dataset *ds = dfui_form_dataset_get_first(data); ds != NULL;
375              ds = dfui_dataset_get_next(ds)) {
376                 mLayout->insertRows(row);
377                 buildRow(row, main, mLayout, ds);
378                 row++;
379         }
380
381         if (extensible) {
382                 QPushButton *add = new QPushButton(tr("Add"), main);
383
384                 mLayout->insertRows(row);
385                 mLayout->setRowReadOnly(row, true);
386                 mLayout->setCellWidget(row, mLayout->numCols() - 2, add);
387                 connect(add, SIGNAL(clicked()), this, SLOT(actAddRow()));
388         }
389
390         for (struct dfui_action *action = dfui_form_action_get_first(data); action != NULL;
391             action = dfui_action_get_next(action)) {
392                 QPushButton *button = buildActWidget(main, action);
393                 bLayout->addWidget(button);
394         }
395
396         multiple = true;
397         main->setMinimumWidth(viewport()->width() -
398             verticalScrollBar()->width());
399         main->setMinimumHeight(viewport()->height());
400         main->show();
401
402         return true;
403 }
404
405 void Form::actButton()
406 {
407         const QObject *wid = QObject::sender();
408         const QString widname = wid->name();
409
410         if (multiple)
411                 submitMultiple(&widname);
412         else
413                 submitSingle(&widname);
414
415         if (data) {
416                 dfui_form_free(data); // We're done with it
417                 data = NULL;
418         }
419 }
420
421 void Form::renumberControls(QTable *table)
422 {
423         int maxcols = table->numCols();
424
425         // Cycle through all rows except last since it's only used for Add
426         for (int row = 0; row < table->numRows() - 1; row++) {
427                 QString row_id;
428                 row_id.setNum(row);
429
430                 // Change Insert Row ID
431                 QWidget *widget = table->cellWidget(row, maxcols - 2);
432                 if (widget)
433                         widget->setName(row_id);
434
435
436                 // Change Delete Row ID
437                 widget = table->cellWidget(row, maxcols - 1);
438                 if (widget)
439                         widget->setName(row_id);
440         }
441 }
442
443 void Form::actAddRow()
444 {
445         QTable *table = ((QTable *)(child("main")->child("table")));
446         table->insertRows(table->numRows() - 1, 1);
447         buildRow(table->numRows() - 2, (QWidget *)child("main"), table, NULL);
448 }
449
450 void Form::actInsertRow()
451 {
452         const QObject *wid = QObject::sender();
453         const QString row = wid->name();
454         QTable *table = ((QTable *)(child("main")->child("table")));
455         table->insertRows(row.toInt());
456         buildRow(row.toInt(), (QWidget *)child("main"), table, NULL);
457         renumberControls(table);
458 }
459
460 void Form::actDeleteRow()
461 {
462         const QObject *wid = QObject::sender();
463         const QString row = wid->name();
464         QTable *table = ((QTable *)(child("main")->child("table")));
465         table->removeRow(row.toInt());
466         renumberControls(table);
467 }
468
469 void Form::submitSingle(const QString *action)
470 {
471         struct dfui_dataset *ds;
472         struct dfui_response *response;
473
474         ds = dfui_dataset_new();
475         response = dfui_response_new(name(), action->ascii());
476
477         QObjectList *widgets = topLevelWidget()->queryList();
478         QObjectListIterator it(*widgets);
479         QObject *widget;
480
481         while ((widget = it.current()) != 0) {
482                 QString value;
483
484                 if (widget->isA("QCheckBox")) {
485                         if (((QCheckBox *)widget)->isOn())
486                                 value.setAscii("Y", 1);
487                         else
488                                 value.setAscii("N", 1);
489                 } else if (widget->isA("QLineEdit")) {
490                         QLineEdit *textbox = (QLineEdit *)widget;
491                         value.setAscii(textbox->text());
492                 } else if (widget->isA("QComboBox")) {
493                         QComboBox *combobox = (QComboBox *)widget;
494                         value.setAscii(combobox->currentText());
495                 } else {
496                         ++it;
497                         continue;
498                 }
499
500                 dfui_dataset_celldata_add(ds,
501                     widget->name(), value.ascii());
502
503                 ++it;
504         }
505         delete widgets;
506
507         dfui_response_dataset_add(response, ds);
508
509         dfui_fe_submit(connection, response);
510         dfui_response_free(response);
511
512         extensible = false;
513         multiple = false;
514         processing = false;
515         close();
516
517         child("main")->deleteLater(); // Clear the form
518 }
519
520 void Form::submitMultiple(const QString *action)
521 {
522         struct dfui_dataset *ds;
523         struct dfui_response *response;
524         QTable *table;
525         int row, col;
526         int maxcols;
527
528         response = dfui_response_new(name(), action->ascii());
529
530         table = (QTable *)(child("main")->child("table"));
531         maxcols = table->numCols();
532         if (extensible)
533                 maxcols -= 2; // Ignore Insert / Delete Columns
534
535         for (row = 0; row < table->numRows(); row++) {
536                 bool submit = false;
537
538                 ds = dfui_dataset_new();
539                 for (col = 0; col < maxcols; col++) {
540                         QString value;
541                         QWidget *widget = table->cellWidget(row, col);
542
543                         if (widget) {
544                                 if (widget->isA("QCheckBox")) {
545                                         if (((QCheckBox *)widget)->isOn())
546                                                 value.setAscii("Y", 1);
547                                         else
548                                                 value.setAscii("N", 1);
549                                 } else if (widget->isA("QLineEdit")) {
550                                         QLineEdit *textbox = (QLineEdit *)widget;
551                                         value.setAscii(textbox->text());
552                                 } else if (widget->isA("QComboBox")) {
553                                         QComboBox *combobox = (QComboBox *)widget;
554                                         value.setAscii(combobox->currentText());
555                                 } else {
556                                         continue;
557                                 }
558                         } else {
559                                 continue;
560                         }
561
562                         dfui_dataset_celldata_add(ds,
563                             widget->name(), value.ascii());
564                         submit = true;
565                 }
566
567                 if (submit)
568                         dfui_response_dataset_add(response, ds);
569                 else
570                         dfui_dataset_free(ds);
571         }
572
573         dfui_fe_submit(connection, response);
574         dfui_response_free(response);
575
576         extensible = false;
577         multiple = false;
578         processing = false;
579         close();
580
581         child("main")->deleteLater(); // Clear the form
582 }
583
584 bool Form::present(struct dfui_form *payload)
585 {
586         bool result;
587
588         data = payload;
589         if (dfui_form_is_multiple(data))
590                 result = buildMultiple();
591         else
592                 result = buildSingle();
593
594         if (result) {
595                 processing = true;
596                 show();
597         }
598
599         return result;
600 }
601
602 bool Form::present(struct dfui_progress *payload)
603 {
604         bool result;
605
606         result = buildProgress((struct dfui_progress *)payload);
607         if (result)
608                 show();
609
610         return result;
611 }