00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022 #include "widgetfactory.h"
00023
00024 #include <qcursor.h>
00025 #include <qobjectlist.h>
00026 #include <qdict.h>
00027 #include <qmetaobject.h>
00028
00029 #include <kdebug.h>
00030 #include <klocale.h>
00031
00032 #include <ktextedit.h>
00033
00034 #include <klineedit.h>
00035
00036 #include <kdialogbase.h>
00037 #include <keditlistbox.h>
00038 #include <kxmlguiclient.h>
00039 #include <kactioncollection.h>
00040
00041 #include "richtextdialog.h"
00042 #include "editlistviewdialog.h"
00043 #include "resizehandle.h"
00044 #include "formmanager.h"
00045 #include "form.h"
00046 #include "container.h"
00047 #include "objecttree.h"
00048 #include "widgetlibrary.h"
00049 #include "utils.h"
00050 #include "widgetpropertyset.h"
00051 #include "widgetwithsubpropertiesinterface.h"
00052 #include <koproperty/property.h>
00053
00054 using namespace KFormDesigner;
00055
00057
00058 WidgetInfo::WidgetInfo(WidgetFactory *f)
00059 : m_inheritedClass(0)
00060 , m_overriddenAlternateNames(0)
00061 , m_factory(f)
00062 , m_propertiesWithDisabledAutoSync(0)
00063 , m_customTypesForProperty(0)
00064 {
00065 }
00066
00067 WidgetInfo::WidgetInfo(WidgetFactory *f, const char* parentFactoryName,
00068 const char* inheritedClassName)
00069 : m_parentFactoryName( QCString("kformdesigner_")+parentFactoryName )
00070 , m_inheritedClassName(inheritedClassName)
00071 , m_inheritedClass(0)
00072 , m_overriddenAlternateNames(0)
00073 , m_factory(f)
00074 , m_propertiesWithDisabledAutoSync(0)
00075 , m_customTypesForProperty(0)
00076 {
00077 m_class = inheritedClassName;
00078 }
00079
00080 WidgetInfo::~WidgetInfo()
00081 {
00082 delete m_overriddenAlternateNames;
00083 delete m_propertiesWithDisabledAutoSync;
00084 delete m_customTypesForProperty;
00085 }
00086
00087 void WidgetInfo::addAlternateClassName(const QCString& alternateName, bool override)
00088 {
00089 m_alternateNames += alternateName;
00090 if (override) {
00091 if (!m_overriddenAlternateNames)
00092 m_overriddenAlternateNames = new QAsciiDict<char>(101);
00093 m_overriddenAlternateNames->insert(alternateName, (char*)1);
00094 }
00095 else {
00096 if (m_overriddenAlternateNames)
00097 m_overriddenAlternateNames->take(alternateName);
00098 }
00099 }
00100
00101 bool WidgetInfo::isOverriddenClassName(const QCString& alternateName) const
00102 {
00103 return m_overriddenAlternateNames && (m_overriddenAlternateNames->find(alternateName) != 0);
00104 }
00105
00106 void WidgetInfo::setAutoSyncForProperty(const char *propertyName, tristate flag)
00107 {
00108 if (!m_propertiesWithDisabledAutoSync) {
00109 if (~flag)
00110 return;
00111 m_propertiesWithDisabledAutoSync = new QAsciiDict<char>(101);
00112 }
00113
00114 if (~flag) {
00115 m_propertiesWithDisabledAutoSync->remove(propertyName);
00116 }
00117 else {
00118 m_propertiesWithDisabledAutoSync->insert(propertyName, flag==true ? (char*)1 : (char*)2);
00119 }
00120 }
00121
00122 tristate WidgetInfo::autoSyncForProperty(const char *propertyName) const
00123 {
00124 char* flag = m_propertiesWithDisabledAutoSync ? m_propertiesWithDisabledAutoSync->find(propertyName) : 0;
00125 if (!flag)
00126 return cancelled;
00127 return flag==(char*)1 ? true : false;
00128 }
00129
00130 void WidgetInfo::setCustomTypeForProperty(const char *propertyName, int type)
00131 {
00132 if (!propertyName || type==KoProperty::Auto)
00133 return;
00134 if (!m_customTypesForProperty) {
00135 m_customTypesForProperty = new QMap<QCString,int>();
00136 }
00137 m_customTypesForProperty->replace(propertyName, type);
00138 }
00139
00140 int WidgetInfo::customTypeForProperty(const char *propertyName) const
00141 {
00142 if (!m_customTypesForProperty || !m_customTypesForProperty->contains(propertyName))
00143 return KoProperty::Auto;
00144 return (*m_customTypesForProperty)[propertyName];
00145 }
00146
00147
00149
00150 WidgetFactory::WidgetFactory(QObject *parent, const char *name)
00151 : QObject(parent, (const char*)(QCString("kformdesigner_")+name))
00152 {
00153 m_showAdvancedProperties = true;
00154 m_classesByName.setAutoDelete(true);
00155 m_hiddenClasses = 0;
00156 m_guiClient = 0;
00157 }
00158
00159 WidgetFactory::~WidgetFactory()
00160 {
00161 delete m_hiddenClasses;
00162 }
00163
00164 void WidgetFactory::addClass(WidgetInfo *w)
00165 {
00166 WidgetInfo *oldw = m_classesByName[w->className()];
00167 if (oldw==w)
00168 return;
00169 if (oldw) {
00170 kdWarning() << "WidgetFactory::addClass(): class with name '" << w->className()
00171 << "' already exists for factory '" << name() << "'" << endl;
00172 return;
00173 }
00174 m_classesByName.insert( w->className(), w );
00175 }
00176
00177 void WidgetFactory::hideClass(const char *classname)
00178 {
00179 if (!m_hiddenClasses)
00180 m_hiddenClasses = new QAsciiDict<char>(101, false);
00181 m_hiddenClasses->insert(classname, (char*)1);
00182 }
00183
00184 void
00185 WidgetFactory::createEditor(const QCString &classname, const QString &text,
00186 QWidget *w, Container *container, QRect geometry,
00187 int align, bool useFrame, bool multiLine, BackgroundMode background)
00188 {
00189
00190 if (multiLine) {
00191 KTextEdit *textedit = new KTextEdit(text, QString::null, w->parentWidget());
00192 textedit->setTextFormat(Qt::PlainText);
00193 textedit->setAlignment(align);
00194 if (dynamic_cast<QTextEdit*>(w)) {
00195 textedit->setWordWrap(dynamic_cast<QTextEdit*>(w)->wordWrap());
00196 textedit->setWrapPolicy(dynamic_cast<QTextEdit*>(w)->wrapPolicy());
00197 }
00198 textedit->setPalette(w->palette());
00199 textedit->setFont(w->font());
00200 textedit->setResizePolicy(QScrollView::Manual);
00201 textedit->setGeometry(geometry);
00202 if(background == Qt::NoBackground)
00203 textedit->setBackgroundMode(w->backgroundMode());
00204 else
00205 textedit->setBackgroundMode(background);
00206
00207 textedit->setPaletteBackgroundColor(w->paletteBackgroundColor());
00208 for(int i =0; i <= textedit->paragraphs(); i++)
00209 textedit->setParagraphBackgroundColor(i, w->paletteBackgroundColor());
00210 textedit->selectAll(true);
00211 textedit->setColor(w->paletteForegroundColor());
00212 textedit->selectAll(false);
00213 textedit->moveCursor(QTextEdit::MoveEnd, false);
00214 textedit->setParagraphBackgroundColor(0, w->paletteBackgroundColor());
00215 textedit->setVScrollBarMode(QScrollView::AlwaysOff);
00216 textedit->setHScrollBarMode(QScrollView::AlwaysOff);
00217 textedit->installEventFilter(this);
00218 textedit->setFrameShape(useFrame ? QFrame::LineEditPanel : QFrame::NoFrame);
00219 textedit->setMargin(2);
00220 textedit->show();
00221 textedit->setFocus();
00222 textedit->selectAll();
00223 setEditor(w, textedit);
00224
00225 connect(textedit, SIGNAL(textChanged()), this, SLOT(slotTextChanged()));
00226 connect(w, SIGNAL(destroyed()), this, SLOT(widgetDestroyed()));
00227 connect(textedit, SIGNAL(destroyed()), this, SLOT(editorDeleted()));
00228
00229 }
00230 else {
00231 KLineEdit *editor = new KLineEdit(text, w->parentWidget());
00232 editor->setAlignment(align);
00233 editor->setPalette(w->palette());
00234 editor->setFont(w->font());
00235 editor->setGeometry(geometry);
00236 if(background == Qt::NoBackground)
00237 editor->setBackgroundMode(w->backgroundMode());
00238 else
00239 editor->setBackgroundMode(background);
00240 editor->installEventFilter(this);
00241 editor->setFrame(useFrame);
00242 editor->setMargin(2);
00243 editor->show();
00244 editor->setFocus();
00245 editor->selectAll();
00246 connect(editor, SIGNAL(textChanged(const QString&)), this, SLOT(changeTextInternal(const QString&)));
00247 connect(w, SIGNAL(destroyed()), this, SLOT(widgetDestroyed()));
00248 connect(editor, SIGNAL(destroyed()), this, SLOT(editorDeleted()));
00249
00250 setEditor(w, editor);
00251
00252 }
00253
00254 WidgetWithSubpropertiesInterface* subpropIface = dynamic_cast<WidgetWithSubpropertiesInterface*>(w);
00255 QWidget *subwidget = (subpropIface && subpropIface->subwidget()) ? subpropIface->subwidget() : w;
00256 if (-1!=m_editor->metaObject()->findProperty("margin", true) && -1!=subwidget->metaObject()->findProperty("margin", true))
00257 m_editor->setProperty("margin", subwidget->property("margin"));
00258
00259
00260 m_handles = container->form()->resizeHandlesForWidget(w);
00261 if (m_handles) {
00262 m_handles->setEditingMode(true);
00263 m_handles->raise();
00264 }
00265
00266 ObjectTreeItem *tree = container->form()->objectTree()->lookup(w->name());
00267 if(!tree)
00268 return;
00269 tree->eventEater()->setContainer(this);
00270
00271
00272 setWidget(w, container);
00273 m_editedWidgetClass = classname;
00274 m_firstText = text;
00275
00276
00277 changeTextInternal(text);
00278 }
00279
00280 void
00281 WidgetFactory::disableFilter(QWidget *w, Container *container)
00282 {
00283 ObjectTreeItem *tree = container->form()->objectTree()->lookup(w->name());
00284 if(!tree)
00285 return;
00286 tree->eventEater()->setContainer(this);
00287
00288 w->setFocus();
00289
00290 m_handles = container->form()->resizeHandlesForWidget(w);
00291 if (m_handles) {
00292 m_handles->setEditingMode(true);
00293 m_handles->raise();
00294 }
00295
00296
00297 setWidget(w, container);
00298
00299 setEditor(w, 0);
00300
00301
00302
00303 if(!tree->isEnabled()) {
00304 QPalette p = w->palette();
00305 QColorGroup cg = p.active();
00306 p.setActive(p.disabled());
00307 p.setDisabled(cg);
00308 w->setPalette(p);
00309 }
00310
00311 connect(w, SIGNAL(destroyed()), this, SLOT(widgetDestroyed()));
00312 }
00313
00314 bool
00315 WidgetFactory::editList(QWidget *w, QStringList &list)
00316 {
00317 KDialogBase dialog(w->topLevelWidget(), "stringlist_dialog", true, i18n("Edit List of Items"),
00318 KDialogBase::Ok|KDialogBase::Cancel, KDialogBase::Ok, false);
00319
00320 KEditListBox *edit = new KEditListBox(i18n("Contents of %1").arg(w->name()), &dialog, "editlist");
00321 dialog.setMainWidget(edit);
00322 edit->insertStringList(list);
00323
00324
00325 if(dialog.exec() == QDialog::Accepted)
00326 {
00327 list = edit->items();
00328 return true;
00329 }
00330 return false;
00331 }
00332
00333 bool
00334 WidgetFactory::editRichText(QWidget *w, QString &text)
00335 {
00336 RichTextDialog dlg(w, text);
00337 if(dlg.exec()== QDialog::Accepted)
00338 {
00339 text = dlg.text();
00340 return true;
00341 }
00342 return false;
00343 }
00344
00345 void
00346 WidgetFactory::editListView(QListView *listview)
00347 {
00348 EditListViewDialog dlg(((QWidget*)listview)->topLevelWidget());
00349
00350 }
00351
00352 bool
00353 WidgetFactory::eventFilter(QObject *obj, QEvent *ev)
00354 {
00355 if( ((ev->type() == QEvent::Resize) || (ev->type() == QEvent::Move) ) && (obj == m_widget) && editor(m_widget)) {
00356
00357 QWidget *ed = editor(m_widget);
00358 resizeEditor(ed, m_widget, m_widget->className());
00359 }
00360 else if((ev->type() == QEvent::Paint) && (obj == m_widget) && editor(m_widget)) {
00361
00362 return m_container->eventFilter(obj, ev);
00363 }
00364 else if((ev->type() == QEvent::MouseButtonPress) && (obj == m_widget) && editor(m_widget)) {
00365
00366 Container *cont = m_container;
00367 resetEditor();
00368 return cont->eventFilter(obj, ev);
00369 }
00370
00371 if(ev->type() == QEvent::FocusOut)
00372 {
00373 QWidget *w = editor(m_widget);
00374 if (!w)
00375 w = (QWidget *)m_widget;
00376 if(obj != (QObject *)w)
00377 return false;
00378
00379 QWidget *focus = w->topLevelWidget()->focusWidget();
00380 if(focus && w != focus && !w->child(focus->name(), focus->className()))
00381 resetEditor();
00382 }
00383 else if(ev->type() == QEvent::KeyPress)
00384 {
00385 QWidget *w = editor(m_widget);
00386 if (!w)
00387 w = (QWidget *)m_widget;
00388 if(obj != (QObject *)w)
00389 return false;
00390
00391 QKeyEvent *e = static_cast<QKeyEvent*>(ev);
00392 if(((e->key() == Qt::Key_Return) || (e->key() == Qt::Key_Enter)) && (e->state() != AltButton))
00393 resetEditor();
00394 if(e->key() == Qt::Key_Escape)
00395 {
00396 setEditorText(m_firstText);
00397
00398 resetEditor();
00399 }
00400 }
00401 else if(ev->type() == QEvent::ContextMenu) {
00402 QWidget *w = editor(m_widget);
00403 if (!w)
00404 w = (QWidget *)m_widget;
00405 if(obj != (QObject *)w)
00406 return false;
00407
00408 return true;
00409 }
00410
00411
00412
00413 return false;
00414 }
00415
00416 void
00417 WidgetFactory::resetEditor()
00418 {
00419 if (m_container)
00420 m_container->stopInlineEditing();
00421
00422 QWidget *ed = editor(m_widget);
00423 if(m_widget)
00424 {
00425 ObjectTreeItem *tree = m_container ? m_container->form()->objectTree()->lookup(m_widget->name()) : 0;
00426 if(!tree)
00427 {
00428 kdDebug() << "WidgetFactory::resetEditor() : error cannot found a tree item " << endl;
00429 return;
00430 }
00431 tree->eventEater()->setContainer(m_container);
00432 if(m_widget) {
00433 setRecursiveCursor(m_widget, m_container->form());
00434 if (m_widget->inherits("QLineEdit") || m_widget->inherits("QTextEdit")) {
00435 m_widget->unsetCursor();
00436 m_widget->setCursor(Qt::ArrowCursor);
00437 }
00438 }
00439
00440
00441 if(!ed && !tree->isEnabled()) {
00442 QPalette p = m_widget->palette();
00443 QColorGroup cg = p.active();
00444 p.setActive(p.disabled());
00445 p.setDisabled(cg);
00446 m_widget->setPalette(p);
00447 }
00448 }
00449 if(ed)
00450 {
00451 changeTextInternal(editorText());
00452 disconnect(ed, 0, this, 0);
00453 ed->deleteLater();
00454 }
00455
00456 if(m_widget)
00457 {
00458 disconnect(m_widget, 0, this, 0);
00459 m_widget->repaint();
00460 }
00461
00462
00463 if (m_handles) {
00464 m_handles->setEditingMode(false);
00465 }
00466 setEditor(m_widget, 0);
00467
00468 setWidget(0, 0);
00469
00470 m_handles = 0;
00471
00472 }
00473
00474 void
00475 WidgetFactory::widgetDestroyed()
00476 {
00477 if(m_editor)
00478 {
00479 m_editor->deleteLater();
00480 m_editor = 0;
00481 }
00482
00483
00484 if (m_handles) {
00485 m_handles->setEditingMode(false);
00486
00487 }
00488 m_widget = 0;
00489 m_handles = 0;
00490 m_container = 0;
00491 }
00492
00493 void
00494 WidgetFactory::editorDeleted()
00495 {
00496
00497 if (m_handles) {
00498 m_handles->setEditingMode(false);
00499 }
00500 setEditor(m_widget, 0);
00501 setWidget(0, 0);
00502
00503 m_handles = 0;
00504
00505 }
00506
00507 void
00508 WidgetFactory::changeProperty(const char *name, const QVariant &value, Form *form)
00509
00510 {
00511
00512
00513 if(form->selectedWidgets()->count() > 1)
00514 {
00515 if(m_widget)
00516 m_widget->setProperty(name, value);
00517 else
00518 form->selectedWidgets()->first()->setProperty(name, value);
00519 }
00520 else
00521 {
00522 WidgetPropertySet *set = KFormDesigner::FormManager::self()->propertySet();
00523 if(set->contains(name))
00524 (*set)[name] = value;
00525 }
00526 }
00527
00528
00529
00530
00531
00532
00533
00534
00535
00536
00537
00538
00539
00540
00541
00542
00543 bool
00544 WidgetFactory::isPropertyVisible(const QCString &classname, QWidget *w,
00545 const QCString &property, bool multiple, bool isTopLevel)
00546 {
00547 if (multiple)
00548 {
00549 return property=="font" || property=="paletteBackgroundColor" || property=="enabled"
00550 || property=="paletteForegroundColor" || property=="cursor" || property=="paletteBackgroundPixmap";
00551 }
00552
00553
00554
00555
00556
00557
00558 return isPropertyVisibleInternal(classname, w, property, isTopLevel);
00559
00560 }
00561
00562 bool
00563 WidgetFactory::isPropertyVisibleInternal(const QCString &, QWidget *w,
00564 const QCString &property, bool isTopLevel)
00565 {
00566 Q_UNUSED( w );
00567
00568 #ifdef KEXI_NO_CURSOR_PROPERTY
00570 if (property=="cursor")
00571 return false;
00572 #endif
00573
00574 if (!isTopLevel
00575 && (property=="caption" || property=="icon" || property=="sizeIncrement" || property=="iconText")) {
00576
00577 return false;
00578 }
00579 return true;
00580 }
00581
00582 bool
00583 WidgetFactory::propertySetShouldBeReloadedAfterPropertyChange(const QCString& classname, QWidget *w,
00584 const QCString& property)
00585 {
00586 Q_UNUSED(classname);
00587 Q_UNUSED(w);
00588 Q_UNUSED(property);
00589 return false;
00590 }
00591
00592 void
00593 WidgetFactory::resizeEditor(QWidget *, QWidget *, const QCString&)
00594 {
00595 }
00596
00597 void
00598 WidgetFactory::slotTextChanged()
00599 {
00600 changeTextInternal(editorText());
00601 }
00602
00603 bool
00604 WidgetFactory::clearWidgetContent(const QCString &, QWidget *)
00605 {
00606 return false;
00607 }
00608
00609 void
00610 WidgetFactory::changeTextInternal(const QString& text)
00611 {
00612 if (changeText( text ))
00613 return;
00614
00615 if (!m_editedWidgetClass.isEmpty()) {
00616 WidgetInfo *wi = m_classesByName[ m_editedWidgetClass ];
00617 if (wi && wi->inheritedClass()) {
00618
00619 wi->inheritedClass()->factory()->changeText( text );
00620 }
00621 }
00622 }
00623
00624 bool
00625 WidgetFactory::changeText(const QString& text)
00626 {
00627 changeProperty( "text", text, m_container->form() );
00628 return true;
00629 }
00630
00631 bool
00632 WidgetFactory::readSpecialProperty(const QCString &, QDomElement &, QWidget *, ObjectTreeItem *)
00633 {
00634 return false;
00635 }
00636
00637 bool
00638 WidgetFactory::saveSpecialProperty(const QCString &, const QString &, const QVariant&, QWidget *, QDomElement &, QDomDocument &)
00639 {
00640 return false;
00641 }
00642
00643 bool WidgetFactory::inheritsFactories()
00644 {
00645 for (QAsciiDictIterator<WidgetInfo> it(m_classesByName); it.current(); ++it) {
00646 if (!it.current()->parentFactoryName().isEmpty())
00647 return true;
00648 }
00649 return false;
00650 }
00651
00652 QString WidgetFactory::editorText() const {
00653 QWidget *ed = editor(m_widget);
00654 return dynamic_cast<KTextEdit*>(ed) ? dynamic_cast<KTextEdit*>(ed)->text() : dynamic_cast<KLineEdit*>(ed)->text();
00655 }
00656
00657 void WidgetFactory::setEditorText(const QString& text) {
00658 QWidget *ed = editor(m_widget);
00659 if (dynamic_cast<KTextEdit*>(ed))
00660 dynamic_cast<KTextEdit*>(ed)->setText(text);
00661 else
00662 dynamic_cast<KLineEdit*>(ed)->setText(text);
00663 }
00664
00665 void WidgetFactory::setEditor(QWidget *widget, QWidget *editor)
00666 {
00667 if (!widget)
00668 return;
00669 WidgetInfo *winfo = m_classesByName[widget->className()];
00670 if (!winfo || winfo->parentFactoryName().isEmpty()) {
00671 m_editor = editor;
00672 }
00673 else {
00674 WidgetFactory *f = m_library->factory(winfo->parentFactoryName());
00675 if (f!=this)
00676 f->setEditor(widget, editor);
00677 m_editor = editor;
00678 }
00679 }
00680
00681 QWidget *WidgetFactory::editor(QWidget *widget) const
00682 {
00683 if (!widget)
00684 return 0;
00685 WidgetInfo *winfo = m_classesByName[widget->className()];
00686 if (!winfo || winfo->parentFactoryName().isEmpty()) {
00687 return m_editor;
00688 }
00689 else {
00690 WidgetFactory *f = m_library->factoryForClassName(widget->className());
00691 if (f!=this)
00692 return f->editor(widget);
00693 return m_editor;
00694 }
00695 }
00696
00697 void WidgetFactory::setWidget(QWidget *widget, Container* container)
00698 {
00699 WidgetInfo *winfo = widget ? m_classesByName[widget->className()] : 0;
00700 if (winfo && !winfo->parentFactoryName().isEmpty()) {
00701 WidgetFactory *f = m_library->factory(winfo->parentFactoryName());
00702 if (f!=this)
00703 f->setWidget(widget, container);
00704 }
00705 m_widget = widget;
00706 m_container = container;
00707 }
00708
00709 QWidget *WidgetFactory::widget() const
00710 {
00711 return m_widget;
00712 }
00713
00714 void WidgetFactory::setInternalProperty(const QCString& classname, const QCString& property,
00715 const QString& value)
00716 {
00717 m_internalProp[classname+":"+property]=value;
00718 }
00719
00720 void WidgetFactory::setPropertyOptions( WidgetPropertySet& , const WidgetInfo& , QWidget * )
00721 {
00722
00723 }
00724
00725 #include "widgetfactory.moc"