1 /***************************************************************************
2  * form.cpp
3  * This file is part of the KDE project
4  * copyright (C)2006-2007 by Sebastian Sauer (mail@dipe.org)
5  *
6  * This program is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU Library General Public
8  * License as published by the Free Software Foundation; either
9  * version 2 of the License, or (at your option) any later version.
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 GNU
13  * Library General Public License for more details.
14  * You should have received a copy of the GNU Library General Public License
15  * along with this program; see the file COPYING.  If not, write to
16  * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
17  * Boston, MA 02110-1301, USA.
18  ***************************************************************************/
19 
20 #include "form.h"
21 #include <QDomDocument>
22 
23 #include <QByteRef>
24 #include <QBuffer>
25 #include <QRegExp>
26 #include <QFile>
27 #include <QArgument>
28 #include <QMetaEnum>
29 #include <QAction>
30 #include <QDialogButtonBox>
31 #include <QKeyEvent>
32 #include <QDialog>
33 #include <QBoxLayout>
34 #include <QStackedLayout>
35 #include <QSizePolicy>
36 #include <QApplication>
37 #include <QProgressBar>
38 //#include <QProgressDialog>
39 #include <QPushButton>
40 #include <QTextBrowser>
41 #include <QtUiTools/QUiLoader>
42 #include <QTextCursor>
43 #include <QTextBlock>
44 #include <QElapsedTimer>
45 
46 #include <QDebug>
47 #include <klocalizedstring.h>
48 //#include <kurlcombobox.h>
49 //#include <kdiroperator.h>
50 #include <kmessagebox.h>
51 #include <kpluginloader.h>
52 #include <kpluginfactory.h>
53 #include <kparts/readonlypart.h>
54 //#include <kio/netaccess.h>
55 //#include <klocalizedstring.h>
56 //#include <kmimetype.h>
57 //
58 #include <kfilewidget.h>
59 #include <kurlcombobox.h>
60 #include <ksqueezedtextlabel.h>
61 
62 extern "C"
63 {
krossmodule()64     Q_DECL_EXPORT QObject *krossmodule()
65     {
66         return new Kross::FormModule();
67     }
68 }
69 
70 using namespace Kross;
71 
72 /*********************************************************************************
73  * FormList
74  */
75 
FormListView(QWidget * parent)76 FormListView::FormListView(QWidget *parent) : QListWidget(parent) {}
~FormListView()77 FormListView::~FormListView() {}
clear()78 void FormListView::clear()
79 {
80     QListWidget::clear();
81 }
remove(int index)82 void FormListView::remove(int index)
83 {
84     delete QListWidget::item(index);
85 }
addItem(const QString & text)86 void FormListView::addItem(const QString &text)
87 {
88     QListWidget::addItem(text);
89 }
count()90 int FormListView::count()
91 {
92     return QListWidget::count();
93 }
current()94 int FormListView::current()
95 {
96     return QListWidget::currentRow();
97 }
setCurrent(int row)98 void FormListView::setCurrent(int row)
99 {
100     QListWidget::setCurrentRow(row);
101 }
text(int row)102 QString FormListView::text(int row)
103 {
104     QListWidgetItem *item = QListWidget::item(row);
105     return item ? item->text() : QString();
106 }
107 
108 /*********************************************************************************
109  * FormFileWidget
110  */
111 
112 namespace Kross
113 {
114 
115 /// \internal d-pointer class.
116 class FormFileWidget::Private
117 {
118 public:
119     KFileWidget *filewidget;
120     QString filename;
121 };
122 
123 }
124 
FormFileWidget(QWidget * parent,const QString & startDirOrVariable)125 FormFileWidget::FormFileWidget(QWidget *parent, const QString &startDirOrVariable)
126     : QWidget(parent), d(new Private())
127 {
128     QVBoxLayout *layout = new QVBoxLayout(this);
129     layout->setSpacing(0);
130     layout->setContentsMargins(0, 0, 0, 0);
131     setLayout(layout);
132 
133     d->filewidget = new KFileWidget(QUrl(startDirOrVariable), this);
134     layout->addWidget(d->filewidget);
135     //QMetaObject::invokeMethod(d->filewidget, "toggleSpeedbar", Q_ARG(bool,false));
136     //KFileDialog::setMode( KFile::File | KFile::LocalOnly );
137 
138     // slotOk() emits accepted, accept() emits fileSelected()
139     QObject::connect(d->filewidget, SIGNAL(fileSelected(QUrl)), this, SLOT(slotFileSelected(QUrl)));
140     QObject::connect(d->filewidget, SIGNAL(fileHighlighted(QUrl)), this, SIGNAL(slotFileHighlighted(QUrl)));
141     QObject::connect(d->filewidget, SIGNAL(selectionChanged()), this, SIGNAL(selectionChanged()));
142     QObject::connect(d->filewidget, SIGNAL(filterChanged(QString)), this, SIGNAL(filterChanged(QString)));
143 
144 //     d->impl->setOperationMode(d->mode);
145 //     if( d->mimeFilter.count() > 0 )
146 //         d->impl->setMimeFilter(d->mimeFilter);
147 //     else if( ! d->filter.isEmpty() )
148 //         d->impl->setFilter(d->filter);
149 
150     if (parent && parent->layout()) {
151         parent->layout()->addWidget(this);
152     }
153     setMinimumSize(QSize(480, 360));
154 }
155 
~FormFileWidget()156 FormFileWidget::~FormFileWidget()
157 {
158     delete d;
159 }
160 
setMode(const QString & mode)161 void FormFileWidget::setMode(const QString &mode)
162 {
163     QMetaEnum e = metaObject()->enumerator(metaObject()->indexOfEnumerator("Mode"));
164     KFileWidget::OperationMode m = (KFileWidget::OperationMode) e.keysToValue(mode.toLatin1().constData());
165     d->filewidget->setOperationMode(m);
166 }
167 
currentFilter() const168 QString FormFileWidget::currentFilter() const
169 {
170     return d->filewidget->currentFilter();
171 }
172 
setFilter(const QString & filter)173 void FormFileWidget::setFilter(const QString &filter)
174 {
175     QString f = filter;
176     f.replace(QRegExp("([^\\\\]{1,1})/"), "\\1\\/"); // escape '/' chars else KFileDialog assumes they are mimetypes :-/
177     d->filewidget->setFilter(f);
178 }
179 
currentMimeFilter() const180 QString FormFileWidget::currentMimeFilter() const
181 {
182     return d->filewidget->currentMimeFilter();
183 }
184 
setMimeFilter(const QStringList & filter)185 void FormFileWidget::setMimeFilter(const QStringList &filter)
186 {
187     d->filewidget->setMimeFilter(filter);
188 }
189 
slotFileSelected(const QUrl & fn)190 void FormFileWidget::slotFileSelected(const QUrl &fn)
191 {
192     //qDebug()<<fn;
193     d->filename = fn.toString();
194     emit fileSelected(fn.toString());
195 }
196 
slotFileHighlighted(const QUrl & fn)197 void FormFileWidget::slotFileHighlighted(const QUrl &fn)
198 {
199     emit fileHighlighted(fn.toString());
200 }
201 
selectedFile() const202 QString FormFileWidget::selectedFile() const
203 {
204     if (d->filewidget->operationMode() != KFileWidget::Saving) {
205         d->filewidget->accept();
206     } else {
207         //qDebug()<<d->filename<<d->filewidget->operationMode();
208         if (d->filename.isEmpty()) {
209             // make KFileWidget create an url for us (including extension if necessary)
210             QObject::connect(d->filewidget, SIGNAL(accepted()), d->filewidget, SLOT(accept()));
211             d->filewidget->slotOk();
212             QObject::disconnect(d->filewidget, SIGNAL(accepted()), d->filewidget, SLOT(accept()));
213         }
214     }
215     //qDebug()<<d->filename;
216     QUrl url = QUrl::fromLocalFile(d->filename);
217     return url.path(); // strip file:// at least python chokes on it
218 }
219 
220 /*********************************************************************************
221  * FormProgressDialog
222  */
223 
224 namespace Kross
225 {
226 /// \internal d-pointer class.
227 class FormProgressDialog::Private
228 {
229 public:
230     QTextBrowser *browser;
231     QProgressBar *bar;
232     bool gotCanceled;
233     QElapsedTimer time;
update()234     void update()
235     {
236         if (time.elapsed() >= 1000) {
237             time.restart();
238             qApp->processEvents();
239         }
240     }
241 };
242 }
243 
FormProgressDialog(const QString & caption,const QString & labelText)244 FormProgressDialog::FormProgressDialog(const QString &caption, const QString &labelText) : KPageDialog(), d(new Private)
245 {
246     d->gotCanceled = false;
247     d->time.start();
248 
249     setWindowTitle(caption);
250     setFaceType(KPageDialog::Plain);
251     buttonBox()->button(QDialogButtonBox::Ok)->setEnabled(false);
252     //setWindowModality(Qt::WindowModal);
253     setModal(false); //true);
254     setMinimumWidth(540);
255     setMinimumHeight(400);
256 
257     QWidget *widget = new QWidget(this);
258     KPageWidgetItem *item = KPageDialog::addPage(widget, QString());
259     item->setHeader(labelText);
260     //item->setIcon( QIcon::fromTheme(iconname) );
261     widget = item->widget();
262     QVBoxLayout *layout = new QVBoxLayout(widget);
263     layout->setContentsMargins(0, 0, 0, 0);
264     widget->setLayout(layout);
265 
266     d->browser = new QTextBrowser(this);
267     d->browser->setHtml(labelText);
268     layout->addWidget(d->browser);
269 
270     d->bar = new QProgressBar(this);
271     //d->bar->setFormat("%v");
272     d->bar->setVisible(false);
273     layout->addWidget(d->bar);
274 
275     setSizePolicy(QSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding));
276     show();
277     qApp->processEvents();
278 }
279 
~FormProgressDialog()280 FormProgressDialog::~FormProgressDialog()
281 {
282     delete d;
283 }
284 
setValue(int progress)285 void FormProgressDialog::setValue(int progress)
286 {
287     if (progress < 0) {
288         if (d->bar->isVisible()) {
289             d->bar->setVisible(false);
290             d->bar->setValue(0);
291             qApp->processEvents();
292         }
293         return;
294     }
295     if (! d->bar->isVisible()) {
296         d->bar->setVisible(true);
297     }
298     d->bar->setValue(progress);
299     d->update();
300 }
301 
setRange(int minimum,int maximum)302 void FormProgressDialog::setRange(int minimum, int maximum)
303 {
304     d->bar->setRange(minimum, maximum);
305 }
306 
setText(const QString & text)307 void FormProgressDialog::setText(const QString &text)
308 {
309     d->browser->setHtml(text);
310     d->update();
311 }
312 
addText(const QString & text)313 void FormProgressDialog::addText(const QString &text)
314 {
315     QTextCursor cursor(d->browser->document()->end());
316     cursor.movePosition(QTextCursor::End);
317     cursor.insertBlock();
318     cursor.insertHtml(text);
319     d->browser->moveCursor(QTextCursor::End);
320     d->browser->ensureCursorVisible();
321     d->update();
322 }
323 
done(int r)324 void FormProgressDialog::done(int r)
325 {
326     if (r == Rejected && ! d->gotCanceled) {
327         if (KMessageBox::messageBox(this, KMessageBox::WarningContinueCancel, i18n("Cancel?")) == KMessageBox::Continue) {
328             d->gotCanceled = true;
329             buttonBox()->button(QDialogButtonBox::Cancel)->setEnabled(false);
330             emit canceled();
331         }
332         return;
333     }
334     KPageDialog::done(r);
335 }
336 
exec()337 int FormProgressDialog::exec()
338 {
339     buttonBox()->button(QDialogButtonBox::Ok)->setEnabled(true);
340     buttonBox()->button(QDialogButtonBox::Cancel)->setEnabled(false);
341     if (d->bar->isVisible()) {
342         d->bar->setValue(d->bar->maximum());
343     }
344     return QDialog::exec();
345 }
346 
isCanceled()347 bool FormProgressDialog::isCanceled()
348 {
349     return d->gotCanceled;
350 }
351 
352 /*********************************************************************************
353  * FormDialog
354  */
355 
356 namespace Kross
357 {
358 
359 /// \internal d-pointer class.
360 class FormDialog::Private
361 {
362 public:
363     QDialogButtonBox::StandardButton buttoncode;
364     QHash<QString, KPageWidgetItem *> items;
365 };
366 
367 }
368 
FormDialog(const QString & caption)369 FormDialog::FormDialog(const QString &caption)
370     : KPageDialog(/*0, Qt::WShowModal | Qt::WDestructiveClose*/)
371     , d(new Private())
372 {
373     setWindowTitle(caption);
374     buttonBox()->setStandardButtons(QDialogButtonBox::Ok);
375     setSizePolicy(QSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding));
376 
377     connect(buttonBox(), SIGNAL(clicked(QAbstractButton*)), this, SLOT(slotButtonClicked(QAbstractButton*)));
378     connect(this, SIGNAL(currentPageChanged(KPageWidgetItem*,KPageWidgetItem*)),
379             this, SLOT(slotCurrentPageChanged(KPageWidgetItem*)));
380 }
381 
~FormDialog()382 FormDialog::~FormDialog()
383 {
384     qWarning() << "dtor";
385     delete d;
386 }
387 
setButtons(const QString & buttons)388 bool FormDialog::setButtons(const QString &buttons)
389 {
390     int i = buttonBox()->metaObject()->indexOfEnumerator("StandardButtons");
391     Q_ASSERT(i >= 0);
392     QMetaEnum e = buttonBox()->metaObject()->enumerator(i);
393     int v = e.keysToValue(buttons.toUtf8().constData());
394     if (v < 0) {
395         return false;
396     }
397     buttonBox()->setStandardButtons((QDialogButtonBox::StandardButton) v);
398     return true;
399 }
400 
setButtonText(const QString & button,const QString & text)401 bool FormDialog::setButtonText(const QString &button, const QString &text)
402 {
403     int i = buttonBox()->metaObject()->indexOfEnumerator("StandardButtons");
404     Q_ASSERT(i >= 0);
405     QMetaEnum e = buttonBox()->metaObject()->enumerator(i);
406     int v = e.keysToValue(button.toUtf8().constData());
407     if (v < 0) {
408         return false;
409     }
410     QPushButton *pushButton = buttonBox()->button((QDialogButtonBox::StandardButton) v);
411     if (!pushButton) {
412         return false;
413     }
414     pushButton->setText(text);
415     return true;
416 }
417 
setFaceType(const QString & facetype)418 bool FormDialog::setFaceType(const QString &facetype)
419 {
420     int i = KPageView::staticMetaObject.indexOfEnumerator("FaceType");
421     Q_ASSERT(i >= 0);
422     QMetaEnum e = KPageView::staticMetaObject.enumerator(i);
423     int v = e.keysToValue(facetype.toUtf8().constData());
424     if (v < 0) {
425         return false;
426     }
427     KPageDialog::setFaceType((KPageDialog::FaceType) v);
428     return true;
429 }
430 
currentPage() const431 QString FormDialog::currentPage() const
432 {
433     KPageWidgetItem *item = KPageDialog::currentPage();
434     return item ? item->name() : QString();
435 }
436 
setCurrentPage(const QString & name)437 bool FormDialog::setCurrentPage(const QString &name)
438 {
439     if (! d->items.contains(name)) {
440         return false;
441     }
442     KPageDialog::setCurrentPage(d->items[name]);
443     return true;
444 }
445 
page(const QString & name) const446 QWidget *FormDialog::page(const QString &name) const
447 {
448     return d->items.contains(name) ? d->items[name]->widget() : nullptr;
449 }
450 
451 //shared by FormDialog and FormAssistant
formAddPage(KPageDialog * dialog,const QString & name,const QString & header,const QString & iconname)452 static KPageWidgetItem *formAddPage(KPageDialog *dialog, const QString &name, const QString &header, const QString &iconname)
453 {
454     QWidget *widget = new QWidget(dialog);
455     QVBoxLayout *boxlayout = new QVBoxLayout(widget);
456     boxlayout->setSpacing(0);
457     boxlayout->setContentsMargins(0, 0, 0, 0);
458     widget->setLayout(boxlayout);
459 
460     KPageWidgetItem *item = dialog->addPage(widget, name);
461     item->setHeader(header.isNull() ? name : header);
462     if (! iconname.isEmpty()) {
463         item->setIcon(QIcon::fromTheme(iconname));
464     }
465     //d->items.insert(name, item);
466 
467     return item;
468 }
469 
addPage(const QString & name,const QString & header,const QString & iconname)470 QWidget *FormDialog::addPage(const QString &name, const QString &header, const QString &iconname)
471 {
472     return d->items.insert(name, formAddPage((KPageDialog *)this, name, header, iconname)).value()->widget();
473 }
474 
result()475 QString FormDialog::result()
476 {
477     int i = buttonBox()->metaObject()->indexOfEnumerator("StandardButtons");
478     if (i < 0) {
479         qWarning() << "Kross::FormDialog::setButtons No such enumerator \"StandardButtons\"";
480         return QString();
481     }
482     QMetaEnum e = buttonBox()->metaObject()->enumerator(i);
483     return e.valueToKey(d->buttoncode);
484 }
485 
slotButtonClicked(QAbstractButton * button)486 void FormDialog::slotButtonClicked(QAbstractButton *button)
487 {
488     d->buttoncode = buttonBox()->standardButton(button);
489 }
490 
slotCurrentPageChanged(KPageWidgetItem * current)491 void FormDialog::slotCurrentPageChanged(KPageWidgetItem *current)
492 {
493     Q_UNUSED(current);
494     //qDebug() << "FormDialog::slotCurrentPageChanged current=" << current->name();
495     //foreach(QWidget* widget, current->widget()->findChildren< QWidget* >("")) widget->setFocus();
496 }
497 
498 namespace Kross
499 {
500 /// \internal d-pointer class.
501 class FormAssistant::Private
502 {
503 public:
504     QDialogButtonBox::StandardButton buttoncode;
505     QHash<QString, KPageWidgetItem *> items;
506 };
507 }
FormAssistant(const QString & caption)508 FormAssistant::FormAssistant(const QString &caption)
509     : KAssistantDialog(/*0, Qt::WShowModal | Qt::WDestructiveClose*/)
510     , d(new Private())
511 {
512     setWindowTitle(caption);
513     setSizePolicy(QSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding));
514 
515     connect(buttonBox(), SIGNAL(clicked(QAbstractButton*)), this, SLOT(slotButtonClicked(QAbstractButton*)));
516     connect(this, SIGNAL(currentPageChanged(KPageWidgetItem*,KPageWidgetItem*)),
517             this, SLOT(slotCurrentPageChanged(KPageWidgetItem*)));
518     /* unlike boost qt does not support defining of slot call order!
519     connect(this, SIGNAL(user2Clicked()), this, SIGNAL (nextClicked()));
520     connect(this, SIGNAL(user3Clicked()), this, SIGNAL (backClicked()));
521     */
522 }
523 
~FormAssistant()524 FormAssistant::~FormAssistant()
525 {
526     delete d;
527 }
528 
showHelpButton(bool show)529 void FormAssistant::showHelpButton(bool show)
530 {
531     QPushButton *helpButton = buttonBox()->button(QDialogButtonBox::Help);
532     if (helpButton) {
533         helpButton->setVisible(show);
534     }
535 }
536 
back()537 void FormAssistant::back()
538 {
539     emit backClicked();
540     KAssistantDialog::back();
541 }
next()542 void FormAssistant::next()
543 {
544     emit nextClicked();
545     KAssistantDialog::next();
546 }
547 
currentPage() const548 QString FormAssistant::currentPage() const
549 {
550     KPageWidgetItem *item = KPageDialog::currentPage();
551     return item ? item->name() : QString();
552 }
553 
setCurrentPage(const QString & name)554 bool FormAssistant::setCurrentPage(const QString &name)
555 {
556     if (! d->items.contains(name)) {
557         return false;
558     }
559     KPageDialog::setCurrentPage(d->items[name]);
560     return true;
561 }
562 
page(const QString & name) const563 QWidget *FormAssistant::page(const QString &name) const
564 {
565     return d->items.contains(name) ? d->items[name]->widget() : nullptr;
566 }
567 
addPage(const QString & name,const QString & header,const QString & iconname)568 QWidget *FormAssistant::addPage(const QString &name, const QString &header, const QString &iconname)
569 {
570     return d->items.insert(name, formAddPage((KPageDialog *)this, name, header, iconname)).value()->widget();
571 }
572 
isAppropriate(const QString & name) const573 bool FormAssistant::isAppropriate(const QString &name) const
574 {
575     return d->items.contains(name) && KAssistantDialog::isAppropriate(d->items[name]);
576 }
setAppropriate(const QString & name,bool appropriate)577 void FormAssistant::setAppropriate(const QString &name, bool appropriate)
578 {
579     if (!d->items.contains(name)) {
580         return;
581     }
582 
583     KAssistantDialog::setAppropriate(d->items[name], appropriate);
584 }
isValid(const QString & name) const585 bool FormAssistant::isValid(const QString &name) const
586 {
587     return d->items.contains(name) && KAssistantDialog::isValid(d->items[name]);
588 }
setValid(const QString & name,bool enable)589 void FormAssistant::setValid(const QString &name, bool enable)
590 {
591     if (!d->items.contains(name)) {
592         return;
593     }
594 
595     KAssistantDialog::setValid(d->items[name], enable);
596 }
597 
result()598 QString FormAssistant::result()
599 {
600     int i = metaObject()->indexOfEnumerator("AssistantButtonCode");
601     if (i < 0) {
602         qWarning() << "Kross::FormAssistant::setButtons No such enumerator \"AssistantButtonCode\"";
603         return QString();
604     }
605     QMetaEnum e = metaObject()->enumerator(i);
606     return e.valueToKey(FormAssistant::AssistantButtonCode(int(d->buttoncode)));
607 }
608 
slotButtonClicked(QAbstractButton * button)609 void FormAssistant::slotButtonClicked(QAbstractButton *button)
610 {
611     d->buttoncode = buttonBox()->standardButton(button);
612 }
613 
slotCurrentPageChanged(KPageWidgetItem * current)614 void FormAssistant::slotCurrentPageChanged(KPageWidgetItem *current)
615 {
616     Q_UNUSED(current);
617     //qDebug() << "FormAssistant::slotCurrentPageChanged current=" << current->name();
618     //foreach(QWidget* widget, current->widget()->findChildren< QWidget* >("")) widget->setFocus();
619 }
620 
621 /*********************************************************************************
622  * FormModule
623  */
624 
625 namespace Kross
626 {
627 
628 /// \internal extension of the QUiLoader class.
629 class UiLoader : public QUiLoader
630 {
631 public:
UiLoader()632     UiLoader() : QUiLoader() {}
~UiLoader()633     ~UiLoader() override {}
634 
635     /*
636     virtual QAction* createAction(QObject* parent = 0, const QString& name = QString())
637     {
638     }
639 
640     virtual QActionGroup* createActionGroup(QObject* parent = 0, const QString& name = QString())
641     {
642     }
643 
644     virtual QLayout* createLayout(const QString& className, QObject* parent = 0, const QString& name = QString())
645     {
646     }
647 
648     virtual QWidget* createWidget(const QString& className, QWidget* parent = 0, const QString& name = QString())
649     {
650     }
651     */
652 };
653 
654 /// \internal d-pointer class.
655 class FormModule::Private
656 {
657 public:
658 };
659 
660 }
661 
FormModule()662 FormModule::FormModule()
663     : QObject()
664     , d(new Private())
665 {
666 }
667 
~FormModule()668 FormModule::~FormModule()
669 {
670     delete d;
671 }
672 
activeModalWidget()673 QWidget *FormModule::activeModalWidget()
674 {
675     return QApplication::activeModalWidget();
676 }
677 
activeWindow()678 QWidget *FormModule::activeWindow()
679 {
680     return QApplication::activeWindow();
681 }
682 
showMessageBox(const QString & dialogtype,const QString & caption,const QString & message,const QString & details)683 QString FormModule::showMessageBox(const QString &dialogtype, const QString &caption, const QString &message, const QString &details)
684 {
685     KMessageBox::DialogType type;
686     if (dialogtype == "Error") {
687         if (! details.isNull()) {
688             KMessageBox::detailedError(nullptr, message, details, caption);
689             return QString();
690         }
691         type = KMessageBox::Error;
692     } else if (dialogtype == "Sorry") {
693         if (! details.isNull()) {
694             KMessageBox::detailedSorry(nullptr, message, details, caption);
695             return QString();
696         }
697         type = KMessageBox::Sorry;
698     } else if (dialogtype == "QuestionYesNo") {
699         type = KMessageBox::QuestionYesNo;
700     } else if (dialogtype == "WarningYesNo") {
701         type = KMessageBox::WarningYesNo;
702     } else if (dialogtype == "WarningContinueCancel") {
703         type = KMessageBox::WarningContinueCancel;
704     } else if (dialogtype == "WarningYesNoCancel") {
705         type = KMessageBox::WarningYesNoCancel;
706     } else if (dialogtype == "QuestionYesNoCancel") {
707         type = KMessageBox::QuestionYesNoCancel;
708     } else { /*if(dialogtype == "Information")*/
709         type = KMessageBox::Information;
710     }
711     switch (KMessageBox::messageBox(nullptr, type, message, caption)) {
712     case KMessageBox::Ok: return "Ok";
713     case KMessageBox::Cancel: return "Cancel";
714     case KMessageBox::Yes: return "Yes";
715     case KMessageBox::No: return "No";
716     case KMessageBox::Continue: return "Continue";
717     default: break;
718     }
719     return QString();
720 }
721 
showProgressDialog(const QString & caption,const QString & labelText)722 QWidget *FormModule::showProgressDialog(const QString &caption, const QString &labelText)
723 {
724     return new FormProgressDialog(caption, labelText);
725 }
726 
createDialog(const QString & caption)727 QWidget *FormModule::createDialog(const QString &caption)
728 {
729     return new FormDialog(caption);
730 }
731 
createAssistant(const QString & caption)732 QWidget *FormModule::createAssistant(const QString &caption)
733 {
734     return new FormAssistant(caption);
735 }
736 
createLayout(QWidget * parent,const QString & layout)737 QObject *FormModule::createLayout(QWidget *parent, const QString &layout)
738 {
739     QLayout *l = nullptr;
740     if (layout == "QVBoxLayout") {
741         l = new QVBoxLayout();
742     } else if (layout == "QHBoxLayout") {
743         l = new QHBoxLayout();
744     } else if (layout == "QStackedLayout") {
745         l = new QStackedLayout();
746     }
747     if (parent && l) {
748         parent->setLayout(l);
749     }
750     return l;
751 }
752 
createWidget(const QString & className)753 QWidget *FormModule::createWidget(const QString &className)
754 {
755     UiLoader loader;
756     QWidget *widget = loader.createWidget(className);
757     return widget;
758 }
759 
createWidget(QWidget * parent,const QString & className,const QString & name)760 QWidget *FormModule::createWidget(QWidget *parent, const QString &className, const QString &name)
761 {
762     UiLoader loader;
763     QWidget *widget = loader.createWidget(className, parent, name);
764     if (parent && parent->layout()) {
765         parent->layout()->addWidget(widget);
766     }
767     return widget;
768 }
769 
tr(const QString & str)770 QString FormModule::tr(const QString &str)
771 {
772     return tr(str.toUtf8().constData());
773 }
tr(const QString & str,const QString & comment)774 QString FormModule::tr(const QString &str, const QString &comment)
775 {
776     return tr(str.toUtf8().constData(), comment.toUtf8().constData());
777 }
778 
createWidgetFromUI(QWidget * parent,const QString & xml)779 QWidget *FormModule::createWidgetFromUI(QWidget *parent, const QString &xml)
780 {
781     QUiLoader loader;
782 
783     QDomDocument doc("mydocument");
784     doc.setContent(xml.toUtf8());
785 
786     QDomNodeList strings = doc.elementsByTagName("string");
787     int i = strings.size();
788     while (--i >= 0) {
789         QDomElement e = strings.at(i).toElement();
790         QString i18nd = e.attribute("comment").isEmpty() ? tr(e.text()) : tr(e.text(), e.attribute("comment"));
791         if (i18nd == e.text()) {
792             continue;
793         }
794         QDomNode n = e.firstChild();
795         while (!n.isNull()) {
796             QDomNode nn = n.nextSibling();
797             if (n.isCharacterData()) {
798                 e.removeChild(n);
799             }
800             n = nn;
801         }
802         e.appendChild(e.ownerDocument().createTextNode(i18nd));
803     }
804 
805     QByteArray ba = doc.toByteArray();
806     QBuffer buffer(&ba);
807     buffer.open(QIODevice::ReadOnly);
808 
809     QWidget *widget = loader.load(&buffer, parent);
810     if (widget && parent && parent->layout()) {
811         parent->layout()->addWidget(widget);
812     }
813     return widget;
814 }
815 
createWidgetFromUIFile(QWidget * parent,const QString & filename)816 QWidget *FormModule::createWidgetFromUIFile(QWidget *parent, const QString &filename)
817 {
818     QFile file(filename);
819     if (! file.exists()) {
820         // qDebug() << QString("Kross::FormModule::createWidgetFromUIFile: There exists no such file \"%1\"").arg(filename);
821         return nullptr;
822     }
823     if (! file.open(QFile::ReadOnly)) {
824         // qDebug() << QString("Kross::FormModule::createWidgetFromUIFile: Failed to open the file \"%1\"").arg(filename);
825         return nullptr;
826     }
827     const QString xml = file.readAll();
828     file.close();
829     return createWidgetFromUI(parent, xml);
830 }
831 
createFileWidget(QWidget * parent,const QString & startDirOrVariable)832 QWidget *FormModule::createFileWidget(QWidget *parent, const QString &startDirOrVariable)
833 {
834     FormFileWidget *widget = new FormFileWidget(parent, startDirOrVariable);
835     if (parent && parent->layout()) {
836         parent->layout()->addWidget(widget);
837     }
838     return widget;
839 }
840 
createListView(QWidget * parent)841 QWidget *FormModule::createListView(QWidget *parent)
842 {
843     FormListView *widget = new FormListView(parent);
844     if (parent && parent->layout()) {
845         parent->layout()->addWidget(widget);
846     }
847     return widget;
848 }
849 
createAction(QObject * parent)850 QAction *FormModule::createAction(QObject *parent)
851 {
852     return new QAction(parent);
853 }
854 
loadPart(QWidget * parent,const QString & name,const QUrl & url)855 QObject *FormModule::loadPart(QWidget *parent, const QString &name, const QUrl &url)
856 {
857     //name e.g. "libkghostview"
858     KPluginFactory *factory = KPluginLoader(name.toLatin1()).factory();
859     if (! factory) {
860         qWarning() << QString("Kross::FormModule::loadPart: No such library \"%1\"").arg(name);
861         return nullptr;
862     }
863     KParts::ReadOnlyPart *part = factory->create< KParts::ReadOnlyPart >(parent);
864     if (! part) {
865         qWarning() << QString("Kross::FormModule::loadPart: Library \"%1\" is not a KPart").arg(name);
866         return nullptr;
867     }
868     if (url.isValid()) {
869         part->openUrl(url);
870     }
871     if (parent && parent->layout() && part->widget()) {
872         parent->layout()->addWidget(part->widget());
873     }
874     return part;
875 }
876 
877