/*************************************************************************** * form.cpp * This file is part of the KDE project * copyright (C)2006-2007 by Sebastian Sauer (mail@dipe.org) * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Library General Public License for more details. * You should have received a copy of the GNU Library General Public License * along with this program; see the file COPYING. If not, write to * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, * Boston, MA 02110-1301, USA. ***************************************************************************/ #include "form.h" #include #include #include #include #include #include #include #include #include #include #include #include #include //#include #include #include #include #include #include #include #include #include //#include //#include //#include #include #include #include #include #include #include #include //#include //#include //#include //#include #include #include #include #include extern "C" { KDE_EXPORT QObject* krossmodule() { return new Kross::FormModule(); } } using namespace Kross; /********************************************************************************* * FormList */ FormListView::FormListView(QWidget* parent) : QListWidget(parent) {} FormListView::~FormListView() {} void FormListView::clear() { QListWidget::clear(); } void FormListView::remove(int index) { delete QListWidget::item(index); } void FormListView::addItem(const QString& text) { QListWidget::addItem(text); } int FormListView::count() { return QListWidget::count(); } int FormListView::current() { return QListWidget::currentRow(); } void FormListView::setCurrent(int row) { QListWidget::setCurrentRow(row); } QString FormListView::text(int row) { QListWidgetItem *item = QListWidget::item(row); return item ? item->text() : QString(); } /********************************************************************************* * FormFileWidget */ namespace Kross { /// \internal d-pointer class. class FormFileWidget::Private { public: KFileWidget* filewidget; QString filename; }; } FormFileWidget::FormFileWidget(QWidget* parent, const QString& startDirOrVariable) : QWidget(parent), d(new Private()) { QVBoxLayout* layout = new QVBoxLayout(this); layout->setSpacing(0); layout->setMargin(0); setLayout(layout); d->filewidget = new KFileWidget(KUrl(startDirOrVariable), this); layout->addWidget( d->filewidget ); //QMetaObject::invokeMethod(d->filewidget, "toggleSpeedbar", Q_ARG(bool,false)); //KFileDialog::setMode( KFile::File | KFile::LocalOnly ); // slotOk() emits accepted, accept() emits fileSelected() QObject::connect(d->filewidget, SIGNAL(fileSelected(QString)), this, SLOT(slotFileSelected(QString))); QObject::connect(d->filewidget, SIGNAL(fileSelected(QString)), this, SIGNAL(fileSelected(QString))); QObject::connect(d->filewidget, SIGNAL(fileHighlighted(QString)), this, SIGNAL(fileHighlighted(QString))); QObject::connect(d->filewidget, SIGNAL(selectionChanged()), this, SIGNAL(selectionChanged())); QObject::connect(d->filewidget, SIGNAL(filterChanged(QString)), this, SIGNAL(filterChanged(QString))); // d->impl->setOperationMode(d->mode); // if( d->mimeFilter.count() > 0 ) // d->impl->setMimeFilter(d->mimeFilter); // else if( ! d->filter.isEmpty() ) // d->impl->setFilter(d->filter); if( parent && parent->layout() ) parent->layout()->addWidget(this); setMinimumSize( QSize(480,360) ); } FormFileWidget::~FormFileWidget() { delete d; } void FormFileWidget::setMode(const QString& mode) { QMetaEnum e = metaObject()->enumerator( metaObject()->indexOfEnumerator("Mode") ); KFileWidget::OperationMode m = (KFileWidget::OperationMode) e.keysToValue( mode.toLatin1() ); d->filewidget->setOperationMode(m); } QString FormFileWidget::currentFilter() const { return d->filewidget->currentFilter(); } void FormFileWidget::setFilter(const QString &filter) { QString f = filter; f.replace(QRegExp("([^\\\\]{1,1})/"), "\\1\\/"); // escape '/' chars else KFileDialog assumes they are mimetypes :-/ d->filewidget->setFilter(f); } QString FormFileWidget::currentMimeFilter() const { return d->filewidget->currentMimeFilter(); } void FormFileWidget::setMimeFilter(const QStringList& filter) { d->filewidget->setMimeFilter(filter); } void FormFileWidget::slotFileSelected( const QString & fn ) { //kDebug()<filename = fn; } QString FormFileWidget::selectedFile() const { if ( d->filewidget->operationMode() != KFileWidget::Saving ) { d->filewidget->accept(); } else { //kDebug()<filename<filewidget->operationMode(); if ( d->filename.isEmpty() ) { // make KFileWidget create an url for us (including extension if necessary) QObject::connect(d->filewidget, SIGNAL(accepted()), d->filewidget, SLOT(accept())); d->filewidget->slotOk(); QObject::disconnect(d->filewidget, SIGNAL(accepted()), d->filewidget, SLOT(accept())); } } //kDebug()<filename; KUrl url( d->filename ); return url.path(); // strip file:// at least python chokes on it } /********************************************************************************* * FormProgressDialog */ namespace Kross { /// \internal d-pointer class. class FormProgressDialog::Private { public: QTextBrowser* browser; QProgressBar* bar; bool gotCanceled; QTime time; void update() { if( time.elapsed() >= 1000 ) { time.restart(); qApp->processEvents(); } } }; } FormProgressDialog::FormProgressDialog(const QString& caption, const QString& labelText) : KPageDialog(), d(new Private) { d->gotCanceled = false; d->time.start(); setCaption(caption); KDialog::setButtons(KDialog::Ok|KDialog::Cancel); setFaceType(KPageDialog::Plain); enableButton(KDialog::Ok, false); //setWindowModality(Qt::WindowModal); setModal(false); //true); setMinimumWidth(540); setMinimumHeight(400); QWidget* widget = new QWidget( mainWidget() ); KPageWidgetItem* item = KPageDialog::addPage(widget, QString()); item->setHeader(labelText); //item->setIcon( KIcon(iconname) ); widget = item->widget(); QVBoxLayout* layout = new QVBoxLayout(widget); layout->setMargin(0); widget->setLayout(layout); d->browser = new QTextBrowser(this); d->browser->setHtml(labelText); layout->addWidget(d->browser); d->bar = new QProgressBar(this); //d->bar->setFormat("%v"); d->bar->setVisible(false); layout->addWidget(d->bar); setSizePolicy( QSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding) ); show(); qApp->processEvents(); } FormProgressDialog::~FormProgressDialog() { delete d; } void FormProgressDialog::setValue(int progress) { if( progress < 0 ) { if( d->bar->isVisible() ) { d->bar->setVisible(false); d->bar->setValue(0); qApp->processEvents(); } return; } if( ! d->bar->isVisible() ) d->bar->setVisible(true); d->bar->setValue(progress); d->update(); } void FormProgressDialog::setRange(int minimum, int maximum) { d->bar->setRange(minimum, maximum); } void FormProgressDialog::setText(const QString& text) { d->browser->setHtml(text); d->update(); } void FormProgressDialog::addText(const QString& text) { QTextCursor cursor( d->browser->document()->end() ); cursor.movePosition(QTextCursor::End); cursor.insertBlock(); cursor.insertHtml(text); d->browser->moveCursor(QTextCursor::End); d->browser->ensureCursorVisible(); d->update(); } void FormProgressDialog::done(int r) { if( r == Rejected && ! d->gotCanceled ) { if( KMessageBox::messageBox(this, KMessageBox::WarningContinueCancel, i18n("Cancel?")) == KMessageBox::Continue ) { d->gotCanceled = true; enableButton(KDialog::Cancel, false); emit canceled(); } return; } KPageDialog::done(r); } int FormProgressDialog::exec() { enableButton(KDialog::Ok, true); enableButton(KDialog::Cancel, false); if( d->bar->isVisible() ) d->bar->setValue( d->bar->maximum() ); return KDialog::exec(); } bool FormProgressDialog::isCanceled() { return d->gotCanceled; } /********************************************************************************* * FormDialog */ namespace Kross { /// \internal d-pointer class. class FormDialog::Private { public: KDialog::ButtonCode buttoncode; QHash items; }; } FormDialog::FormDialog(const QString& caption) : KPageDialog( /*0, Qt::WShowModal | Qt::WDestructiveClose*/ ) , d( new Private() ) { setCaption(caption); KDialog::setButtons(KDialog::Ok); setSizePolicy( QSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding) ); connect(this, SIGNAL(currentPageChanged(KPageWidgetItem*,KPageWidgetItem*)), this, SLOT(slotCurrentPageChanged(KPageWidgetItem*))); } FormDialog::~FormDialog() { kWarning()<<"dtor"; delete d; } bool FormDialog::setButtons(const QString& buttons) { int i = metaObject()->indexOfEnumerator("ButtonCode"); Q_ASSERT( i >= 0 ); QMetaEnum e = metaObject()->enumerator(i); int v = e.keysToValue( buttons.toUtf8() ); if( v < 0 ) return false; KDialog::setButtons( (KDialog::ButtonCode) v ); return true; } bool FormDialog::setButtonText(const QString& button, const QString& text) { int i = metaObject()->indexOfEnumerator("ButtonCode"); Q_ASSERT( i >= 0 ); QMetaEnum e = metaObject()->enumerator(i); int v = e.keysToValue( button.toUtf8() ); if( v < 0 ) return false; KDialog::setButtonText( (KDialog::ButtonCode) v, text); return true; } bool FormDialog::setFaceType(const QString& facetype) { int i = KPageView::staticMetaObject.indexOfEnumerator("FaceType"); Q_ASSERT( i >= 0 ); QMetaEnum e = KPageView::staticMetaObject.enumerator(i); int v = e.keysToValue( facetype.toUtf8() ); if( v < 0 ) return false; KPageDialog::setFaceType( (KPageDialog::FaceType) v ); return true; } QString FormDialog::currentPage() const { KPageWidgetItem* item = KPageDialog::currentPage(); return item ? item->name() : QString(); } bool FormDialog::setCurrentPage(const QString& name) { if( ! d->items.contains(name) ) return false; KPageDialog::setCurrentPage( d->items[name] ); return true; } QWidget* FormDialog::page(const QString& name) const { return d->items.contains(name) ? d->items[name]->widget() : 0; } //shared by FormDialog and FormAssistant static KPageWidgetItem* formAddPage(KPageDialog* dialog, const QString& name, const QString& header, const QString& iconname) { QWidget* widget = new QWidget( dialog->mainWidget() ); QVBoxLayout* boxlayout = new QVBoxLayout(widget); boxlayout->setSpacing(0); boxlayout->setMargin(0); widget->setLayout(boxlayout); KPageWidgetItem* item = dialog->addPage(widget, name); item->setHeader(header.isNull() ? name : header); if( ! iconname.isEmpty() ) item->setIcon( KIcon(iconname) ); //d->items.insert(name, item); return item; } QWidget* FormDialog::addPage(const QString& name, const QString& header, const QString& iconname) { return d->items.insert(name, formAddPage((KPageDialog*)this,name,header,iconname)).value()->widget(); } void FormDialog::setMainWidget(QWidget *newMainWidget) { KDialog::setMainWidget(newMainWidget); } QString FormDialog::result() { int i = metaObject()->indexOfEnumerator("ButtonCode"); if( i < 0 ) { kWarning() << "Kross::FormDialog::setButtons No such enumerator \"ButtonCode\""; return QString(); } QMetaEnum e = metaObject()->enumerator(i); return e.valueToKey(d->buttoncode); } void FormDialog::slotButtonClicked(int button) { d->buttoncode = (KDialog::ButtonCode) button; KDialog::slotButtonClicked(button); } void FormDialog::slotCurrentPageChanged(KPageWidgetItem* current) { Q_UNUSED(current); //kDebug() << "FormDialog::slotCurrentPageChanged current=" << current->name(); //foreach(QWidget* widget, current->widget()->findChildren< QWidget* >("")) widget->setFocus(); } namespace Kross { /// \internal d-pointer class. class FormAssistant::Private { public: KDialog::ButtonCode buttoncode; QHash items; }; } FormAssistant::FormAssistant(const QString& caption) : KAssistantDialog( /*0, Qt::WShowModal | Qt::WDestructiveClose*/ ) , d( new Private() ) { setCaption(caption); setSizePolicy( QSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding) ); connect(this, SIGNAL(currentPageChanged(KPageWidgetItem*,KPageWidgetItem*)), this, SLOT(slotCurrentPageChanged(KPageWidgetItem*))); /* unlike boost qt does not support defining of slot call order! connect(this, SIGNAL(user2Clicked()), this, SIGNAL (nextClicked())); connect(this, SIGNAL(user3Clicked()), this, SIGNAL (backClicked())); */ } FormAssistant::~FormAssistant() { delete d; } void FormAssistant::showHelpButton(bool show) { showButton(KDialog::Help, show); } void FormAssistant::back() { emit backClicked(); KAssistantDialog::back(); } void FormAssistant::next() { emit nextClicked(); KAssistantDialog::next(); } QString FormAssistant::currentPage() const { KPageWidgetItem* item = KPageDialog::currentPage(); return item ? item->name() : QString(); } bool FormAssistant::setCurrentPage(const QString& name) { if( ! d->items.contains(name) ) return false; KPageDialog::setCurrentPage( d->items[name] ); return true; } QWidget* FormAssistant::page(const QString& name) const { return d->items.contains(name) ? d->items[name]->widget() : 0; } QWidget* FormAssistant::addPage(const QString& name, const QString& header, const QString& iconname) { return d->items.insert(name, formAddPage((KPageDialog*)this,name,header,iconname)).value()->widget(); } bool FormAssistant::isAppropriate (const QString& name) const { return d->items.contains(name) && KAssistantDialog::isAppropriate(d->items[name]); } void FormAssistant::setAppropriate (const QString& name, bool appropriate) { if (!d->items.contains(name)) return; KAssistantDialog::setAppropriate(d->items[name],appropriate); } bool FormAssistant::isValid (const QString& name) const { return d->items.contains(name) && KAssistantDialog::isValid(d->items[name]); } void FormAssistant::setValid (const QString& name, bool enable) { if (!d->items.contains(name)) return; KAssistantDialog::setValid(d->items[name],enable); } QString FormAssistant::result() { int i = metaObject()->indexOfEnumerator("AssistantButtonCode"); if( i < 0 ) { kWarning() << "Kross::FormAssistant::setButtons No such enumerator \"AssistantButtonCode\""; return QString(); } QMetaEnum e = metaObject()->enumerator(i); return e.valueToKey(FormAssistant::AssistantButtonCode(int(d->buttoncode))); } void FormAssistant::slotButtonClicked(int button) { d->buttoncode = (KDialog::ButtonCode) button; KDialog::slotButtonClicked(button); } void FormAssistant::slotCurrentPageChanged(KPageWidgetItem* current) { Q_UNUSED(current); //kDebug() << "FormAssistant::slotCurrentPageChanged current=" << current->name(); //foreach(QWidget* widget, current->widget()->findChildren< QWidget* >("")) widget->setFocus(); } /********************************************************************************* * FormModule */ namespace Kross { /// \internal extension of the QUiLoader class. class UiLoader : public QUiLoader { public: UiLoader() : QUiLoader() {} virtual ~UiLoader() {} /* virtual QAction* createAction(QObject* parent = 0, const QString& name = QString()) { } virtual QActionGroup* createActionGroup(QObject* parent = 0, const QString& name = QString()) { } virtual QLayout* createLayout(const QString& className, QObject* parent = 0, const QString& name = QString()) { } virtual QWidget* createWidget(const QString& className, QWidget* parent = 0, const QString& name = QString()) { } */ }; /// \internal d-pointer class. class FormModule::Private { public: }; } FormModule::FormModule() : QObject() , d( new Private() ) { } FormModule::~FormModule() { delete d; } QWidget* FormModule::activeModalWidget() { return QApplication::activeModalWidget(); } QWidget* FormModule::activeWindow() { return QApplication::activeWindow(); } QString FormModule::showMessageBox(const QString& dialogtype, const QString& caption, const QString& message, const QString& details) { KMessageBox::DialogType type; if(dialogtype == "Error") { if( ! details.isNull() ) { KMessageBox::detailedError(0, message, details, caption); return QString(); } type = KMessageBox::Error; } else if(dialogtype == "Sorry") { if( ! details.isNull() ) { KMessageBox::detailedSorry(0, message, details, caption); return QString(); } type = KMessageBox::Sorry; } else if(dialogtype == "QuestionYesNo") type = KMessageBox::QuestionYesNo; else if(dialogtype == "WarningYesNo") type = KMessageBox::WarningYesNo; else if(dialogtype == "WarningContinueCancel") type = KMessageBox::WarningContinueCancel; else if(dialogtype == "WarningYesNoCancel") type = KMessageBox::WarningYesNoCancel; else if(dialogtype == "QuestionYesNoCancel") type = KMessageBox::QuestionYesNoCancel; else /*if(dialogtype == "Information")*/ type = KMessageBox::Information; switch( KMessageBox::messageBox(0, type, message, caption) ) { case KMessageBox::Ok: return "Ok"; case KMessageBox::Cancel: return "Cancel"; case KMessageBox::Yes: return "Yes"; case KMessageBox::No: return "No"; case KMessageBox::Continue: return "Continue"; default: break; } return QString(); } QWidget* FormModule::showProgressDialog(const QString& caption, const QString& labelText) { return new FormProgressDialog(caption, labelText); } QWidget* FormModule::createDialog(const QString& caption) { return new FormDialog(caption); } QWidget* FormModule::createAssistant(const QString& caption) { return new FormAssistant(caption); } QObject* FormModule::createLayout(QWidget* parent, const QString& layout) { QLayout* l = 0; if( layout == "QVBoxLayout" ) l = new QVBoxLayout(); else if( layout == "QHBoxLayout" ) l = new QHBoxLayout(); else if( layout == "QStackedLayout" ) l = new QStackedLayout(); if( parent && l ) parent->setLayout(l); return l; } QWidget* FormModule::createWidget(const QString& className) { UiLoader loader; QWidget* widget = loader.createWidget(className); return widget; } QWidget* FormModule::createWidget(QWidget* parent, const QString& className, const QString& name) { UiLoader loader; QWidget* widget = loader.createWidget(className, parent, name); if( parent && parent->layout() ) parent->layout()->addWidget(widget); return widget; } QString FormModule::tr(const QString& str) { return QObject::tr(str.toUtf8()); } QString FormModule::tr(const QString& str, const QString& comment) { return QObject::tr(str.toUtf8(),comment.toUtf8()); } QWidget* FormModule::createWidgetFromUI(QWidget* parent, const QString& xml) { QUiLoader loader; QDomDocument doc("mydocument"); doc.setContent(xml.toUtf8()); QDomNodeList strings=doc.elementsByTagName("string"); int i=strings.size(); while(--i>=0) { QDomElement e=strings.at(i).toElement(); QString i18nd=e.attribute("comment").isEmpty()?QObject::tr(e.text().toUtf8()):QObject::tr(e.text().toUtf8(),e.attribute("comment").toUtf8()); if (i18nd==e.text()) continue; QDomNode n = e.firstChild(); while (!n.isNull()) { QDomNode nn=n.nextSibling(); if (n.isCharacterData()) e.removeChild(n); n = nn; } e.appendChild(e.ownerDocument().createTextNode(i18nd)); } QByteArray ba = doc.toByteArray(); QBuffer buffer(&ba); buffer.open(QIODevice::ReadOnly); QWidget* widget = loader.load(&buffer, parent); if( widget && parent && parent->layout() ) parent->layout()->addWidget(widget); return widget; } QWidget* FormModule::createWidgetFromUIFile(QWidget* parent, const QString& filename) { QFile file(filename); if( ! file.exists() ) { kDebug() << QString("Kross::FormModule::createWidgetFromUIFile: There exists no such file \"%1\"").arg(filename); return 0; } if( ! file.open(QFile::ReadOnly) ) { kDebug() << QString("Kross::FormModule::createWidgetFromUIFile: Failed to open the file \"%1\"").arg(filename); return 0; } const QString xml = file.readAll(); file.close(); return createWidgetFromUI(parent, xml); } QWidget* FormModule::createFileWidget(QWidget* parent, const QString& startDirOrVariable) { FormFileWidget* widget = new FormFileWidget(parent, startDirOrVariable); if( parent && parent->layout() ) parent->layout()->addWidget(widget); return widget; } QWidget* FormModule::createListView(QWidget* parent) { FormListView* widget = new FormListView(parent); if( parent && parent->layout() ) parent->layout()->addWidget(widget); return widget; } QAction* FormModule::createAction(QObject* parent) { return new QAction(parent); } QObject* FormModule::loadPart(QWidget* parent, const QString& name, const QUrl& url) { //name e.g. "libkghostview" KPluginFactory* factory = KPluginLoader( name.toLatin1() ).factory(); if( ! factory ) { kWarning() << QString("Kross::FormModule::loadPart: No such library \"%1\"").arg(name); return 0; } KParts::ReadOnlyPart* part = factory->create< KParts::ReadOnlyPart >( parent ); if( ! part ) { kWarning() << QString("Kross::FormModule::loadPart: Library \"%1\" is not a KPart").arg(name); return 0; } if( url.isValid() ) part->openUrl(url); if( parent && parent->layout() && part->widget() ) parent->layout()->addWidget( part->widget() ); return part; } #include "form.moc"