kexi

keximainwindowimpl.cpp

00001 /* This file is part of the KDE project
00002    Copyright (C) 2003 Lucijan Busch <lucijan@kde.org>
00003    Copyright (C) 2003-2006 Jaroslaw Staniek <js@iidea.pl>
00004 
00005    This library is free software; you can redistribute it and/or
00006    modify it under the terms of the GNU Library General Public
00007    License as published by the Free Software Foundation; either
00008    version 2 of the License, or (at your option) any later version.
00009 
00010    This library is distributed in the hope that it will be useful,
00011    but WITHOUT ANY WARRANTY; without even the implied warranty of
00012    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00013    Library General Public License for more details.
00014 
00015    You should have received a copy of the GNU Library General Public License
00016    along with this library; see the file COPYING.LIB.  If not, write to
00017    the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
00018  * Boston, MA 02110-1301, USA.
00019 */
00020 
00021 #include "keximainwindowimpl.h"
00022 
00023 #include <unistd.h>
00024 
00025 #include <qapplication.h>
00026 #include <qeventloop.h>
00027 #include <qfile.h>
00028 #include <qtimer.h>
00029 #include <qobjectlist.h>
00030 #include <qprocess.h>
00031 #include <qtoolbutton.h>
00032 #include <qtooltip.h>
00033 #include <qmutex.h>
00034 #include <qwaitcondition.h>
00035 
00036 #include <kapplication.h>
00037 #include <kcmdlineargs.h>
00038 #include <kaction.h>
00039 #include <klocale.h>
00040 #include <kstdaccel.h>
00041 #include <kconfig.h>
00042 #include <kglobal.h>
00043 #include <kdebug.h>
00044 #include <kkeydialog.h>
00045 #include <kedittoolbar.h>
00046 #include <kdeversion.h>
00047 #include <kglobalsettings.h>
00048 #include <kparts/componentfactory.h>
00049 #include <ktip.h>
00050 #include <kstandarddirs.h>
00051 #include <kpushbutton.h>
00052 #include <ktextbrowser.h>
00053 #include <kiconloader.h>
00054 #include <ktabwidget.h>
00055 #include <kimageio.h>
00056 #include <khelpmenu.h>
00057 
00058 #include <kexidb/connection.h>
00059 #include <kexidb/utils.h>
00060 #include <kexidb/cursor.h>
00061 #include <kexidb/dbobjectnamevalidator.h>
00062 #include <kexidb/admin.h>
00063 #include <kexiutils/utils.h>
00064 
00065 //#include "projectsettingsui.h"
00066 #include "kexibrowser.h"
00067 #include "kexiactionproxy.h"
00068 #include "kexidialogbase.h"
00069 #include "kexipartmanager.h"
00070 #include "kexipart.h"
00071 #include "kexipartinfo.h"
00072 #include "kexipartguiclient.h"
00073 #include "kexiproject.h"
00074 #include "kexiprojectdata.h"
00075 #include "kexiprojectset.h"
00076 #include "kexi.h"
00077 #include "kexistatusbar.h"
00078 #include "kexiinternalpart.h"
00079 #include "kde2_closebutton.xpm"
00080 
00081 #include <widget/kexipropertyeditorview.h>
00082 #include <koproperty/editor.h>
00083 #include <koproperty/set.h>
00084 
00085 #include "startup/KexiStartup.h"
00086 #include "startup/KexiNewProjectWizard.h"
00087 #include "startup/KexiStartupDialog.h"
00088 /*
00089 #include "startup/KexiConnSelector.h"
00090 #include "startup/KexiProjectSelectorBase.h"
00091 #include "startup/KexiProjectSelector.h"
00092 */
00093 #include "kexinamedialog.h"
00094 #include "printing/kexisimpleprintingpart.h"
00095 #include "printing/kexisimpleprintingpagesetup.h"
00096 
00097 //Extreme verbose debug
00098 #if defined(Q_WS_WIN)
00099 //# define KexiVDebug kdDebug()
00100 #endif
00101 #if !defined(KexiVDebug)
00102 # define KexiVDebug if (0) kdDebug()
00103 #endif
00104 
00105 //first fix the geometry
00106 //#define KEXI_NO_CTXT_HELP 1
00107 
00108 #ifndef KEXI_NO_CTXT_HELP
00109 #include <kexicontexthelp.h>
00110 #endif
00111 
00112 #ifdef HAVE_KNEWSTUFF
00113 #include <knewstuff/downloaddialog.h>
00114 #include "kexinewstuff.h"
00115 #endif
00116 
00117 //show property editor
00118 #define KEXI_PROP_EDITOR 1
00119 
00122 //#define PROPEDITOR_VISIBILITY_CHANGES
00123 
00124 //temporary fix to manage layout
00125 #include "ksplitter.h"
00126 #define KDOCKWIDGET_P 1
00127 
00128 #ifndef KEXI_NO_FEEDBACK_AGENT
00129 #ifdef FEEDBACK_INCLUDE
00130 #include FEEDBACK_INCLUDE
00131 #endif
00132 #include <kapplication.h>
00133 #include <kaboutdata.h>
00134 #endif
00135 
00136 #include "keximainwindowimpl_p.h"
00137 
00138 //-------------------------------------------------
00139 
00140 //static
00141 int KexiMainWindowImpl::create(int argc, char *argv[], KAboutData* aboutdata)
00142 {
00143     Kexi::initCmdLineArgs( argc, argv, aboutdata );
00144 
00145     bool GUIenabled = true;
00146     QWidget *dummyWidget = 0; //needed to have icon for dialogs before KexiMainWindowImpl is created
00148     KApplication* app = new KApplication(true, GUIenabled);
00149 #ifdef KEXI_STANDALONE
00150     KGlobal::locale()->removeCatalogue("kexi");
00151     KGlobal::locale()->insertCatalogue("standalone_kexi");
00152 #endif
00153     KGlobal::locale()->insertCatalogue("koffice");
00154     KGlobal::locale()->insertCatalogue("koproperty");
00155 
00156 #ifdef KEXI_DEBUG_GUI
00157     QWidget* debugWindow = 0;
00158 #endif
00159     if (GUIenabled) {
00160         dummyWidget = new QWidget();
00161         dummyWidget->setIcon( DesktopIcon( "kexi" ) );
00162         app->setMainWidget(dummyWidget);
00163 #ifdef KEXI_DEBUG_GUI
00164         app->config()->setGroup("General");
00165         if (app->config()->readBoolEntry("showKexiDBDebugger", false)) {
00166             debugWindow = KexiUtils::createDebugWindow(0);
00167         }
00168 #endif
00169     }
00170 
00171     tristate res = Kexi::startupHandler().init(argc, argv);
00172     if (!res || ~res) {
00173 #ifdef KEXI_DEBUG_GUI
00174         delete debugWindow;
00175 #endif
00176         delete app;
00177         return (~res) ? 0 : 1;
00178     }
00179     
00180     kdDebug() << "startupActions OK" <<endl;
00181 
00182     /* Exit requested, e.g. after database removing. */
00183     if (Kexi::startupHandler().action() == KexiStartupData::Exit) {
00184 #ifdef KEXI_DEBUG_GUI
00185         delete debugWindow;
00186 #endif
00187         delete app;
00188         return 0;
00189     }
00190 
00191 #ifdef CUSTOM_VERSION
00192 # include "custom_exec.h"
00193 #endif
00194 
00195     KexiMainWindowImpl *win = new KexiMainWindowImpl();
00196     app->setMainWidget(win);
00197 #ifdef KEXI_DEBUG_GUI
00198     //if (debugWindow)
00199         //debugWindow->reparent(win, QPoint(1,1));
00200 #endif
00201     delete dummyWidget;
00202 
00203     if (true != win->startup()) {
00204         delete win;
00205         delete app;
00206         return 1;
00207     }
00208 
00209     win->show();
00210     app->processEvents();//allow refresh our app
00211 
00212 //#ifdef KEXI_DEBUG_GUI
00213 //  delete debugWindow;
00214 //#endif
00215     return 0;
00216 }
00217 
00218 //-------------------------------------------------
00219 
00220 KexiMainWindowImpl::KexiMainWindowImpl()
00221  : KexiMainWindow()
00222  , KexiGUIMessageHandler(this)
00223  , d(new KexiMainWindowImpl::Private(this) )
00224 {
00225     KImageIO::registerFormats();
00226     KexiProjectData *pdata = Kexi::startupHandler().projectData();
00227     d->final = Kexi::startupHandler().forcedFinalMode() /* <-- simply forced final mode */
00228         /* project has 'final mode' set as default and not 'design mode' override is found: */
00229         || (pdata && pdata->finalMode() && !Kexi::startupHandler().forcedDesignMode());
00230 
00231     if(d->final)
00232         kdDebug() << "KexiMainWindowImpl::KexiMainWindowImpl(): starting up in final mode" << endl;
00233 
00234     d->config = kapp->config();
00235 
00236     if ( !initialGeometrySet() ) {
00237         int scnum = QApplication::desktop()->screenNumber(parentWidget());
00238         QRect desk = QApplication::desktop()->screenGeometry(scnum);
00239         d->config->setGroup("MainWindow");
00240         QSize s ( d->config->readNumEntry( QString::fromLatin1("Width %1").arg(desk.width()), 700 ),
00241             d->config->readNumEntry( QString::fromLatin1("Height %1").arg(desk.height()), 480 ) );
00242         resize (kMin (s.width(), desk.width()), kMin(s.height(), desk.height()));
00243     }
00244 
00245     setManagedDockPositionModeEnabled(true);//TODO(js): remove this if will be default in kmdi :)
00246     manager()->setSplitterHighResolution(true);
00247     manager()->setSplitterKeepSize(true);
00248     setStandardMDIMenuEnabled(false);
00249     setAsDefaultHost(); //this is default host now.
00250     KGlobal::iconLoader()->addAppDir("kexi");
00251     KGlobal::iconLoader()->addAppDir("koffice");
00252 
00253     //get informed
00254     connect(&Kexi::partManager(),SIGNAL(partLoaded(KexiPart::Part*)),this,SLOT(slotPartLoaded(KexiPart::Part*)));
00255     connect( m_pMdi, SIGNAL(nowMaximized(bool)), this, SLOT(slotCaptionForCurrentMDIChild(bool)) );
00256     connect( m_pMdi, SIGNAL(noMaximizedChildFrmLeft(KMdiChildFrm*)), this, SLOT(slotNoMaximizedChildFrmLeft(KMdiChildFrm*)));
00257 //  connect( this, SIGNAL(lastChildFrmClosed()), this, SLOT(slotLastChildFrmClosed()));
00258     connect( this, SIGNAL(lastChildViewClosed()), this, SLOT(slotLastChildViewClosed()));
00259 
00260     connect( this, SIGNAL(childViewIsDetachedNow(QWidget*)), this, SLOT(slotChildViewIsDetachedNow(QWidget*)));
00261     connect( this, SIGNAL(mdiModeHasBeenChangedTo(KMdi::MdiMode)),
00262         this, SLOT(slotMdiModeHasBeenChangedTo(KMdi::MdiMode)));
00263 
00264 
00265     if(!d->final)
00266     {
00267         setXMLFile("kexiui.rc");
00268         setAcceptDrops(true);
00269         initActions();
00270         createShellGUI(true);
00271     }
00272 
00273     d->statusBar = new KexiStatusBar(this, "status_bar");
00274 
00275     d->origAppCaption = caption();
00276 
00277     restoreSettings();
00278 
00279     if(!d->final)
00280     {
00281         initContextHelp();
00282         initPropertyEditor();
00283     }
00284 
00285     {//store menu popups list
00286         QObjectList *l = queryList( "QPopupMenu" );
00287         for (QObjectListIt it( *l ); it.current(); ++it ) {
00288             //kdDebug() << "name=" <<it.current()->name() << " cname="<<it.current()->className()<<endl;
00289             //KexiMainWindowImpl::eventFilter() will filter our popups:
00290             it.current()->installEventFilter(this);
00291             d->popups.insert(it.current()->name(), static_cast<QPopupMenu*>(it.current()));
00292         }
00293         delete l;
00294         d->createMenu = d->popups["create"];
00295 
00296 #ifdef KEXI_NO_REPORTBUG_COMMAND
00297         //remove "bug report" action to avoid confusion for supported with commercial technical support
00298         QPopupMenu *helpMenu = d->popups["help"];
00299         if (helpMenu) {
00300             //const int idx = helpMenu->indexOf( (int)KHelpMenu::menuReportBug );
00301             helpMenu->removeItemAt(int(KHelpMenu::menuReportBug)-1);
00302             helpMenu->removeItemAt(int(KHelpMenu::menuReportBug)-1); //separator
00303         }
00304 #endif
00305     }
00306 
00307     //fix menus a bit more:
00308 #ifndef KEXI_SHOW_UNIMPLEMENTED
00309 //disabled (possible crash) d->hideMenuItem("file", i18n("&Import"), true);
00310 //disabled (possible crash) d->hideMenuItem("help", i18n( "&Report Bug..." ), true);
00311 #endif
00312     KAction *kmdi_tooldock_menu_action = childClients()->getFirst() ? childClients()->getFirst()->actionCollection()->action("kmdi_tooldock_menu") : 0;
00313     if (kmdi_tooldock_menu_action) {
00314         kmdi_tooldock_menu_action->setEnabled(false);
00315     }
00316 
00317     if (!isFakingSDIApplication() && !d->final) {
00318 //      QPopupMenu *menu = (QPopupMenu*) child( "window", "KPopupMenu" );
00319         QPopupMenu *menu = d->popups["window"];
00320         unsigned int count = menuBar()->count();
00321         if (menu)
00322             setWindowMenu(menu);
00323         else
00324             menuBar()->insertItem( i18n("&Window"), windowMenu(), -1, count-2); // standard position is left to the last ('Help')
00325     }
00326 
00327     m_pTaskBar->setCaption(i18n("Task Bar"));   //js TODO: move this to KMDIlib
00328 
00329     if (!d->final) {
00330         invalidateActions();
00331         d->timer.singleShot(0,this,SLOT(slotLastActions()));
00332     }
00333 
00334     setTabWidgetVisibility(KMdi::AlwaysShowTabs);
00335     if (mdiMode()==KMdi::IDEAlMode) {
00336         d->config->setGroup("MainWindow");
00337         tabWidget()->setHoverCloseButton(d->config->readBoolEntry("HoverCloseButtonForTabs", false));
00338         //create special close button as corner widget for IDEAl mode
00339         QToolButton *closeButton = new QToolButton( tabWidget() );
00340         closeButton->setAutoRaise( true );
00341         closeButton->setPixmap( QPixmap( kde2_closebutton ) );
00342         closeButton->setPaletteBackgroundColor(closeButton->palette().active().background()); 
00343 //      closeButton->setIconSet(SmallIconSet("tab_remove"));
00344         tabWidget()->setCornerWidget( closeButton, Qt::TopRight );
00345         QToolTip::add(closeButton, 
00346             i18n("Close the current tab page in Kexi tab interface", "Close the current tab"));
00347         QObject::connect( closeButton, SIGNAL( clicked() ), this, SLOT( closeActiveView() ) );
00348     }
00349 
00350 //  manager()->readConfig( d->config, "DockWindows" );
00351 }
00352 
00353 KexiMainWindowImpl::~KexiMainWindowImpl()
00354 {
00355     d->forceDialogClosing=true;
00356     closeProject();
00357     delete d;
00358 }
00359 
00360 KexiProject *KexiMainWindowImpl::project()
00361 {
00362     return d->prj;
00363 }
00364 
00365 void KexiMainWindowImpl::setWindowMenu(QPopupMenu *menu)
00366 {
00367     delete m_pWindowMenu;
00368     m_pWindowMenu = menu;
00369     int count = menuBar()->count();
00370     //try to move "window" menu just before "Settings" menu (count-3)
00371     const QString txt = i18n("&Window");
00372     int i;
00373     for (i=0; i<count; i++) {
00374         //kdDebug() << menuBar()->text( menuBar()->idAt(i) ) << endl;
00375         if (txt==menuBar()->text( menuBar()->idAt(i) ))
00376             break;
00377     }
00378     if (i<count) {
00379         const int id = menuBar()->idAt(i);
00380         menuBar()->removeItemAt(i);
00381         menuBar()->insertItem(txt, m_pWindowMenu, id, count-3);
00382     }
00383     m_pWindowMenu->setCheckable(true);
00384     QObject::connect( m_pWindowMenu, SIGNAL(aboutToShow()), this, SLOT(fillWindowMenu()) );
00385 }
00386 
00387 void KexiMainWindowImpl::fillWindowMenu()
00388 {
00389     KexiMainWindow::fillWindowMenu();
00390 
00391 /*  int i;
00392     for (i=0; i < (int)m_pWindowMenu->count(); i++) {
00393         if (m_pWindowMenu->text( m_pWindowMenu->idAt( i ) ) == i18n( "&MDI Mode" )) {
00394 //          kdDebug() << m_pWindowMenu->text( m_pWindowMenu->idAt( i ) ) << endl;
00395             m_pWindowMenu->removeItem( m_pWindowMenu->idAt( i ) );
00396             break;
00397         }
00398     }*/
00399 
00400     m_pMdiModeMenu->removeItem( m_pMdiModeMenu->idAt( 0 ) ); //hide toplevel mode
00401     m_pMdiModeMenu->removeItem( m_pMdiModeMenu->idAt( 1 ) ); //hide tabbed mode
00402     //update
00403     if (d->mdiModeToSwitchAfterRestart != (KMdi::MdiMode)0) {
00404         m_pMdiModeMenu->setItemChecked( m_pMdiModeMenu->idAt( 0 ), 
00405             d->mdiModeToSwitchAfterRestart == KMdi::ChildframeMode );
00406         m_pMdiModeMenu->setItemChecked( m_pMdiModeMenu->idAt( 1 ), 
00407             d->mdiModeToSwitchAfterRestart == KMdi::IDEAlMode );
00408     }
00409 
00410     //insert window_next, window_previous actions:
00411 //  const QString t = i18n("&Dock/Undock...");
00412     int i = m_pWindowMenu->count()-1;
00413     for (int index;; i--) {
00414         index = m_pWindowMenu->idAt(i);
00415         if (index==-1 || m_pWindowMenu->text(index).isNull())
00416                 break;
00417     }
00418     i++;
00419     d->action_window_next->plug( m_pWindowMenu, i++ );
00420     d->action_window_previous->plug( m_pWindowMenu, i++ );
00421     if (!m_pDocumentViews->isEmpty())
00422         m_pWindowMenu->insertSeparator( i++ );
00423 }
00424 
00425 void KexiMainWindowImpl::switchToIDEAlMode()
00426 {
00427     switchToIDEAlMode(true);
00428 }
00429 
00430 void KexiMainWindowImpl::switchToIDEAlMode(bool showMessage)
00431 {
00432     if (showMessage) {
00433         if ((int)d->mdiModeToSwitchAfterRestart == 0 && mdiMode()==KMdi::IDEAlMode)
00434             return;
00435         if (d->mdiModeToSwitchAfterRestart == KMdi::IDEAlMode)
00436             return;
00437         if (mdiMode()==KMdi::IDEAlMode) {//current mode
00438             d->mdiModeToSwitchAfterRestart = (KMdi::MdiMode)0;
00439         }
00440         else {
00441             KMessageBox::information(this,
00442                 i18n("User interface mode will be switched to IDEAl at next %1 application startup.")
00443                 .arg(KEXI_APP_NAME));
00444             //delayed
00445             d->mdiModeToSwitchAfterRestart = KMdi::IDEAlMode;
00446         }
00447     }
00448     else
00449         KexiMainWindow::switchToIDEAlMode();
00450 }
00451 
00452 void KexiMainWindowImpl::switchToChildframeMode()
00453 {
00454     switchToChildframeMode(true);
00455 }
00456 
00457 void KexiMainWindowImpl::switchToChildframeMode(bool showMessage)
00458 {
00459     if (showMessage) {
00460         if ((int)d->mdiModeToSwitchAfterRestart == 0 && mdiMode()==KMdi::ChildframeMode)
00461             return;
00462         if (d->mdiModeToSwitchAfterRestart == KMdi::ChildframeMode)
00463             return;
00464         if (mdiMode()==KMdi::ChildframeMode) {//current mode
00465             d->mdiModeToSwitchAfterRestart = (KMdi::MdiMode)0;
00466         }
00467         else {
00468             KMessageBox::information(this,
00469                 i18n("User interface mode will be switched to Childframe at next %1 application startup.")
00470                 .arg(KEXI_APP_NAME));
00471             //delayed
00472             d->mdiModeToSwitchAfterRestart = KMdi::ChildframeMode;
00473         }
00474     }
00475     else
00476         KexiMainWindow::switchToChildframeMode();
00477 }
00478 
00479 QPopupMenu* KexiMainWindowImpl::findPopupMenu(const char *popupName)
00480 {
00481     return d->popups[popupName];
00482 }
00483 
00484 KActionPtrList KexiMainWindowImpl::allActions() const
00485 {
00486     return actionCollection()->actions();
00487 }
00488 
00489 KexiDialogBase* KexiMainWindowImpl::currentDialog() const
00490 {
00491     return d->curDialog;
00492 }
00493 
00494 void KexiMainWindowImpl::initActions()
00495 {
00496 //  setupGUI(KMainWindow::Keys|KMainWindow::StatusBar|KMainWindow::Save|KMainWindow::Create);
00497 
00498 //  d->actionMapper = new QSignalMapper(this, "act_map");
00499 //  connect(d->actionMapper, SIGNAL(mapped(const QString &)), this, SLOT(slotAction(const QString &)));
00500 
00501     // PROJECT MENU
00502     KAction *action = new KAction(i18n("&New..."), "filenew", KStdAccel::shortcut(KStdAccel::New),
00503         this, SLOT(slotProjectNew()), actionCollection(), "project_new");
00504     action->setToolTip(i18n("Create a new project"));
00505     action->setWhatsThis(i18n("Creates a new project. Currently opened project is not affected."));
00506 
00507     action = KStdAction::open( this, SLOT( slotProjectOpen() ), actionCollection(), "project_open" );
00508     action->setToolTip(i18n("Open an existing project"));
00509     action->setWhatsThis(i18n("Opens an existing project. Currently opened project is not affected."));
00510 
00511 #ifdef HAVE_KNEWSTUFF
00512     action = new KAction(i18n("&Download Example Databases..."), "kget", KShortcut(0),
00513         this, SLOT(slotGetNewStuff()), actionCollection(), "project_download_examples");
00514     action->setToolTip(i18n("Download example databases from the Internet"));
00515     action->setWhatsThis(i18n("Downloads example databases from the Internet."));
00516 #endif
00517 
00518 //  d->action_open_recent = KStdAction::openRecent( this, SLOT(slotProjectOpenRecent(const KURL&)), actionCollection(), "project_open_recent" );
00519 
00520 //#ifdef KEXI_SHOW_UNIMPLEMENTED
00521 #ifndef KEXI_NO_UNFINISHED
00522     d->action_open_recent = new KActionMenu(i18n("Open Recent"),
00523         actionCollection(), "project_open_recent");
00524     connect(d->action_open_recent->popupMenu(),SIGNAL(activated(int)),
00525         this,SLOT(slotProjectOpenRecent(int)));
00526     connect(d->action_open_recent->popupMenu(), SIGNAL(aboutToShow()),
00527         this,SLOT(slotProjectOpenRecentAboutToShow()));
00528 //moved down        d->action_open_recent_projects_title_id = 
00529 //      d->action_open_recent->popupMenu()->insertTitle(i18n("Recently Opened Databases"));
00530 //moved down    d->action_open_recent_connections_title_id = 
00531 //      d->action_open_recent->popupMenu()->insertTitle(i18n("Recently Connected Database Servers"));
00532 //  d->action_open_recent->popupMenu()->insertSeparator();
00533 //  d->action_open_recent_more_id = d->action_open_recent->popupMenu()
00534 //      ->insertItem(i18n("&More Projects..."), this, SLOT(slotProjectOpenRecentMore()), 0, 1000);
00535 #else
00536     d->action_open_recent = d->dummy_action;
00537 #endif
00538 
00539     d->action_save = KStdAction::save( 
00540         this, SLOT( slotProjectSave() ), actionCollection(), "project_save" );
00541 //  d->action_save = new KAction(i18n("&Save"), "filesave", KStdAccel::shortcut(KStdAccel::Save),
00542 //      this, SLOT(slotProjectSave()), actionCollection(), "project_save");
00543     d->action_save->setToolTip(i18n("Save object changes"));
00544     d->action_save->setWhatsThis(i18n("Saves object changes from currently selected window."));
00545 
00546 #ifdef KEXI_SHOW_UNIMPLEMENTED
00547     d->action_save_as = new KAction(i18n("Save &As..."), "filesaveas", 0,
00548         this, SLOT(slotProjectSaveAs()), actionCollection(), "project_saveas");
00549     d->action_save_as->setToolTip(i18n("Save object as"));
00550     d->action_save_as->setWhatsThis(
00551         i18n("Saves object changes from currently selected window under a new name (within the same project)."));
00552 
00553     d->action_project_properties = new KAction(i18n("Project Properties"), "info", 0,
00554         this, SLOT(slotProjectProperties()), actionCollection(), "project_properties");
00555 #else
00556     d->action_save_as = d->dummy_action;
00557     d->action_project_properties = d->dummy_action;
00558 #endif
00559 
00560     d->action_close = new KAction(i18n("&Close Project"), "fileclose", 0,
00561         this, SLOT(slotProjectClose()), actionCollection(), "project_close" );
00562     d->action_close->setToolTip(i18n("Close the current project"));
00563     d->action_close->setWhatsThis(i18n("Closes the current project."));
00564 
00565     KStdAction::quit( this, SLOT(slotProjectQuit()), actionCollection(), "quit");
00566 
00567 #ifdef KEXI_SHOW_UNIMPLEMENTED
00568     d->action_project_relations = new KAction(i18n("&Relationships..."), "relation", CTRL + Key_R,
00569         this, SLOT(slotProjectRelations()), actionCollection(), "project_relations");
00570     d->action_project_relations->setToolTip(i18n("Project relationships"));
00571     d->action_project_relations->setWhatsThis(i18n("Shows project relationships."));
00572 
00573 #else
00574     d->action_project_relations = d->dummy_action;
00575 #endif
00576     d->action_tools_data_migration = new KAction(
00577         i18n("&Import Database..."), "database_import", 0,
00578         this, SLOT(slotToolsProjectMigration()), actionCollection(), "tools_import_project");
00579     d->action_tools_data_migration->setToolTip(i18n("Import entire database as a Kexi project"));
00580     d->action_tools_data_migration->setWhatsThis(i18n("Imports entire database as a Kexi project."));
00581 
00582     d->action_tools_compact_database = new KAction(
00583         i18n("&Compact Database..."), "", 0,
00584         this, SLOT(slotToolsCompactDatabase()), actionCollection(), "tools_compact_database");
00585     d->action_tools_compact_database->setToolTip(i18n("Compact the current database project"));
00586     d->action_tools_compact_database->setWhatsThis(
00587         i18n("Compacts the current database project, so it will take less space and work faster."));
00588 
00589     d->action_project_import_data_table = new KAction(
00590         i18n("Import->Table Data From File...", "Table Data From &File..."),
00591         "table",
00592         0, this, SLOT(slotProjectImportDataTable()), actionCollection(), 
00593         "project_import_data_table");
00594     d->action_project_import_data_table->setToolTip(i18n("Import table data from a file"));
00595     d->action_project_import_data_table->setWhatsThis(i18n("Imports table data from a file."));
00596 
00597     d->action_project_export_data_table = new KAction(i18n("Export->Table or Query Data to File...", 
00598         "Table or Query Data to &File..."),
00599         "table",
00600         0, this, SLOT(slotProjectExportDataTable()), actionCollection(), 
00601         "project_export_data_table");
00602     d->action_project_export_data_table->setToolTip(
00603         i18n("Export data from the active table or query data to a file"));
00604     d->action_project_export_data_table->setWhatsThis(
00605         i18n("Exports data from the active table or query data to a file."));
00606 
00607 //TODO  new KAction(i18n("From File..."), "fileopen", 0,
00608 //TODO      this, SLOT(slotImportFile()), actionCollection(), "project_import_file");
00609 //TODO  new KAction(i18n("From Server..."), "server", 0,
00610 //TODO      this, SLOT(slotImportServer()), actionCollection(), "project_import_server");
00611 
00612     d->action_project_print = KStdAction::print(this, SLOT(slotProjectPrint()),
00613         actionCollection(), "project_print" ); 
00614     d->action_project_print->setToolTip(i18n("Print data from the active table or query"));
00615     d->action_project_print->setWhatsThis(i18n("Prints data from the active table or query."));
00616 
00617     d->action_project_print_preview = KStdAction::printPreview(
00618         this, SLOT(slotProjectPrintPreview()),
00619         actionCollection(), "project_print_preview" ); 
00620     d->action_project_print_preview->setToolTip(
00621         i18n("Show print preview for the active table or query"));
00622     d->action_project_print_preview->setWhatsThis(
00623         i18n("Shows print preview for the active table or query."));
00624 
00625     d->action_project_print_setup = new KAction(i18n("Page Set&up..."),
00626         "", 0, this, SLOT(slotProjectPageSetup()), actionCollection(), 
00627         "project_print_setup");
00628     d->action_project_print_setup->setToolTip(
00629         i18n("Show page setup for printing the active table or query"));
00630     d->action_project_print_setup->setWhatsThis(
00631         i18n("Shows page setup for printing the active table or query."));
00632 
00633     //EDIT MENU
00634     d->action_edit_cut = createSharedAction( KStdAction::Cut, "edit_cut");
00635     d->action_edit_copy = createSharedAction( KStdAction::Copy, "edit_copy");
00636     d->action_edit_paste = createSharedAction( KStdAction::Paste, "edit_paste");
00637 
00638     d->action_edit_paste_special_data_table = 
00639         new KAction(i18n("Paste Special->As Data &Table...", "As Data &Table..."),
00640         "table", 0, this, SLOT(slotEditPasteSpecialDataTable()),
00641         actionCollection(), "edit_paste_special_data_table");
00642     d->action_edit_paste_special_data_table->setToolTip(
00643         i18n("Paste clipboard data as a table"));
00644     d->action_edit_paste_special_data_table->setWhatsThis(
00645         i18n("Pastes clipboard data to a table."));
00646 
00647     d->action_edit_copy_special_data_table =
00648         new KAction(i18n("Copy Special->Table or Query Data...", 
00649             "Table or Query as Data Table..."),
00650         "table", 0, this, SLOT(slotEditCopySpecialDataTable()),
00651         actionCollection(), "edit_copy_special_data_table");
00652     d->action_edit_copy_special_data_table->setToolTip(
00653         i18n("Copy selected table or query data to clipboard"));
00654     d->action_edit_copy_special_data_table->setWhatsThis(
00655         i18n("Copies selected table or query data to clipboard."));
00656 
00657     d->action_edit_undo = createSharedAction( KStdAction::Undo, "edit_undo");
00658     d->action_edit_undo->setWhatsThis(i18n("Reverts the most recent editing action."));
00659     d->action_edit_redo = createSharedAction( KStdAction::Redo, "edit_redo");
00660     d->action_edit_redo->setWhatsThis(i18n("Reverts the most recent undo action."));
00661 
00662     d->action_edit_select_all =  createSharedAction( KStdAction::SelectAll, "edit_select_all");
00663 
00664     d->action_edit_delete = createSharedAction(i18n("&Delete"), "editdelete",
00665         0/*Key_Delete*/, "edit_delete");
00666     d->action_edit_delete->setToolTip(i18n("Delete object"));
00667     d->action_edit_delete->setWhatsThis(i18n("Deletes currently selected object."));
00668 
00669     d->action_edit_delete_row = createSharedAction(i18n("Delete Row"), "delete_table_row",
00670         CTRL+Key_Delete, "edit_delete_row");
00671     d->action_edit_delete_row->setToolTip(i18n("Delete currently selected row from a table"));
00672     d->action_edit_delete_row->setWhatsThis(i18n("Deletes currently selected row from a table."));
00673 
00674     d->action_edit_clear_table = createSharedAction(i18n("Clear Table Contents"), "clear_table_contents",
00675         0, "edit_clear_table");
00676     d->action_edit_clear_table->setToolTip(i18n("Clear table contents"));
00677     d->action_edit_clear_table->setWhatsThis(i18n("Clears table contents."));
00678     setActionVolatile( d->action_edit_clear_table, true );
00679 
00680     d->action_edit_edititem = createSharedAction(i18n("Edit Item"), 0, 0, /* CONFLICT in TV: Key_F2,  */
00681         "edit_edititem");
00682     d->action_edit_edititem->setToolTip(i18n("Edit currently selected item"));
00683     d->action_edit_edititem->setWhatsThis(i18n("Edits currently selected item."));
00684 
00685     d->action_edit_insert_empty_row = createSharedAction(i18n("&Insert Empty Row"), "insert_table_row", SHIFT | CTRL | Key_Insert, "edit_insert_empty_row");
00686     setActionVolatile( d->action_edit_insert_empty_row, true );
00687     d->action_edit_insert_empty_row->setToolTip(i18n("Insert one empty row above"));
00688     d->action_edit_insert_empty_row->setWhatsThis(i18n("Inserts one empty row above currently selected table row."));
00689 
00690     //VIEW MENU
00691     d->action_view_data_mode = new KRadioAction(i18n("&Data View"), "state_data", Key_F6,
00692         this, SLOT(slotViewDataMode()), actionCollection(), "view_data_mode");
00693     d->actions_for_view_modes.insert( Kexi::DataViewMode, d->action_view_data_mode );
00694     d->action_view_data_mode->setExclusiveGroup("view_mode");
00695     d->action_view_data_mode->setToolTip(i18n("Switch to data view"));
00696     d->action_view_data_mode->setWhatsThis(i18n("Switches to data view."));
00697 
00698     d->action_view_design_mode = new KRadioAction(i18n("D&esign View"), "state_edit", Key_F7,
00699         this, SLOT(slotViewDesignMode()), actionCollection(), "view_design_mode");
00700     d->actions_for_view_modes.insert( Kexi::DesignViewMode, d->action_view_design_mode );
00701     d->action_view_design_mode->setExclusiveGroup("view_mode");
00702     d->action_view_design_mode->setToolTip(i18n("Switch to design view"));
00703     d->action_view_design_mode->setWhatsThis(i18n("Switches to design view."));
00704 
00705     d->action_view_text_mode = new KRadioAction(i18n("&Text View"), "state_sql", Key_F8,
00706         this, SLOT(slotViewTextMode()), actionCollection(), "view_text_mode");
00707     d->actions_for_view_modes.insert( Kexi::TextViewMode, d->action_view_text_mode );
00708     d->action_view_text_mode->setExclusiveGroup("view_mode");
00709     d->action_view_text_mode->setToolTip(i18n("Switch to text view"));
00710     d->action_view_text_mode->setWhatsThis(i18n("Switches to text view."));
00711 
00712     d->action_view_nav = new KAction(i18n("Project Navigator"), "", ALT + Key_1,
00713         this, SLOT(slotViewNavigator()), actionCollection(), "view_navigator");
00714     d->action_view_nav->setToolTip(i18n("Go to project navigator panel"));
00715     d->action_view_nav->setWhatsThis(i18n("Goes to project navigator panel."));
00716 
00717     d->action_view_mainarea = new KAction(i18n("Main Area"), "", ALT + Key_2,
00718         this, SLOT(slotViewMainArea()), actionCollection(), "view_mainarea");
00719     d->action_view_mainarea->setToolTip(i18n("Go to main area"));
00720     d->action_view_mainarea->setWhatsThis(i18n("Goes to main area."));
00721 
00722 #ifdef KEXI_PROP_EDITOR
00723     d->action_view_propeditor = new KAction(i18n("Property Editor"), "", ALT + Key_3,
00724         this, SLOT(slotViewPropertyEditor()), actionCollection(), "view_propeditor");
00725     d->action_view_propeditor->setToolTip(i18n("Go to property editor panel"));
00726     d->action_view_propeditor->setWhatsThis(i18n("Goes to property editor panel."));
00727 #endif
00728 
00729     //DATA MENU
00730     d->action_data_save_row = createSharedAction(i18n("&Save Row"), "button_ok", SHIFT | Key_Return, "data_save_row");
00731     d->action_data_save_row->setToolTip(i18n("Save currently selected table row's data"));
00732     d->action_data_save_row->setWhatsThis(i18n("Saves currently selected table row's data."));
00733 //temp. disable because of problems with volatile actions   setActionVolatile( d->action_data_save_row, true );
00734 
00735     d->action_data_cancel_row_changes = createSharedAction(i18n("&Cancel Row Changes"), "button_cancel", 0 , "data_cancel_row_changes");
00736     d->action_data_cancel_row_changes->setToolTip(i18n("Cancel changes made to currently selected table row"));
00737     d->action_data_cancel_row_changes->setWhatsThis(i18n("Cancels changes made to currently selected table row."));
00738 //temp. disable because of problems with volatile actions   setActionVolatile( d->action_data_cancel_row_changes, true );
00739 
00740     d->action_data_execute = createSharedAction(i18n("&Execute"), "player_play", 0 , "data_execute");
00741     //d->action_data_execute->setToolTip(i18n("")); //TODO
00742     //d->action_data_execute->setWhatsThis(i18n("")); //TODO
00743 
00744     action = createSharedAction(i18n("&Filter"), "filter", 0, "data_filter");
00745     setActionVolatile( action, true );
00746 //  action->setToolTip(i18n("")); //todo
00747 //  action->setWhatsThis(i18n("")); //todo
00748 
00749 //  setSharedMenu("data_sort");
00750     action = createSharedAction(i18n("&Ascending"), "sort_az", 0, "data_sort_az");
00751 //temp. disable because of problems with volatile actions   setActionVolatile( action, true );
00752     action->setToolTip(i18n("Sort data in ascending order"));
00753     action->setWhatsThis(i18n("Sorts data in ascending order (from A to Z and from 0 to 9). Data from selected column is used for sorting."));
00754 
00755     action = createSharedAction(i18n("&Descending"), "sort_za", 0, "data_sort_za");
00756 //temp. disable because of problems with volatile actions   setActionVolatile( action, true );
00757     action->setToolTip(i18n("Sort data in descending order"));
00758     action->setWhatsThis(i18n("Sorts data in descending (from Z to A and from 9 to 0). Data from selected column is used for sorting."));
00759 
00760     //FORMAT MENU
00761     d->action_format_font = createSharedAction(i18n("&Font..."), "fonts", 0, "format_font");
00762     d->action_format_font->setToolTip(i18n("Change font for selected object"));
00763     d->action_format_font->setWhatsThis(i18n("Changes font for selected object."));
00764 
00765     //TOOLS MENU
00766 
00767     //WINDOW MENU
00768 #ifndef Q_WS_WIN
00769     //KMDI <= 3.5.1 has no shortcut here:
00770     KAction *closeWindowAction = actionCollection()->action("window_close");
00771     if (closeWindowAction)
00772         closeWindowAction->setShortcut(KStdAccel::close());
00773 #endif
00774 
00775     //additional 'Window' menu items
00776     d->action_window_next = new KAction( i18n("&Next Window"), "",
00777 #ifdef Q_WS_WIN
00778         CTRL+Key_Tab,
00779 #else
00780         ALT+Key_Right,
00781 #endif
00782         this, SLOT(activateNextWin()), actionCollection(), "window_next");
00783     d->action_window_next->setToolTip( i18n("Next window") );
00784     d->action_window_next->setWhatsThis(i18n("Switches to the next window."));
00785 
00786     d->action_window_previous = new KAction( i18n("&Previous Window"), "",
00787 #ifdef Q_WS_WIN
00788         CTRL+SHIFT+Key_Tab,
00789 #else
00790         ALT+Key_Left,
00791 #endif
00792         this, SLOT(activatePrevWin()), actionCollection(), "window_previous");
00793     d->action_window_previous->setToolTip( i18n("Previous window") );
00794     d->action_window_previous->setWhatsThis(i18n("Switches to the previous window."));
00795 
00796     //SETTINGS MENU
00797     setStandardToolBarMenuEnabled( true );
00798     action = KStdAction::keyBindings(this, SLOT( slotConfigureKeys() ), actionCollection() );
00799     action->setWhatsThis(i18n("Lets you configure shortcut keys."));
00800 
00801 #ifdef KEXI_SHOW_UNIMPLEMENTED
00802     action = KStdAction::configureToolbars( this, SLOT( slotConfigureToolbars() ), actionCollection() );
00803     action->setWhatsThis(i18n("Lets you configure toolbars."));
00804 #endif
00805 
00806     d->action_show_other = new KActionMenu(i18n("Other"),
00807         actionCollection(), "options_show_other");
00808 #ifndef KEXI_NO_CTXT_HELP
00809     d->action_show_helper = new KToggleAction(i18n("Show Context Help"), "", CTRL + Key_H,
00810      actionCollection(), "options_show_contexthelp");
00811 #if KDE_IS_VERSION(3,2,90)
00812     d->action_show_helper->setCheckedState(i18n("Hide Context Help"));
00813 #endif
00814 #endif
00815 
00816 #ifdef KEXI_FORMS_SUPPORT
00817     slotOptionsEnableForms(true, true);
00818 #else
00819     slotOptionsEnableForms(false, true);
00820 #endif
00821 
00822 #ifdef KEXI_REPORTS_SUPPORT
00823     Kexi::tempShowReports() = true;
00824 #else
00825     Kexi::tempShowReports() = false;
00826 #endif
00827 
00828 #ifdef KEXI_MACROS_SUPPORT
00829     Kexi::tempShowMacros() = true;
00830 #else
00831     Kexi::tempShowMacros() = false;
00832 #endif
00833 
00834 #ifdef KEXI_SCRIPTS_SUPPORT
00835     Kexi::tempShowScripts() = true;
00836 #else
00837     Kexi::tempShowScripts() = false;
00838 #endif
00839 
00840 #ifdef KEXI_SHOW_UNIMPLEMENTED
00841     d->action_configure = KStdAction::preferences(this, SLOT(slotShowSettings()), actionCollection());
00842     action->setWhatsThis(i18n("Lets you configure Kexi."));
00843 #endif
00844 
00845     //HELP MENU
00846 #if 0//js: todo reenable later
00847     KStdAction::tipOfDay( this, SLOT( slotTipOfTheDayAction() ), actionCollection() )
00848         ->setWhatsThis(i18n("This shows useful tips on the use of this application."));
00849 #endif
00850 #if 0 //we don't have a time for updating info text for each new version
00851     new KAction(i18n("Important Information"), "messagebox_info", 0,
00852         this, SLOT(slotImportantInfo()), actionCollection(), "help_show_important_info");
00853 #endif
00854 //TODO: UNCOMMENT TO REMOVE MDI MODES SETTING   m_pMdiModeMenu->hide();
00855 
00856 #ifndef KEXI_NO_FEEDBACK_AGENT
00857 #ifdef FEEDBACK_CLASS
00858     new KAction(i18n("Give Feedback..."), "messagebox_info", 0,
00859         this, SLOT(slotStartFeedbackAgent()), actionCollection(), "help_start_feedback_agent");
00860 #endif
00861 #endif
00862 //  KAction *actionSettings = new KAction(i18n("Configure Kexi..."), "configure", 0,
00863 //   actionCollection(), "kexi_settings");
00864 //  actionSettings->setWhatsThis(i18n("Lets you configure Kexi."));
00865 //  connect(actionSettings, SIGNAL(activated()), this, SLOT(slotShowSettings()));
00866 }
00867 
00868 void KexiMainWindowImpl::invalidateActions()
00869 {
00870     invalidateProjectWideActions();
00871     invalidateSharedActions();
00872 }
00873 
00874 void KexiMainWindowImpl::invalidateSharedActions(QObject *o)
00875 {
00876     //TODO: enabling is more complex...
00877 /*  d->action_edit_cut->setEnabled(true);
00878     d->action_edit_copy->setEnabled(true);
00879     d->action_edit_paste->setEnabled(true);*/
00880 
00881     if (!o)
00882         o = focusWindow();
00883     KexiSharedActionHost::invalidateSharedActions(o);
00884 }
00885 
00886 void KexiMainWindowImpl::invalidateSharedActions()
00887 {
00888     invalidateSharedActions(0);
00889 }
00890 
00891 // unused, I think
00892 void KexiMainWindowImpl::invalidateSharedActionsLater()
00893 {
00894     QTimer::singleShot(1, this, SLOT(invalidateSharedActions()));
00895 }
00896 
00897 void KexiMainWindowImpl::invalidateProjectWideActions()
00898 {
00899 //  stateChanged("project_opened",d->prj ? StateNoReverse : StateReverse);
00900 
00901     if(d->final)
00902         return;
00903 
00904     const bool have_dialog = d->curDialog;
00905     const bool dialog_dirty = d->curDialog && d->curDialog->dirty();
00906     const bool readOnly = d->prj && d->prj->dbConnection() && d->prj->dbConnection()->isReadOnly();
00907 
00908     //PROJECT MENU
00909     d->action_save->setEnabled(have_dialog && dialog_dirty && !readOnly);
00910     d->action_save_as->setEnabled(have_dialog && !readOnly);
00911     d->action_project_properties->setEnabled(d->prj);
00912     d->action_close->setEnabled(d->prj);
00913     d->action_project_relations->setEnabled(d->prj);
00914     d->action_project_import_data_table->setEnabled(d->prj && !readOnly);
00915     d->action_project_export_data_table->setEnabled( 
00916         d->curDialog && d->curDialog->part()->info()->isDataExportSupported() 
00917         && !d->curDialog->neverSaved() );
00918 
00919     const bool printingActionsEnabled = 
00920         d->curDialog && d->curDialog->part()->info()->isPrintingSupported()
00921         && !d->curDialog->neverSaved();
00922     d->action_project_print->setEnabled( printingActionsEnabled );
00923     d->action_project_print_preview->setEnabled( printingActionsEnabled );
00924     d->action_project_print_setup->setEnabled( printingActionsEnabled );
00925 
00926     //EDIT MENU
00927     d->action_edit_paste_special_data_table->setEnabled(d->prj && !readOnly);
00928 
00931     if (d->curDialog && d->curDialog->currentViewMode()==Kexi::DataViewMode) {
00932         KexiPart::Info *activePartInfo = d->curDialog->part()->info();
00933         d->action_edit_copy_special_data_table->setEnabled(
00934             activePartInfo ? activePartInfo->isDataExportSupported() : false );
00935     }
00936     else
00937         d->action_edit_copy_special_data_table->setEnabled( false );
00938 
00939     //VIEW MENU
00940     d->action_view_nav->setEnabled(d->prj);
00941     d->action_view_mainarea->setEnabled(d->prj);
00942     d->action_view_propeditor->setEnabled(d->prj);
00943     d->action_view_data_mode->setEnabled( have_dialog && d->curDialog->supportsViewMode(Kexi::DataViewMode) );
00944     if (!d->action_view_data_mode->isEnabled())
00945         d->action_view_data_mode->setChecked(false);
00946     d->action_view_design_mode->setEnabled( have_dialog && d->curDialog->supportsViewMode(Kexi::DesignViewMode) );
00947     if (!d->action_view_design_mode->isEnabled())
00948         d->action_view_design_mode->setChecked(false);
00949     d->action_view_text_mode->setEnabled( have_dialog && d->curDialog->supportsViewMode(Kexi::TextViewMode) );
00950     if (!d->action_view_text_mode->isEnabled())
00951         d->action_view_text_mode->setChecked(false);
00952 #ifndef KEXI_NO_CTXT_HELP
00953     d->action_show_helper->setEnabled(d->prj);
00954 #endif
00955 
00956     //CREATE MENU
00957     if (d->createMenu)
00958         d->createMenu->setEnabled(d->prj);
00959 
00960     // DATA MENU
00961     //d->action_data_execute->setEnabled( d->curDialog && d->curDialog->part()->info()->isExecuteSupported() );
00962 
00963     //TOOLS MENU
00964     // "compact db" supported if there's no db or the current db supports compacting and is opened r/w:
00965     d->action_tools_compact_database->setEnabled( 
00966         !d->prj || !readOnly && d->prj && d->prj->dbConnection() 
00967         && (d->prj->dbConnection()->driver()->features() & KexiDB::Driver::CompactingDatabaseSupported) );
00968 
00969     //WINDOW MENU
00970     if (d->action_window_next) {
00971         d->action_window_next->setEnabled(!m_pDocumentViews->isEmpty());
00972         d->action_window_previous->setEnabled(!m_pDocumentViews->isEmpty());
00973     }
00974 
00975     //DOCKS
00976     if (d->nav)
00977         d->nav->setEnabled(d->prj);
00978     if (d->propEditor)
00979         d->propEditorTabWidget->setEnabled(d->prj);
00980 }
00981 
00982 void KexiMainWindowImpl::invalidateViewModeActions()
00983 {
00984     if (d->curDialog) {
00985         //update toggle action
00986         if (d->curDialog->currentViewMode()==Kexi::DataViewMode)
00987             d->action_view_data_mode->setChecked( true );
00988         else if (d->curDialog->currentViewMode()==Kexi::DesignViewMode)
00989             d->action_view_design_mode->setChecked( true );
00990         else if (d->curDialog->currentViewMode()==Kexi::TextViewMode)
00991             d->action_view_text_mode->setChecked( true );
00992     }
00993 }
00994 
00995 tristate KexiMainWindowImpl::startup()
00996 {
00997     switch (Kexi::startupHandler().action()) {
00998     case KexiStartupHandler::CreateBlankProject:
00999         makeDockInvisible( manager()->findWidgetParentDock(d->propEditorTabWidget) );
01000         return createBlankProject();
01001     case KexiStartupHandler::UseTemplate:
01002         return cancelled;
01003         //TODO
01004         break;
01005     case KexiStartupHandler::OpenProject:
01006         return openProject(*Kexi::startupHandler().projectData());
01007     case KexiStartupHandler::ImportProject:
01008         return showProjectMigrationWizard(
01009             Kexi::startupHandler().importActionData().mimeType,
01010             Kexi::startupHandler().importActionData().fileName
01011         );
01012     default:;
01013         makeDockInvisible( manager()->findWidgetParentDock(d->propEditorTabWidget) );
01014     }
01015     return true;
01016 }
01017 
01018 static QString internalReason(KexiDB::Object *obj)
01019 {
01020     const QString &s = obj->errorMsg();
01021     if (s.isEmpty())
01022         return s;
01023     return QString("<br>(%1) ").arg(i18n("reason:")+" <i>"+s+"</i>");
01024 }
01025 
01026 tristate KexiMainWindowImpl::openProject(const KexiProjectData& projectData)
01027 {
01028     KexiProjectData *newProjectData = new KexiProjectData(projectData);
01029     if (d->final) {
01030         //TODO: maybe also auto allow to open objects...
01031         return initFinalMode(newProjectData);
01032     }
01033     createKexiProject( newProjectData );
01034     if (!newProjectData->connectionData()->savePassword 
01035         && newProjectData->connectionData()->password.isEmpty()
01036         && newProjectData->connectionData()->fileName().isEmpty() 
01037     )
01038     {
01039         //ask for password
01040         KexiDBPasswordDialog pwdDlg(this, *newProjectData->connectionData(), 
01041             false );
01042         if (QDialog::Accepted!=pwdDlg.exec()) {
01043             delete d->prj;
01044             d->prj = 0;
01045             return cancelled;
01046         }
01047     }
01048     bool incompatibleWithKexi;
01049     tristate res = d->prj->open(incompatibleWithKexi);
01050     if (~res) {
01051         delete d->prj;
01052         d->prj = 0;
01053         return cancelled;
01054     }
01055     else if (!res) {
01056         delete d->prj;
01057         d->prj = 0;
01058         if (incompatibleWithKexi) {
01059             if (KMessageBox::Yes == KMessageBox::questionYesNo(this,
01060                 i18n("<qt>Database project %1 does not appear to have been created using Kexi.<br><br>"
01061                 "Do you want to import it as a new Kexi project?</qt>").arg(projectData.infoString()),
01062                 0, KGuiItem(i18n("Import Database", "&Import..."), "database_import"),
01063                 KStdGuiItem::quit()))
01064             {
01065                 const bool anotherProjectAlreadyOpened = d->prj;
01066                 tristate res = showProjectMigrationWizard("application/x-kexi-connectiondata", 
01067                     projectData.databaseName(), projectData.constConnectionData());
01068                 
01069                 if (!anotherProjectAlreadyOpened) //the project could have been opened within this instance
01070                     return res;
01071 
01072                 //always return cancelled because even if migration succeeded, new Kexi instance 
01073                 //will be started if user wanted to open the imported db
01074                 return cancelled;
01075             }
01076             return cancelled;
01077         }
01078         return false;
01079     }
01080     initNavigator();
01081 //  initPropertyEditor();
01082     Kexi::recentProjects().addProjectData( newProjectData );
01083     updateReadOnlyState();
01084     invalidateActions();
01085 //  d->disableErrorMessages = true;
01086     enableMessages( false );
01087 
01088     QTimer::singleShot(1, this, SLOT(slotAutoOpenObjectsLater()));
01089     return true;
01090 }
01091 
01092 void KexiMainWindowImpl::updateReadOnlyState()
01093 {
01094     const bool readOnly = d->prj && d->prj->dbConnection() && d->prj->dbConnection()->isReadOnly();
01095     d->statusBar->setReadOnlyFlag( readOnly );
01096     if (d->nav)
01097         d->nav->setReadOnly(readOnly);
01098     // update "insert ....." actions for every part
01099     KActionCollection *ac = actionCollection();
01100     for (KexiPart::PartInfoListIterator it(*Kexi::partManager().partInfoList()); it.current(); ++it) {
01101         KAction *a = ac->action( KexiPart::nameForCreateAction( *it.current() ) );
01102         if (a)
01103             a->setEnabled(!readOnly);
01104     }
01105 }
01106 
01107 void KexiMainWindowImpl::slotAutoOpenObjectsLater()
01108 {
01109     QString not_found_msg;
01110     //ok, now open "autoopen: objects
01111     if (d->prj) {
01112         for (QValueList<KexiProjectData::ObjectInfo>::ConstIterator it = 
01113                 d->prj->data()->autoopenObjects.constBegin();
01114             it != d->prj->data()->autoopenObjects.constEnd(); ++it )
01115         {
01116             KexiProjectData::ObjectInfo info = *it;
01117             KexiPart::Info *i = Kexi::partManager().infoForMimeType( 
01118                 QCString("kexi/")+info["type"].lower().latin1() );
01119             if (!i) {
01120                 not_found_msg += "<li>";
01121                 if (!info["name"].isEmpty())
01122                     not_found_msg += (QString("\"") + info["name"] + "\" - ");
01123                 if (info["action"]=="new")
01124                     not_found_msg += i18n("cannot create object - unknown object type \"%1\"")
01125                         .arg(info["type"]);
01126                 else
01127                     not_found_msg += i18n("unknown object type \"%1\"").arg(info["type"]);
01128                 not_found_msg += internalReason(&Kexi::partManager())+"<br></li>";
01129                 continue;
01130             }
01131             // * NEW
01132             if (info["action"]=="new") {
01133                 if (!newObject( i )) {
01134                     not_found_msg += "<li>";
01135                     not_found_msg += (i18n("cannot create object of type \"%1\"").arg(info["type"])+
01136                         internalReason(d->prj)+"<br></li>");
01137                 }
01138                 else
01139                     d->wasAutoOpen = true;
01140                 continue;
01141             }
01142 
01143             KexiPart::Item *item = d->prj->item(i, info["name"]);
01144 
01145             if (!item) {
01146                 not_found_msg += "<li>";
01147                 QString taskName;
01148                 if (info["action"]=="print-preview")
01149                     taskName = i18n("making print preview for");
01150                 else if (info["action"]=="print")
01151                     taskName = i18n("printing");
01152                 else if (info["action"]=="execute")
01153                     taskName = i18n("\"executing object\" action", "executing");
01154                 else 
01155                     taskName = i18n("opening");
01156 
01157                 not_found_msg += (QString("<li>")+ taskName + " \"" + info["name"] + "\" - ");
01158                 if ("table"==info["type"].lower())
01159                     not_found_msg += i18n("table not found");
01160                 else if ("query"==info["type"].lower())
01161                     not_found_msg += i18n("query not found");
01162                 else if ("macro"==info["type"].lower())
01163                     not_found_msg += i18n("macro not found");
01164                 else if ("script"==info["type"].lower())
01165                     not_found_msg += i18n("script not found");
01166                 else
01167                     not_found_msg += i18n("object not found");
01168                 not_found_msg += (internalReason(d->prj)+"<br></li>");
01169                 continue;
01170             }
01171             // * EXECUTE, PRINT, PRINT PREVIEW
01172             if (info["action"]=="execute") {
01173                 tristate res = executeItem(item);
01174                 if (false == res) {
01175                     not_found_msg += "<li>";
01176                     not_found_msg += ( QString("<li>\"")+ info["name"] + "\" - " + i18n("cannot execute object")+
01177                     internalReason(d->prj)+"<br></li>" );
01178                 }
01179                 continue;
01180             }
01181             else if (info["action"]=="print") {
01182                 tristate res = printItem(item);
01183                 if (false == res) {
01184                     not_found_msg += "<li>";
01185                     not_found_msg += ( QString("<li>\"")+ info["name"] + "\" - " + i18n("cannot print object")+
01186                     internalReason(d->prj)+"<br></li>" );
01187                 }
01188                 continue;
01189             }
01190             else if (info["action"]=="print-preview") {
01191                 tristate res = printPreviewForItem(item);
01192                 if (false == res) {
01193                     not_found_msg += "<li>";
01194                     not_found_msg += ( QString("<li>\"")+ info["name"] + "\" - " + i18n("cannot make print preview of object")+
01195                     internalReason(d->prj)+"<br></li>" );
01196                 }
01197                 continue;
01198             }
01199 
01200             int viewMode;
01201             if (info["action"]=="open")
01202                 viewMode = Kexi::DataViewMode;
01203             else if (info["action"]=="design")
01204                 viewMode = Kexi::DesignViewMode;
01205             else if (info["action"]=="edittext")
01206                 viewMode = Kexi::TextViewMode;
01207             else
01208                 continue; //sanity
01209             bool openingCancelled;
01210             if (!openObject(item, viewMode, openingCancelled) && !openingCancelled) {
01211                 not_found_msg += "<li>";
01212                 not_found_msg += ( QString("<li>\"")+ info["name"] + "\" - " + i18n("cannot open object")+
01213                     internalReason(d->prj)+"<br></li>" );
01214                 continue;
01215             }
01216             else
01217                 d->wasAutoOpen = true;
01218         }
01219     }
01220     enableMessages( true );
01221 //  d->disableErrorMessages = false;
01222 
01223     if (!not_found_msg.isEmpty())
01224         showErrorMessage(i18n("You have requested selected objects to be automatically opened "
01225             "or processed on startup. Several objects cannot be opened or processed."),
01226             QString("<ul>%1</ul>").arg(not_found_msg) );
01227 
01228     d->updatePropEditorVisibility(d->curDialog ? d->curDialog->currentViewMode() : 0);
01229 #if defined(KDOCKWIDGET_P)
01230     if (d->propEditor) {
01231                 KDockWidget *dw = (KDockWidget *)d->propEditorTabWidget->parentWidget();
01232                 KDockSplitter *ds = (KDockSplitter *)dw->parentWidget();
01233                 if(ds)
01234                     ds->setSeparatorPosInPercent(d->config->readNumEntry("RightDockPosition", 80/* % */));
01235     }
01236 #endif
01237 
01238     updateAppCaption();
01239 
01240 //  d->navToolWindow->wrapperWidget()->setFixedWidth(200);
01241 //js TODO: make visible FOR OTHER MODES if needed
01242     if (mdiMode()==KMdi::ChildframeMode || mdiMode()==KMdi::TabPageMode) {
01243         //make docks visible again
01244         if (!d->navToolWindow->wrapperWidget()->isVisible())
01245             static_cast<KDockWidget*>(d->navToolWindow->wrapperWidget())->makeDockVisible();
01246 //      if (!d->propEditorToolWindow->wrapperWidget()->isVisible())
01247 //          static_cast<KDockWidget*>(d->propEditorToolWindow->wrapperWidget())->makeDockVisible();
01248     }
01249 
01250     //  if (!d->prj->data()->autoopenObjects.isEmpty())
01251     d->restoreNavigatorWidth();
01252 
01253 #ifndef PROPEDITOR_VISIBILITY_CHANGES
01254 //  KDockWidget *dw = (KDockWidget *)d->nav->parentWidget();
01255 //  KDockSplitter *ds = (KDockSplitter *)dw->parentWidget();
01256 //  const int pos = ds->separatorPos();
01257 
01258     //if (!d->curDialog || d->curDialog->currentViewMode()==Kexi::DataViewMode)
01259 //      d->propEditorToolWindow->hide();
01260 
01261 //  ds->setSeparatorPos( pos, true );
01262 #endif
01263     if (d->nav) {
01264         d->nav->updateGeometry();
01265     }
01266     qApp->processEvents();
01267     emit projectOpened();
01268 }
01269 
01270 tristate KexiMainWindowImpl::closeProject()
01271 {
01272 #ifndef KEXI_NO_PENDING_DIALOGS
01273     if (d->pendingDialogsExist()) {
01274         kdDebug() << "KexiMainWindowImpl::closeProject() pendingDialogsExist..." << endl;
01275         d->actionToExecuteWhenPendingJobsAreFinished = Private::CloseProjectAction;
01276         return cancelled;
01277     }
01278 #endif
01279 
01280     d->saveSettingsForShowProjectNavigator = d->prj; //only save nav. visibility setting is project is opened
01281     if (!d->prj) {
01282         return true;
01283     }
01284 
01285     {
01286         // make sure the project can be closed
01287         bool cancel = false;
01288         emit acceptProjectClosingRequested(cancel);
01289         if (cancel)
01290             return cancelled;
01291     }
01292 
01293     d->dialogExistedBeforeCloseProject = !d->curDialog.isNull();
01294 
01295 #if defined(KDOCKWIDGET_P)
01296     //remember docks position - will be used on storeSettings()
01297     if (d->propEditor) {
01298         KDockWidget *dw = (KDockWidget *)d->propEditorTabWidget->parentWidget();
01299         KDockSplitter *ds = (KDockSplitter *)dw->parentWidget();
01300         if (ds)
01301             d->propEditorDockSeparatorPos = ds->separatorPosInPercent();
01302     }
01303     if (d->nav) {
01304 //      makeDockInvisible( manager()->findWidgetParentDock(d->propEditor) );
01305 
01306         if (d->propEditor) {
01307             if (d->openedDialogsCount() == 0)
01308                 makeWidgetDockVisible(d->propEditorTabWidget);
01309             KDockWidget *dw = (KDockWidget *)d->propEditorTabWidget->parentWidget();
01310             KDockSplitter *ds = (KDockSplitter *)dw->parentWidget();
01311             if(ds)
01312                 ds->setSeparatorPosInPercent(80);
01313         }
01314 
01315         KDockWidget *dw = (KDockWidget *)d->nav->parentWidget();
01316         KDockSplitter *ds = (KDockSplitter *)dw->parentWidget();
01317         int dwWidth = dw->width();
01318         if (ds) {
01319                 if (d->openedDialogsCount()!=0 && d->propEditorTabWidget->isVisible())
01320                     d->navDockSeparatorPos = ds->separatorPosInPercent();
01321                 else
01322                     d->navDockSeparatorPos = (100 * dwWidth) / width();
01323 
01324 //              int navDockSeparatorPosWithAutoOpen = (100 * dw->width()) / width() + 4;
01325 //              d->navDockSeparatorPos = (100 * dw->width()) / width() + 1;
01326         }
01327     }
01328 #endif
01329 
01330     //close each window, optionally asking if user wants to close (if data changed)
01331     while (!d->curDialog.isNull()) {
01332         tristate res = closeDialog( d->curDialog );
01333         if (!res || ~res)
01334             return res;
01335     }
01336 
01337     // now we will close for sure
01338     emit beforeProjectClosing();
01339 
01340     if (!d->prj->closeConnection())
01341         return false;
01342 
01343     if(d->nav)
01344     {
01345         d->navWasVisibleBeforeProjectClosing = manager()->findWidgetParentDock(d->nav)->isVisible();
01346         d->nav->clear();
01347 #if 0 //do not confuse users 
01348         d->navToolWindow->hide();
01349 #endif
01350     }
01351 
01352     if (d->propEditor)
01353         makeDockInvisible( manager()->findWidgetParentDock(d->propEditorTabWidget) );
01354 
01355 //  if(d->propEditorToolWindow)
01356     //  d->propEditorToolWindow->hide();
01357 
01358     d->clearDialogs(); //sanity!
01359     delete d->prj;
01360     d->prj=0;
01361 
01362 //  Kexi::partManager().unloadAllParts();
01363 
01364     updateReadOnlyState();
01365     invalidateActions();
01366     if(!d->final)
01367         updateAppCaption();
01368 
01369     emit projectClosed();
01370     return true;
01371 }
01372 
01373 void KexiMainWindowImpl::initContextHelp() {
01374 #ifndef KEXI_NO_CTXT_HELP
01375     d->ctxHelp=new KexiContextHelp(this,this);
01376 /*todo
01377     d->ctxHelp->setContextHelp(i18n("Welcome"),i18n("The <B>KEXI team</B> wishes you a lot of productive work, "
01378         "with this product. <BR><HR><BR>If you have found a <B>bug</B> or have a <B>feature</B> request, please don't "
01379         "hesitate to report it at our <A href=\"http://www.kexi-project.org/cgi-bin/bug.pl\"> issue "
01380         "tracking system </A>.<BR><HR><BR>If you would like to <B>join</B> our effort, the <B>development</B> documentation "
01381         "at <A href=\"http://www.kexi-project.org\">www.kexi-project.org</A> is a good starting point."),0);
01382 */
01383     addToolWindow(d->ctxHelp,KDockWidget::DockBottom | KDockWidget::DockLeft,getMainDockWidget(),20);
01384 #endif
01385 }
01386 
01387 void
01388 KexiMainWindowImpl::initNavigator()
01389 {
01390     kdDebug() << "KexiMainWindowImpl::initNavigator()" << endl;
01391 
01392     if(!d->nav)
01393     {
01394         d->nav = new KexiBrowser(this);
01395         d->nav->installEventFilter(this);
01396         d->navToolWindow = addToolWindow(d->nav, KDockWidget::DockLeft, getMainDockWidget(), 20/*, lv, 35, "2"*/);
01397 //      d->navToolWindow->hide();
01398 
01399         connect(d->nav,SIGNAL(openItem(KexiPart::Item*,int)),this,SLOT(openObject(KexiPart::Item*,int)));
01400         connect(d->nav,SIGNAL(openOrActivateItem(KexiPart::Item*,int)),
01401             this,SLOT(openObjectFromNavigator(KexiPart::Item*,int)));
01402         connect(d->nav,SIGNAL(newItem( KexiPart::Info* )),
01403             this,SLOT(newObject(KexiPart::Info*)));
01404         connect(d->nav,SIGNAL(removeItem(KexiPart::Item*)),
01405             this,SLOT(removeObject(KexiPart::Item*)));
01406         connect(d->nav,SIGNAL(renameItem(KexiPart::Item*,const QString&, bool&)),
01407             this,SLOT(renameObject(KexiPart::Item*,const QString&, bool&)));
01408         connect(d->nav,SIGNAL(executeItem(KexiPart::Item*)),
01409             this,SLOT(executeItem(KexiPart::Item*)));
01410         connect(d->nav,SIGNAL(exportItemAsDataTable(KexiPart::Item*)),
01411             this,SLOT(exportItemAsDataTable(KexiPart::Item*)));
01412         connect(d->nav,SIGNAL(printItem( KexiPart::Item* )),
01413             this,SLOT(printItem(KexiPart::Item*)));
01414         connect(d->nav,SIGNAL(pageSetupForItem( KexiPart::Item*)),
01415             this,SLOT(pageSetupForItem(KexiPart::Item*)));
01416         if (d->prj) {//connect to the project
01417             connect(d->prj, SIGNAL(itemRemoved(const KexiPart::Item&)),
01418                 d->nav, SLOT(slotRemoveItem(const KexiPart::Item&)));
01419         }
01420         connect(d->nav,SIGNAL(selectionChanged(KexiPart::Item*)),
01421             this,SLOT(slotPartItemSelectedInNavigator(KexiPart::Item*)));
01422 
01423 //      d->restoreNavigatorWidth();
01424     }
01425     if(d->prj->isConnected()) {
01426         d->nav->clear();
01427 
01428         QString partManagerErrorMessages;
01429         KexiPart::PartInfoList *pl = Kexi::partManager().partInfoList();
01430         for(KexiPart::Info *it = pl->first(); it; it = pl->next())
01431         {
01432             if (!it->isVisibleInNavigator())
01433                 continue;
01434             kdDebug() << "KexiMainWindowImpl::initNavigator(): adding " << it->groupName() << endl;
01435 
01436 /*          KexiPart::Part *p=Kexi::partManager().part(it);
01437             if (!p) {
01438                 //TODO: js - OPTIONALLY: show error
01439                 continue;
01440             }
01441             p->createGUIClient(this);*/
01442 
01443             //load part - we need this to have GUI merged with part's actions
01445             KexiPart::Part *p=Kexi::partManager().part(it);
01446             if (p) {
01447                 d->nav->addGroup(*it);
01448                 //lookup project's objects (part items)
01450                 KexiPart::ItemDict *item_dict = d->prj->items(it);
01451                 if (!item_dict)
01452                     continue;
01453                 for (KexiPart::ItemDictIterator item_it( *item_dict ); item_it.current(); ++item_it) {
01454                     d->nav->addItem(*item_it.current());
01455                 }
01456             }
01457             else {
01458                 //add this error to the list that will be displayed later
01459                 QString msg, details;
01460                 KexiDB::getHTMLErrorMesage(&Kexi::partManager(), msg, details);
01461                 if (!msg.isEmpty()) {
01462                     if (partManagerErrorMessages.isEmpty()) {
01463                         partManagerErrorMessages = QString("<qt><p>")
01464                             +futureI18n("Errors encountered during loading plugins:")+"<ul>";
01465                     }
01466                     partManagerErrorMessages.append( QString("<li>") + msg );
01467                     if (!details.isEmpty())
01468                         partManagerErrorMessages.append(QString("<br>")+details);
01469                     partManagerErrorMessages.append("</li>");
01470                 }
01471             }
01472         }
01473         if (!partManagerErrorMessages.isEmpty()) {
01474             partManagerErrorMessages.append("</ul></p>");
01475             showWarningContinueMessage(partManagerErrorMessages, QString::null,
01476                 "dontShowWarningsRelatedToPluginsLoading");
01477         }
01478     }
01479     connect(d->prj, SIGNAL(newItemStored(KexiPart::Item&)), d->nav, SLOT(addItem(KexiPart::Item&)));
01480     d->nav->setFocus();
01481 
01482     if (d->forceShowProjectNavigatorOnCreation) {
01483         slotViewNavigator();
01484         d->forceShowProjectNavigatorOnCreation = false;
01485     }
01486     else if (d->forceHideProjectNavigatorOnCreation) {
01487         d->navToolWindow->hide();
01488 //      makeDockInvisible( manager()->findWidgetParentDock(d->nav) );
01489         d->forceHideProjectNavigatorOnCreation = false;
01490     }
01491 
01492     invalidateActions();
01493 }
01494 
01495 void KexiMainWindowImpl::slotLastActions()
01496 {
01497 #if defined(KEXI_PROP_EDITOR) && defined(KDOCKWIDGET_P)
01498     if (mdiMode()==KMdi::ChildframeMode || mdiMode()==KMdi::TabPageMode) {
01499 //      KDockWidget *dw = (KDockWidget *)d->propEditor->parentWidget();
01500         //KDockSplitter *ds = (KDockSplitter *)dw->parentWidget();
01501 //      Q_UNUSED(ds);
01502 //1     ds->resize(ds->width()*3, ds->height());
01503 //1     ds->setSeparatorPos(30, true);
01504 //1     ds->setForcedFixedWidth( dw, 200 );
01505     }
01506 #endif
01507 #ifdef Q_WS_WIN
01508     showMaximized();//js: workaround for not yet completed layout settings storage on win32
01509 #endif
01510 }
01511 
01512 void KexiMainWindowImpl::initPropertyEditor()
01513 {
01514 #ifdef KEXI_PROP_EDITOR
01515     if (!d->propEditor) {
01516 //TODO: FIX LAYOUT PROBLEMS
01517         d->propEditorTabWidget = new KTabWidget(this);
01518         d->propEditorTabWidget->hide();
01519         d->propEditor = new KexiPropertyEditorView(this, d->propEditorTabWidget);
01520         d->propEditorTabWidget->setCaption(d->propEditor->caption());
01521         d->propEditorTabWidget->addTab(d->propEditor, i18n("Properties"));
01522         d->propEditor->installEventFilter(this);
01523         d->propEditorToolWindow = addToolWindow(d->propEditorTabWidget,
01524             KDockWidget::DockRight, getMainDockWidget(), 20);
01525 
01526         d->config->setGroup("PropertyEditor");
01527         int size = d->config->readNumEntry("FontSize", -1);
01528         QFont f( Kexi::smallFont(this/*init*/) );
01529         if (size>0)
01530             f.setPixelSize( size );
01531         d->propEditorTabWidget->setFont(f);
01532 
01533         if (mdiMode()==KMdi::ChildframeMode || mdiMode()==KMdi::TabPageMode) {
01534         KDockWidget *dw = (KDockWidget *)d->propEditorTabWidget->parentWidget();
01535     #if defined(KDOCKWIDGET_P)
01536             KDockSplitter *ds = (KDockSplitter *)dw->parentWidget();
01537 //          ds->setKeepSize(true);
01538             makeWidgetDockVisible(d->propEditorTabWidget);
01539     //      ds->show();
01540         //  ds->resize(400, ds->height());
01541     //      ds->setSeparatorPos(400, true);
01542     //      ds->setForcedFixedWidth( dw, 400 );
01543     //      ds->setSeparatorPos(600, true);
01544 
01545 
01546             d->config->setGroup("MainWindow");
01547             ds->setSeparatorPosInPercent(d->config->readNumEntry("RightDockPosition", 80/* % */));
01548 //          makeDockInvisible( manager()->findWidgetParentDock(d->propEditor) );
01549 
01550     //      ds->setForcedFixedWidth( dw, d->config->readNumEntry("RightDockPosition", 80) );
01551         //  ds->resize(400, ds->height());
01552         //  dw->resize(400, dw->height());
01553     #endif
01554 
01555     //1     dw->setMinimumWidth(200);
01556 
01557     //  ds->setSeparatorPos(d->propEditor->sizeHint().width(), true);
01558 
01559             //heh, this is for IDEAl only, I suppose?
01560     //js        if (m_rightContainer) {
01561     //js            m_rightContainer->setForcedFixedWidth( 400 );
01562     //js        }
01563         }
01564     #endif
01565 
01566     //  int w = d->propEditor->width();
01567     /*    KMdiToolViewAccessor *tmp=createToolWindow();
01568             tmp->setWidgetToWrap(d->propEditor);
01569         d->propEditor->show(); // I'm not sure, if this is a bug in kdockwidget, which I would better fix there
01570             tmp->show(KDockWidget::DockRight,getMainDockWidget(),20);
01571     */
01572     }
01573 //  makeDockInvisible(manager()->findWidgetParentDock(d->propEditorTabWidget));
01574 }
01575 
01576 void KexiMainWindowImpl::slotPartLoaded(KexiPart::Part* p)
01577 {
01578     if (!p)
01579         return;
01580     connect(p, SIGNAL(newObjectRequest(KexiPart::Info*)),
01581         this, SLOT(newObject(KexiPart::Info*)));
01582     p->createGUIClients(this);
01583 }
01584 
01586 void KexiMainWindowImpl::slotCaptionForCurrentMDIChild(bool childrenMaximized)
01587 {
01588     //js todo: allow to set custom "static" app caption
01589 
01590     KMdiChildView *view = 0L;
01591     if (!d->curDialog)
01592         view = 0;
01593     else if (d->curDialog->isAttached()) {
01594         view = d->curDialog;
01595     } else {
01596         //current dialog isn't attached! - find top level child
01597         if (m_pMdi->topChild()) {
01598             view = m_pMdi->topChild()->m_pClient;
01599             childrenMaximized = view->mdiParent()->state()==KMdiChildFrm::Maximized;
01600         }
01601         else
01602             view = 0;
01603     }
01604 
01605     if (childrenMaximized && view) {
01606         setCaption( d->curDialog->caption()
01607             + (d->appCaptionPrefix.isEmpty() ? QString::null : (QString::fromLatin1(" - ") + d->appCaptionPrefix)) );
01608     }
01609     else {
01610         setCaption( (d->appCaptionPrefix.isEmpty() ? QString::null : (d->appCaptionPrefix + QString::fromLatin1(" - ")))
01611             + d->origAppCaption );
01612     }
01613 }
01614 
01615 void KexiMainWindowImpl::updateAppCaption()
01616 {
01617     //js todo: allow to set custom "static" app caption
01618 
01619     d->appCaptionPrefix = "";
01620     if (d->prj && d->prj->data()) {//add project name
01621         d->appCaptionPrefix = d->prj->data()->caption();
01622         if (d->appCaptionPrefix.isEmpty())
01623             d->appCaptionPrefix = d->prj->data()->databaseName();
01624     }
01625 //  if (!d->appCaptionPrefix.isEmpty())
01626 //      d->appCaptionPrefix = d->appCaptionPrefix;
01627 
01628     bool max = false;
01629     if (d->curDialog && d->curDialog->mdiParent())
01630         max = d->curDialog->mdiParent()->state()==KMdiChildFrm::Maximized;
01631 
01632     slotCaptionForCurrentMDIChild(max);
01633 /*
01634     KMdiChildView *view;
01635     if (!d->curDialog)
01636         view = 0;
01637     else if (d->curDialog->isAttached()) {
01638         view = d->curDialog;
01639     } else {
01640         //current dialog isn't attached! - find top level child
01641         if (m_pMdi->topChild()) {
01642             view = m_pMdi->topChild()->m_pClient;
01643         }
01644         else
01645             view = 0;
01646     }
01647 
01648     kApp->setCaption( d->appCaption );
01649     if (view && view->mdiParent()->state()==KMdiChildFrm::Maximized) {
01650         setCaption( view->caption() );
01651     }
01652     else {
01653         setCaption( d->appCaption );
01654     }*/
01655 }
01656 
01657 void KexiMainWindowImpl::slotNoMaximizedChildFrmLeft(KMdiChildFrm*)
01658 {
01659     slotCaptionForCurrentMDIChild(false);
01660 }
01661 
01662 void KexiMainWindowImpl::slotLastChildViewClosed() //slotLastChildFrmClosed()
01663 {
01664     if (m_pDocumentViews->count()>0) //a fix for KMDI bug (will be fixed in KDE 3.4)
01665         return;
01666 
01667     slotCaptionForCurrentMDIChild(false);
01668     activeWindowChanged(0);
01669 
01670 //js: too WEIRD if (d->propEditor)
01671 //js: too WEIRD     makeDockInvisible( manager()->findWidgetParentDock(d->propEditorTabWidget) );
01672 //  if (d->propEditorToolWindow)
01673     //  d->propEditorToolWindow->hide();
01674 }
01675 
01676 void KexiMainWindowImpl::slotChildViewIsDetachedNow(QWidget*)
01677 {
01678     slotCaptionForCurrentMDIChild(false);
01679 }
01680 
01681 /*void
01682 KexiMainWindowImpl::closeEvent(QCloseEvent *ev)
01683 {
01684     storeSettings();
01685 
01686     bool cancelled = false;
01687     if (!closeProject(cancelled)) {
01688         //todo: error message
01689         return;
01690     }
01691     if (cancelled) {
01692         ev->ignore();
01693         return;
01694     }
01695 
01696     ev->accept();
01697 }*/
01698 
01699 bool
01700 KexiMainWindowImpl::queryClose()
01701 {
01702 #ifndef KEXI_NO_PENDING_DIALOGS
01703     if (d->pendingDialogsExist()) {
01704         kdDebug() << "KexiMainWindowImpl::queryClose() pendingDialogsExist..." << endl;
01705         d->actionToExecuteWhenPendingJobsAreFinished = Private::QuitAction;
01706         return false;
01707     }
01708 #endif
01709 //  storeSettings();
01710     const tristate res = closeProject();
01711     if (~res)
01712         return false;
01713 
01714     if (res==true)
01715         storeSettings();
01716 
01717     return ! ~res;
01718 }
01719 
01720 bool
01721 KexiMainWindowImpl::queryExit()
01722 {
01723 //  storeSettings();
01724     return true;
01725 }
01726 
01727 void
01728 KexiMainWindowImpl::restoreSettings()
01729 {
01730     d->config->setGroup("MainWindow");
01731 
01732     // Saved settings
01733     applyMainWindowSettings( d->config, "MainWindow" );
01734 
01735     //small hack - set the default -- bottom
01736 //  d->config->setGroup(QString(name()) + " KMdiTaskBar Toolbar style");
01737     d->config->setGroup("MainWindow Toolbar KMdiTaskBar");
01738     const bool tbe = d->config->readEntry("Position").isEmpty();
01739     if (tbe || d->config->readEntry("Position")=="Bottom") {
01740         if (tbe)
01741             d->config->writeEntry("Position","Bottom");
01742         moveDockWindow(m_pTaskBar, DockBottom);
01743     }
01744 
01745     d->config->setGroup("MainWindow");
01746     int mdimode = d->config->readNumEntry("MDIMode", -1);//KMdi::TabPageMode);
01747 
01748     const bool showProjectNavigator = d->config->readBoolEntry("ShowProjectNavigator", true);
01749 
01750     switch(mdimode)
01751     {
01752 /*      case KMdi::ToplevelMode:
01753             switchToToplevelMode();
01754             m_pTaskBar->switchOn(true);
01755             break;*/
01756         case KMdi::ChildframeMode:
01757             switchToChildframeMode(false);
01758             m_pTaskBar->switchOn(true);
01759 
01760             // restore a possible maximized Childframe mode,
01761             // will be used in KexiMainWindowImpl::addWindow()
01762             d->maximizeFirstOpenedChildFrm = d->config->readBoolEntry("maximized childframes", true);
01763             setEnableMaximizedChildFrmMode(d->maximizeFirstOpenedChildFrm);
01764 
01765             if (!showProjectNavigator) {
01766                 //it's visible by default but we want to hide it on navigator creation
01767                 d->forceHideProjectNavigatorOnCreation = true;
01768             }
01769 
01770             break;
01771 
01772 #define DEFAULT_MDI_MODE KMdi::IDEAlMode
01773 
01774         case DEFAULT_MDI_MODE:
01775         default:
01776             switchToIDEAlMode(false);
01777             if (showProjectNavigator) {
01778                 //it's invisible by default but we want to show it on navigator creation
01779                 d->forceShowProjectNavigatorOnCreation = true;
01780             }
01781             break;
01782 /*      case KMdi::TabPageMode:
01783             switchToTabPageMode();
01784             break;
01785 */
01786     }
01787 
01788 #if 0
01789     if ( !initialGeometrySet() ) {
01790         // Default size
01791 //      int restoredWidth, restoredHeight;
01792         int scnum = QApplication::desktop()->screenNumber(parentWidget());
01793         QRect desk = QApplication::desktop()->screenGeometry(scnum);
01794 //#if KDE_IS_VERSION(3,1,90)
01795 //      restoredWidth = KGlobalSettings::screenGeometry(scnum).width();
01796     //  restoredHeight = KGlobalSettings::screenGeometry(scnum).height();
01797 //#else
01798 //      restoredWidth = QApplication::desktop()->width();
01799 //      restoredHeight = QApplication::desktop()->height();
01800 //#endif
01801 /*      if (restoredWidth > 1100) {// very big desktop ?
01802             restoredWidth = 1000;
01803             restoredHeight = 800;
01804         }
01805         if (restoredWidth > 850) {// big desktop ?
01806             restoredWidth = 800;
01807             restoredHeight = 600;
01808         }
01809         else {// small (800x600, 640x480) desktop
01810             restoredWidth = QMIN( restoredWidth, 600 );
01811             restoredHeight = QMIN( restoredHeight, 400 );
01812         }*/
01813 
01814         config->setGroup("MainWindow");
01815         QSize s ( config->readNumEntry( QString::fromLatin1("Width %1").arg(desk.width()), 700 ),
01816               config->readNumEntry( QString::fromLatin1("Height %1").arg(desk.height()), 480 ) );
01817         resize (kMin (s.width(), desk.width()), kMin(s.height(), desk.height()));
01818     }
01819 #endif
01820 }
01821 
01822 void
01823 KexiMainWindowImpl::storeSettings()
01824 {
01825     kdDebug() << "KexiMainWindowImpl::storeSettings()" << endl;
01826 
01827 //  saveWindowSize( d->config ); //instance()->config() );
01828     saveMainWindowSettings( d->config, "MainWindow" );
01829     d->config->setGroup("MainWindow");
01830     KMdi::MdiMode modeToSave = mdiMode();
01831     if (d->mdiModeToSwitchAfterRestart!=(KMdi::MdiMode)0)
01832         modeToSave = d->mdiModeToSwitchAfterRestart;
01833     if (modeToSave == DEFAULT_MDI_MODE)
01834         d->config->deleteEntry("MDIMode");
01835     else
01836         d->config->writeEntry("MDIMode", modeToSave);
01837     d->config->writeEntry("maximized childframes", isInMaximizedChildFrmMode());
01838 
01839 //  if (manager()->findWidgetParentDock(d->nav)->isVisible())
01840     if (d->saveSettingsForShowProjectNavigator) {
01841         if (d->navWasVisibleBeforeProjectClosing)
01842             d->config->deleteEntry("ShowProjectNavigator");
01843         else
01844             d->config->writeEntry("ShowProjectNavigator", false);
01845     }
01846 
01847     if (modeToSave==KMdi::ChildframeMode || modeToSave==KMdi::TabPageMode) {
01848         if (d->propEditor && d->propEditorDockSeparatorPos >= 0 && d->propEditorDockSeparatorPos <= 100) {
01849             d->config->setGroup("MainWindow");
01850             d->config->writeEntry("RightDockPosition", d->propEditorDockSeparatorPos);
01851         }
01852         else
01853             d->propEditorDockSeparatorPos = 80;
01854         if (d->nav && d->navDockSeparatorPos >= 0 && d->navDockSeparatorPos <= 100) {
01855             d->config->setGroup("MainWindow");
01856             //KDockWidget *dw = (KDockWidget *)d->nav->parentWidget();
01857             //int w = dw->width();
01858             //int ww = width();
01859             //int d1 = (100 * dw->width()) / width() + 1;
01860             //KDockSplitter *ds = (KDockSplitter *)dw->parentWidget();
01861             //int d2 = ds->separatorPosInPercent();
01862             if (d->wasAutoOpen && d->dialogExistedBeforeCloseProject) {
01863 #ifdef Q_WS_WIN
01864                 d->config->writeEntry("LeftDockPositionWithAutoOpen",
01865                     d->navDockSeparatorPos);
01866 #endif
01867 //          d->config->writeEntry("LeftDockPosition", dw->width());
01868 //          d->config->writeEntry("LeftDockPosition", d->nav->width());
01869             } else {
01870 #ifdef Q_WS_WIN
01871                 if (d->dialogExistedBeforeCloseProject)
01872                     d->config->writeEntry("LeftDockPosition", d->navDockSeparatorPos);
01873                 else
01874                     d->config->writeEntry("LeftDockPosition", qRound(double(d->navDockSeparatorPos) / 0.77
01875                      / (double(d->propEditorDockSeparatorPos) / 80) ));
01876 #endif
01877             }
01878         }
01879     }
01880 
01881     if (d->propEditor) {
01882         d->config->setGroup("PropertyEditor");
01883         d->config->writeEntry("FontSize", d->propEditorTabWidget->font().pixelSize());
01884     }
01885 }
01886 
01887 void
01888 KexiMainWindowImpl::restoreWindowConfiguration(KConfig *config)
01889 {
01890     kdDebug()<<"preparing session restoring"<<endl;
01891 
01892     config->setGroup("MainWindow");
01893 
01894     QString dockGrp;
01895 
01896     if (kapp->isRestored())
01897         dockGrp=config->group()+"-Docking";
01898     else
01899         dockGrp="MainWindow0-Docking";
01900 
01901     if (config->hasGroup(dockGrp))
01902         readDockConfig(config,dockGrp);
01903 }
01904 
01905 void
01906 KexiMainWindowImpl::storeWindowConfiguration(KConfig *config)
01907 {
01908     kdDebug()<<"preparing session saving"<<endl;
01909     config->setGroup("MainWindow");
01910     QString dockGrp;
01911 
01912 #if KDE_IS_VERSION(3,1,9) && !defined(Q_WS_WIN)
01913     if (kapp->sessionSaving())
01914         dockGrp=config->group()+"-Docking";
01915     else
01916 #endif
01917         dockGrp="MainWindow0-Docking";
01918 
01919     kdDebug()<<"Before write dock config"<<endl;
01920     writeDockConfig(config,dockGrp);
01921     kdDebug()<<"After write dock config"<<endl;
01922 }
01923 
01924 void
01925 KexiMainWindowImpl::readProperties(KConfig *config) {
01926     restoreWindowConfiguration(config);
01927 }
01928 
01929 void
01930 KexiMainWindowImpl::saveProperties(KConfig *config)
01931 {
01932     storeWindowConfiguration(config);
01933 //        m_docManager->saveDocumentList (config);
01934   //      m_projectManager->saveProjectList (config);
01935 }
01936 
01937 void
01938 KexiMainWindowImpl::saveGlobalProperties( KConfig* sessionConfig ) {
01939     storeWindowConfiguration(sessionConfig);
01940 }
01941 
01942 void
01943 KexiMainWindowImpl::registerChild(KexiDialogBase *dlg)
01944 {
01945     kdDebug() << "KexiMainWindowImpl::registerChild()" << endl;
01946     connect(dlg, SIGNAL(activated(KMdiChildView *)),
01947         this, SLOT(activeWindowChanged(KMdiChildView *)));
01948     connect(dlg, SIGNAL(dirtyChanged(KexiDialogBase*)),
01949         this, SLOT(slotDirtyFlagChanged(KexiDialogBase*)));
01950 
01951 //  connect(dlg, SIGNAL(childWindowCloseRequest(KMdiChildView *)), this, SLOT(childClosed(KMdiChildView *)));
01952     if(dlg->id() != -1) {
01953         d->insertDialog(dlg);
01954     }
01955     kdDebug() << "KexiMainWindowImpl::registerChild() ID = " << dlg->id() << endl;
01956 
01957     if (m_mdiMode==KMdi::ToplevelMode || m_mdiMode==KMdi::ChildframeMode) {//kmdi fix
01958         //js TODO: check if taskbar is switched in menu
01959         if (m_pTaskBar && !m_pTaskBar->isSwitchedOn())
01960             m_pTaskBar->switchOn(true);
01961     }
01962     //KMdiChildFrm *frm = dlg->mdiParent();
01963     //if (frm) {
01964 //      dlg->setMargin(20);
01965         //dlg->setLineWidth(20);
01966     //}
01967 }
01968 
01969 void
01970 KexiMainWindowImpl::updateDialogViewGUIClient(KXMLGUIClient *viewClient)
01971 {
01972     if (viewClient!=d->curDialogViewGUIClient) {
01973         //view clients differ
01974         kdDebug()<<"KexiMainWindowImpl::activeWindowChanged(): old view gui client:"
01975             <<(d->curDialogViewGUIClient ? d->curDialogViewGUIClient->xmlFile() : "")
01976             <<" new view gui client: "<<( viewClient ? viewClient->xmlFile() : "") <<endl;
01977         if (d->curDialogViewGUIClient) {
01978             guiFactory()->removeClient(d->curDialogViewGUIClient);
01979         }
01980         if (viewClient) {
01981             if (d->closedDialogViewGUIClient) {
01982                 //ooh, there is a client which dialog is already closed -- BUT it is the same client as our
01983                 //so: give up
01984             }
01985             else {
01986                 guiFactory()->addClient(viewClient);
01987             }
01988         }
01989     }
01990 }
01991 
01992 void KexiMainWindowImpl::updateCustomPropertyPanelTabs(KexiDialogBase *prevDialog, int prevViewMode)
01993 {
01994     updateCustomPropertyPanelTabs(
01995         prevDialog ? prevDialog->part() : 0,
01996         prevDialog ? prevDialog->currentViewMode() : prevViewMode,
01997         d->curDialog ? d->curDialog->part() : 0,
01998         d->curDialog ? d->curDialog->currentViewMode() : Kexi::NoViewMode
01999     );
02000 }
02001 
02002 void KexiMainWindowImpl::updateCustomPropertyPanelTabs(
02003     KexiPart::Part *prevDialogPart, int prevViewMode, KexiPart::Part *curDialogPart, int curViewMode )
02004 {
02005     if (!d->propEditorTabWidget)
02006         return;
02007 
02008     if (!curDialogPart
02009         || (/*prevDialogPart &&*/ curDialogPart
02010             && (prevDialogPart!=curDialogPart || prevViewMode!=curViewMode)
02011          ))
02012     {
02013         if (d->partForPreviouslySetupPropertyPanelTabs) {
02014             //remember current page number for this part
02015             if (prevViewMode==Kexi::DesignViewMode && 
02016                 ((KexiPart::Part*)d->partForPreviouslySetupPropertyPanelTabs != curDialogPart) //part changed
02017                 || curViewMode!=Kexi::DesignViewMode) //..or switching to other view mode
02018             {
02019                 d->recentlySelectedPropertyPanelPages.insert( d->partForPreviouslySetupPropertyPanelTabs, 
02020                     d->propEditorTabWidget->currentPageIndex() );
02021             }
02022         }
02023         
02024         //delete old custom tabs (other than 'property' tab)
02025         const uint count = d->propEditorTabWidget->count();
02026         for (uint i=1; i < count; i++)
02027             d->propEditorTabWidget->removePage( d->propEditorTabWidget->page(1) );
02028     }
02029 
02030     //don't change anything if part is not switched nor view mode changed
02031     if ((!prevDialogPart && !curDialogPart)
02032         || (prevDialogPart == curDialogPart && prevViewMode==curViewMode)
02033         || (curDialogPart && curViewMode!=Kexi::DesignViewMode))
02034     {
02035         //new part for 'previously setup tabs'
02036         d->partForPreviouslySetupPropertyPanelTabs = curDialogPart;
02037         return;
02038     }
02039 
02040     if (curDialogPart) {
02041         //recreate custom tabs
02042         curDialogPart->setupCustomPropertyPanelTabs(d->propEditorTabWidget, this);
02043 
02044         //restore current page number for this part
02045         if (d->recentlySelectedPropertyPanelPages.contains( curDialogPart )) {
02046             d->propEditorTabWidget->setCurrentPage( 
02047                 d->recentlySelectedPropertyPanelPages[ curDialogPart ] 
02048             );
02049         }
02050     }
02051 
02052     //new part for 'previously setup tabs'
02053     d->partForPreviouslySetupPropertyPanelTabs = curDialogPart;
02054 }
02055 
02056 void KexiMainWindowImpl::activeWindowChanged(KMdiChildView *v)
02057 {
02058     KexiDialogBase *dlg = static_cast<KexiDialogBase *>(v);
02059     kdDebug() << "KexiMainWindowImpl::activeWindowChanged() to = " << (dlg ? dlg->caption() : "<none>") << endl;
02060 
02061     KXMLGUIClient *client=0; //common for all views
02062     KXMLGUIClient *viewClient=0; //specific for current dialog's view
02063     KexiDialogBase* prevDialog = d->curDialog;
02064 
02065     if (!dlg)
02066         client=0;
02067     else if ( dlg->isRegistered()) {
02068 //      client=dlg->guiClient();
02069         client=dlg->commonGUIClient();
02070         viewClient=dlg->guiClient();
02071         if (d->closedDialogGUIClient) {
02072             if (client!=d->closedDialogGUIClient) {
02073                 //ooh, there is a client which dialog is already closed -- and we don't want it
02074                 guiFactory()->removeClient(d->closedDialogGUIClient);
02075                 d->closedDialogGUIClient=0;
02076             }
02077         }
02078         if (d->closedDialogViewGUIClient) {
02079             if (viewClient!=d->closedDialogViewGUIClient) {
02080                 //ooh, there is a client which dialog is already closed -- and we don't want it
02081                 guiFactory()->removeClient(d->closedDialogViewGUIClient);
02082                 d->closedDialogViewGUIClient=0;
02083             }
02084         }
02085         if (client!=d->curDialogGUIClient) {
02086             //clients differ
02087             kdDebug()<<"KexiMainWindowImpl::activeWindowChanged(): old gui client:"
02088                 <<(d->curDialogGUIClient ? d->curDialogGUIClient->xmlFile() : "")
02089                 <<" new gui client: "<<( client ? client->xmlFile() : "") <<endl;
02090             if (d->curDialogGUIClient) {
02091                 guiFactory()->removeClient(d->curDialogGUIClient);
02092                 d->curDialog->detachFromGUIClient();
02093             }
02094             if (client) {
02095                 if (d->closedDialogGUIClient) {
02096                     //ooh, there is a client which dialog is already closed -- BUT it is the same client as our
02097                     //so: give up
02098                 }
02099                 else {
02100                     guiFactory()->addClient(client);
02101                 }
02102                 dlg->attachToGUIClient();
02103             }
02104         } else {
02105             //clients are the same
02106             if ((KexiDialogBase*)d->curDialog!=dlg) {
02107                 if (d->curDialog)
02108                     d->curDialog->detachFromGUIClient();
02109                 if (dlg)
02110                     dlg->attachToGUIClient();
02111             }
02112         }
02113         updateDialogViewGUIClient(viewClient);
02114 /*      if (viewClient!=d->curDialogViewGUIClient) {
02115             //view clients differ
02116             kdDebug()<<"KexiMainWindowImpl::activeWindowChanged(): old view gui client:"
02117                 <<d->curDialogViewGUIClient<<" new view gui client: "<<viewClient<<endl;
02118             if (d->curDialogViewGUIClient) {
02119                 guiFactory()->removeClient(d->curDialogViewGUIClient);
02120             }
02121             if (viewClient) {
02122                 if (d->closedDialogViewGUIClient) {
02123                     //ooh, there is a client which dialog is already closed -- BUT it is the same client as our
02124                     //so: give up
02125                 }
02126                 else {
02127                     guiFactory()->addClient(viewClient);
02128                 }
02129             }
02130         }*/
02131     }
02132     bool update_dlg_caption = dlg && dlg!=(KexiDialogBase*)d->curDialog && dlg->mdiParent();
02133 
02134     if (d->curDialogGUIClient && !client)
02135         guiFactory()->removeClient(d->curDialogGUIClient);
02136     d->curDialogGUIClient=client;
02137 
02138     if (d->curDialogViewGUIClient && !viewClient)
02139         guiFactory()->removeClient(d->curDialogViewGUIClient);
02140     d->curDialogViewGUIClient=viewClient;
02141 
02142     bool dialogChanged = ((KexiDialogBase*)d->curDialog)!=dlg;
02143 
02144     if (dialogChanged) {
02145         if (d->curDialog) {
02146             //inform previously activated dialog about deactivation
02147             d->curDialog->deactivate();
02148         }
02149     }
02150     d->curDialog=dlg;
02151 
02152 //moved below:  propertySetSwitched(d->curDialog);
02153 
02154     updateCustomPropertyPanelTabs(prevDialog, prevDialog ? prevDialog->currentViewMode() : Kexi::NoViewMode);
02155 
02156     // inform the current view of the new dialog about property switching
02157     // (this will also call KexiMainWindowImpl::propertySetSwitched() to update the current property editor's set
02158     if (dialogChanged && d->curDialog)
02159         d->curDialog->selectedView()->propertySetSwitched();
02160 
02161     if (dialogChanged) {
02162 //      invalidateSharedActions();
02163         //update property editor's contents...
02164 //      if ((KexiPropertyBuffer*)d->propBuffer!=d->curDialog->propertyBuffer()) {
02165 //      propertyBufferSwitched();//d->curDialog);
02166 //          d->propBuffer = d->curDialog->propertyBuffer();
02167 //          d->propEditor->editor()->setBuffer( d->propBuffer );
02168 //      }
02169         if (d->curDialog && d->curDialog->currentViewMode()!=0) //on opening new dialog it can be 0; we don't want this
02170             d->updatePropEditorVisibility(d->curDialog->currentViewMode());
02171     }
02172 
02173     //update caption...
02174     if (update_dlg_caption) {//d->curDialog is != null for sure
02175         slotCaptionForCurrentMDIChild(d->curDialog->mdiParent()->state()==KMdiChildFrm::Maximized);
02176     }
02177 //  if (!d->curDialog.isNull())
02178 //      d->last_checked_mode = d->actions_for_view_modes[ d->curDialog->currentViewMode() ];
02179     invalidateViewModeActions();
02180     invalidateActions();
02181     if (dlg)
02182         dlg->setFocus();
02183 }
02184 
02185 bool
02186 KexiMainWindowImpl::activateWindow(int id)
02187 {
02188     kdDebug() << "KexiMainWindowImpl::activateWindow()" << endl;
02189 #ifndef KEXI_NO_PENDING_DIALOGS
02190     Private::PendingJobType pendingType;
02191     return activateWindow( d->openedDialogFor( id, pendingType ) );
02192 #else
02193     return activateWindow( d->openedDialogFor( id ) );
02194 #endif
02195 }
02196 
02197 bool
02198 KexiMainWindowImpl::activateWindow(KexiDialogBase *dlg)
02199 {
02200     kdDebug() << "KexiMainWindowImpl::activateWindow(KexiDialogBase *)" << endl;
02201     if(!dlg)
02202         return false;
02203 
02204     d->focus_before_popup = dlg;
02205     dlg->activate();
02206     return true;
02207 }
02208 
02209 void
02210 KexiMainWindowImpl::childClosed(KMdiChildView *v)
02211 {
02212     KexiDialogBase *dlg = static_cast<KexiDialogBase *>(v);
02213     d->removeDialog(dlg->id());
02214 #ifndef KEXI_NO_PENDING_DIALOGS
02215     d->removePendingDialog(dlg->id());
02216 #endif
02217 
02218     //focus navigator if nothing else available
02219     if (d->openedDialogsCount() == 0)
02220         d->nav->setFocus();
02221 }
02222 
02223 void
02224 KexiMainWindowImpl::slotShowSettings()
02225 {
02226     KEXI_UNFINISHED(d->action_configure->text());
02227 //TODO  KexiSettings s(this);
02228 //  s.exec();
02229 }
02230 
02231 void
02232 KexiMainWindowImpl::slotConfigureKeys()
02233 {
02234 /*    KKeyDialog dlg;
02235     dlg.insert( actionCollection() );
02236     dlg.configure();*/
02237     KKeyDialog::configure( actionCollection(), false/*bAllowLetterShortcuts*/, this );
02238 }
02239 
02240 void
02241 KexiMainWindowImpl::slotConfigureToolbars()
02242 {
02243     KEditToolbar edit(factory());
02244 //    connect(&edit,SIGNAL(newToolbarConfig()),this,SLOT(slotNewToolbarConfig()));
02245     (void) edit.exec();
02246 }
02247 
02248 void
02249 KexiMainWindowImpl::slotProjectNew()
02250 {
02251     if (!d->prj) {
02252         //create within this instance
02253         createBlankProject();
02254         return;
02255     }
02256 //TODO use KexiStartupDialog(KexiStartupDialog::Templates...)
02257 
02258     bool cancel;
02259     QString fileName;
02260     KexiProjectData *new_data = createBlankProjectData(
02261         cancel,
02262         false, /* do not confirm prj overwrites: user will be asked on process startup */
02263         &fileName //shortcut fname
02264     );
02265     if (!new_data)
02266         return;
02267 
02268   QStringList args;
02269     args << qApp->applicationFilePath() << "-create-opendb";
02270     if (new_data->connectionData()->fileName().isEmpty()) {
02271         //server based - pass .kexic file
02272         if (fileName.isEmpty())
02273             return;
02274         args << new_data->databaseName() << fileName;
02275         //args << "--skip-conn-dialog"; //user does not expect conn. dialog to be shown here
02276     }
02277     else {
02278         //file based
02279         fileName = new_data->connectionData()->fileName();
02280         args << fileName;
02281     }
02282 //todo:         pass new_data->caption()
02283     //start new instance
02285     QProcess proc(args, this, "process");
02286     proc.setCommunication((QProcess::Communication)0);
02287 //      proc.setWorkingDirectory( QFileInfo(new_data->connectionData()->fileName()).dir(true) );
02288     proc.setWorkingDirectory( QFileInfo(fileName).dir(true) );
02289     if (!proc.start()) {
02290             d->showStartProcessMsg(args);
02291     }
02292     delete new_data;
02293 }
02294 
02295 void
02296 KexiMainWindowImpl::createKexiProject(KexiProjectData* new_data)
02297 {
02298     d->prj = new KexiProject( new_data, this );
02299 //  d->prj = ::createKexiProject(new_data);
02300 //provided by KexiMessageHandler    connect(d->prj, SIGNAL(error(const QString&,KexiDB::Object*)), this, SLOT(showErrorMessage(const QString&,KexiDB::Object*)));
02301 //provided by KexiMessageHandler    connect(d->prj, SIGNAL(error(const QString&,const QString&)), this, SLOT(showErrorMessage(const QString&,const QString&)));
02302     connect(d->prj, SIGNAL(itemRenamed(const KexiPart::Item&, const QCString&)), this, SLOT(slotObjectRenamed(const KexiPart::Item&, const QCString&)));
02303 
02304     if (d->nav)
02305         connect(d->prj, SIGNAL(itemRemoved(const KexiPart::Item&)), d->nav, SLOT(slotRemoveItem(const KexiPart::Item&)));
02306 }
02307 
02308 KexiProjectData*
02309 KexiMainWindowImpl::createBlankProjectData(bool &cancelled, bool confirmOverwrites, 
02310     QString* shortcutFileName)
02311 {
02312     cancelled = false;
02313     KexiNewProjectWizard wiz(Kexi::connset(), 0, "KexiNewProjectWizard", true);
02314     wiz.setConfirmOverwrites(confirmOverwrites);
02315     if (wiz.exec() != QDialog::Accepted) {
02316         cancelled=true;
02317         return 0;
02318     }
02319 
02320     KexiProjectData *new_data;
02321 
02322     if (shortcutFileName)
02323         *shortcutFileName = QString::null;
02324     if (wiz.projectConnectionData()) {
02325         //server-based project
02326         KexiDB::ConnectionData *cdata = wiz.projectConnectionData();
02327         kdDebug() << "DBNAME: " << wiz.projectDBName() << " SERVER: " << cdata->serverInfoString() << endl;
02328         new_data = new KexiProjectData( *cdata, wiz.projectDBName(), wiz.projectCaption() );
02329         if (shortcutFileName)
02330             *shortcutFileName = Kexi::connset().fileNameForConnectionData(cdata); 
02331     }
02332     else if (!wiz.projectDBName().isEmpty()) {
02333         //file-based project
02334         KexiDB::ConnectionData cdata;
02335         cdata.caption = wiz.projectCaption();
02336         cdata.driverName = KexiDB::Driver::defaultFileBasedDriverName();
02337         cdata.setFileName( wiz.projectDBName() );
02338         new_data = new KexiProjectData( cdata, wiz.projectDBName(), wiz.projectCaption() );
02339     }
02340     else {
02341         cancelled = true;
02342         return 0;
02343     }
02344     return new_data;
02345 }
02346 
02347 tristate
02348 KexiMainWindowImpl::createBlankProject()
02349 {
02350     bool cancel;
02351     KexiProjectData *new_data = createBlankProjectData(cancel);
02352     if (cancel)
02353         return cancelled;
02354     if (!new_data)
02355         return false;
02356 
02357     createKexiProject( new_data );
02358 
02359     tristate res = d->prj->create(true /*overwrite*/ );
02360     if (res != true) {
02361         delete d->prj;
02362         d->prj = 0;
02363         return res;
02364     }
02365     kdDebug() << "KexiMainWindowImpl::slotProjectNew(): new project created --- " << endl;
02366     initNavigator();
02367     Kexi::recentProjects().addProjectData( new_data );
02368 
02369     invalidateActions();
02370     updateAppCaption();
02371     return true;
02372 }
02373 
02374 void
02375 KexiMainWindowImpl::slotProjectOpen()
02376 {
02377     KexiStartupDialog dlg(
02378         KexiStartupDialog::OpenExisting, 0, Kexi::connset(), Kexi::recentProjects(),
02379         this, "KexiOpenDialog");
02380 
02381     if (dlg.exec()!=QDialog::Accepted)
02382         return;
02383 
02384     openProject(dlg.selectedExistingFile(), dlg.selectedExistingConnection());
02385 }
02386 
02387 tristate KexiMainWindowImpl::openProject(const QString& aFileName, 
02388     const QString& fileNameForConnectionData, const QString& dbName)
02389 {
02390     if (d->prj)
02391         return openProjectInExternalKexiInstance(aFileName, fileNameForConnectionData, dbName);
02392 
02393     KexiDB::ConnectionData *cdata = 0;
02394     if (!fileNameForConnectionData.isEmpty()) {
02395         cdata = Kexi::connset().connectionDataForFileName( fileNameForConnectionData );
02396         if (!cdata) {
02397             kdWarning() << "KexiMainWindowImpl::openProject() cdata?" << endl;
02398             return false;
02399         }
02400     }
02401     return openProject(aFileName, cdata, dbName);
02402 }
02403 
02404 tristate KexiMainWindowImpl::openProject(const QString& aFileName, 
02405     KexiDB::ConnectionData *cdata, const QString& dbName)
02406 {
02407     if (d->prj) {
02408         return openProjectInExternalKexiInstance(aFileName, cdata, dbName);
02409     }
02410 
02411     KexiProjectData* projectData = 0;
02412     bool deleteAfterOpen = false;
02413     if (cdata) {
02414         //server-based project
02415         if (dbName.isEmpty()) {//no database name given, ask user
02416             bool cancel;
02417             projectData = Kexi::startupHandler().selectProject( cdata, cancel, this );
02418             if (cancel)
02419                 return cancelled;
02420         }
02421         else {
02423             projectData = new KexiProjectData( *cdata, dbName );
02424             deleteAfterOpen = true;
02425         }
02426     }
02427     else {
02428 //      QString selFile = dlg.selectedExistingFile();
02429         if (aFileName.isEmpty()) {
02430             kdWarning() << "KexiMainWindowImpl::openProject(): aFileName.isEmpty()" << endl;
02431             return false;
02432         }
02433         //file-based project
02434         kdDebug() << "Project File: " << aFileName << endl;
02435         KexiDB::ConnectionData cdata;
02436         cdata.setFileName( aFileName );
02437 //          cdata.driverName = KexiStartupHandler::detectDriverForFile( cdata.driverName, fileName, this );
02438         QString detectedDriverName;
02439         KexiStartupData::Import importActionData;
02440         const tristate res = KexiStartupHandler::detectActionForFile( 
02441             importActionData, detectedDriverName, cdata.driverName, aFileName, this );
02442         if (true != res)
02443             return res;
02444 
02445         if (importActionData) { //importing requested
02446             return showProjectMigrationWizard( importActionData.mimeType, importActionData.fileName );
02447         }
02448         cdata.driverName = detectedDriverName;
02449 
02450         if (cdata.driverName.isEmpty())
02451             return false;
02452 
02453         //opening requested
02454         projectData = new KexiProjectData(cdata, aFileName);
02455         deleteAfterOpen = true;
02456     }
02457     if (!projectData)
02458         return false;
02459     const tristate res = openProject(*projectData);
02460     if (deleteAfterOpen) //projectData object has been copied
02461         delete projectData;
02462     return res;
02463 }
02464 
02465 tristate KexiMainWindowImpl::openProjectInExternalKexiInstance(const QString& aFileName, 
02466     KexiDB::ConnectionData *cdata, const QString& dbName)
02467 {
02468     QString fileNameForConnectionData;
02469     if (aFileName.isEmpty()) { //try .kexic file
02470         if (cdata)
02471             fileNameForConnectionData = Kexi::connset().fileNameForConnectionData(cdata);
02472     }
02473     return openProjectInExternalKexiInstance(aFileName, fileNameForConnectionData, dbName);
02474 }
02475 
02476 tristate KexiMainWindowImpl::openProjectInExternalKexiInstance(const QString& aFileName, 
02477     const QString& fileNameForConnectionData, const QString& dbName)
02478 {
02479     QString fileName(aFileName);
02480     QStringList args;
02481     args << qApp->applicationFilePath();
02482     // open a file-based project or a server connection provided as a .kexic file
02483     // (we have no other simple way to provide the startup data to a new process)
02484     if (fileName.isEmpty()) { //try .kexic file
02485         if (!fileNameForConnectionData.isEmpty())
02486             args << "--skip-conn-dialog"; //user does not expect conn. dialog to be shown here
02487 
02488         if (dbName.isEmpty()) { //use 'kexi --skip-conn-dialog file.kexic'
02489             fileName = fileNameForConnectionData;
02490         }
02491         else { //use 'kexi --skip-conn-dialog --connection file.kexic dbName'
02492             args << "--connection" << fileNameForConnectionData;
02493             fileName = dbName;
02494         }
02495     }
02496     if (fileName.isEmpty()) {
02497         kdWarning() << "KexiMainWindowImpl::openProjectInExternalKexiInstance() fileName?" << endl;
02498         return false;
02499     }
02501     args << fileName;
02502     QProcess proc(args, this, "process");
02503     proc.setWorkingDirectory( QFileInfo(fileName).dir(true) );
02504     const bool ok = proc.start();
02505     if (!ok) {
02506         d->showStartProcessMsg(args);
02507     }
02508     return ok;
02509 }
02510 
02511 void
02512 KexiMainWindowImpl::slotProjectOpenRecentAboutToShow()
02513 {
02514     /*
02515     //setup
02516     KPopupMenu *popup = d->action_open_recent->popupMenu();
02517     const int cnt = popup->count();
02518     //remove older
02519     for (int i = 0; i<cnt; i++) {
02520         int id = popup->idAt(0);
02521         if (id==d->action_open_recent_more_id)
02522             break;
02523         if (id>=0) {
02524             popup->removeItem(id);
02525         }
02526     }
02527     //insert current items
02528     int cur_id = 0, cur_idx = 0;
02529     //TODO:
02530     cur_id = popup->insertItem("My example project 1", ++cur_id, cur_idx++);
02531     cur_id = popup->insertItem("My example project 2", ++cur_id, cur_idx++);
02532     cur_id = popup->insertItem("My example project 3", ++cur_id, cur_idx++);
02533     */
02534 
02535     //show recent databases
02536     KPopupMenu *popup = d->action_open_recent->popupMenu();
02537     popup->clear();
02538 #if 0
02539     d->action_open_recent_projects_title_id = popup->insertTitle(i18n("Recently Opened Databases"));
02540 #endif
02541 //  int action_open_recent_projects_title_index = popup->indexOf(d->action_open_recent_projects_title_id);
02542 //  int count = popup->count();
02543 //  int action_open_recent_connections_title_index = popup->indexOf(d->action_open_recent_connections_title_id);
02544 //  for (int i=action_open_recent_projects_title_index+1; 
02545 //      i<action_open_recent_connections_title_index; i++)
02546 //  {
02547 //      popup->removeItemAt(action_open_recent_projects_title_index+1);
02548 //  }
02549 
02550 //  int cur_idx = action_open_recent_projects_title_index+1;
02551     popup->insertItem(SmallIconSet("kexiproject_sqlite"), "My project 1");
02552     popup->insertItem(SmallIconSet("kexiproject_sqlite"), "My project 2");
02553     popup->insertItem(SmallIconSet("kexiproject_sqlite"), "My project 3");
02554 
02555 #if 0
02556     //show recent connections
02557     d->action_open_recent_connections_title_id = 
02558         d->action_open_recent->popupMenu()->insertTitle(i18n("Recently Connected Database Servers"));
02559     
02560 //  cur_idx = popup->indexOf(d->action_open_recent_connections_title_id) + 1;
02561 //  for (int i=cur_idx; i<count; i++) {
02562 //      popup->removeItemAt(cur_idx);
02563 //  }
02564     popup->insertItem(SmallIconSet("socket"), "My connection 1");
02565     popup->insertItem(SmallIconSet("socket"), "My connection 2");
02566     popup->insertItem(SmallIconSet("socket"), "My connection 3");
02567     popup->insertItem(SmallIconSet("socket"), "My connection 4");
02568 #endif
02569 }
02570 
02571 void
02572 KexiMainWindowImpl::slotProjectOpenRecent(int id)
02573 {
02574     if (id<0) // || id==d->action_open_recent_more_id)
02575         return;
02576     kdDebug() << "KexiMainWindowImpl::slotProjectOpenRecent("<<id<<")"<<endl;
02577 }
02578 
02579 void
02580 KexiMainWindowImpl::slotProjectOpenRecentMore()
02581 {
02582     KEXI_UNFINISHED(i18n("Open Recent"));
02583 }
02584 
02585 void
02586 KexiMainWindowImpl::slotProjectSave()
02587 {
02588     if (!d->curDialog)
02589         return;
02590     saveObject( d->curDialog );
02591     updateAppCaption();
02592     invalidateActions();
02593 }
02594 
02595 void
02596 KexiMainWindowImpl::slotProjectSaveAs()
02597 {
02598     KEXI_UNFINISHED(i18n("Save object as"));
02599 }
02600 
02601 void
02602 KexiMainWindowImpl::slotProjectPrint()
02603 {
02604     if (d->curDialog && d->curDialog->partItem())
02605         printItem(d->curDialog->partItem());
02606 }
02607 
02608 void
02609 KexiMainWindowImpl::slotProjectPrintPreview()
02610 {
02611     if (d->curDialog && d->curDialog->partItem())
02612         printPreviewForItem(d->curDialog->partItem());
02613 }
02614 
02615 void
02616 KexiMainWindowImpl::slotProjectPageSetup()
02617 {
02618     if (d->curDialog && d->curDialog->partItem())
02619         pageSetupForItem(d->curDialog->partItem());
02620 }
02621 
02622 void KexiMainWindowImpl::slotProjectExportDataTable()
02623 {
02624     if (d->curDialog && d->curDialog->partItem())
02625         exportItemAsDataTable(d->curDialog->partItem());
02626 }
02627 
02628 void
02629 KexiMainWindowImpl::slotProjectProperties()
02630 {
02631     //TODO: load the implementation not the ui :)
02632 //  ProjectSettingsUI u(this);
02633 //  u.exec();
02634 }
02635 
02636 void
02637 KexiMainWindowImpl::slotProjectClose()
02638 {
02639     closeProject();
02640 }
02641 
02642 void KexiMainWindowImpl::slotProjectRelations()
02643 {
02644     if (!d->prj)
02645         return;
02646     KexiDialogBase *d = KexiInternalPart::createKexiDialogInstance("relation", this, this);
02647     activateWindow(d);
02648 /*  KexiRelationPart *p = relationPart();
02649     if(!p)
02650         return;
02651 
02652     p->createWindow(this);*/
02653 }
02654 
02655 void KexiMainWindowImpl::slotImportFile()
02656 {
02657     KEXI_UNFINISHED("Import: " + i18n("From File..."));
02658 }
02659 
02660 void KexiMainWindowImpl::slotImportServer()
02661 {
02662     KEXI_UNFINISHED("Import: " + i18n("From Server..."));
02663 }
02664 
02665 void
02666 KexiMainWindowImpl::slotProjectQuit()
02667 {
02668     if (~ closeProject())
02669         return;
02670     close();
02671 }
02672 
02673 void KexiMainWindowImpl::slotViewNavigator()
02674 {
02675     if (!d->nav || !d->navToolWindow)
02676         return;
02677     if (!d->nav->isVisible())
02678         makeWidgetDockVisible(d->nav);
02679 //      makeDockVisible(dynamic_cast<KDockWidget*>(d->navToolWindow->wrapperWidget()));
02680 //      d->navToolWindow->wrapperWidget()->show();
02681 //      d->navToolWindow->show(KDockWidget::DockLeft, getMainDockWidget());
02682 
02683     d->navToolWindow->wrapperWidget()->raise();
02684 //
02685     d->block_KMdiMainFrm_eventFilter=true;
02686         d->nav->setFocus();
02687     d->block_KMdiMainFrm_eventFilter=false;
02688 }
02689 
02690 void KexiMainWindowImpl::slotViewMainArea()
02691 {
02692     if (d->curDialog)
02693         d->curDialog->setFocus();
02694 }
02695 
02696 void KexiMainWindowImpl::slotViewPropertyEditor()
02697 {
02698     if (!d->propEditor || !d->propEditorToolWindow)
02699         return;
02700 
02701 //js        d->config->setGroup("MainWindow");
02702 //js        ds->setSeparatorPos(d->config->readNumEntry("RightDockPosition", 80/* % */), true);
02703 
02704     if (!d->propEditorTabWidget->isVisible())
02705         makeWidgetDockVisible(d->propEditorTabWidget);
02706 
02707 
02708     d->propEditorToolWindow->wrapperWidget()->raise();
02709 
02710     d->block_KMdiMainFrm_eventFilter=true;
02711     if (d->propEditorTabWidget->currentPage())
02712         d->propEditorTabWidget->currentPage()->setFocus();
02713     d->block_KMdiMainFrm_eventFilter=false;
02714 
02715 /*#if defined(KDOCKWIDGET_P)
02716         KDockWidget *dw = (KDockWidget *)d->propEditor->parentWidget();
02717         KDockSplitter *ds = (KDockSplitter *)dw->parentWidget();
02718         ds->setSeparatorPos(80,true);//d->config->readNumEntry("RightDockPosition", 80), true);
02719 #endif*/
02720 }
02721 
02722 bool KexiMainWindowImpl::switchToViewMode(int viewMode)
02723 {
02724     if (!d->curDialog) {
02725         d->toggleLastCheckedMode();
02726         return false;
02727     }
02728     if (!d->curDialog->supportsViewMode( viewMode )) {
02729         showErrorMessage(i18n("Selected view is not supported for \"%1\" object.")
02730             .arg(d->curDialog->partItem()->name()),
02731         i18n("Selected view (%1) is not supported by this object type (%2).")
02732             .arg(Kexi::nameForViewMode(viewMode))
02733             .arg(d->curDialog->part()->instanceCaption()) );
02734         d->toggleLastCheckedMode();
02735         return false;
02736     }
02737     int prevViewMode = d->curDialog->currentViewMode();
02738     updateCustomPropertyPanelTabs(d->curDialog->part(), prevViewMode,
02739         d->curDialog->part(), viewMode );
02740     tristate res = d->curDialog->switchToViewMode( viewMode );
02741     if (!res) {
02742         updateCustomPropertyPanelTabs(0, Kexi::NoViewMode); //revert
02743         showErrorMessage(i18n("Switching to other view failed (%1).").arg(Kexi::nameForViewMode(viewMode)),
02744             d->curDialog);
02745         d->toggleLastCheckedMode();
02746         return false;
02747     }
02748     if (~res) {
02749         updateCustomPropertyPanelTabs(0, Kexi::NoViewMode); //revert
02750         d->toggleLastCheckedMode();
02751         return false;
02752     }
02753 
02754     //view changed: switch to this view's gui client
02755     KXMLGUIClient *viewClient=d->curDialog->guiClient();
02756     updateDialogViewGUIClient(viewClient);
02757     if (d->curDialogViewGUIClient && !viewClient)
02758         guiFactory()->removeClient(d->curDialogViewGUIClient);
02759     d->curDialogViewGUIClient=viewClient; //remember
02760 
02761     d->updatePropEditorVisibility(viewMode);
02762     invalidateProjectWideActions();
02763     invalidateSharedActions();
02764     return true;
02765 }
02766 
02767 
02768 void KexiMainWindowImpl::slotViewDataMode()
02769 {
02770     switchToViewMode(Kexi::DataViewMode);
02771 }
02772 
02773 void KexiMainWindowImpl::slotViewDesignMode()
02774 {
02775     switchToViewMode(Kexi::DesignViewMode);
02776 }
02777 
02778 void KexiMainWindowImpl::slotViewTextMode()
02779 {
02780     switchToViewMode(Kexi::TextViewMode);
02781 }
02782 
02783 void KexiMainWindowImpl::closeWindow(KMdiChildView *pWnd, bool layoutTaskBar)
02784 {
02785     if (d->insideCloseDialog && dynamic_cast<KexiDialogBase *>(pWnd)) {
02786         d->windowsToClose.append(dynamic_cast<KexiDialogBase *>(pWnd));
02787         return;
02788     }
02789     /*moved to closeDialog()
02790     if (pWnd == d->curDialog && !pWnd->isAttached()) {
02791         if (d->propEditor) {
02792             // ah, closing detached window - better switch off property buffer right now...
02793             d->propBuffer = 0;
02794             d->propEditor->editor()->setBuffer( 0, false );
02795         }
02796     }
02797     */
02798     closeDialog(dynamic_cast<KexiDialogBase *>(pWnd), layoutTaskBar);
02799 }
02800 
02801 tristate KexiMainWindowImpl::getNewObjectInfo(
02802     KexiPart::Item *partItem, KexiPart::Part *part,
02803     bool& allowOverwriting, const QString& messageWhenAskingForName )
02804 {
02805     //data was never saved in the past -we need to create a new object at the backend
02806     KexiPart::Info *info = part->info();
02807 #ifdef KEXI_ADD_CUSTOM_OBJECT_CREATION
02808 # include "keximainwindowimpl_customobjcreation.h"
02809 #endif
02810     if (!d->nameDialog) {
02811         d->nameDialog = new KexiNameDialog(
02812             messageWhenAskingForName, this, "nameDialog");
02813         //check if that name is allowed
02814         d->nameDialog->widget()->addNameSubvalidator(
02815             new KexiDB::ObjectNameValidator(project()->dbConnection()->driver(), 0, "sub"));
02816     }
02817     else {
02818         d->nameDialog->widget()->setMessageText( messageWhenAskingForName );
02819     }
02820     d->nameDialog->widget()->setCaptionText(partItem->caption());
02821     d->nameDialog->widget()->setNameText(partItem->name());
02822     d->nameDialog->setCaption(i18n("Save Object As"));
02823     d->nameDialog->setDialogIcon( DesktopIcon( info->itemIcon(), KIcon::SizeMedium ) );
02824     allowOverwriting = false;
02825     bool found;
02826     do {
02827         if (d->nameDialog->exec()!=QDialog::Accepted)
02828             return cancelled;
02829         //check if that name already exists
02830         KexiDB::SchemaData tmp_sdata;
02831         tristate result = project()->dbConnection()->loadObjectSchemaData(
02832             info->projectPartID(),
02833             d->nameDialog->widget()->nameText(), tmp_sdata );
02834         if (!result)
02835             return false;
02836         found = result==true;
02837         if (found) {
02838             if (allowOverwriting) {
02839                 int res = KMessageBox::warningYesNoCancel(this,
02840                     "<p>"+part->i18nMessage("Object \"%1\" already exists.", 0)
02841                         .arg(d->nameDialog->widget()->nameText())
02842                     +"</p><p>"+i18n("Do you want to replace it?")+"</p>", 0,
02843                     KGuiItem(i18n("&Replace"), "button_yes"),
02844                     KGuiItem(i18n("&Choose Other Name...")),
02845                     QString::null, KMessageBox::Notify|KMessageBox::Dangerous);
02846                 if (res == KMessageBox::No)
02847                     continue;
02848                 else if (res == KMessageBox::Cancel)
02849                     return cancelled;
02850                 else {//yes
02851                     allowOverwriting = true;
02852                     break;
02853                 }
02854             }
02855             else {
02856                 KMessageBox::information(this,
02857                     "<p>"+part->i18nMessage("Object \"%1\" already exists.", 0)
02858                         .arg(d->nameDialog->widget()->nameText())
02859                     +"</p><p>"+i18n("Please choose other name.")+"</p>");
02860 //              " For example: Table \"my_table\" already exists" ,
02861 //              "%1 \"%2\" already exists.\nPlease choose other name.")
02862 //              .arg(dlg->part()->instanceName()).arg(d->nameDialog->widget()->nameText()));
02863                 continue;
02864             }
02865         }
02866     }
02867     while (found);
02868 
02869     //update name and caption
02870     partItem->setName( d->nameDialog->widget()->nameText() );
02871     partItem->setCaption( d->nameDialog->widget()->captionText() );
02872     return true;
02873 }
02874 
02875 tristate KexiMainWindowImpl::saveObject( KexiDialogBase *dlg, const QString& messageWhenAskingForName,
02876     bool dontAsk)
02877 {
02878     tristate res;
02879     if (!dlg->neverSaved()) {
02880         //data was saved in the past -just save again
02881         res = dlg->storeData(dontAsk);
02882         if (!res)
02883             showErrorMessage(i18n("Saving \"%1\" object failed.").arg(dlg->partItem()->name()),
02884                 d->curDialog);
02885         return res;
02886     }
02887 
02888     const int oldItemID = dlg->partItem()->identifier();
02889 
02890     bool allowOverwriting = false;
02891     res = getNewObjectInfo( dlg->partItem(), dlg->part(), allowOverwriting,
02892         messageWhenAskingForName );
02893     if (res != true)
02894         return res;
02895 
02896     res = dlg->storeNewData();
02897     if (~res)
02898         return cancelled;
02899     if (!res) {
02900         showErrorMessage(i18n("Saving new \"%1\" object failed.").arg(dlg->partItem()->name()),
02901             d->curDialog);
02902         return false;
02903     }
02904 
02905     //update navigator
02906 //this is alreday done in KexiProject::addStoredItem(): d->nav->addItem(dlg->partItem());
02907     //item id changed to final one: update association in dialogs' dictionary
02908 //  d->dialogs.take(oldItemID);
02909     d->updateDialogId(dlg, oldItemID);
02910     invalidateProjectWideActions();
02911     return true;
02912 }
02913 
02914 tristate KexiMainWindowImpl::closeDialog(KexiDialogBase *dlg)
02915 {
02916     return closeDialog(dlg, true);
02917 }
02918 
02919 tristate KexiMainWindowImpl::closeDialog(KexiDialogBase *dlg, bool layoutTaskBar, bool doNotSaveChanges)
02920 {
02921     if (!dlg) 
02922         return true;
02923     if (d->insideCloseDialog)
02924         return true;
02925 
02926 #ifndef KEXI_NO_PENDING_DIALOGS
02927     d->addItemToPendingDialogs(dlg->partItem(), Private::DialogClosingJob);
02928 #endif
02929 
02930     d->insideCloseDialog = true;
02931 
02932     if (dlg == d->curDialog && !dlg->isAttached()) {
02933         if (d->propEditor) {
02934             // ah, closing detached window - better switch off property buffer right now...
02935             d->propBuffer = 0;
02936             d->propEditor->editor()->changeSet( 0, false );
02937         }
02938     }
02939 
02940     bool remove_on_closing = dlg->partItem() ? dlg->partItem()->neverSaved() : false;
02941     if (dlg->dirty() && !d->forceDialogClosing && !doNotSaveChanges) {
02942         //more accurate tool tips and what's this
02943         KGuiItem saveChanges( KStdGuiItem::save() ); 
02944         saveChanges.setToolTip(i18n("Save changes"));
02945         saveChanges.setWhatsThis(
02946             i18n( "Pressing this button will save all recent changes made in \"%1\" object." )
02947             .arg(dlg->partItem()->name()) );
02948         KGuiItem discardChanges( KStdGuiItem::discard() );
02949         discardChanges.setWhatsThis(
02950             i18n( "Pressing this button will discard all recent changes made in \"%1\" object." )
02951             .arg(dlg->partItem()->name()) );
02952 
02953         //dialog's data is dirty:
02954         //--adidional message, e.g. table designer will return 
02955         //  "Note: This table is already filled with data which will be removed."
02956         //  if the dlg is in design view mode.
02957         QString additionalMessage = dlg->part()->i18nMessage(
02958             ":additional message before saving design", dlg);
02959         if (additionalMessage.startsWith(":"))
02960             additionalMessage = QString::null;
02961         if (!additionalMessage.isEmpty())
02962             additionalMessage = "<p>"+additionalMessage+"</p>";
02963 
02964         const int questionRes = KMessageBox::warningYesNoCancel( this,
02965             "<p>"+dlg->part()->i18nMessage("Design of object \"%1\" has been modified.", dlg)
02966             .arg(dlg->partItem()->name())+"</p><p>"+i18n("Do you want to save changes?")+"</p>"
02967             + additionalMessage /*may be empty*/,
02968             QString::null,
02969             saveChanges,
02970             discardChanges);
02971         if (questionRes==KMessageBox::Cancel) {
02972 #ifndef KEXI_NO_PENDING_DIALOGS
02973             d->removePendingDialog(dlg->id());
02974 #endif
02975             d->insideCloseDialog = false;
02976             d->windowsToClose.clear(); //give up with 'close all'
02977             return cancelled;
02978         }
02979         if (questionRes==KMessageBox::Yes) {
02980             //save it
02981 //          if (!dlg->storeData())
02982             tristate res = saveObject( dlg, QString::null, true /*dontAsk*/ );
02983             if (!res || ~res) {
02984 //js:TODO show error info; (retry/ignore/cancel)
02985 #ifndef KEXI_NO_PENDING_DIALOGS
02986                 d->removePendingDialog(dlg->id());
02987 #endif
02988                 d->insideCloseDialog = false;
02989                 d->windowsToClose.clear(); //give up with 'close all'
02990                 return res;
02991             }
02992             remove_on_closing = false;
02993         }
02994     }
02995 
02996     const int dlg_id = dlg->id(); //remember now, because removeObject() can destruct partitem object
02997 
02998     if (remove_on_closing) {
02999         //we won't save this object, and it was never saved -remove it
03000         if (!removeObject( dlg->partItem(), true )) {
03001 #ifndef KEXI_NO_PENDING_DIALOGS
03002             d->removePendingDialog(dlg->id());
03003 #endif
03004             //msg?
03005             //TODO: ask if we'd continue and return true/false
03006             d->insideCloseDialog = false;
03007             d->windowsToClose.clear(); //give up with 'close all'
03008             return false;
03009         }
03010     }
03011     else {
03012         //not dirty now
03013         if(d->nav)
03014             d->nav->updateItemName( *dlg->partItem(), false );
03015     }
03016 
03017     d->removeDialog(dlg_id); //don't remove -KMDI will do that
03018     //also remove from 'print setup dialogs' cache, if needed
03019     int printedObjectID = 0;
03020     if (d->pageSetupDialogItemID2dataItemID_map.contains(dlg_id))
03021         printedObjectID = d->pageSetupDialogItemID2dataItemID_map[ dlg_id ];
03022     d->pageSetupDialogs.take(printedObjectID);
03023 
03024     KXMLGUIClient *client = dlg->commonGUIClient();
03025     KXMLGUIClient *viewClient = dlg->guiClient();
03026     if (d->curDialogGUIClient==client) {
03027         d->curDialogGUIClient=0;
03028     }
03029     if (d->curDialogViewGUIClient==viewClient) {
03030         d->curDialogViewGUIClient=0;
03031     }
03032     if (client) {
03033         //sanity: ouch, it is not removed yet? - do it now
03034         if (d->closedDialogGUIClient && d->closedDialogGUIClient!=client)
03035             guiFactory()->removeClient(d->closedDialogGUIClient);
03036         if (d->openedDialogsCount()==0) {//now there is no dialogs - remove client RIGHT NOW!
03037             d->closedDialogGUIClient=0;
03038             guiFactory()->removeClient(client);
03039         }
03040         else {
03041             //remember this - and MAYBE remove later, if needed
03042             d->closedDialogGUIClient=client;
03043         }
03044     }
03045     if (viewClient) {
03046         //sanity: ouch, it is not removed yet? - do it now
03047         if (d->closedDialogViewGUIClient && d->closedDialogViewGUIClient!=viewClient)
03048             guiFactory()->removeClient(d->closedDialogViewGUIClient);
03049         if (d->openedDialogsCount()==0) {//now there is no dialogs - remove client RIGHT NOW!
03050             d->closedDialogViewGUIClient=0;
03051             guiFactory()->removeClient(viewClient);
03052         }
03053         else {
03054             //remember this - and MAYBE remove later, if needed
03055             d->closedDialogViewGUIClient=viewClient;
03056         }
03057     }
03058 
03059     const bool isInMaximizedChildFrmMode = this->isInMaximizedChildFrmMode();
03060 
03061     KMdiMainFrm::closeWindow(dlg, layoutTaskBar);
03062 
03063     //focus navigator if nothing else available
03064     if (d->openedDialogsCount()==0) {
03065         d->maximizeFirstOpenedChildFrm = isInMaximizedChildFrmMode;
03066         if (d->nav)
03067             d->nav->setFocus();
03068         d->updatePropEditorVisibility(0);
03069     }
03070 
03071     invalidateActions();
03072     d->insideCloseDialog = false;
03073     if (!d->windowsToClose.isEmpty()) //continue 'close all'
03074         closeDialog(d->windowsToClose.take(0), true);
03075 
03076 #ifndef KEXI_NO_PENDING_DIALOGS
03077     d->removePendingDialog( dlg_id );
03078 
03079     //perform pending global action that was suspended:
03080     if (!d->pendingDialogsExist()) {
03081         d->executeActionWhenPendingJobsAreFinished();
03082     }
03083 #endif
03084     return true;
03085 }
03086 
03087 void KexiMainWindowImpl::detachWindow(KMdiChildView *pWnd,bool bShow)
03088 {
03089     KMdiMainFrm::detachWindow(pWnd,bShow);
03090     // update icon - from small to large
03091     pWnd->setIcon( DesktopIcon( static_cast<KexiDialogBase *>(pWnd)->itemIcon() ) );
03092 //  pWnd->setIcon( DesktopIcon( static_cast<KexiDialogBase *>(pWnd)->part()->info()->itemIcon() ) );
03093     if (dynamic_cast<KexiDialogBase*>(pWnd))
03094         dynamic_cast<KexiDialogBase*>(pWnd)->sendDetachedStateToCurrentView();
03095 }
03096 
03097 void KexiMainWindowImpl::attachWindow(KMdiChildView *pWnd, bool /*bShow*/, bool bAutomaticResize)
03098 {
03099 //  if (bAutomaticResize || w->size().isEmpty() || (w->size() == QSize(1,1))) {
03100     KMdiMainFrm::attachWindow(pWnd,true,bAutomaticResize);
03101     //for dialogs in normal state: decrease dialog's height if it exceeds area contents
03102     if (pWnd->mdiParent()->state() == KMdiChildFrm::Normal
03103         && pWnd->geometry().bottom() > pWnd->mdiParent()->mdiAreaContentsRect().bottom())
03104     {
03105         QRect r = pWnd->geometry();
03106         r.setBottom( pWnd->mdiParent()->mdiAreaContentsRect().bottom() - 5 );
03107         pWnd->setGeometry( r );
03108     }
03109     // update icon - from large to small
03110     pWnd->mdiParent()->setIcon( SmallIcon( static_cast<KexiDialogBase *>(pWnd)->itemIcon() ) );
03111     if (dynamic_cast<KexiDialogBase*>(pWnd))
03112         dynamic_cast<KexiDialogBase*>(pWnd)->sendAttachedStateToCurrentView();
03113 }
03114 
03115 QWidget* KexiMainWindowImpl::findWindow(QWidget *w)
03116 {
03117     while (w && !acceptsSharedActions(w))
03118         w = w->parentWidget();
03119     return w;
03120 }
03121 
03122 bool KexiMainWindowImpl::acceptsSharedActions(QObject *w)
03123 {
03124     return w->inherits("KexiDialogBase") || w->inherits("KexiViewBase");
03125 }
03126 
03127 bool KexiMainWindowImpl::eventFilter( QObject *obj, QEvent * e )
03128 {
03129     //KexiVDebug << "eventFilter: " <<e->type() << " " <<obj->name()<<endl;
03130     if (e->type()==QEvent::KeyPress) {
03131         KexiVDebug << "KEY EVENT " << QString::number(static_cast<QKeyEvent*>(e)->key(), 16) << endl;
03132         KexiVDebug << endl;
03133     }
03134     if (e->type()==QEvent::AccelOverride) {
03135         //KexiVDebug << "AccelOverride EVENT " << static_cast<QKeyEvent*>(e)->key() << " " << static_cast<QKeyEvent*>(e)->state() == ControlButton << endl;
03136 
03137         //avoid sending CTRL+Tab key twice for tabbed/ideal mode, epecially for win32
03138         if (static_cast<QKeyEvent*>(e)->key()==Key_Tab && static_cast<QKeyEvent*>(e)->state() == ControlButton) {
03139             if (d->action_window_next->shortcut().keyCodeQt()==Key_Tab+CTRL && d->action_window_next->shortcut().count()==1
03140                 && (mdiMode()==KMdi::TabPageMode || mdiMode()==KMdi::IDEAlMode))
03141             {
03142                 static_cast<QKeyEvent*>(e)->accept();
03143             }
03144         }
03145     }
03146     if (e->type()==QEvent::Close) {
03147         KexiVDebug << "Close EVENT" << endl;
03148     }
03149     if (e->type()==QEvent::Resize) {
03150         KexiVDebug << "Resize EVENT" << endl;
03151     }
03152     if (e->type()==QEvent::ShowMaximized) {
03153         KexiVDebug << "ShowMaximized EVENT" << endl;
03154     }
03155 
03156 /*  if (obj==d->propEditor) {
03157         if (e->type()==QEvent::Resize) {
03158             d->updatePropEditorDockWidthInfo();
03159         }
03160     }*/
03161 
03162     QWidget *focus_w = 0;
03163     if (obj->inherits("QPopupMenu")) {
03164         /* Fixes for popup menus behaviour:
03165          For hiding/showing: focus previously (d->focus_before_popup)
03166          focused window, if known, otherwise focus currently focused one.
03167          And: just invalidate actions.
03168         */
03169         if (e->type()==QEvent::Hide || e->type()==QEvent::Show) {
03170             KexiVDebug << e->type() << endl;
03171             focus_w = focusWindow();
03172             if (!d->focus_before_popup.isNull()) {
03173                 d->focus_before_popup->setFocus();
03174                 d->focus_before_popup=0;
03175                 invalidateSharedActions();
03176             } else {
03177                 if (focus_w) {
03178                     focus_w->setFocus();
03179                     invalidateSharedActions();
03180                 }
03181             }
03182         }
03183         return false;
03184     }
03185 
03187     if (e->type()==QEvent::MouseButtonPress) {
03188         QWidget *w = findWindow(static_cast<QWidget*>(obj));
03189         KexiVDebug << "MouseButtonPress EVENT " <<  (w ? w->name() : 0) << endl;
03190         if (w) {
03191             w->setFocus();
03192             invalidateSharedActions(d->curDialog);
03193         }
03194     }
03195     QWidget *w = findWindow(static_cast<QWidget*>(obj));
03196     if (e->type()==QEvent::FocusIn) {
03197         focus_w = focusWindow();
03198         KexiVDebug << "Focus EVENT" << endl;
03199         KexiVDebug << (focus_w ? focus_w->name() : "" )  << endl;
03200         KexiVDebug << "eventFilter: " <<e->type() << " " <<obj->name() <<endl;
03201 #ifdef KEXI_STATUSBAR_DEBUG
03202         QWidget *focus_widget = focus_w ? focus_w->focusWidget() : 0;
03203         d->statusBar->setStatus(QString("FOCUS VIEW: %1 %2, FOCUS WIDGET: %3 %4")
03204             .arg(focus_w ? focus_w->className() : "").arg(focus_w ? focus_w->name() : "")
03205             .arg(focus_widget ? focus_widget->className() : "").arg(focus_widget ? focus_widget->name() : "")
03206             );
03207 #endif
03208     }
03209     else if (e->type()==QEvent::FocusOut) {
03210         focus_w = focusWindow();
03211         KexiVDebug << "Focus OUT EVENT" << endl;
03212         KexiVDebug << (focus_w ? focus_w->name() : "" )  << endl;
03213         KexiVDebug << "eventFilter: " <<e->type() << " " <<obj->name() <<endl;
03214 #ifdef KEXI_STATUSBAR_DEBUG
03215         QWidget *focus_widget = focus_w ? focus_w->focusWidget() : 0;
03216         d->statusBar->setStatus(QString("FOCUS VIEW: %1 %2, FOCUS WIDGET: %3 %4")
03217             .arg(focus_w ? focus_w->className() : "").arg(focus_w ? focus_w->name() : "")
03218             .arg(focus_widget ? focus_widget->className() : "").arg(focus_widget ? focus_widget->name() : "")
03219             );
03220 #endif
03221     }
03222     if (e->type()==QEvent::WindowActivate) {
03223         KexiVDebug << "WindowActivate EVENT" << endl;
03224         KexiVDebug << "eventFilter: " <<e->type() << " " <<obj->name()<<endl;
03225     }
03226 #if 0
03227     if (e->type()==QEvent::FocusIn) {
03228         if (focus_w) {
03229 //          if (d->actionProxies[ w ])
03230 //          if (d->actionProxies[ focus_w ]) {
03231             if (actionProxyFor( focus_w )) {
03232 //              invalidateSharedActions();
03233             }
03234             else {
03235 /*          QObject* o = focusWidget();
03236             while (o && !o->inherits("KexiDialogBase") && !o->inherits("KexiDockBase"))
03237                 o = o->parent();*/
03238 //js                invalidateSharedActions(focus_w);
03239             }
03240         }
03241 //      /*|| e->type()==QEvent::FocusOut*/) && /*(!obj->inherits("KexiDialogBase")) &&*/ d->actionProxies[ obj ]) {
03242 //      invalidateSharedActions();
03243     }
03244     if (e->type()==QEvent::FocusOut && focus_w && focus_w==d->curDialog && actionProxyFor( obj )) {
03245         invalidateSharedActions(d->curDialog);
03246     }
03247 #endif
03248 
03249     if (!d->focus_before_popup.isNull() && e->type()==QEvent::FocusOut && obj->inherits("KMenuBar")) {
03250         //d->nav->setFocus();
03251         d->focus_before_popup->setFocus();
03252         d->focus_before_popup=0;
03253         invalidateSharedActions(d->curDialog);
03254         return true;
03255     }
03256 
03257     //remember currently focued window invalidate act.
03258     if (e->type()==QEvent::FocusOut) {
03259         if (static_cast<QFocusEvent*>(e)->reason()==QFocusEvent::Popup) {
03260             if (KexiUtils::hasParent(d->curDialog, focus_w)) {
03261                 invalidateSharedActions(d->curDialog);
03262                 d->focus_before_popup=d->curDialog;
03263             }
03264             else {
03265 //not needed???         invalidateSharedActions(focus_w);
03266                 d->focus_before_popup=focus_w;
03267             }
03268         }
03269     }
03270 
03271     //keep focus in main window:
03272     if (w && w==d->nav) {
03273 //      kdDebug() << "NAV" << endl;
03274         if (e->type()==QEvent::FocusIn) {
03275             return true;
03276         } else if (e->type()==QEvent::WindowActivate && w==d->focus_before_popup) {
03277 //          d->nav->setFocus();
03278             d->focus_before_popup=0;
03279             return true;
03280         } else if (e->type()==QEvent::FocusOut) {
03281             if (static_cast<QFocusEvent*>(e)->reason()==QFocusEvent::Tab) {
03282                 //activate current child:
03283                 if (d->curDialog) {
03284                     d->curDialog->activate();
03285                     return true;
03286                 }
03287             }
03288             else if (static_cast<QFocusEvent*>(e)->reason()==QFocusEvent::Popup) {
03289                 d->focus_before_popup=w;
03290             }
03291             //invalidateSharedActions();
03292         } else if (e->type()==QEvent::Hide) {
03293             setFocus();
03294             return false;
03295         }
03296     }
03297     if (d->block_KMdiMainFrm_eventFilter)//we don't want KMDI to eat our event!
03298         return false;
03299     return KMdiMainFrm::eventFilter(obj,e);//let KMDI do its work
03300 }
03301 
03302 KexiDialogBase *
03303 KexiMainWindowImpl::openObject(const QCString& mimeType, const QString& name, 
03304     int viewMode, bool &openingCancelled, QMap<QString,QString>* staticObjectArgs)
03305 {
03306     KexiPart::Item *item = d->prj->itemForMimeType(mimeType,name);
03307     if (!item)
03308         return 0;
03309     return openObject(item, viewMode, openingCancelled, staticObjectArgs);
03310 }
03311 
03312 KexiDialogBase *
03313 KexiMainWindowImpl::openObject(KexiPart::Item* item, int viewMode, bool &openingCancelled,
03314     QMap<QString,QString>* staticObjectArgs)
03315 {
03316     if (!d->prj || !item)
03317         return 0;
03318     KexiUtils::WaitCursor wait;
03319 #ifndef KEXI_NO_PENDING_DIALOGS
03320     Private::PendingJobType pendingType;
03321     KexiDialogBase *dlg = d->openedDialogFor( item, pendingType );
03322     if (pendingType != Private::NoJob) {
03323         openingCancelled = true;
03324         return 0;
03325     }
03326 #else
03327     KexiDialogBase *dlg = d->openedDialogFor( item );
03328 #endif
03329     openingCancelled = false;
03330 
03331     bool needsUpdateViewGUIClient = true;
03332     if (dlg) {
03333         dlg->activate();
03334         if (viewMode!=dlg->currentViewMode()) {
03335             if (!switchToViewMode(viewMode))
03336                 return 0;
03337         }
03338 /*      if (dlg->currentViewMode()!=viewMode) {
03339             //try to switch
03340             bool cancelled;
03341             if (!dlg->switchToViewMode(viewMode, cancelled)) {
03342                 //js TODO: add error msg...
03343                 return 0;
03344             }
03345             if (cancelled)
03346                 return 0;
03347             needsUpdateViewGUIClient = false;
03348         }*/
03349         needsUpdateViewGUIClient = false;
03350     }
03351     else {
03352         d->updatePropEditorVisibility(viewMode);
03353         KexiPart::Part *part = Kexi::partManager().partForMimeType(item->mimeType());
03354         //update tabs before opening
03355         updateCustomPropertyPanelTabs(d->curDialog ? d->curDialog->part() : 0,
03356             d->curDialog ? d->curDialog->currentViewMode() : Kexi::NoViewMode,
03357             part, viewMode);
03358 
03359 #ifndef KEXI_NO_PENDING_DIALOGS
03360         d->addItemToPendingDialogs(item, Private::DialogOpeningJob);
03361 #endif
03362         dlg = d->prj->openObject(this, *item, viewMode, staticObjectArgs);
03363 
03364 //moved up      if (dlg)
03365 //          d->updatePropEditorVisibility(dlg->currentViewMode());
03366     }
03367 
03368     if (!dlg || !activateWindow(dlg)) {
03369 #ifndef KEXI_NO_PENDING_DIALOGS
03370         d->removePendingDialog(item->identifier());
03371 #endif
03372         updateCustomPropertyPanelTabs(0, Kexi::NoViewMode); //revert
03373         //js TODO: add error msg...
03374         return 0;
03375     }
03376 
03377     if (needsUpdateViewGUIClient && !d->final) {
03378         //view changed: switch to this view's gui client
03379         KXMLGUIClient *viewClient=dlg->guiClient();
03380         updateDialogViewGUIClient(viewClient);
03381         if (d->curDialogViewGUIClient && !viewClient)
03382             guiFactory()->removeClient(d->curDialogViewGUIClient);
03383         d->curDialogViewGUIClient=viewClient; //remember
03384     }
03385 
03386     invalidateViewModeActions();
03387     if (viewMode!=dlg->currentViewMode())
03388         invalidateSharedActions();
03389 
03390 #ifndef KEXI_NO_PENDING_DIALOGS
03391     d->removePendingDialog( dlg->id() );
03392 
03393     //perform pending global action that was suspended:
03394     if (!d->pendingDialogsExist()) {
03395         d->executeActionWhenPendingJobsAreFinished();
03396     }
03397 #endif
03398     return dlg;
03399 }
03400 
03401 KexiDialogBase *
03402 KexiMainWindowImpl::openObjectFromNavigator(KexiPart::Item* item, int viewMode)
03403 {
03404     bool openingCancelled;
03405     return openObjectFromNavigator(item, viewMode, openingCancelled);
03406 }
03407 
03408 KexiDialogBase *
03409 KexiMainWindowImpl::openObjectFromNavigator(KexiPart::Item* item, int viewMode, 
03410     bool &openingCancelled)
03411 {
03412     if (!d->prj || !item)
03413         return false;
03414 #ifndef KEXI_NO_PENDING_DIALOGS
03415     Private::PendingJobType pendingType;
03416     KexiDialogBase *dlg = d->openedDialogFor( item, pendingType );
03417     if (pendingType!=Private::NoJob) {
03418         openingCancelled = true;
03419         return 0;
03420     }
03421 #else
03422     KexiDialogBase *dlg = d->openedDialogFor( item );
03423 #endif
03424     openingCancelled = false;
03425     if (dlg) {
03426         if (activateWindow(dlg)) {//item->identifier())) {//just activate
03427             invalidateViewModeActions();
03428             return dlg;
03429         }
03430     }
03431     //if DataViewMode is not supported, try Design, then Text mode (currently useful for script part)
03432     KexiPart::Part *part = Kexi::partManager().partForMimeType(item->mimeType());
03433     if (!part)
03434         return 0;
03435     if (viewMode == Kexi::DataViewMode && !(part->supportedViewModes() & Kexi::DataViewMode)) {
03436         if (part->supportedViewModes() & Kexi::DesignViewMode)
03437             return openObjectFromNavigator( item, Kexi::DesignViewMode, openingCancelled );
03438         else if (part->supportedViewModes() & Kexi::TextViewMode)
03439             return openObjectFromNavigator( item, Kexi::TextViewMode, openingCancelled );
03440     }
03441     //do the same as in openObject()
03442     return openObject(item, viewMode, openingCancelled);
03443 }
03444 
03445 bool KexiMainWindowImpl::newObject( KexiPart::Info *info )
03446 {
03447     if (!d->prj || !info)
03448         return false;
03449     KexiPart::Part *part = Kexi::partManager().partForMimeType(info->mimeType());
03450     if(!part)
03451         return false;
03452 
03453 #if 0 //moved to KexiDialogBase::storeNewData()
03454     if(info->projectPartID() == -1)
03455     {
03456         KexiDB::TableSchema *ts = project()->dbConnection()->tableSchema("kexi__parts");
03457         kdDebug() << "KexiMainWindowImpl::newObject(): schema: " << ts << endl;
03458         if (!ts)
03459             return false;
03460 
03461         //temp. hack: avoid problems with autonumber
03462         // see http://bugs.kde.org/show_bug.cgi?id=89381
03463         int p_id = KexiPart::LastObjectType+1; //min is == 3+1
03464         if (project()->dbConnection()->querySingleNumber("SELECT max(p_id) FROM kexi__parts", p_id))
03465             p_id++;
03466 
03467 //      KexiDB::FieldList *fl = ts->subList("p_name", "p_mime", "p_url");
03468         KexiDB::FieldList *fl = ts->subList("p_id", "p_name", "p_mime", "p_url");
03469         kexidbg << "KexiMainWindowImpl::newObject(): fieldlist: " << (fl ? fl->debugString() : QString::null) << endl;
03470         if (!fl)
03471             return false;
03472 
03473 //      kdDebug() << info->ptr()->genericName() << endl;
03474         kdDebug() << info->ptr()->untranslatedGenericName() << endl;
03475 //      QStringList sl = info->ptr()->propertyNames();
03476 //      for (QStringList::ConstIterator it=sl.constBegin();it!=sl.constEnd();++it)
03477 //          kexidbg << *it << " " << info->ptr()->property(*it).toString() <<  endl;
03478         if (!project()->dbConnection()->insertRecord(*fl,
03479                 QVariant(p_id),
03480                 QVariant(info->ptr()->untranslatedGenericName()),
03481                 QVariant(info->mimeType()), QVariant("http://www.koffice.org/kexi/")))
03482             return false;
03483 
03484         kdDebug() << "KexiMainWindowImpl::newObject(): insert success!" << endl;
03485         info->setProjectPartID( (int) project()->dbConnection()->lastInsertedAutoIncValue("p_id", "kexi__parts"));
03486         kdDebug() << "KexiMainWindowImpl::newObject(): new id is: " << info->projectPartID()  << endl;
03487     }
03488 #endif
03489 
03490 #ifdef KEXI_ADD_CUSTOM_OBJECT_CREATION
03491 # include "keximainwindowimpl_customobjcreation.h"
03492 #endif
03493 
03494     KexiPart::Item *it = d->prj->createPartItem(info); //this, *item, viewMode);
03495     if (!it) {
03496         //js: todo: err
03497         return false;
03498     }
03499 
03500     if (!it->neverSaved()) //only add stored objects to the browser
03501         d->nav->addItem(*it);
03502     bool openingCancelled;
03503     return openObject(it, Kexi::DesignViewMode, openingCancelled);
03504 }
03505 
03506 tristate KexiMainWindowImpl::removeObject( KexiPart::Item *item, bool dontAsk )
03507 {
03508     if (!d->prj || !item)
03509         return false;
03510 
03511     KexiPart::Part *part = Kexi::partManager().partForMimeType(item->mimeType());
03512     if (!part)
03513         return false;
03514 
03515     if (!dontAsk) {
03516         if (KMessageBox::No == KMessageBox::warningYesNo(this, 
03517             "<p>"+i18n("Do you want to permanently delete:\n"
03518             "%1\n"
03519             "If you click Yes, you will not be able to undo the deletion.")
03520                 .arg( "</p><p>"+part->instanceCaption()+" \""+ item->name() + "\"?</p>" ),
03521             0, KGuiItem(i18n("Delete"), "editdelete"), KStdGuiItem::no()))
03522             return cancelled;
03523     }
03524 
03525     //also close 'print setup' dialog for this item, if any
03526     tristate res;
03527 //  int printedObjectID = 0;
03528 //  if (d->pageSetupDialogItemID2dataItemID_map.contains(item->identifier()))
03529 //      printedObjectID = d->pageSetupDialogItemID2dataItemID_map[ item->identifier() ];
03530     KexiDialogBase * pageSetupDlg = d->pageSetupDialogs[ item->identifier() ];
03531     const bool oldInsideCloseDialog = d->insideCloseDialog;
03532     d->insideCloseDialog = false;
03533      res = closeDialog(pageSetupDlg);
03534     d->insideCloseDialog = oldInsideCloseDialog;
03535     if (!res || ~res) {
03536         return res;
03537     }
03538 
03539 #ifndef KEXI_NO_PENDING_DIALOGS
03540     Private::PendingJobType pendingType;
03541     KexiDialogBase *dlg = d->openedDialogFor( item, pendingType );
03542     if (pendingType!=Private::NoJob) {
03543         return cancelled;
03544     }
03545 #else
03546     KexiDialogBase *dlg = d->openedDialogFor( item );
03547 #endif
03548 
03549     if (dlg) {//close existing window
03550 //      if (!dlg->tryClose(true))
03551         const bool tmp = d->forceDialogClosing;
03552         /*const bool remove_on_closing = */dlg->partItem()->neverSaved();
03553         d->forceDialogClosing = true;
03554         res = closeDialog(dlg);
03555         d->forceDialogClosing = tmp; //restore
03556         if (!res || ~res) {
03557             return res;
03558         }
03559 //      if (remove_on_closing) //already removed
03560     //      return true;
03561 //      if (!dlg->close(true))
03562 //          return true; //ok - close cancelled
03563     }
03564 
03565     //in case the dialog is a 'print setup' dialog, also update d->pageSetupDialogs
03566     int dataItemID = d->pageSetupDialogItemID2dataItemID_map[item->identifier()];
03567     d->pageSetupDialogItemID2dataItemID_map.remove(item->identifier());
03568     d->pageSetupDialogs.take( dataItemID );
03569 
03570     if (!d->prj->removeObject(this, *item)) {
03571         //TODO(js) better msg
03572         showSorryMessage( i18n("Could not remove object.") );
03573         return false;
03574     }
03575     return true;
03576 }
03577 
03578 void KexiMainWindowImpl::renameObject( KexiPart::Item *item, const QString& _newName, bool &success )
03579 {
03580     d->pendingDialogsExist();
03581     QString newName = _newName.stripWhiteSpace();
03582     if (newName.isEmpty()) {
03583         showSorryMessage( i18n("Could not set empty name for this object.") );
03584         success = false;
03585         return;
03586     }
03587     enableMessages(false); //to avoid double messages
03588     const bool res = d->prj->renameObject(this, *item, newName);
03589     enableMessages(true);
03590     if (!res) {
03591         showErrorMessage( d->prj, i18n("Renaming object \"%1\" failed.").arg(newName) );
03592         success = false;
03593         return;
03594     }
03595     d->pendingDialogsExist();
03596 }
03597 
03598 void KexiMainWindowImpl::slotObjectRenamed(const KexiPart::Item &item, const QCString& /*oldName*/)
03599 {
03600 #ifndef KEXI_NO_PENDING_DIALOGS
03601     Private::PendingJobType pendingType;
03602     KexiDialogBase *dlg = d->openedDialogFor( &item, pendingType );
03603     if (pendingType!=Private::NoJob)
03604         return;
03605 #else
03606     KexiDialogBase *dlg = d->openedDialogFor( &item );
03607 #endif
03608     if (!dlg)
03609         return;
03610 
03611     //change item
03612     dlg->updateCaption();
03613     if (static_cast<KexiDialogBase*>(d->curDialog)==dlg)//optionally, update app. caption
03614         updateAppCaption();
03615 }
03616 
03617 int KexiMainWindowImpl::generatePrivateID()
03618 {
03619     return --d->privateIDCounter;
03620 }
03621 
03622 void KexiMainWindowImpl::acceptPropertySetEditing()
03623 {
03624     if (d->propEditor)
03625         d->propEditor->editor()->acceptInput();
03626 }
03627 
03628 void KexiMainWindowImpl::propertySetSwitched(KexiDialogBase *dlg, bool force, 
03629     bool preservePrevSelection, const QCString& propertyToSelect)
03630 {
03631     kdDebug() << "KexiMainWindowImpl::propertySetSwitched() d->curDialog: "
03632         << (d->curDialog ? d->curDialog->caption() : QString("NULL")) << " dlg: " << (dlg ? dlg->caption() : QString("NULL"))<< endl;
03633     if ((KexiDialogBase*)d->curDialog!=dlg) {
03634         d->propBuffer = 0; //we'll need to move to another prop. set
03635         return;
03636     }
03637     if (d->propEditor) {
03638         KoProperty::Set *newBuf = d->curDialog ? d->curDialog->propertySet() : 0;
03639         if (!newBuf || (force || static_cast<KoProperty::Set*>(d->propBuffer) != newBuf)) {
03640             d->propBuffer = newBuf;
03641             if (preservePrevSelection) {
03642                 if (propertyToSelect.isEmpty())
03643                     d->propEditor->editor()->changeSet( d->propBuffer, preservePrevSelection );
03644                 else
03645                     d->propEditor->editor()->changeSet( d->propBuffer, propertyToSelect );
03646             }
03647         }
03648     }
03649 }
03650 
03651 void KexiMainWindowImpl::slotDirtyFlagChanged(KexiDialogBase* dlg)
03652 {
03653     KexiPart::Item *item = dlg->partItem();
03654     //update text in navigator and app. caption
03655     if(!d->final)
03656         d->nav->updateItemName( *item, dlg->dirty() );
03657 
03658     invalidateActions();
03659     updateAppCaption();
03660 }
03661 
03662 void KexiMainWindowImpl::slotMdiModeHasBeenChangedTo(KMdi::MdiMode)
03663 {
03664     //after switching to other MDI mode, pointer to current dialog needs to be updated
03665     activateFirstWin();
03666     activeWindowChanged(activeWindow());
03667 }
03668 
03669 void KexiMainWindowImpl::slotTipOfTheDay()
03670 {
03671     //todo
03672 }
03673 
03674 void KexiMainWindowImpl::slotImportantInfo()
03675 {
03676     importantInfo(false);
03677 }
03678 
03679 void KexiMainWindowImpl::slotStartFeedbackAgent()
03680 {
03681 #ifndef KEXI_NO_FEEDBACK_AGENT
03682 #ifdef FEEDBACK_CLASS
03683     const KAboutData* about = KApplication::kApplication()->aboutData();
03684     FEEDBACK_CLASS* wizard = new FEEDBACK_CLASS( about->programName(),
03685         about->version(), 0, 0, 0, FEEDBACK_CLASS::AllPages );
03686 
03687     if ( wizard->exec() )
03688     {
03689         KApplication::kApplication()->invokeMailer( "kexi-reports-dummy@kexi.org",
03690             QString::null, QString::null,
03691             about->appName() + QCString( " [feedback]" ),
03692             wizard->feedbackDocument().toString( 2 ).local8Bit() );
03693     }
03694 
03695     delete wizard;
03696 #endif
03697 #endif
03698 }
03699 
03700 void KexiMainWindowImpl::importantInfo(bool /*onStartup*/)
03701 {
03702 #if 0
03703     if (onStartup && !d->showImportantInfoOnStartup)
03704         return;
03705 
03706     QString key = QString("showImportantInfo %1").arg(KEXI_VERSION_STRING);
03707     d->config->setGroup("Startup");
03708     bool show = d->config->readBoolEntry(key,true);
03709 
03710     if (show || !onStartup) { //if !onStartup - dialog is always shown
03711         d->config->setGroup("TipOfDay");
03712         if (!d->config->hasKey("RunOnStart"))
03713             d->config->writeEntry("RunOnStart",true);
03714 
03715         QString lang = KGlobal::locale()->language();
03716         QString fname = locate("data", QString("kexi/readme_")+lang);
03717         if (fname.isEmpty())//back to default
03718             fname = locate("data", "kexi/readme_en");
03719         KTipDialog tipDialog(new KTipDatabase(QString::null), 0);
03720         tipDialog.setCaption(i18n("Important Information"));
03721         QObjectList *l = tipDialog.queryList( "KPushButton" );//hack: hide <- -> buttons
03722         int i=0;
03723         for (QObjectListIt it( *l ); it.current() && i<2; ++it, i++ )
03724             static_cast<KPushButton*>(it.current())->hide();
03725         QFile f(fname);
03726         if ( f.open( IO_ReadOnly ) ) {
03727             QTextStream ts(&f);
03728             ts.setCodec( KGlobal::locale()->codecForEncoding() );
03729             QTextBrowser *tb = KexiUtils::findFirstChild<KTextBrowser>(&tipDialog,"KTextBrowser");
03730             if (tb) {
03731                 tb->setText( QString("<qt>%1</qt>").arg(ts.read()) );
03732             }
03733             f.close();
03734         }
03735 
03736         tipDialog.adjustSize();
03737         QRect desk = QApplication::desktop()->screenGeometry( QApplication::desktop()->screenNumber(this) );
03738         tipDialog.resize( QMAX(tipDialog.width(),desk.width()*3/5), QMAX(tipDialog.height(),desk.height()*3/5) );
03739         KDialog::centerOnScreen(&tipDialog);
03740         tipDialog.setModal ( true );
03741         tipDialog.exec();
03742         //a hack: get user's settings
03743         d->config->setGroup("TipOfDay");
03744         show = d->config->readBoolEntry("RunOnStart", show);
03745     }
03746 
03747     //write our settings back
03748     d->config->setGroup("Startup");
03749     d->config->writeEntry(key,show);
03750     d->showImportantInfoOnStartup = false;
03751 #endif
03752 }
03753 
03754 void KexiMainWindowImpl::slotOptionsEnableForms(bool show, bool noMessage)
03755 {
03756     Q_UNUSED(noMessage);
03757     Kexi::tempShowForms() = show;
03758 }
03759 
03760 bool KexiMainWindowImpl::inFinalMode() const
03761 {
03762     return d->final;
03763 }
03764 
03765 bool
03766 KexiMainWindowImpl::initFinalMode(KexiProjectData *projectData)
03767 {
03768 //TODO
03769     Kexi::tempShowForms() = true;
03770     Kexi::tempShowReports() = true;
03771     Kexi::tempShowMacros() = true;
03772     Kexi::tempShowScripts() = true;
03773     if(!projectData)
03774         return false;
03775 
03776     createKexiProject(projectData); //initialize project
03777     d->prj->setFinal(true);         //announce that we are in fianl mode
03778 
03779     tristate res = d->prj->open();             //try to open database
03780     if (!res || ~res) {
03781         delete d->prj;
03782         d->prj = 0;
03783         return false;
03784     }
03785 
03786     KexiDB::TableSchema *sch = d->prj->dbConnection()->tableSchema("kexi__final");
03787     QString err_msg = i18n("Could not start project \"%1\" in Final Mode.")
03788         .arg(static_cast<KexiDB::SchemaData*>(projectData)->name());
03789     if(!sch)
03790     {
03791         hide();
03792         showErrorMessage( err_msg, i18n("No Final Mode data found.") );
03793         return false;
03794     }
03795 
03796     KexiDB::Cursor *c = d->prj->dbConnection()->executeQuery(*sch);
03797     if(!c)
03798     {
03799         hide();
03800         showErrorMessage( err_msg, i18n("Error reading Final Mode data.") );
03801         return false;
03802     }
03803 
03804     QString startupPart;
03805     QString startupItem;
03806     while(c->moveNext())
03807     {
03808         kdDebug() << "KexiMainWinImpl::initFinalMode(): property: [" << c->value(1).toString() << "] " << c->value(2).toString() << endl;
03809         if(c->value(1).toString() == "startup-part")
03810             startupPart = c->value(2).toString();
03811         else if(c->value(1).toString() == "startup-item")
03812             startupItem = c->value(2).toString();
03813         else if(c->value(1).toString() == "mainxmlui")
03814             setXML(c->value(2).toString());
03815     }
03816     d->prj->dbConnection()->deleteCursor(c);
03817 
03818     kdDebug() << "KexiMainWinImpl::initFinalMode(): part: " << startupPart << endl;
03819     kdDebug() << "KexiMainWinImpl::initFinalMode(): item: " << startupItem << endl;
03820 
03821     initActions();
03822     initUserActions();
03823     guiFactory()->addClient(this);
03824     setStandardToolBarMenuEnabled(false);
03825     setHelpMenuEnabled(false);
03826 
03827     KexiPart::Info *i = Kexi::partManager().infoForMimeType(startupPart.latin1());
03828     if (!i) {
03829         hide();
03830         showErrorMessage( err_msg, i18n("Specified plugin does not exist.") );
03831         return false;
03832     }
03833 
03834     Kexi::partManager().part(i);
03835     KexiPart::Item *item = d->prj->item(i, startupItem);
03836     bool openingCancelled;
03837     if(!openObject(item, Kexi::DataViewMode, openingCancelled) && !openingCancelled) {
03838         hide();
03839         showErrorMessage( err_msg, i18n("Specified object could not be opened.") );
03840         return false;
03841     }
03842 
03843     QWidget::setCaption("MyApp");//TODO
03844 
03845     return true;
03846 }
03847 
03848 void
03849 KexiMainWindowImpl::initUserActions()
03850 {
03851 #if 0 //unused for now
03852     KexiDB::Cursor *c = d->prj->dbConnection()->executeQuery("SELECT p_id, name, text, icon, method, arguments FROM kexi__useractions WHERE scope = 0");
03853     if(!c)
03854         return;
03855 
03856     while(c->moveNext())
03857     {
03858         KexiUserAction::fromCurrentRecord(this, actionCollection(), c);
03859     }
03860     d->prj->dbConnection()->deleteCursor(c);
03861 /*
03862     KexiUserAction *a1 = new KexiUserAction(this, actionCollection(), "user_dataview", "Change to dataview", "table");
03863     Arguments args;
03864     args.append(QVariant("kexi/table"));
03865     args.append(QVariant("persons"));
03866     a1->setMethod(KexiUserAction::OpenObject, args);
03867 */
03868 #endif
03869 }
03870 
03871 void KexiMainWindowImpl::slotToolsProjectMigration()
03872 {
03873     showProjectMigrationWizard(QString::null, QString::null);
03874 }
03875 
03876 void KexiMainWindowImpl::slotToolsCompactDatabase()
03877 {
03878     KexiProjectData *data = 0;
03879     KexiDB::Driver *drv = 0;
03880     const bool projectWasOpened = d->prj;
03881 
03882     if (!d->prj) {
03883         KexiStartupDialog dlg(
03884             KexiStartupDialog::OpenExisting, 0, Kexi::connset(), Kexi::recentProjects(),
03885             this, "KexiOpenDialog");
03886 
03887         if (dlg.exec()!=QDialog::Accepted)
03888             return;
03889 
03890         if (dlg.selectedExistingFile().isEmpty()) {
03892             return;
03893         }
03894         KexiDB::ConnectionData cdata;
03895         cdata.setFileName( dlg.selectedExistingFile() );
03896         
03897         //detect driver name for the selected file
03898         KexiStartupData::Import detectedImportAction;
03899         tristate res = KexiStartupHandler::detectActionForFile( 
03900             detectedImportAction, cdata.driverName,
03901             "" /*suggestedDriverName*/, cdata.fileName(), 0,
03902             KexiStartupHandler::SkipMessages | KexiStartupHandler::ThisIsAProjectFile 
03903             | KexiStartupHandler::DontConvert);
03904 
03905         if (true==res && !detectedImportAction)
03906             drv = Kexi::driverManager().driver( cdata.driverName );
03907         if (!drv || !(drv->features() & KexiDB::Driver::CompactingDatabaseSupported)) {
03908             KMessageBox::information(this, "<qt>"+
03909                 i18n("Compacting database file <nobr>\"%1\"</nobr> is not supported.")
03910                 .arg(QDir::convertSeparators(cdata.fileName())));
03911             return;
03912         }
03913         data = new KexiProjectData( cdata, cdata.fileName() );
03914     }
03915     else {
03916         //sanity
03917         if ( !(d->prj && d->prj->dbConnection() 
03918             && (d->prj->dbConnection()->driver()->features() & KexiDB::Driver::CompactingDatabaseSupported) ))
03919             return;
03920 
03921         if (KMessageBox::Continue != KMessageBox::warningContinueCancel(this,
03922                 i18n("The current project has to be closed before compacting the database. "
03923                  "It will be open again after compacting.\n\nDo you want to continue?")))
03924             return;
03925 
03926         data = new KexiProjectData(*d->prj->data()); // a copy
03927         drv = d->prj->dbConnection()->driver();
03928         const tristate res = closeProject();
03929         if (~res || !res)
03930             return;
03931     }
03932 
03933     if (!drv->adminTools().vacuum(*data->connectionData(), data->databaseName())) {
03934         //err msg
03935         showErrorMessage( &drv->adminTools() );
03936     }
03937 
03938     if (data && projectWasOpened) {
03939         openProject(*data);
03940         delete data;
03941     }
03942 }
03943 
03944 tristate KexiMainWindowImpl::showProjectMigrationWizard(
03945     const QString& mimeType, const QString& databaseName, const KexiDB::ConnectionData *cdata)
03946 {
03947     //pass arguments
03948     QMap<QString,QString> args;
03949     args.insert("mimeType", mimeType);
03950     args.insert("databaseName", databaseName);
03951     if (cdata) { //pass ConnectionData serialized as a string...
03952         QString str;
03953         KexiUtils::serializeMap( KexiDB::toMap( *cdata ), str );
03954         args.insert("connectionData", str);
03955     }
03956 
03957     QDialog *dlg = KexiInternalPart::createModalDialogInstance("migration", this, this, 0, &args);
03958     if (!dlg)
03959         return false; //error msg has been shown by KexiInternalPart
03960 
03961     const int result = dlg->exec();
03962     delete dlg;
03963     //raise();
03964     if (result!=QDialog::Accepted)
03965         return cancelled;
03966 
03967     //open imported project in a new Kexi instance
03968     QString destinationDatabaseName( args["destinationDatabaseName"] );
03969     QString fileName, destinationConnectionShortcut, dbName;
03970     if (!destinationDatabaseName.isEmpty()) {
03971         if (args.contains("destinationConnectionShortcut")) {
03972             // server-based
03973             destinationConnectionShortcut = args["destinationConnectionShortcut"];
03974         }
03975         else {
03976             // file-based
03977             fileName = destinationDatabaseName;
03978             destinationDatabaseName = QString::null;
03979         }
03980         tristate res = openProject(fileName, destinationConnectionShortcut, 
03981             destinationDatabaseName);
03982         raise();
03983         return res;
03984 //          KexiDB::ConnectionData *connData = new KexiDB::ConnectionData();
03985 //          KexiDB::fromMap( KexiUtils::deserializeMap( args["destinationConnectionData"] ), *connData );
03986 //      return openProject(destinationFileName, 0);
03987     }
03988     return true;
03989 }
03990 
03991 tristate KexiMainWindowImpl::executeItem(KexiPart::Item* item)
03992 {
03993     KexiPart::Info *info = item ? Kexi::partManager().infoForMimeType(item->mimeType()) : 0;
03994     if ( (! info) || (! info->isExecuteSupported()) )
03995         return false;
03996     KexiPart::Part *part = Kexi::partManager().part(info);
03997     if (!part)
03998         return false;
03999     return part->execute(item);
04000 }
04001 
04002 void KexiMainWindowImpl::slotProjectImportDataTable()
04003 {
04004     QMap<QString,QString> args;
04005     args.insert("sourceType", "file");
04006     QDialog *dlg = KexiInternalPart::createModalDialogInstance(
04007         "csv_importexport", "KexiCSVImportDialog", this, this, 0, &args);
04008     if (!dlg)
04009         return; //error msg has been shown by KexiInternalPart
04010     dlg->exec();
04011     delete dlg;
04012 }
04013 
04014 void KexiMainWindowImpl::exportItemAsDataTable(KexiPart::Item* item)
04015 {
04016     if (!item)
04017         return;
04018 
04021 
04022     QMap<QString,QString> args;
04023     args.insert("destinationType", "file");
04024     args.insert("itemId", QString::number(item->identifier()));
04025     QDialog *dlg = KexiInternalPart::createModalDialogInstance(
04026         "csv_importexport", "KexiCSVExportWizard", this, this, 0, &args);
04027     if (!dlg)
04028         return; //error msg has been shown by KexiInternalPart
04029     dlg->exec();
04030     delete dlg;
04031 }
04032 
04033 bool KexiMainWindowImpl::printItem(KexiPart::Item* item, const QString& titleText)
04034 {
04035     return printItem(item, KexiSimplePrintingSettings::load(), titleText);
04036 }
04037 
04038 bool KexiMainWindowImpl::printItem(KexiPart::Item* item, const KexiSimplePrintingSettings& settings,
04039     const QString& titleText)
04040 {
04043     KexiSimplePrintingCommand cmd(this, item->identifier());
04044     //modal
04045     return cmd.print(settings, titleText);
04046 //  return printActionForItem(item, PrintItem);
04047 }
04048 
04049 bool KexiMainWindowImpl::printPreviewForItem(KexiPart::Item* item, const QString& titleText, bool reload)
04050 {
04051     return printPreviewForItem(item, KexiSimplePrintingSettings::load(), titleText, reload);
04052 }
04053 
04054 bool KexiMainWindowImpl::printPreviewForItem(KexiPart::Item* item, 
04055     const KexiSimplePrintingSettings& settings, const QString& titleText, bool reload)
04056 {
04059     KexiSimplePrintingCommand* cmd = d->openedCustomObjectsForItem<KexiSimplePrintingCommand>(
04060         item, "KexiSimplePrintingCommand");
04061     if (!cmd) {
04062         d->addOpenedCustomObjectForItem(
04063             item,
04064             cmd = new KexiSimplePrintingCommand(this, item->identifier()), 
04065             "KexiSimplePrintingCommand"
04066         );
04067     }
04068     return cmd->showPrintPreview(settings, titleText, reload);
04069 //  return printActionForItem(item, PreviewItem);
04070 }
04071 
04072 tristate KexiMainWindowImpl::pageSetupForItem(KexiPart::Item* item)
04073 {
04076     return printActionForItem(item, PageSetupForItem);
04077 }
04078 
04079 tristate KexiMainWindowImpl::printActionForItem(KexiPart::Item* item, PrintActionType action)
04080 {
04081     if (!item)
04082         return false;
04083     KexiPart::Info *info = Kexi::partManager().infoForMimeType( item->mimeType() );
04084     if (!info->isPrintingSupported())
04085         return false;
04086 
04087     KexiDialogBase *printingDialog = d->pageSetupDialogs[ item->identifier() ];
04088     if (printingDialog) {
04089         if (!activateWindow(printingDialog))
04090             return false;
04091         if (action == PreviewItem || action == PrintItem) {
04092             QTimer::singleShot(0,printingDialog->selectedView(),
04093                 (action == PreviewItem) ? SLOT(printPreview()) : SLOT(print()));
04094         }
04095         return true;
04096     }
04097 
04098 #ifndef KEXI_NO_PENDING_DIALOGS
04099     Private::PendingJobType pendingType;
04100     KexiDialogBase *dlg = d->openedDialogFor( item, pendingType );
04101     if (pendingType!=Private::NoJob)
04102         return cancelled;
04103 #else
04104     KexiDialogBase *dlg = d->openedDialogFor( item );
04105 #endif
04106 
04107     if (dlg) {
04108         // accept row changes
04109         QWidget *prevFocusWidget = focusWidget();
04110         dlg->setFocus();
04111         d->action_data_save_row->activate();
04112         if (prevFocusWidget)
04113             prevFocusWidget->setFocus();
04114 
04115         // opened: check if changes made to this dialog are saved, if not: ask for saving
04116         if (dlg->neverSaved()) //sanity check
04117             return false;
04118         if (dlg->dirty()) {
04119             KGuiItem saveChanges( KStdGuiItem::save() ); 
04120             saveChanges.setToolTip(i18n("Save changes"));
04121             saveChanges.setWhatsThis(
04122                 i18n( "Pressing this button will save all recent changes made in \"%1\" object." )
04123                 .arg(item->name()) );
04124             KGuiItem doNotSave( KStdGuiItem::no() );
04125             doNotSave.setWhatsThis(
04126                 i18n( "Pressing this button will ignore all unsaved changes made in \"%1\" object." )
04127                 .arg(dlg->partItem()->name()) );
04128 
04129             QString question;
04130             if (action == PrintItem)
04131                 question = i18n("Do you want to save changes before printing?");
04132             else if (action == PreviewItem)
04133                 question = i18n("Do you want to save changes before making print preview?");
04134             else if (action == PageSetupForItem)
04135                 question = i18n("Do you want to save changes before showing page setup?");
04136             else
04137                 return false;
04138 
04139             const int questionRes = KMessageBox::warningYesNoCancel( this,
04140                 "<p>"+dlg->part()->i18nMessage("Design of object \"%1\" has been modified.", dlg)
04141                 .arg(item->name()) + "</p><p>" + question + "</p>",
04142                 QString::null, 
04143                 saveChanges,
04144                 doNotSave);
04145             if (KMessageBox::Cancel == questionRes)
04146                 return cancelled;
04147             if (KMessageBox::Yes == questionRes) {
04148                 tristate savingRes = saveObject( dlg, QString::null, true /*dontAsk*/ );
04149                 if (true != savingRes)
04150                     return savingRes;
04151             }
04152         }
04153     }
04154     KexiSimplePrintingPart *printingPart = new KexiSimplePrintingPart();
04155     KexiPart::Item* printingPartItem = d->prj->createPartItem(
04156         printingPart, item->name() //<-- this will look like "table1 : printing" on the window list
04157     );
04158     QMap<QString,QString> staticObjectArgs;
04159     staticObjectArgs["identifier"] = QString::number(item->identifier());
04160     if (action == PrintItem)
04161         staticObjectArgs["action"] = "print";
04162     else if (action == PreviewItem)
04163         staticObjectArgs["action"] = "printPreview";
04164     else if (action == PageSetupForItem)
04165         staticObjectArgs["action"] = "pageSetup";
04166     else
04167         return false;
04168     bool openingCancelled;
04169     printingDialog = openObject(printingPartItem, Kexi::DesignViewMode, 
04170         openingCancelled, &staticObjectArgs);
04171     if (openingCancelled)
04172         return cancelled;
04173     if (!printingDialog) //sanity
04174         return false;
04175     d->pageSetupDialogs.insert(item->identifier(), printingDialog);
04176     d->pageSetupDialogItemID2dataItemID_map.insert(
04177         printingDialog->partItem()->identifier(), item->identifier());
04178 
04179     return true;
04180 }
04181 
04182 void KexiMainWindowImpl::slotEditCopySpecialDataTable()
04183 {
04184     KexiPart::Item* item = d->nav->selectedPartItem();
04185     if (!item)
04186         return;
04187     QMap<QString,QString> args;
04188     args.insert("destinationType", "clipboard");
04189     args.insert("itemId", QString::number(item->identifier()));
04190     QDialog *dlg = KexiInternalPart::createModalDialogInstance(
04191         "csv_importexport", "KexiCSVExportWizard", this, this, 0, &args);
04192     if (!dlg)
04193         return; //error msg has been shown by KexiInternalPart
04194     dlg->exec();
04195     delete dlg;
04196 }
04197 
04198 void KexiMainWindowImpl::slotEditPasteSpecialDataTable()
04199 {
04200     QMap<QString,QString> args;
04201     args.insert("sourceType", "clipboard");
04202     QDialog *dlg = KexiInternalPart::createModalDialogInstance(
04203         "csv_importexport", "KexiCSVImportDialog", this, this, 0, &args);
04204     if (!dlg)
04205         return; //error msg has been shown by KexiInternalPart
04206     dlg->exec();
04207     delete dlg;
04208 }
04209 
04210 void KexiMainWindowImpl::addWindow( KMdiChildView* pView, int flags )
04211 {
04212     //maximize this window, if it's
04215     if (d->maximizeFirstOpenedChildFrm) {
04216         flags |= KMdi::Maximize;
04217         d->maximizeFirstOpenedChildFrm = false;
04218     }
04219     KexiMainWindow::addWindow( pView, flags );
04220 }
04221 
04223 void KexiMainWindowImpl::slotGetNewStuff()
04224 {
04225 #ifdef HAVE_KNEWSTUFF
04226     if(!d->newStuff)
04227         d->newStuff = new KexiNewStuff(this);
04228     d->newStuff->download();
04229     
04230     //KNS::DownloadDialog::open(newstuff->customEngine(), "kexi/template");
04231 #endif
04232 }
04233 
04234 void KexiMainWindowImpl::highlightObject(const QCString& mime, const QCString& name)
04235 {
04236     slotViewNavigator();
04237     if (!d->prj)
04238         return;
04239     KexiPart::Item *item = d->prj->itemForMimeType(mime, name);
04240     if (!item)
04241         return;
04242     if (d->nav) {
04243         d->nav->highlightItem(*item);
04244     }
04245 }
04246 
04247 void KexiMainWindowImpl::slotPartItemSelectedInNavigator(KexiPart::Item* item)
04248 {
04249     Q_UNUSED(item);
04250 }
04251 
04252 #include "keximainwindowimpl.moc"
KDE Home | KDE Accessibility Home | Description of Access Keys