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