File indexing completed on 2024-05-12 16:39:51

0001 /* This file is part of the KDE project
0002    Copyright (C) 2003 Lucijan Busch <lucijan@gmx.at>
0003    Copyright (C) 2004 Cedric Pasteur <cedric.pasteur@free.fr>
0004    Copyright (C) 2004-2009 Jarosław Staniek <staniek@kde.org>
0005 
0006    This library is free software; you can redistribute it and/or
0007    modify it under the terms of the GNU Library General Public
0008    License as published by the Free Software Foundation; either
0009    version 2 of the License, or (at your option) any later version.
0010 
0011    This library is distributed in the hope that it will be useful,
0012    but WITHOUT ANY WARRANTY; without even the implied warranty of
0013    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
0014    Library General Public License for more details.
0015 
0016    You should have received a copy of the GNU Library General Public License
0017    along with this library; see the file COPYING.LIB.  If not, write to
0018    the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
0019  * Boston, MA 02110-1301, USA.
0020 */
0021 
0022 #include "widgetfactory.h"
0023 
0024 #include <KEditListWidget>
0025 #include <KLocalizedString>
0026 
0027 #include "richtextdialog.h"
0028 #ifdef KEXI_LIST_FORM_WIDGET_SUPPORT
0029 # include "editlistviewdialog.h"
0030 #endif
0031 
0032 #include "form.h"
0033 #include "container.h"
0034 #include "objecttree.h"
0035 #include "widgetlibrary.h"
0036 #include "WidgetInfo.h"
0037 #include "widgetwithsubpropertiesinterface.h"
0038 #include "utils.h"
0039 #include <kexiutils/utils.h>
0040 
0041 #include <KProperty>
0042 #include <KPropertySet>
0043 
0044 #include <QDialog>
0045 #include <QVBoxLayout>
0046 #include <QDialogButtonBox>
0047 #include <QDebug>
0048 
0049 using namespace KFormDesigner;
0050 
0051 InternalPropertyHandlerInterface::InternalPropertyHandlerInterface()
0052 {
0053 }
0054 
0055 InternalPropertyHandlerInterface::~InternalPropertyHandlerInterface()
0056 {
0057 }
0058 
0059 ///// InlineEditorCreationArguments //////////////////////////
0060 
0061 WidgetFactory::InlineEditorCreationArguments::InlineEditorCreationArguments(
0062     const QByteArray& _classname, QWidget *_widget, Container *_container)
0063     : classname(_classname), widget(_widget), container(_container),
0064       geometry(_widget ? _widget->geometry() : QRect()),
0065       alignment( Qt::AlignLeft ),
0066       useFrame( false ), multiLine( false ), execute( true ), transparentBackground( false )
0067 {
0068 }
0069 
0070 ///// Widget Factory //////////////////////////
0071 
0072 class Q_DECL_HIDDEN WidgetFactory::Private
0073 {
0074 public:
0075     Private();
0076     ~Private();
0077 
0078     WidgetLibrary *library;
0079 
0080     QHash<QByteArray, WidgetInfo*> classesByName;
0081     QSet<QByteArray>* hiddenClasses;
0082 
0083     //! i18n stuff
0084     QHash<QByteArray, QString> propDesc;
0085     QHash<QByteArray, QString> propValDesc;
0086     //! internal properties
0087     QHash<QByteArray, QVariant> internalProp;
0088 
0089     /*! flag useful to decide whether to hide some properties.
0090      It's value is inherited from WidgetLibrary. */
0091     bool advancedPropertiesVisible;
0092 };
0093 
0094 WidgetFactory::Private::Private()
0095     : hiddenClasses(0), advancedPropertiesVisible(true)
0096 {
0097 
0098 }
0099 
0100 WidgetFactory::Private::~Private()
0101 {
0102     qDeleteAll(classesByName);
0103     delete hiddenClasses;
0104 }
0105 
0106 WidgetFactory::WidgetFactory(QObject *parent)
0107     : QObject(parent), d(new Private())
0108 {
0109 }
0110 
0111 WidgetFactory::~WidgetFactory()
0112 {
0113     delete d;
0114 }
0115 
0116 void WidgetFactory::addClass(WidgetInfo *w)
0117 {
0118     WidgetInfo *oldw = d->classesByName.value(w->className());
0119     if (oldw == w)
0120         return;
0121     if (oldw) {
0122         qWarning() << "class with name '"
0123             << w->className()
0124             << "' already exists for factory '" << objectName() << "'";
0125         return;
0126     }
0127     d->classesByName.insert(w->className(), w);
0128 }
0129 
0130 void WidgetFactory::hideClass(const char *classname)
0131 {
0132     if (!d->hiddenClasses)
0133         d->hiddenClasses = new QSet<QByteArray>;
0134     d->hiddenClasses->insert(QByteArray(classname).toLower());
0135 }
0136 
0137 QHash<QByteArray, WidgetInfo*> WidgetFactory::classes() const
0138 {
0139     return d->classesByName;
0140 }
0141 
0142 void WidgetFactory::disableFilter(QWidget *w, Container *container)
0143 {
0144     container->form()->disableFilter(w, container);
0145 }
0146 
0147 bool WidgetFactory::editList(QWidget *w, QStringList &list) const
0148 {
0149     //! @todo KEXI3 port to QDialog
0150 #if 1
0151     Q_UNUSED(w);
0152     Q_UNUSED(list);
0153 #else
0154     QDialog dialog(w->topLevelWidget());
0155     dialog.setObjectName("stringlist_dialog");
0156     dialog.setModal(true);
0157     dialog.setWindowTitle(xi18nc("@title:window", "Edit Contents of %1", w->objectName()));
0158     dialog.setButtons(QDialog::Ok | QDialog::Cancel);
0159 
0160     QVBoxLayout *mainLayout = new QVBoxLayout;
0161     dialog.setLayout(mainLayout);
0162     KEditListWidget *edit = new KEditListWidget(&dialog);
0163     edit->setObjectName("editlist");
0164     edit->insertStringList(list);
0165     mainLayout->addWidget(edit);
0166 
0167     // buttons
0168     QDialogButtonBox *buttonBox = new QDialogButtonBox(QDialogButtonBox::Ok|QDialogButtonBox::Cancel);
0169     mainLayout->addWidget(buttonBox);
0170     QPushButton *okButton = buttonBox->button(QDialogButtonBox::Ok);
0171     okButton->setDefault(true);
0172     okButton->setShortcut(Qt::CTRL | Qt::Key_Return);
0173     connect(buttonBox, SIGNAL(accepted()), &dialog, SLOT(accept()));
0174     connect(buttonBox, SIGNAL(rejected()), &dialog, SLOT(reject()));
0175 
0176     if (dialog.exec() == QDialog::Accepted) {
0177         list = edit->items();
0178         return true;
0179     }
0180 #endif
0181     return false;
0182 }
0183 
0184 bool WidgetFactory::editRichText(QWidget *w, QString &text) const
0185 {
0186     RichTextDialog dlg(w, text);
0187     if (dlg.exec() == QDialog::Accepted) {
0188         text = dlg.text();
0189         return true;
0190     }
0191     return false;
0192 }
0193 
0194 #ifdef KEXI_LIST_FORM_WIDGET_SUPPORT
0195 void
0196 WidgetFactory::editListWidget(QListWidget *listwidget) const
0197 {
0198     EditListViewDialog dlg(static_cast<QWidget*>(listwidget)->topLevelWidget());
0199     Q_UNUSED(dlg)
0200 //! @todo
0201     //dlg.exec(listview);
0202 }
0203 #endif
0204 
0205 void WidgetFactory::changeProperty(Form *form, QWidget *widget, const char *name, const QVariant &value)
0206 {
0207     if (form->selectedWidget()) { // single selection
0208         form->propertySet()->changePropertyIfExists(name, value);
0209         widget->setProperty(name, value);
0210     }
0211     else {
0212         // If eg multiple labels are selected,
0213         // we only want to change the text of one of them (the one the user cliked on)
0214         if (widget) {
0215             widget->setProperty(name, value);
0216         }
0217         else {
0218             form->selectedWidgets()->first()->setProperty(name, value);
0219         }
0220     }
0221 }
0222 
0223 bool
0224 WidgetFactory::isPropertyVisible(const QByteArray &classname, QWidget *w,
0225                                  const QByteArray &property, bool multiple, bool isTopLevel)
0226 {
0227     if (multiple) {
0228         return property == "font" || property == "paletteBackgroundColor" || property == "enabled"
0229                || property == "paletteForegroundColor" || property == "cursor"
0230                || property == "paletteBackgroundPixmap";
0231     }
0232 
0233     return isPropertyVisibleInternal(classname, w, property, isTopLevel);
0234 }
0235 
0236 bool
0237 WidgetFactory::isPropertyVisibleInternal(const QByteArray &, QWidget *w,
0238         const QByteArray &property, bool isTopLevel)
0239 {
0240     Q_UNUSED(w);
0241 
0242 #ifndef KEXI_FORM_CURSOR_PROPERTY_SUPPORT
0243 //! @todo temporary unless cursor works properly in the Designer
0244     if (property == "cursor")
0245         return false;
0246 #endif
0247     if (property == "acceptDrops" || property == "inputMethodHints")
0248         return false;
0249 
0250     if (!isTopLevel
0251             && (property == "windowTitle" || property == "windowIcon" || property == "sizeIncrement" || property == "windowIconText")) {
0252         // don't show these properties for a non-toplevel widget
0253         return false;
0254     }
0255     return true;
0256 }
0257 
0258 bool
0259 WidgetFactory::propertySetShouldBeReloadedAfterPropertyChange(
0260     const QByteArray& classname, QWidget *w, const QByteArray& property)
0261 {
0262     Q_UNUSED(classname)
0263     Q_UNUSED(w)
0264     Q_UNUSED(property)
0265     return false;
0266 }
0267 
0268 void
0269 WidgetFactory::resizeEditor(QWidget *, QWidget *, const QByteArray&)
0270 {
0271 }
0272 
0273 bool
0274 WidgetFactory::clearWidgetContent(const QByteArray &, QWidget *)
0275 {
0276     return false;
0277 }
0278 
0279 bool WidgetFactory::changeInlineText(Form *form, QWidget *widget,
0280                                      const QString& text, QString *oldText)
0281 {
0282     if (oldText) {
0283         *oldText = widget->property("text").toString();
0284     }
0285     changeProperty(form, widget, "text", text);
0286     return true;
0287 }
0288 
0289 bool
0290 WidgetFactory::readSpecialProperty(const QByteArray &, QDomElement &, QWidget *, ObjectTreeItem *)
0291 {
0292     return false;
0293 }
0294 
0295 bool
0296 WidgetFactory::saveSpecialProperty(const QByteArray &, const QString &, const QVariant&, QWidget *, QDomElement &,  QDomDocument &)
0297 {
0298     return false;
0299 }
0300 
0301 bool WidgetFactory::inheritsFactories()
0302 {
0303     foreach (WidgetInfo *winfo, d->classesByName) {
0304         if (!winfo->parentFactoryName().isEmpty())
0305             return true;
0306     }
0307     return false;
0308 }
0309 
0310 void WidgetFactory::setPropertyOptions(KPropertySet& set, const WidgetInfo& info, QWidget *w)
0311 {
0312     Q_UNUSED(set)
0313     Q_UNUSED(info)
0314     Q_UNUSED(w)
0315     //nothing
0316 }
0317 
0318 ObjectTreeItem* WidgetFactory::selectableItem(ObjectTreeItem* item)
0319 {
0320     return item;
0321 }
0322 
0323 void WidgetFactory::setInternalProperty(const QByteArray &classname, const QByteArray &property, const QVariant &value)
0324 {
0325     d->internalProp.insert(classname + ":" + property, value);
0326 }
0327 
0328 QVariant WidgetFactory::internalProperty(const QByteArray &classname, const QByteArray &property) const
0329 {
0330     return d->internalProp.value(classname + ":" + property);
0331 }
0332 
0333 QString WidgetFactory::propertyDescription(const char* name) const
0334 {
0335     return d->propDesc.value(name);
0336 }
0337 
0338 QString WidgetFactory::valueDescription(const char* name) const
0339 {
0340     return d->propValDesc.value(name);
0341 }
0342 
0343 WidgetInfo* WidgetFactory::widgetInfoForClassName(const char* classname)
0344 {
0345     return d->classesByName.value(classname);
0346 }
0347 
0348 const QSet<QByteArray> *WidgetFactory::hiddenClasses() const
0349 {
0350     return d->hiddenClasses;
0351 }
0352 
0353 WidgetLibrary* WidgetFactory::library()
0354 {
0355     return d->library;
0356 }
0357 
0358 bool WidgetFactory::advancedPropertiesVisible() const
0359 {
0360     return d->advancedPropertiesVisible;
0361 }
0362 
0363 void WidgetFactory::setLibrary(WidgetLibrary* library)
0364 {
0365     d->library = library;
0366 }
0367 
0368 void WidgetFactory::setAdvancedPropertiesVisible(bool set)
0369 {
0370     d->advancedPropertiesVisible = set;
0371 }
0372 
0373 void WidgetFactory::setPropertyDescription(const char* property, const QString &description)
0374 {
0375     d->propDesc.insert(property, description);
0376 }
0377 
0378 void WidgetFactory::setValueDescription(const char *valueName, const QString &description)
0379 {
0380     d->propValDesc.insert(valueName, description);
0381 }
0382