/* This file is part of the KDE project Copyright (C) 2004 Lucijan Busch Copyright (C) 2004 Cedric Pasteur Copyright (C) 2005 Jaroslaw Staniek This library 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 library 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 library; see the file COPYING.LIB. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, * Boston, MA 02110-1301, USA. */ #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 "kexiformview.h" #include "widgets/kexidbform.h" #include "kexiformscrollview.h" #include "kexiactionselectiondialog.h" #include "kexiformmanager.h" #include "kexiformpart.h" #include "kexidatasourcepage.h" //! @todo #define KEXI_SHOW_SPLITTER_WIDGET KFormDesigner::WidgetLibrary* KexiFormPart::static_formsLibrary = 0L; //! @internal class KexiFormPart::Private { public: Private() { } ~Private() { delete static_cast(objectTreeView); delete static_cast(dataSourcePage); } // TQGuardedPtr manager; TQGuardedPtr objectTreeView; TQGuardedPtr dataSourcePage; KexiDataSourceComboBox *dataSourceCombo; }; KexiFormPart::KexiFormPart(TQObject *tqparent, const char *name, const TQStringList &l) : KexiPart::Part(tqparent, name, l) , d(new Private()) { // REGISTERED ID: m_registeredPartID = (int)KexiPart::FormObjectType; kexipluginsdbg << "KexiFormPart::KexiFormPart()" << endl; m_names["instanceName"] = i18n("Translate this word using only lowercase alphanumeric characters (a..z, 0..9). " "Use '_' character instead of spaces. First character should be a..z character. " "If you cannot use latin characters in your language, use english word.", "form"); m_names["instanceCaption"] = i18n("Form"); m_supportedViewModes = Kexi::DataViewMode | Kexi::DesignViewMode; m_newObjectsAreDirty = true; // Only create form manager if it's not yet created. // KexiReportPart could have created it already. KFormDesigner::FormManager *formManager = KFormDesigner::FormManager::self(); if (!formManager) formManager = new KexiFormManager(this, "kexi_form_and_report_manager"); // Create and store a handle to forms' library. Reports will have their own library too. /* @todo add configuration for supported factory groups */ TQStringList supportedFactoryGroups; supportedFactoryGroups += "kexi"; static_formsLibrary = KFormDesigner::FormManager::createWidgetLibrary( formManager, supportedFactoryGroups); static_formsLibrary->setAdvancedPropertiesVisible(false); connect(static_formsLibrary, TQT_SIGNAL(widgetCreated(TQWidget*)), this, TQT_SLOT(slotWidgetCreatedByFormsLibrary(TQWidget*))); connect(KFormDesigner::FormManager::self()->propertySet(), TQT_SIGNAL(widgetPropertyChanged(TQWidget *, const TQCString &, const TQVariant&)), this, TQT_SLOT(slotPropertyChanged(TQWidget *, const TQCString &, const TQVariant&))); connect(KFormDesigner::FormManager::self(), TQT_SIGNAL(autoTabStopsSet(KFormDesigner::Form*,bool)), this, TQT_SLOT(slotAutoTabStopsSet(KFormDesigner::Form*,bool))); } KexiFormPart::~KexiFormPart() { delete d; } KFormDesigner::WidgetLibrary* KexiFormPart::library() { return static_formsLibrary; } #if 0 void KexiFormPart::initPartActions(KActionCollection *collection) { //this is automatic? -no //create child guicilent: guiClient()->setXMLFile("kexidatatableui.rc"); kexipluginsdbg<<"FormPart INIT ACTIONS***********************************************************************"<setXMLFile("kexiformui.rc"); //js m_manager->createActions(collection, 0); } void KexiFormPart::initInstanceActions( int mode, KActionCollection *col ) { if (mode==Kexi::DesignViewMode) { KFormDesigner::FormManager::self()->createActions(col, 0); new KAction(i18n("Edit Tab Order..."), "tab_order", KShortcut(0), KFormDesigner::FormManager::self(), TQT_SLOT(editTabOrder()), col, "taborder"); new KAction(i18n("Adjust Size"), "viewmagfit", KShortcut(0), KFormDesigner::FormManager::self(), TQT_SLOT(ajustWidgetSize()), col, "adjust"); } //TODO } #endif void KexiFormPart::initPartActions() { // new KAction(i18n("Show Form UI Code"), "show_form_ui", CTRL+Key_U, m_manager, TQT_SLOT(showFormUICode()), // guiClient()->actionCollection(), "show_form_ui"); } void KexiFormPart::initInstanceActions() { #ifdef KEXI_DEBUG_GUI kapp->config()->setGroup("General"); if (kapp->config()->readBoolEntry("showInternalDebugger", false)) { new KAction(i18n("Show Form UI Code"), "compfile", CTRL+Key_U, KFormDesigner::FormManager::self(), TQT_SLOT(showFormUICode()), actionCollectionForMode(Kexi::DesignViewMode), "show_form_ui"); } #endif KActionCollection *col = actionCollectionForMode(Kexi::DesignViewMode); KFormDesigner::FormManager::self()->createActions( library(), col, (KXMLGUIClient*)col->parentGUIClient() ); //guiClient() ); //connect actions provided by widget factories connect( col->action("widget_assign_action"), TQT_SIGNAL(activated()), this, TQT_SLOT(slotAssignAction())); createSharedAction(Kexi::DesignViewMode, i18n("Clear Widget Contents"), "editclear", 0, "formpart_clear_contents"); createSharedAction(Kexi::DesignViewMode, i18n("Edit Tab Order..."), "tab_order", 0, "formpart_taborder"); //TODO createSharedAction(Kexi::DesignViewMode, i18n("Edit Pixmap Collection"), "icons", 0, "formpart_pixmap_collection"); //TODO createSharedAction(Kexi::DesignViewMode, i18n("Edit Form Connections"), "connections", 0, "formpart_connections"); // KFormDesigner::CreateLayoutCommand KAction *action = createSharedAction(Kexi::DesignViewMode, i18n("Layout Widgets"), "", 0, "formpart_layout_menu", "KActionMenu"); KActionMenu *menu = static_cast(action); menu->insert( createSharedAction(Kexi::DesignViewMode, i18n("&Horizontally"), TQString(), 0, "formpart_layout_hbox")); menu->insert( createSharedAction(Kexi::DesignViewMode, i18n("&Vertically"), TQString(), 0, "formpart_layout_vbox")); menu->insert( createSharedAction(Kexi::DesignViewMode, i18n("In &Grid"), TQString(), 0, "formpart_layout_grid")); #ifdef KEXI_SHOW_SPLITTER_WIDGET menu->insert( createSharedAction(Kexi::DesignViewMode, i18n("Horizontally in &Splitter"), TQString(), 0, "formpart_layout_hsplitter")); menu->insert( createSharedAction(Kexi::DesignViewMode, i18n("Verti&cally in Splitter"), TQString(), 0, "formpart_layout_vsplitter")); #endif createSharedAction(Kexi::DesignViewMode, i18n("&Break Layout"), TQString(), 0, "formpart_break_layout"); /* createSharedAction(Kexi::DesignViewMode, i18n("Lay Out Widgets &Horizontally"), TQString(), 0, "formpart_layout_hbox"); createSharedAction(Kexi::DesignViewMode, i18n("Lay Out Widgets &Vertically"), TQString(), 0, "formpart_layout_vbox"); createSharedAction(Kexi::DesignViewMode, i18n("Lay Out Widgets in &Grid"), TQString(), 0, "formpart_layout_grid"); */ createSharedAction(Kexi::DesignViewMode, i18n("Bring Widget to Front"), "raise", 0, "formpart_format_raise"); createSharedAction(Kexi::DesignViewMode, i18n("Send Widget to Back"), "lower", 0, "formpart_format_lower"); #ifndef KEXI_NO_UNFINISHED action = createSharedAction(Kexi::DesignViewMode, i18n("Other Widgets"), "", 0, "other_widgets_menu", "KActionMenu"); #endif action = createSharedAction(Kexi::DesignViewMode, i18n("Align Widgets Position"), "aoleft", 0, "formpart_align_menu", "KActionMenu"); menu = static_cast(action); menu->insert( createSharedAction(Kexi::DesignViewMode, i18n("To Left"), "aoleft", 0, "formpart_align_to_left") ); menu->insert( createSharedAction(Kexi::DesignViewMode, i18n("To Right"), "aoright", 0, "formpart_align_to_right") ); menu->insert( createSharedAction(Kexi::DesignViewMode, i18n("To Top"), "aotop", 0, "formpart_align_to_top") ); menu->insert( createSharedAction(Kexi::DesignViewMode, i18n("To Bottom"), "aobottom", 0, "formpart_align_to_bottom") ); menu->insert( createSharedAction(Kexi::DesignViewMode, i18n("To Grid"), "aopos2grid", 0, "formpart_align_to_grid") ); action = createSharedAction(Kexi::DesignViewMode, i18n("Adjust Widgets Size"), "aogrid", 0, "formpart_adjust_size_menu", "KActionMenu"); menu = static_cast(action); menu->insert( createSharedAction(Kexi::DesignViewMode, i18n("To Fit"), "aofit", 0, "formpart_adjust_to_fit") ); menu->insert( createSharedAction(Kexi::DesignViewMode, i18n("To Grid"), "aogrid", 0, "formpart_adjust_size_grid") ); menu->insert( createSharedAction(Kexi::DesignViewMode, i18n("To Shortest"), "aoshortest", 0, "formpart_adjust_height_small") ); menu->insert( createSharedAction(Kexi::DesignViewMode, i18n("To Tallest"), "aotallest", 0, "formpart_adjust_height_big") ); menu->insert( createSharedAction(Kexi::DesignViewMode, i18n("To Narrowest"), "aonarrowest", 0, "formpart_adjust_width_small") ); menu->insert( createSharedAction(Kexi::DesignViewMode, i18n("To Widest"), "aowidest", 0, "formpart_adjust_width_big") ); } KexiDialogTempData* KexiFormPart::createTempData(KexiDialogBase* dialog) { return new KexiFormPart::TempData(TQT_TQOBJECT(dialog)); } KexiViewBase* KexiFormPart::createView(TQWidget *tqparent, KexiDialogBase* dialog, KexiPart::Item &item, int viewMode, TQMap*) { Q_UNUSED( viewMode ); kexipluginsdbg << "KexiFormPart::createView()" << endl; KexiMainWindow *win = dialog->mainWin(); if (!win || !win->project() || !win->project()->dbConnection()) return 0; KexiFormView *view = new KexiFormView(win, tqparent, item.name().latin1(), win->project()->dbConnection() ); return view; } void KexiFormPart::generateForm(KexiDB::FieldList *list, TQDomDocument &domDoc) { //this form generates a .ui from FieldList list //basically that is a Label and a LineEdit for each field domDoc = TQDomDocument("UI"); TQDomElement uiElement = domDoc.createElement("UI"); domDoc.appendChild(uiElement); uiElement.setAttribute("version", "3.1"); uiElement.setAttribute("stdsetdef", 1); TQDomElement baseClass = domDoc.createElement("class"); uiElement.appendChild(baseClass); TQDomText baseClassV = domDoc.createTextNode(TQWIDGET_OBJECT_NAME_STRING); baseClass.appendChild(baseClassV); TQDomElement baseWidget = domDoc.createElement("widget"); baseWidget.setAttribute("class", TQWIDGET_OBJECT_NAME_STRING); int y=0; for(unsigned int i=0; i < list->fieldCount(); i++) { TQDomElement lclass = domDoc.createElement("widget"); baseWidget.appendChild(lclass); lclass.setAttribute("class", TQLABEL_OBJECT_NAME_STRING); TQDomElement lNameProperty = domDoc.createElement("property"); lNameProperty.setAttribute("name", "name"); TQDomElement lType = domDoc.createElement("cstring"); TQDomText lClassN = domDoc.createTextNode(TQString("l%1").tqarg(list->field(i)->name())); lType.appendChild(lClassN); lNameProperty.appendChild(lType); lclass.appendChild(lNameProperty); TQDomElement gNameProperty = domDoc.createElement("property"); gNameProperty.setAttribute("name", "geometry"); TQDomElement lGType = domDoc.createElement("rect"); TQDomElement lx = domDoc.createElement("x"); TQDomText lxV = domDoc.createTextNode("10"); lx.appendChild(lxV); TQDomElement ly = domDoc.createElement("y"); TQDomText lyV = domDoc.createTextNode(TQString::number(y + 10)); ly.appendChild(lyV); TQDomElement lWidth = domDoc.createElement("width"); TQDomText lWidthV = domDoc.createTextNode("100"); lWidth.appendChild(lWidthV); TQDomElement lHeight = domDoc.createElement("height"); TQDomText lHeightV = domDoc.createTextNode("20"); lHeight.appendChild(lHeightV); lGType.appendChild(lx); lGType.appendChild(ly); lGType.appendChild(lWidth); lGType.appendChild(lHeight); gNameProperty.appendChild(lGType); lclass.appendChild(gNameProperty); TQDomElement tNameProperty = domDoc.createElement("property"); tNameProperty.setAttribute("name", "text"); TQDomElement lTType = domDoc.createElement("string"); TQDomText lTextV = domDoc.createTextNode(list->field(i)->name()); lTType.appendChild(lTextV); tNameProperty.appendChild(lTType); lclass.appendChild(tNameProperty); ///line edit! TQDomElement vclass = domDoc.createElement("widget"); baseWidget.appendChild(vclass); vclass.setAttribute("class", "KLineEdit"); TQDomElement vNameProperty = domDoc.createElement("property"); vNameProperty.setAttribute("name", "name"); TQDomElement vType = domDoc.createElement("cstring"); TQDomText vClassN = domDoc.createTextNode(list->field(i)->name()); vType.appendChild(vClassN); vNameProperty.appendChild(vType); vclass.appendChild(vNameProperty); TQDomElement vgNameProperty = domDoc.createElement("property"); vgNameProperty.setAttribute("name", "geometry"); TQDomElement vGType = domDoc.createElement("rect"); TQDomElement vx = domDoc.createElement("x"); TQDomText vxV = domDoc.createTextNode("110"); vx.appendChild(vxV); TQDomElement vy = domDoc.createElement("y"); TQDomText vyV = domDoc.createTextNode(TQString::number(y + 10)); vy.appendChild(vyV); TQDomElement vWidth = domDoc.createElement("width"); TQDomText vWidthV = domDoc.createTextNode("200"); vWidth.appendChild(vWidthV); TQDomElement vHeight = domDoc.createElement("height"); TQDomText vHeightV = domDoc.createTextNode("20"); vHeight.appendChild(vHeightV); vGType.appendChild(vx); vGType.appendChild(vy); vGType.appendChild(vWidth); vGType.appendChild(vHeight); vgNameProperty.appendChild(vGType); vclass.appendChild(vgNameProperty); y += 20; } TQDomElement lNameProperty = domDoc.createElement("property"); lNameProperty.setAttribute("name", "name"); TQDomElement lType = domDoc.createElement("cstring"); TQDomText lClassN = domDoc.createTextNode("DBForm"); lType.appendChild(lClassN); lNameProperty.appendChild(lType); baseWidget.appendChild(lNameProperty); TQDomElement wNameProperty = domDoc.createElement("property"); wNameProperty.setAttribute("name", "geometry"); TQDomElement wGType = domDoc.createElement("rect"); TQDomElement wx = domDoc.createElement("x"); TQDomText wxV = domDoc.createTextNode("0"); wx.appendChild(wxV); TQDomElement wy = domDoc.createElement("y"); TQDomText wyV = domDoc.createTextNode("0"); wy.appendChild(wyV); TQDomElement wWidth = domDoc.createElement("width"); TQDomText wWidthV = domDoc.createTextNode("340"); wWidth.appendChild(wWidthV); TQDomElement wHeight = domDoc.createElement("height"); TQDomText wHeightV = domDoc.createTextNode(TQString::number(y + 30)); wHeight.appendChild(wHeightV); wGType.appendChild(wx); wGType.appendChild(wy); wGType.appendChild(wWidth); wGType.appendChild(wHeight); wNameProperty.appendChild(wGType); baseWidget.appendChild(wNameProperty); uiElement.appendChild(baseWidget); } void KexiFormPart::slotAutoTabStopsSet(KFormDesigner::Form *form, bool set) { Q_UNUSED( form ); KoProperty::Property &p = (*KFormDesigner::FormManager::self()->propertySet())["autoTabStops"]; if (!p.isNull()) p.setValue(TQVariant(set, 4)); } void KexiFormPart::slotAssignAction() { KexiDBForm *dbform; if (!KFormDesigner::FormManager::self()->activeForm() || !KFormDesigner::FormManager::self()->activeForm()->designMode() || !(dbform = dynamic_cast(KFormDesigner::FormManager::self()->activeForm()->formWidget()))) return; KFormDesigner::WidgetPropertySet * propSet = KFormDesigner::FormManager::self()->propertySet(); KoProperty::Property &onClickActionProp = propSet->property("onClickAction"); if (onClickActionProp.isNull()) return; KoProperty::Property &onClickActionOptionProp = propSet->property("onClickActionOption"); KexiFormEventAction::ActionData data; data.string = onClickActionProp.value().toString(); if (!onClickActionOptionProp.isNull()) data.option = onClickActionOptionProp.value().toString(); KexiFormScrollView *scrollViewWidget = dynamic_cast(dbform->dataAwareObject()); if (!scrollViewWidget) return; KexiFormView* formViewWidget = dynamic_cast(scrollViewWidget->tqparent()); if (!formViewWidget) return; KexiMainWindow * mainWin = formViewWidget->parentDialog()->mainWin(); KexiActionSelectionDialog dlg(mainWin, dbform, data, propSet->property("name").value().toCString()); if(dlg.exec() == TQDialog::Accepted) { data = dlg.currentAction(); //update property value propSet->property("onClickAction").setValue(data.string); propSet->property("onClickActionOption").setValue(data.option); } } TQString KexiFormPart::i18nMessage(const TQCString& englishMessage, KexiDialogBase* dlg) const { Q_UNUSED(dlg); if (englishMessage=="Design of object \"%1\" has been modified.") return i18n("Design of form \"%1\" has been modified."); if (englishMessage=="Object \"%1\" already exists.") return i18n("Form \"%1\" already exists."); return englishMessage; } void KexiFormPart::slotPropertyChanged(TQWidget *w, const TQCString &name, const TQVariant &value) { Q_UNUSED( w ); if (!KFormDesigner::FormManager::self()->activeForm()) return; if (name == "autoTabStops") { //TQWidget *w = KFormDesigner::FormManager::self()->activeForm()->selectedWidget(); //update autoTabStops setting at KFD::Form level KFormDesigner::FormManager::self()->activeForm()->setAutoTabStops( value.toBool() ); } if (KFormDesigner::FormManager::self()->activeForm()->widget() && name == "geometry") { //fall back to sizeInternal property.... if (KFormDesigner::FormManager::self()->propertySet()->contains("sizeInternal")) KFormDesigner::FormManager::self()->propertySet()->property("sizeInternal").setValue(TQSize(value.toRect().size())); } } /*KFormDesigner::FormManager* KexiFormPart::manager() const { return d->manager; }*/ KexiDataSourcePage* KexiFormPart::dataSourcePage() const { return d->dataSourcePage; } void KexiFormPart::setupCustomPropertyPanelTabs(KTabWidget *tab, KexiMainWindow* mainWin) { if (!d->objectTreeView) { d->objectTreeView = new KFormDesigner::ObjectTreeView(0, "KexiFormPart:ObjectTreeView"); KFormDesigner::FormManager::self()->setObjectTreeView(d->objectTreeView); //important: assign to manager d->dataSourcePage = new KexiDataSourcePage(0, "dataSourcePage"); connect(d->dataSourcePage, TQT_SIGNAL(jumpToObjectRequested(const TQCString&, const TQCString&)), mainWin, TQT_SLOT(highlightObject(const TQCString&, const TQCString&))); connect(d->dataSourcePage, TQT_SIGNAL(formDataSourceChanged(const TQCString&, const TQCString&)), KFormDesigner::FormManager::self(), TQT_SLOT(setFormDataSource(const TQCString&, const TQCString&))); connect(d->dataSourcePage, TQT_SIGNAL(dataSourceFieldOrExpressionChanged(const TQString&, const TQString&, KexiDB::Field::Type)), KFormDesigner::FormManager::self(), TQT_SLOT(setDataSourceFieldOrExpression(const TQString&, const TQString&, KexiDB::Field::Type))); connect(d->dataSourcePage, TQT_SIGNAL(insertAutoFields(const TQString&, const TQString&, const TQStringList&)), KFormDesigner::FormManager::self(), TQT_SLOT(insertAutoFields(const TQString&, const TQString&, const TQStringList&))); } KexiProject *prj = mainWin->project(); d->dataSourcePage->setProject(prj); tab->addTab( d->dataSourcePage, SmallIconSet("database"), ""); tab->setTabToolTip( d->dataSourcePage, i18n("Data Source")); tab->addTab( d->objectTreeView, SmallIconSet("widgets"), ""); tab->setTabToolTip( d->objectTreeView, i18n("Widgets")); } void KexiFormPart::slotWidgetCreatedByFormsLibrary(TQWidget* widget) { TQStrList signalNames(widget->tqmetaObject()->signalNames()); if (!signalNames.isEmpty()) { const char *handleDragMoveEventSignal = "handleDragMoveEvent(TQDragMoveEvent*)"; const char *handleDropEventSignal = "handleDropEvent(TQDropEvent*)"; for (TQStrListIterator it(signalNames); it.current(); ++it) { if (0==qstrcmp(it.current(), handleDragMoveEventSignal)) { kdDebug() << it.current() << endl; KexiFormView *formView = KexiUtils::findParent(widget, "KexiFormView"); if (formView) { connect(widget, TQT_SIGNAL(handleDragMoveEvent(TQDragMoveEvent*)), formView, TQT_SLOT(slotHandleDragMoveEvent(TQDragMoveEvent*))); } } else if (0==qstrcmp(it.current(), handleDropEventSignal)) { kdDebug() << it.current() << endl; KexiFormView *formView = KexiUtils::findParent(widget, "KexiFormView"); if (formView) { connect(widget, TQT_SIGNAL(handleDropEvent(TQDropEvent*)), formView, TQT_SLOT(slotHandleDropEvent(TQDropEvent*))); } } } } } //---------------- KexiFormPart::TempData::TempData(TQObject* tqparent) : KexiDialogTempData(tqparent) { } KexiFormPart::TempData::~TempData() { } #include "kexiformpart.moc"