00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022 #include <kdebug.h>
00023 #include <kgenericfactory.h>
00024 #include <kdialogbase.h>
00025 #include <klistview.h>
00026 #include <ktabwidget.h>
00027 #include <kiconloader.h>
00028 #include <kcombobox.h>
00029 #include <kapplication.h>
00030 #include <kconfig.h>
00031
00032 #include <kexiviewbase.h>
00033 #include <keximainwindow.h>
00034 #include <kexiproject.h>
00035 #include <kexipartitem.h>
00036 #include <kexidialogbase.h>
00037 #include <kexidatasourcecombobox.h>
00038 #include <kexidb/connection.h>
00039 #include <kexidb/fieldlist.h>
00040 #include <kexidb/field.h>
00041
00042 #include <form.h>
00043 #include <formIO.h>
00044 #include <widgetpropertyset.h>
00045 #include <widgetlibrary.h>
00046 #include <objecttreeview.h>
00047 #include <koproperty/property.h>
00048
00049 #include "kexiformview.h"
00050 #include "widgets/kexidbform.h"
00051 #include "kexiformscrollview.h"
00052 #include "kexiactionselectiondialog.h"
00053 #include "kexiformmanager.h"
00054 #include "kexiformpart.h"
00055 #include "kexidatasourcepage.h"
00056
00058
00059 KFormDesigner::WidgetLibrary* KexiFormPart::static_formsLibrary = 0L;
00060
00062 class KexiFormPart::Private
00063 {
00064 public:
00065 Private()
00066 {
00067 }
00068 ~Private()
00069 {
00070 delete static_cast<KFormDesigner::ObjectTreeView*>(objectTreeView);
00071 delete static_cast<KexiDataSourcePage*>(dataSourcePage);
00072 }
00073
00074 QGuardedPtr<KFormDesigner::ObjectTreeView> objectTreeView;
00075 QGuardedPtr<KexiDataSourcePage> dataSourcePage;
00076 KexiDataSourceComboBox *dataSourceCombo;
00077 };
00078
00079 KexiFormPart::KexiFormPart(QObject *parent, const char *name, const QStringList &l)
00080 : KexiPart::Part(parent, name, l)
00081 , d(new Private())
00082 {
00083
00084 m_registeredPartID = (int)KexiPart::FormObjectType;
00085
00086 kexipluginsdbg << "KexiFormPart::KexiFormPart()" << endl;
00087 m_names["instanceName"]
00088 = i18n("Translate this word using only lowercase alphanumeric characters (a..z, 0..9). "
00089 "Use '_' character instead of spaces. First character should be a..z character. "
00090 "If you cannot use latin characters in your language, use english word.",
00091 "form");
00092 m_names["instanceCaption"] = i18n("Form");
00093 m_supportedViewModes = Kexi::DataViewMode | Kexi::DesignViewMode;
00094 m_newObjectsAreDirty = true;
00095
00096
00097
00098 KFormDesigner::FormManager *formManager = KFormDesigner::FormManager::self();
00099 if (!formManager)
00100 formManager = new KexiFormManager(this, "kexi_form_and_report_manager");
00101
00102
00103
00104 QStringList supportedFactoryGroups;
00105 supportedFactoryGroups += "kexi";
00106 static_formsLibrary = KFormDesigner::FormManager::createWidgetLibrary(
00107 formManager, supportedFactoryGroups);
00108 static_formsLibrary->setAdvancedPropertiesVisible(false);
00109
00110 connect(KFormDesigner::FormManager::self()->propertySet(), SIGNAL(widgetPropertyChanged(QWidget *, const QCString &, const QVariant&)),
00111 this, SLOT(slotPropertyChanged(QWidget *, const QCString &, const QVariant&)));
00112 connect(KFormDesigner::FormManager::self(), SIGNAL(autoTabStopsSet(KFormDesigner::Form*,bool)),
00113 this, SLOT(slotAutoTabStopsSet(KFormDesigner::Form*,bool)));
00114 }
00115
00116 KexiFormPart::~KexiFormPart()
00117 {
00118 delete d;
00119 }
00120
00121 KFormDesigner::WidgetLibrary* KexiFormPart::library()
00122 {
00123 return static_formsLibrary;
00124 }
00125
00126 #if 0
00127 void KexiFormPart::initPartActions(KActionCollection *collection)
00128 {
00129
00130
00131
00132 kexipluginsdbg<<"FormPart INIT ACTIONS***********************************************************************"<<endl;
00133
00134
00135
00136
00137 }
00138
00139 void KexiFormPart::initInstanceActions( int mode, KActionCollection *col )
00140 {
00141 if (mode==Kexi::DesignViewMode) {
00142 KFormDesigner::FormManager::self()->createActions(col, 0);
00143 new KAction(i18n("Edit Tab Order..."), "tab_order", KShortcut(0), KFormDesigner::FormManager::self(), SLOT(editTabOrder()), col, "taborder");
00144 new KAction(i18n("Adjust Size"), "viewmagfit", KShortcut(0), KFormDesigner::FormManager::self(), SLOT(ajustWidgetSize()), col, "adjust");
00145 }
00146
00147 }
00148 #endif
00149
00150 void KexiFormPart::initPartActions()
00151 {
00152
00153
00154 }
00155
00156 void KexiFormPart::initInstanceActions()
00157 {
00158 #ifdef KEXI_DEBUG_GUI
00159 kapp->config()->setGroup("General");
00160 if (kapp->config()->readBoolEntry("showInternalDebugger", false)) {
00161 new KAction(i18n("Show Form UI Code"), "compfile",
00162 CTRL+Key_U, KFormDesigner::FormManager::self(), SLOT(showFormUICode()),
00163 actionCollectionForMode(Kexi::DesignViewMode), "show_form_ui");
00164 }
00165 #endif
00166
00167 KActionCollection *col = actionCollectionForMode(Kexi::DesignViewMode);
00168 KFormDesigner::FormManager::self()->createActions( library(), col, (KXMLGUIClient*)col->parentGUIClient() );
00169
00170
00171 connect( col->action("widget_assign_action"), SIGNAL(activated()), this, SLOT(slotAssignAction()));
00172
00173 createSharedAction(Kexi::DesignViewMode, i18n("Clear Widget Contents"), "editclear", 0, "formpart_clear_contents");
00174 createSharedAction(Kexi::DesignViewMode, i18n("Edit Tab Order..."), "tab_order", 0, "formpart_taborder");
00175
00176
00177
00178
00179
00180 KAction *action = createSharedAction(Kexi::DesignViewMode, i18n("Layout Widgets"), "", 0, "formpart_layout_menu", "KActionMenu");
00181 KActionMenu *menu = static_cast<KActionMenu*>(action);
00182
00183 menu->insert( createSharedAction(Kexi::DesignViewMode, i18n("&Horizontally"),
00184 QString::null, 0, "formpart_layout_hbox"));
00185 menu->insert( createSharedAction(Kexi::DesignViewMode, i18n("&Vertically"),
00186 QString::null, 0, "formpart_layout_vbox"));
00187 menu->insert( createSharedAction(Kexi::DesignViewMode, i18n("In &Grid"),
00188 QString::null, 0, "formpart_layout_grid"));
00189 #ifdef KEXI_SHOW_SPLITTER_WIDGET
00190 menu->insert( createSharedAction(Kexi::DesignViewMode, i18n("Horizontally in &Splitter"),
00191 QString::null, 0, "formpart_layout_hsplitter"));
00192 menu->insert( createSharedAction(Kexi::DesignViewMode, i18n("Verti&cally in Splitter"),
00193 QString::null, 0, "formpart_layout_vsplitter"));
00194 #endif
00195
00196 createSharedAction(Kexi::DesignViewMode, i18n("&Break Layout"), QString::null, 0, "formpart_break_layout");
00197
00198
00199
00200
00201
00202 createSharedAction(Kexi::DesignViewMode, i18n("Bring Widget to Front"), "raise", 0, "formpart_format_raise");
00203 createSharedAction(Kexi::DesignViewMode, i18n("Send Widget to Back"), "lower", 0, "formpart_format_lower");
00204
00205 #ifndef KEXI_NO_UNFINISHED
00206 action = createSharedAction(Kexi::DesignViewMode, i18n("Other Widgets"), "", 0, "other_widgets_menu", "KActionMenu");
00207 #endif
00208
00209 action = createSharedAction(Kexi::DesignViewMode, i18n("Align Widgets Position"), "aoleft", 0, "formpart_align_menu", "KActionMenu");
00210 menu = static_cast<KActionMenu*>(action);
00211 menu->insert( createSharedAction(Kexi::DesignViewMode, i18n("To Left"), "aoleft", 0, "formpart_align_to_left") );
00212 menu->insert( createSharedAction(Kexi::DesignViewMode, i18n("To Right"), "aoright", 0, "formpart_align_to_right") );
00213 menu->insert( createSharedAction(Kexi::DesignViewMode, i18n("To Top"), "aotop", 0, "formpart_align_to_top") );
00214 menu->insert( createSharedAction(Kexi::DesignViewMode, i18n("To Bottom"), "aobottom", 0, "formpart_align_to_bottom") );
00215 menu->insert( createSharedAction(Kexi::DesignViewMode, i18n("To Grid"), "aopos2grid", 0, "formpart_align_to_grid") );
00216
00217 action = createSharedAction(Kexi::DesignViewMode, i18n("Adjust Widgets Size"), "aogrid", 0, "formpart_adjust_size_menu", "KActionMenu");
00218 menu = static_cast<KActionMenu*>(action);
00219 menu->insert( createSharedAction(Kexi::DesignViewMode, i18n("To Fit"), "aofit", 0, "formpart_adjust_to_fit") );
00220 menu->insert( createSharedAction(Kexi::DesignViewMode, i18n("To Grid"), "aogrid", 0, "formpart_adjust_size_grid") );
00221 menu->insert( createSharedAction(Kexi::DesignViewMode, i18n("To Shortest"), "aoshortest", 0, "formpart_adjust_height_small") );
00222 menu->insert( createSharedAction(Kexi::DesignViewMode, i18n("To Tallest"), "aotallest", 0, "formpart_adjust_height_big") );
00223 menu->insert( createSharedAction(Kexi::DesignViewMode, i18n("To Narrowest"), "aonarrowest", 0, "formpart_adjust_width_small") );
00224 menu->insert( createSharedAction(Kexi::DesignViewMode, i18n("To Widest"), "aowidest", 0, "formpart_adjust_width_big") );
00225 }
00226
00227 KexiDialogTempData*
00228 KexiFormPart::createTempData(KexiDialogBase* dialog)
00229 {
00230 return new KexiFormPart::TempData(dialog);
00231 }
00232
00233 KexiViewBase* KexiFormPart::createView(QWidget *parent, KexiDialogBase* dialog,
00234 KexiPart::Item &item, int viewMode, QMap<QString,QString>*)
00235 {
00236 Q_UNUSED( viewMode );
00237
00238 kexipluginsdbg << "KexiFormPart::createView()" << endl;
00239 KexiMainWindow *win = dialog->mainWin();
00240 if (!win || !win->project() || !win->project()->dbConnection())
00241 return 0;
00242
00243 KexiFormView *view = new KexiFormView(win, parent, item.name().latin1(),
00244 win->project()->dbConnection() );
00245
00246 return view;
00247 }
00248
00249 void
00250 KexiFormPart::generateForm(KexiDB::FieldList *list, QDomDocument &domDoc)
00251 {
00252
00253
00254 domDoc = QDomDocument("UI");
00255 QDomElement uiElement = domDoc.createElement("UI");
00256 domDoc.appendChild(uiElement);
00257 uiElement.setAttribute("version", "3.1");
00258 uiElement.setAttribute("stdsetdef", 1);
00259
00260 QDomElement baseClass = domDoc.createElement("class");
00261 uiElement.appendChild(baseClass);
00262 QDomText baseClassV = domDoc.createTextNode("QWidget");
00263 baseClass.appendChild(baseClassV);
00264 QDomElement baseWidget = domDoc.createElement("widget");
00265 baseWidget.setAttribute("class", "QWidget");
00266
00267 int y=0;
00268
00269 for(unsigned int i=0; i < list->fieldCount(); i++)
00270 {
00271 QDomElement lclass = domDoc.createElement("widget");
00272 baseWidget.appendChild(lclass);
00273 lclass.setAttribute("class", "QLabel");
00274 QDomElement lNameProperty = domDoc.createElement("property");
00275 lNameProperty.setAttribute("name", "name");
00276 QDomElement lType = domDoc.createElement("cstring");
00277 QDomText lClassN = domDoc.createTextNode(QString("l%1").arg(list->field(i)->name()));
00278 lType.appendChild(lClassN);
00279 lNameProperty.appendChild(lType);
00280 lclass.appendChild(lNameProperty);
00281
00282 QDomElement gNameProperty = domDoc.createElement("property");
00283 gNameProperty.setAttribute("name", "geometry");
00284 QDomElement lGType = domDoc.createElement("rect");
00285
00286 QDomElement lx = domDoc.createElement("x");
00287 QDomText lxV = domDoc.createTextNode("10");
00288 lx.appendChild(lxV);
00289 QDomElement ly = domDoc.createElement("y");
00290 QDomText lyV = domDoc.createTextNode(QString::number(y + 10));
00291 ly.appendChild(lyV);
00292 QDomElement lWidth = domDoc.createElement("width");
00293 QDomText lWidthV = domDoc.createTextNode("100");
00294 lWidth.appendChild(lWidthV);
00295 QDomElement lHeight = domDoc.createElement("height");
00296 QDomText lHeightV = domDoc.createTextNode("20");
00297 lHeight.appendChild(lHeightV);
00298
00299 lGType.appendChild(lx);
00300 lGType.appendChild(ly);
00301 lGType.appendChild(lWidth);
00302 lGType.appendChild(lHeight);
00303
00304 gNameProperty.appendChild(lGType);
00305 lclass.appendChild(gNameProperty);
00306
00307 QDomElement tNameProperty = domDoc.createElement("property");
00308 tNameProperty.setAttribute("name", "text");
00309 QDomElement lTType = domDoc.createElement("string");
00310 QDomText lTextV = domDoc.createTextNode(list->field(i)->name());
00311 lTType.appendChild(lTextV);
00312 tNameProperty.appendChild(lTType);
00313 lclass.appendChild(tNameProperty);
00314
00315
00317
00318
00319 QDomElement vclass = domDoc.createElement("widget");
00320 baseWidget.appendChild(vclass);
00321 vclass.setAttribute("class", "KLineEdit");
00322 QDomElement vNameProperty = domDoc.createElement("property");
00323 vNameProperty.setAttribute("name", "name");
00324 QDomElement vType = domDoc.createElement("cstring");
00325 QDomText vClassN = domDoc.createTextNode(list->field(i)->name());
00326 vType.appendChild(vClassN);
00327 vNameProperty.appendChild(vType);
00328 vclass.appendChild(vNameProperty);
00329
00330 QDomElement vgNameProperty = domDoc.createElement("property");
00331 vgNameProperty.setAttribute("name", "geometry");
00332 QDomElement vGType = domDoc.createElement("rect");
00333
00334 QDomElement vx = domDoc.createElement("x");
00335 QDomText vxV = domDoc.createTextNode("110");
00336 vx.appendChild(vxV);
00337 QDomElement vy = domDoc.createElement("y");
00338 QDomText vyV = domDoc.createTextNode(QString::number(y + 10));
00339 vy.appendChild(vyV);
00340 QDomElement vWidth = domDoc.createElement("width");
00341 QDomText vWidthV = domDoc.createTextNode("200");
00342 vWidth.appendChild(vWidthV);
00343 QDomElement vHeight = domDoc.createElement("height");
00344 QDomText vHeightV = domDoc.createTextNode("20");
00345 vHeight.appendChild(vHeightV);
00346
00347 vGType.appendChild(vx);
00348 vGType.appendChild(vy);
00349 vGType.appendChild(vWidth);
00350 vGType.appendChild(vHeight);
00351
00352 vgNameProperty.appendChild(vGType);
00353 vclass.appendChild(vgNameProperty);
00354
00355 y += 20;
00356 }
00357
00358 QDomElement lNameProperty = domDoc.createElement("property");
00359 lNameProperty.setAttribute("name", "name");
00360 QDomElement lType = domDoc.createElement("cstring");
00361 QDomText lClassN = domDoc.createTextNode("DBForm");
00362 lType.appendChild(lClassN);
00363 lNameProperty.appendChild(lType);
00364 baseWidget.appendChild(lNameProperty);
00365
00366 QDomElement wNameProperty = domDoc.createElement("property");
00367 wNameProperty.setAttribute("name", "geometry");
00368 QDomElement wGType = domDoc.createElement("rect");
00369
00370 QDomElement wx = domDoc.createElement("x");
00371 QDomText wxV = domDoc.createTextNode("0");
00372 wx.appendChild(wxV);
00373 QDomElement wy = domDoc.createElement("y");
00374 QDomText wyV = domDoc.createTextNode("0");
00375 wy.appendChild(wyV);
00376 QDomElement wWidth = domDoc.createElement("width");
00377 QDomText wWidthV = domDoc.createTextNode("340");
00378 wWidth.appendChild(wWidthV);
00379 QDomElement wHeight = domDoc.createElement("height");
00380 QDomText wHeightV = domDoc.createTextNode(QString::number(y + 30));
00381 wHeight.appendChild(wHeightV);
00382
00383 wGType.appendChild(wx);
00384 wGType.appendChild(wy);
00385 wGType.appendChild(wWidth);
00386 wGType.appendChild(wHeight);
00387
00388 wNameProperty.appendChild(wGType);
00389 baseWidget.appendChild(wNameProperty);
00390
00391 uiElement.appendChild(baseWidget);
00392 }
00393
00394 void KexiFormPart::slotAutoTabStopsSet(KFormDesigner::Form *form, bool set)
00395 {
00396 Q_UNUSED( form );
00397
00398 KoProperty::Property &p = (*KFormDesigner::FormManager::self()->propertySet())["autoTabStops"];
00399 if (!p.isNull())
00400 p.setValue(QVariant(set, 4));
00401 }
00402
00403 void KexiFormPart::slotAssignAction()
00404 {
00405 KexiDBForm *dbform;
00406 if (!KFormDesigner::FormManager::self()->activeForm() || !KFormDesigner::FormManager::self()->activeForm()->designMode()
00407 || !(dbform = dynamic_cast<KexiDBForm*>(KFormDesigner::FormManager::self()->activeForm()->formWidget())))
00408 return;
00409
00410 KFormDesigner::WidgetPropertySet * propSet = KFormDesigner::FormManager::self()->propertySet();
00411
00412 KoProperty::Property &onClickActionProp = propSet->property("onClickAction");
00413 if (onClickActionProp.isNull())
00414 return;
00415 KoProperty::Property &onClickActionOptionProp = propSet->property("onClickActionOption");
00416 KexiFormEventAction::ActionData data;
00417 data.string = onClickActionProp.value().toString();
00418 if (!onClickActionOptionProp.isNull())
00419 data.option = onClickActionOptionProp.value().toString();
00420
00421 KexiFormScrollView *scrollViewWidget = dynamic_cast<KexiFormScrollView*>(dbform->dataAwareObject());
00422 if (!scrollViewWidget)
00423 return;
00424 KexiFormView* formViewWidget = dynamic_cast<KexiFormView*>(scrollViewWidget->parent());
00425 if (!formViewWidget)
00426 return;
00427
00428 KexiMainWindow * mainWin = formViewWidget->parentDialog()->mainWin();
00429 KexiActionSelectionDialog dlg(mainWin, dbform, data,
00430 propSet->property("name").value().toCString());
00431
00432 if(dlg.exec() == QDialog::Accepted) {
00433 data = dlg.currentAction();
00434
00435 propSet->property("onClickAction").setValue(data.string);
00436 propSet->property("onClickActionOption").setValue(data.option);
00437 }
00438 }
00439
00440 QString
00441 KexiFormPart::i18nMessage(const QCString& englishMessage, KexiDialogBase* dlg) const
00442 {
00443 Q_UNUSED(dlg);
00444 if (englishMessage=="Design of object \"%1\" has been modified.")
00445 return i18n("Design of form \"%1\" has been modified.");
00446 if (englishMessage=="Object \"%1\" already exists.")
00447 return i18n("Form \"%1\" already exists.");
00448
00449 return englishMessage;
00450 }
00451
00452 void
00453 KexiFormPart::slotPropertyChanged(QWidget *w, const QCString &name, const QVariant &value)
00454 {
00455 Q_UNUSED( w );
00456
00457 if (!KFormDesigner::FormManager::self()->activeForm())
00458 return;
00459 if (name == "autoTabStops") {
00460
00461
00462 KFormDesigner::FormManager::self()->activeForm()->setAutoTabStops( value.toBool() );
00463 }
00464 if (KFormDesigner::FormManager::self()->activeForm()->widget() && name == "geometry") {
00465
00466 if (KFormDesigner::FormManager::self()->propertySet()->contains("sizeInternal"))
00467 KFormDesigner::FormManager::self()->propertySet()->property("sizeInternal").setValue(value.toRect().size());
00468 }
00469 }
00470
00471
00472
00473
00474
00475
00476
00477 KexiDataSourcePage* KexiFormPart::dataSourcePage() const
00478 {
00479 return d->dataSourcePage;
00480 }
00481
00482 void KexiFormPart::setupCustomPropertyPanelTabs(KTabWidget *tab, KexiMainWindow* mainWin)
00483 {
00484 if (!d->objectTreeView) {
00485 d->objectTreeView = new KFormDesigner::ObjectTreeView(0, "KexiFormPart:ObjectTreeView");
00486 KFormDesigner::FormManager::self()->setObjectTreeView(d->objectTreeView);
00487 d->dataSourcePage = new KexiDataSourcePage(0, "dataSourcePage");
00488 connect(d->dataSourcePage, SIGNAL(jumpToObjectRequested(const QCString&, const QCString&)),
00489 mainWin, SLOT(highlightObject(const QCString&, const QCString&)));
00490 connect(d->dataSourcePage, SIGNAL(formDataSourceChanged(const QCString&, const QCString&)),
00491 KFormDesigner::FormManager::self(), SLOT(setFormDataSource(const QCString&, const QCString&)));
00492 connect(d->dataSourcePage, SIGNAL(dataSourceFieldOrExpressionChanged(const QString&, const QString&, KexiDB::Field::Type)),
00493 KFormDesigner::FormManager::self(), SLOT(setDataSourceFieldOrExpression(const QString&, const QString&, KexiDB::Field::Type)));
00494 connect(d->dataSourcePage, SIGNAL(insertAutoFields(const QString&, const QString&, const QStringList&)),
00495 KFormDesigner::FormManager::self(), SLOT(insertAutoFields(const QString&, const QString&, const QStringList&)));
00496 }
00497
00498 KexiProject *prj = mainWin->project();
00499 d->dataSourcePage->setProject(prj);
00500
00501 tab->addTab( d->dataSourcePage, SmallIconSet("database"), "");
00502 tab->setTabToolTip( d->dataSourcePage, i18n("Data Source"));
00503
00504 tab->addTab( d->objectTreeView, SmallIconSet("widgets"), "");
00505 tab->setTabToolTip( d->objectTreeView, i18n("Widgets"));
00506 }
00507
00508
00509
00510 KexiFormPart::TempData::TempData(QObject* parent)
00511 : KexiDialogTempData(parent)
00512 {
00513 }
00514
00515 KexiFormPart::TempData::~TempData()
00516 {
00517 }
00518
00519 #include "kexiformpart.moc"