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