00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021 #include "kexidialogbase.h"
00022
00023 #include "keximainwindow.h"
00024 #include "kexiviewbase.h"
00025 #include "kexicontexthelp_p.h"
00026 #include "kexipart.h"
00027 #include "kexistaticpart.h"
00028 #include "kexipartitem.h"
00029 #include "kexipartinfo.h"
00030 #include "kexiproject.h"
00031
00032 #include <kexidb/connection.h>
00033 #include <kexidb/utils.h>
00034 #include <kexiutils/utils.h>
00035
00036 #include <qwidgetstack.h>
00037 #include <qobjectlist.h>
00038
00039 #include <kdebug.h>
00040 #include <kapplication.h>
00041 #include <kiconloader.h>
00042
00043 KexiDialogBase::KexiDialogBase(KexiMainWindow *parent, const QString &caption)
00044 : KMdiChildView(caption, parent, "KexiDialogBase")
00045 , KexiActionProxy(this, parent)
00046 , m_isRegistered(false)
00047 , m_origCaption(caption)
00048 , m_schemaData(0)
00049 , m_destroying(false)
00050 , m_disableDirtyChanged(false)
00051
00052 {
00053 m_supportedViewModes = 0;
00054 m_openedViewModes = 0;
00055 m_currentViewMode = Kexi::NoViewMode;
00056 m_parentWindow = parent;
00057 m_creatingViewsMode = -1;
00058
00059 QVBoxLayout *lyr = new QVBoxLayout(this);
00060 m_stack = new QWidgetStack(this, "stack");
00061 lyr->addWidget(m_stack);
00062
00063 #ifdef KEXI_NO_CTXT_HELP
00064 m_contextHelpInfo=new KexiContextHelpInfo();
00065 #endif
00066
00067 m_id = -1;
00068 m_item = 0;
00069
00070 hide();
00071 }
00072
00073 KexiDialogBase::~KexiDialogBase()
00074 {
00075 m_destroying = true;
00076 }
00077
00078 KexiViewBase *KexiDialogBase::selectedView() const
00079 {
00080 if (m_destroying)
00081 return 0;
00082
00083 return static_cast<KexiViewBase*>( m_stack->widget(m_currentViewMode) );
00084 }
00085
00086 KexiViewBase *KexiDialogBase::viewForMode(int mode) const
00087 {
00088 return static_cast<KexiViewBase*>( m_stack->widget(mode) );
00089 }
00090
00091 void KexiDialogBase::addView(KexiViewBase *view)
00092 {
00093 addView(view,0);
00094 }
00095
00096 void KexiDialogBase::addView(KexiViewBase *view, int mode)
00097 {
00098 m_stack->addWidget(view, mode);
00099
00100
00101
00102 QWidget *ch = static_cast<QWidget*>(view->child( 0, "QWidget", false ));
00103 if (ch)
00104 view->setFocusProxy(ch);
00105
00106 m_openedViewModes |= mode;
00107 }
00108
00109 QSize KexiDialogBase::minimumSizeHint() const
00110 {
00111 KexiViewBase *v = selectedView();
00112 if (!v)
00113 return KMdiChildView::minimumSizeHint();
00114 return v->minimumSizeHint() + QSize(0, mdiParent() ? mdiParent()->captionHeight() : 0);
00115 }
00116
00117 QSize KexiDialogBase::sizeHint() const
00118 {
00119 KexiViewBase *v = selectedView();
00120 if (!v)
00121 return KMdiChildView::sizeHint();
00122 return v->preferredSizeHint( v->sizeHint() );
00123 }
00124
00125
00126
00127
00128
00129
00130 void KexiDialogBase::registerDialog() {
00131 if (m_isRegistered)
00132 return;
00133 m_parentWindow->registerChild(this);
00134 m_isRegistered=true;
00135 if ( m_parentWindow->mdiMode() == KMdi::ToplevelMode ) {
00136 m_parentWindow->addWindow( (KMdiChildView *)this, KMdi::Detach );
00137 m_parentWindow->detachWindow((KMdiChildView *)this, true);
00138 }
00139 else
00140 m_parentWindow->addWindow((KMdiChildView *)this);
00141
00142
00143 }
00144
00145 bool KexiDialogBase::isRegistered(){
00146 return m_isRegistered;
00147 }
00148
00149 void KexiDialogBase::attachToGUIClient() {
00150 if (!guiClient())
00151 return;
00152
00153 }
00154
00155 void KexiDialogBase::detachFromGUIClient() {
00156 if (!guiClient())
00157 return;
00158
00159 }
00160
00161 int KexiDialogBase::id() const
00162 {
00163 return (partItem() && partItem()->identifier()>0) ? partItem()->identifier() : m_id;
00164 }
00165
00166 void KexiDialogBase::setContextHelp(const QString& caption, const QString& text, const QString& iconName) {
00167 #ifdef KEXI_NO_CTXT_HELP
00168 m_contextHelpInfo->caption=caption;
00169 m_contextHelpInfo->text=text;
00170 m_contextHelpInfo->text=iconName;
00171 updateContextHelp();
00172 #endif
00173 }
00174
00175 void KexiDialogBase::closeEvent( QCloseEvent * e )
00176 {
00177 m_parentWindow->acceptPropertySetEditing();
00178
00179
00180 QObjectList *list = m_stack->queryList( "KexiViewBase", 0, false, false);
00181 KexiViewBase *view;
00182 QObjectListIt it( *list );
00183 for ( ;(view = static_cast<KexiViewBase*>(it.current()) ) != 0; ++it ) {
00184 bool cancel = false;
00185 emit view->closing(cancel);
00186 if (cancel) {
00187 e->ignore();
00188 return;
00189 }
00190 }
00191 delete list;
00192 emit closing();
00193 KMdiChildView::closeEvent(e);
00194 }
00195
00196 #if 0
00197
00198 bool KexiDialogBase::tryClose(bool dontSaveChanges)
00199 {
00200 if (!dontSaveChanges && dirty()) {
00201
00202
00203
00204
00205
00206 }
00207 close(true);
00208 return true;
00209 }
00210 #endif
00211
00212 bool KexiDialogBase::dirty() const
00213 {
00214
00215 int m = m_openedViewModes, mode = 1;
00216 while (m>0) {
00217 if (m & 1) {
00218 if (static_cast<KexiViewBase*>(m_stack->widget(mode))->dirty())
00219 return true;
00220 }
00221 m >>= 1;
00222 mode <<= 1;
00223 }
00224 return false;
00225
00226
00227 }
00228
00229 void KexiDialogBase::setDirty(bool dirty)
00230 {
00231 m_disableDirtyChanged = true;
00232 int m = m_openedViewModes, mode = 1;
00233 while (m>0) {
00234 if (m & 1) {
00235 static_cast<KexiViewBase*>(m_stack->widget(mode))->setDirty(dirty);
00236 }
00237 m >>= 1;
00238 mode <<= 1;
00239 }
00240 m_disableDirtyChanged = false;
00241 dirtyChanged(m_viewThatRecentlySetDirtyFlag);
00242 }
00243
00244 QString KexiDialogBase::itemIcon()
00245 {
00246 if (!m_part || !m_part->info()) {
00247 KexiViewBase *v = selectedView();
00248 if (v) {
00249 return v->m_defaultIconName;
00250 }
00251 return QString::null;
00252 }
00253 return m_part->info()->itemIcon();
00254 }
00255
00256 KexiPart::GUIClient* KexiDialogBase::guiClient() const
00257 {
00258 if (!m_part || m_currentViewMode<1)
00259 return 0;
00260 return m_part->instanceGuiClient(m_currentViewMode);
00261 }
00262
00263 KexiPart::GUIClient* KexiDialogBase::commonGUIClient() const
00264 {
00265 if (!m_part)
00266 return 0;
00267 return m_part->instanceGuiClient(0);
00268 }
00269
00270 tristate KexiDialogBase::switchToViewMode( int newViewMode, QMap<QString,QString>* staticObjectArgs )
00271 {
00272 m_parentWindow->acceptPropertySetEditing();
00273
00274 const bool designModePreloadedForTextModeHack =
00275 newViewMode==Kexi::TextViewMode
00276 && !viewForMode(Kexi::DesignViewMode)
00277 && supportsViewMode(Kexi::DesignViewMode);
00278
00279 tristate res = true;
00280 if (designModePreloadedForTextModeHack) {
00281
00282 res = switchToViewMode( Kexi::DesignViewMode, staticObjectArgs );
00283 if (!res || ~res)
00284 return res;
00285 }
00286
00287 kdDebug() << "KexiDialogBase::switchToViewMode()" << endl;
00288 bool dontStore = false;
00289 KexiViewBase *view = selectedView();
00290
00291 if (m_currentViewMode == newViewMode)
00292 return true;
00293 if (!supportsViewMode(newViewMode))
00294 return false;
00295
00296 if (view) {
00297 res = true;
00298 if (!designModePreloadedForTextModeHack) {
00299 res = view->beforeSwitchTo(newViewMode, dontStore);
00300 }
00301 if (~res || !res)
00302 return res;
00303 if (!dontStore && view->dirty()) {
00304 res = m_parentWindow->saveObject(this, i18n("Design has been changed. "
00305 "You must save it before switching to other view."));
00306 if (~res || !res)
00307 return res;
00308
00309
00310 }
00311 }
00312
00313
00314 KexiViewBase *newView
00315 = (m_stack->widget(newViewMode) && m_stack->widget(newViewMode)->inherits("KexiViewBase"))
00316 ? static_cast<KexiViewBase*>(m_stack->widget(newViewMode)) : 0;
00317 if (!newView) {
00318 KexiUtils::setWaitCursor();
00319
00320 m_creatingViewsMode = newViewMode;
00321 KexiPart::StaticPart *staticPart = dynamic_cast<KexiPart::StaticPart*>((KexiPart::Part*)m_part);
00322 if (staticPart)
00323 newView = staticPart->createView(m_stack, this, *m_item, newViewMode, staticObjectArgs);
00324 else
00325 newView = m_part->createView(m_stack, this, *m_item, newViewMode, staticObjectArgs);
00326 KexiUtils::removeWaitCursor();
00327 if (!newView) {
00328
00329 kdDebug() << "Switching to mode " << newViewMode << " failed. Previous mode "
00330 << m_currentViewMode << " restored." << endl;
00331 return false;
00332 }
00333 m_creatingViewsMode = -1;
00334 addView(newView, newViewMode);
00335 }
00336 const int prevViewMode = m_currentViewMode;
00337 res = true;
00338 if (designModePreloadedForTextModeHack) {
00339 m_currentViewMode = Kexi::NoViewMode;
00340 }
00341 res = newView->beforeSwitchTo(newViewMode, dontStore);
00342 if (!res) {
00343 kdDebug() << "Switching to mode " << newViewMode << " failed. Previous mode "
00344 << m_currentViewMode << " restored." << endl;
00345 return false;
00346 }
00347 m_currentViewMode = newViewMode;
00348 m_newlySelectedView = newView;
00349 if (prevViewMode==Kexi::NoViewMode)
00350 m_newlySelectedView->setDirty(false);
00351
00352 res = newView->afterSwitchFrom(
00353 designModePreloadedForTextModeHack ? Kexi::NoViewMode : prevViewMode);
00354 if (!res) {
00355 kdDebug() << "Switching to mode " << newViewMode << " failed. Previous mode "
00356 << prevViewMode << " restored." << endl;
00357 setStatus(mainWin()->project()->dbConnection(),
00358 i18n("Switching to other view failed (%1).").arg(Kexi::nameForViewMode(newViewMode)),"");
00359 m_currentViewMode = prevViewMode;
00360 return false;
00361 }
00362 m_newlySelectedView = 0;
00363 if (~res) {
00364 m_currentViewMode = prevViewMode;
00365 return cancelled;
00366 }
00367 if (view)
00368 takeActionProxyChild( view );
00369 addActionProxyChild( newView );
00370 m_stack->raiseWidget( newView );
00371 newView->propertySetSwitched();
00372 m_parentWindow->invalidateSharedActions( newView );
00373
00374 return true;
00375 }
00376
00377 tristate KexiDialogBase::switchToViewMode( int newViewMode )
00378 {
00379 return switchToViewMode( newViewMode, 0 );
00380 }
00381
00382 void KexiDialogBase::setFocus()
00383 {
00384 if (m_stack->visibleWidget()) {
00385 if (m_stack->visibleWidget()->inherits("KexiViewBase"))
00386 static_cast<KexiViewBase*>( m_stack->visibleWidget() )->setFocus();
00387 else
00388 m_stack->visibleWidget()->setFocus();
00389 }
00390 else {
00391 KMdiChildView::setFocus();
00392 }
00393 activate();
00394 }
00395
00396 KoProperty::Set*
00397 KexiDialogBase::propertySet()
00398 {
00399 KexiViewBase *v = selectedView();
00400 if (!v)
00401 return 0;
00402 return v->propertySet();
00403 }
00404
00405 bool KexiDialogBase::eventFilter(QObject *obj, QEvent *e)
00406 {
00407 if (KMdiChildView::eventFilter(obj, e))
00408 return true;
00409
00410
00411
00412
00413 if ((e->type()==QEvent::FocusIn && m_parentWindow->activeWindow()==this)
00414 || e->type()==QEvent::MouseButtonPress) {
00415 if (m_stack->visibleWidget() && KexiUtils::hasParent(m_stack->visibleWidget(), obj)) {
00416
00417 activate();
00418 }
00419 }
00420 return false;
00421 }
00422
00423 void KexiDialogBase::dirtyChanged(KexiViewBase* view)
00424 {
00425 if (m_disableDirtyChanged)
00426 return;
00427 m_viewThatRecentlySetDirtyFlag = dirty() ? view : 0;
00428
00429
00430
00431
00432
00433
00434
00435
00436 updateCaption();
00437 emit dirtyChanged(this);
00438 }
00439
00440
00441
00442
00443
00444
00445
00446
00447
00448
00449 void KexiDialogBase::updateCaption()
00450 {
00451 if (!m_item || !m_part || !m_origCaption.isEmpty())
00452 return;
00453
00454 QString capt = m_item->name();
00455 QString fullCapt = capt;
00456 if (m_part)
00457 fullCapt += (" : " + m_part->instanceCaption());
00458 if (dirty()) {
00459 KMdiChildView::setCaption(fullCapt+"*");
00460 KMdiChildView::setTabCaption(capt+"*");
00461 }
00462 else {
00463 KMdiChildView::setCaption(fullCapt);
00464 KMdiChildView::setTabCaption(capt);
00465 }
00466 }
00467
00468 bool KexiDialogBase::neverSaved() const
00469 {
00470 return m_item ? m_item->neverSaved() : true;
00471 }
00472
00473 tristate KexiDialogBase::storeNewData()
00474 {
00475 if (!neverSaved())
00476 return false;
00477 KexiViewBase *v = selectedView();
00478 if (m_schemaData)
00479 return false;
00480 if (!v)
00481 return false;
00482
00483 KexiDB::SchemaData sdata(m_part->info()->projectPartID());
00484 sdata.setName( m_item->name() );
00485 sdata.setCaption( m_item->caption() );
00486 sdata.setDescription( m_item->description() );
00487
00488 bool cancel = false;
00489 m_schemaData = v->storeNewData(sdata, cancel);
00490 if (cancel)
00491 return cancelled;
00492 if (!m_schemaData) {
00493 setStatus(m_parentWindow->project()->dbConnection(), i18n("Saving object's definition failed."),"");
00494 return false;
00495 }
00496
00497 if (!part()->info()->isIdStoredInPartDatabase()) {
00498
00499 KexiDB::TableSchema *ts = m_parentWindow->project()->dbConnection()->tableSchema("kexi__parts");
00500 kdDebug() << "KexiMainWindowImpl::newObject(): schema: " << ts << endl;
00501 if (!ts)
00502 return false;
00503
00504
00505
00506 int p_id = part()->info()->projectPartID();
00507
00508 if (p_id<0) {
00509
00510
00511 p_id = (int)KexiPart::UserObjectType;
00512 tristate success = m_parentWindow->project()->dbConnection()->querySingleNumber(
00513 "SELECT max(p_id) FROM kexi__parts", p_id);
00514 if (!success) {
00515
00516 return false;
00517 } else {
00518
00519 p_id = p_id + 1;
00520 p_id = QMAX(p_id, (int)KexiPart::UserObjectType);
00521 }
00522 }
00523
00524 KexiDB::FieldList *fl = ts->subList("p_id", "p_name", "p_mime", "p_url");
00525 kexidbg << "KexiMainWindowImpl::newObject(): fieldlist: "
00526 << (fl ? fl->debugString() : QString::null) << endl;
00527 if (!fl)
00528 return false;
00529
00530 kexidbg << part()->info()->ptr()->untranslatedGenericName() << endl;
00531
00532
00533
00534 if (!m_parentWindow->project()->dbConnection()->insertRecord(
00535 *fl,
00536 QVariant(p_id),
00537 QVariant(part()->info()->ptr()->untranslatedGenericName()),
00538 QVariant(part()->info()->mimeType()), QVariant("http://www.koffice.org/kexi/" )))
00539 return false;
00540
00541 kdDebug() << "KexiMainWindowImpl::newObject(): insert success!" << endl;
00542 part()->info()->setProjectPartID( p_id );
00543
00544 kdDebug() << "KexiMainWindowImpl::newObject(): new id is: "
00545 << part()->info()->projectPartID() << endl;
00546
00547 part()->info()->setIdStoredInPartDatabase(true);
00548 }
00549
00550
00551 setDirty(false);
00552
00553
00554
00555 m_item->setIdentifier( m_schemaData->id() );
00556 m_parentWindow->project()->addStoredItem( part()->info(), m_item );
00557
00558 return true;
00559 }
00560
00561 tristate KexiDialogBase::storeData(bool dontAsk)
00562 {
00563 if (neverSaved())
00564 return false;
00565 KexiViewBase *v = selectedView();
00566 if (!v)
00567 return false;
00568
00569 #define storeData_ERR \
00570 setStatus(m_parentWindow->project()->dbConnection(), i18n("Saving object's data failed."),"");
00571
00572
00573 KexiDB::Transaction transaction = m_parentWindow->project()->dbConnection()->beginTransaction();
00574 if (transaction.isNull()) {
00575 storeData_ERR;
00576 return false;
00577 }
00578 KexiDB::TransactionGuard tg(transaction);
00579
00580 const tristate res = v->storeData(dontAsk);
00581 if (~res)
00582 return res;
00583 if (!res) {
00584 storeData_ERR;
00585 return res;
00586 }
00587 if (!tg.commit()) {
00588 storeData_ERR;
00589 return false;
00590 }
00591
00592 setDirty(false);
00593
00594 return true;
00595 }
00596
00597 void KexiDialogBase::activate()
00598 {
00599 KexiViewBase *v = selectedView();
00600
00601 if (KexiUtils::hasParent( v, KMdiChildView::focusedChildWidget()))
00602 KMdiChildView::activate();
00603 else {
00604 if (v)
00605 v->setFocus();
00606 }
00607 if (v)
00608 v->updateActions(true);
00609
00610 }
00611
00612 void KexiDialogBase::deactivate()
00613 {
00614 KexiViewBase *v = selectedView();
00615 if (v)
00616 v->updateActions(false);
00617 }
00618
00619 void KexiDialogBase::sendDetachedStateToCurrentView()
00620 {
00621 KexiViewBase *v = selectedView();
00622 if (v)
00623 v->parentDialogDetached();
00624 }
00625
00626 void KexiDialogBase::sendAttachedStateToCurrentView()
00627 {
00628 KexiViewBase *v = selectedView();
00629 if (v)
00630 v->parentDialogAttached();
00631 }
00632
00633 #include "kexidialogbase.moc"
00634