File indexing completed on 2024-05-19 12:54:51
0001 /* This file is part of the KDE project 0002 Copyright (C) 2003 Lucijan Busch <lucijan@kde.org> 0003 Copyright (C) 2003-2018 Jarosław Staniek <staniek@kde.org> 0004 0005 This library is free software; you can redistribute it and/or 0006 modify it under the terms of the GNU Library General Public 0007 License as published by the Free Software Foundation; either 0008 version 2 of the License, or (at your option) any later version. 0009 0010 This library is distributed in the hope that it will be useful, 0011 but WITHOUT ANY WARRANTY; without even the implied warranty of 0012 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 0013 Library General Public License for more details. 0014 0015 You should have received a copy of the GNU Library General Public License 0016 along with this library; see the file COPYING.LIB. If not, write to 0017 the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, 0018 * Boston, MA 02110-1301, USA. 0019 */ 0020 0021 #include "KexiMainWindow.h" 0022 #include "KexiMainWindow_p.h" 0023 #include "kexiactionproxy.h" 0024 #include "kexipartmanager.h" 0025 #include "kexipart.h" 0026 #include "kexipartinfo.h" 0027 #include "kexipartguiclient.h" 0028 #include "kexiproject.h" 0029 #include "kexiprojectdata.h" 0030 #include "kexi.h" 0031 #include "kexiinternalpart.h" 0032 #include "kexiactioncategories.h" 0033 #include "kexifinddialog.h" 0034 #include "kexisearchandreplaceiface.h" 0035 #include "KexiBugReportDialog.h" 0036 #define KEXI_SKIP_REGISTERICONSRESOURCE 0037 #define KEXI_SKIP_SETUPPRIVATEICONSRESOURCE 0038 #include "KexiRegisterResource_p.h" 0039 #include "KexiObjectViewWidget.h" 0040 #include "KexiObjectViewTabWidget.h" 0041 #include <kexiutils/utils.h> 0042 #include <kexiutils_global.h> 0043 #include <KexiStyle.h> 0044 #include <kexiutils/KexiCloseButton.h> 0045 #include <kexiutils/KexiTester.h> 0046 #include <KexiVersion.h> 0047 #include <core/KexiWindow.h> 0048 #include <core/KexiRecentProjects.h> 0049 #include <core/kexiaboutdata.h> 0050 #include <core/KexiCommandLineOptions.h> 0051 #include <KexiIcon.h> 0052 #include <kexi_global.h> 0053 #include <KexiPropertyPaneWidget.h> 0054 #include <widget/utils/kexirecordnavigator.h> 0055 #include <widget/utils/KexiDockableWidget.h> 0056 #include <widget/navigator/KexiProjectNavigator.h> 0057 #include <widget/navigator/KexiProjectModel.h> 0058 #include <widget/KexiNameDialog.h> 0059 #include <widget/KexiNameWidget.h> 0060 #include <widget/KexiDBPasswordDialog.h> 0061 #include "startup/KexiStartup.h" 0062 #include "startup/KexiNewProjectAssistant.h" 0063 #include "startup/KexiOpenProjectAssistant.h" 0064 #include "startup/KexiWelcomeAssistant.h" 0065 #include "startup/KexiImportExportAssistant.h" 0066 #include <KexiAssistantPage.h> 0067 0068 #include <KDbConnection> 0069 #include <KDbConnectionOptions> 0070 #include <KDbCursor> 0071 #include <KDbAdmin> 0072 #include <KDbDriverManager> 0073 #include <KDbObjectNameValidator> 0074 0075 #include <KPropertyEditorView> 0076 #include <KPropertySet> 0077 0078 #include <KActionCollection> 0079 #include <KActionMenu> 0080 #include <KToggleAction> 0081 #include <KStandardShortcut> 0082 #include <KStandardGuiItem> 0083 #include <KConfig> 0084 #include <KShortcutsDialog> 0085 #include <KEditToolBar> 0086 #include <KToggleFullScreenAction> 0087 #include <KIconLoader> 0088 #include <KHelpMenu> 0089 #include <KMultiTabBar> 0090 #include <KLocalizedString> 0091 #include <KMessageBox> 0092 #include <KConfigGroup> 0093 #include <KAcceleratorManager> 0094 0095 #include <QApplication> 0096 #include <QFile> 0097 #include <QProcess> 0098 #include <QToolButton> 0099 #include <QDebug> 0100 #include <QHash> 0101 #include <QStylePainter> 0102 #include <QStyleFactory> 0103 #include <QDesktopWidget> 0104 #include <QResource> 0105 #include <QMenuBar> 0106 0107 #if !defined(KexiVDebug) 0108 # define KexiVDebug if (0) qDebug() 0109 #endif 0110 0111 #ifdef HAVE_KCRASH 0112 #include <kcrash.h> 0113 //! @todo else, add Breakpad? https://phabricator.kde.org/T1642 0114 #endif 0115 0116 KexiDockWidgetStyle::KexiDockWidgetStyle(const QString &baseStyleName) 0117 : QProxyStyle(baseStyleName) 0118 { 0119 } 0120 0121 KexiDockWidgetStyle::~KexiDockWidgetStyle() 0122 { 0123 } 0124 0125 void KexiDockWidgetStyle::polish(QWidget* widget) 0126 { 0127 baseStyle()->polish(widget); 0128 widget->setContentsMargins(0, 0, 0, 0); 0129 } 0130 0131 class Q_DECL_HIDDEN KexiDockWidget::Private 0132 { 0133 public: 0134 Private() {} 0135 QSize hint; 0136 }; 0137 0138 KexiDockWidget::KexiDockWidget(const QString &_tabText, QWidget *parent) 0139 : QDockWidget(parent), tabText(_tabText), d(new Private) 0140 { 0141 // No floatable dockers, Dolphin had problems, we don't want the same... 0142 // https://bugs.kde.org/show_bug.cgi?id=288629 0143 // https://bugs.kde.org/show_bug.cgi?id=322299 0144 setFeatures(QDockWidget::NoDockWidgetFeatures);//DockWidgetClosable); 0145 setAllowedAreas(Qt::LeftDockWidgetArea|Qt::RightDockWidgetArea); 0146 setFocusPolicy(Qt::NoFocus); 0147 if (style()->objectName().compare("windowsvista", Qt::CaseInsensitive) == 0) { 0148 // windowsvista style has broken accelerator visualization support 0149 KAcceleratorManager::setNoAccel(this); 0150 } 0151 KexiDockWidgetStyle *customStyle = new KexiDockWidgetStyle(style()->objectName()); 0152 customStyle->setParent(this); 0153 setStyle(customStyle); 0154 setTitleBarWidget(new QWidget(this)); // hide the title 0155 layout()->setContentsMargins(0, 0, 0, 0); 0156 layout()->setSpacing(0); 0157 } 0158 0159 KexiDockWidget::~KexiDockWidget() 0160 { 0161 delete d; 0162 } 0163 0164 void KexiDockWidget::paintEvent(QPaintEvent *pe) 0165 { 0166 Q_UNUSED(pe); 0167 QStylePainter p(this); 0168 if (isFloating()) { 0169 QStyleOptionFrame framOpt; 0170 framOpt.initFrom(this); 0171 p.drawPrimitive(QStyle::PE_FrameDockWidget, framOpt); 0172 } 0173 0174 // Title must be painted after the frame, since the areas overlap, and 0175 // the title may wish to extend out to all sides (eg. XP style) 0176 QStyleOptionDockWidget titleOpt; 0177 initStyleOption(&titleOpt); 0178 p.drawControl(QStyle::CE_DockWidgetTitle, titleOpt); 0179 } 0180 0181 void KexiDockWidget::setSizeHint(const QSize& hint) 0182 { 0183 d->hint = hint; 0184 } 0185 0186 QSize KexiDockWidget::sizeHint() const 0187 { 0188 return d->hint.isValid() ? d->hint : QDockWidget::sizeHint(); 0189 } 0190 0191 //------------------------------------------------- 0192 0193 static bool setupIconTheme(KLocalizedString *errorMessage, KLocalizedString *detailsErrorMessage) 0194 { 0195 // Register kexi resource first to have priority over the standard breeze theme. 0196 // For example "table" icon exists in both resources. 0197 if (!registerResource("icons/kexi_breeze.rcc", QStandardPaths::AppDataLocation, 0198 QString(), QString(), errorMessage, detailsErrorMessage) 0199 || !registerGlobalBreezeIconsResource(errorMessage, detailsErrorMessage)) 0200 { 0201 return false; 0202 } 0203 setupBreezeIconTheme(); 0204 0205 // tell KIconLoader an co. about the theme 0206 KConfigGroup cg(KSharedConfig::openConfig(), "Icons"); 0207 cg.writeEntry("Theme", "breeze"); 0208 cg.sync(); 0209 return true; 0210 } 0211 0212 //! @todo 3.1 replace with KexiStyle 0213 bool setupApplication() 0214 { 0215 #if defined Q_OS_WIN || defined Q_OS_MACOS 0216 // Only this style matches current KEXI theme and can be supported/tested 0217 const char *name = "breeze"; 0218 QScopedPointer<QStyle> style(QStyleFactory::create(name)); 0219 if (!style || style->objectName() != name) { 0220 qWarning() << 0221 qPrintable(QString("Could not find application style %1. " 0222 "KEXI will not start. Please check if KEXI is properly installed. ") 0223 .arg(name)); 0224 return false; 0225 } 0226 qApp->setStyle(style.take()); 0227 #endif 0228 return true; 0229 } 0230 0231 //static 0232 int KexiMainWindow::create(const QStringList &arguments, const QString &componentName, 0233 const QList<QCommandLineOption> &extraOptions) 0234 { 0235 qApp->setQuitOnLastWindowClosed(false); 0236 0237 KLocalizedString::setApplicationDomain("kexi"); 0238 //! @todo KEXI3 app->setAttribute(Qt::AA_UseHighDpiPixmaps, true); 0239 0240 KexiAboutData aboutData; 0241 if (!componentName.isEmpty()) { 0242 aboutData.setComponentName(componentName); 0243 } 0244 KAboutData::setApplicationData(aboutData); 0245 0246 if (!setupApplication()) { 0247 return 1; 0248 } 0249 0250 #ifdef HAVE_KCRASH 0251 KCrash::initialize(); 0252 #endif 0253 0254 KLocalizedString errorMessage; 0255 KLocalizedString detailsErrorMessage; 0256 if (!setupIconTheme(&errorMessage, &detailsErrorMessage) 0257 || !KexiStyle::setupApplication(&errorMessage)) 0258 { 0259 if (detailsErrorMessage.isEmpty()) { 0260 KMessageBox::error(nullptr, errorMessage.toString()); 0261 } else { 0262 KMessageBox::detailedError(nullptr, errorMessage.toString(), detailsErrorMessage.toString()); 0263 } 0264 qWarning() << qPrintable(errorMessage.toString(Kuit::PlainText)); 0265 return 1; 0266 } 0267 QApplication::setWindowIcon(koIcon("kexi")); 0268 0269 const tristate res = KexiStartupHandler::global()->init(arguments, extraOptions); 0270 if (!res || ~res) { 0271 return (~res) ? 0 : 1; 0272 } 0273 //qDebug() << "startupActions OK"; 0274 0275 /* Exit requested, e.g. after database removing. */ 0276 if (KexiStartupHandler::global()->action() == KexiStartupData::Exit) { 0277 return 0; 0278 } 0279 0280 KexiMainWindow *win = new KexiMainWindow(); 0281 #ifdef KEXI_DEBUG_GUI 0282 KConfigGroup generalGroup = KSharedConfig::openConfig()->group("General"); 0283 if (generalGroup.readEntry("ShowInternalDebugger", false)) { 0284 QWidget* debugWindow = KexiUtils::createDebugWindow(win); 0285 debugWindow->show(); 0286 } 0287 #endif 0288 0289 if (true != win->startup()) { 0290 delete win; 0291 return 1; 0292 } 0293 0294 win->restoreSettings(); 0295 win->show(); 0296 #ifdef KEXI_DEBUG_GUI 0297 win->raise(); 0298 static_cast<QWidget*>(win)->activateWindow(); 0299 #endif 0300 /*foreach (QWidget *widget, QApplication::topLevelWidgets()) { 0301 qDebug() << widget; 0302 }*/ 0303 return 0; 0304 } 0305 0306 //------------------------------------------------- 0307 0308 KexiMainMenuActionShortcut::KexiMainMenuActionShortcut(const QKeySequence& key, 0309 QAction *action, QWidget *parent) 0310 : QShortcut(key, parent) 0311 , m_action(action) 0312 { 0313 connect(this, SIGNAL(activated()), this, SLOT(slotActivated())); 0314 } 0315 0316 KexiMainMenuActionShortcut::~KexiMainMenuActionShortcut() 0317 { 0318 } 0319 0320 void KexiMainMenuActionShortcut::slotActivated() 0321 { 0322 if (!m_action->isEnabled()) { 0323 return; 0324 } 0325 m_action->trigger(); 0326 } 0327 0328 //------------------------------------------------- 0329 0330 KexiMainWindow::KexiMainWindow(QWidget *parent) 0331 : QMainWindow(parent) 0332 , KexiMainWindowIface() 0333 , KexiGUIMessageHandler(this) 0334 , d(new KexiMainWindow::Private(this)) 0335 { 0336 setObjectName("KexiMainWindow"); 0337 setAttribute(Qt::WA_DeleteOnClose); 0338 kexiTester() << KexiTestObject(this); 0339 0340 if (d->userMode) { 0341 //qDebug() << "starting up in the User Mode"; 0342 } 0343 setAsDefaultHost(); //this is default host now. 0344 0345 //get informed 0346 connect(&Kexi::partManager(), SIGNAL(partLoaded(KexiPart::Part*)), 0347 this, SLOT(slotPartLoaded(KexiPart::Part*))); 0348 connect(&Kexi::partManager(), SIGNAL(newObjectRequested(KexiPart::Info*)), 0349 this, SLOT(newObject(KexiPart::Info*))); 0350 0351 setAcceptDrops(true); 0352 setupActions(); 0353 setupMainWidget(); 0354 setupMainMenu(); 0355 updateAppCaption(); 0356 0357 if (!d->userMode) { 0358 setupContextHelp(); 0359 //setupPropertyEditor(); 0360 } 0361 0362 invalidateActions(); 0363 d->timer.singleShot(0, this, SLOT(slotLastActions())); 0364 if (KexiStartupHandler::global()->forcedFullScreen()) { 0365 toggleFullScreen(true); 0366 } 0367 0368 // --- global config 0369 //! @todo move to specialized KexiConfig class 0370 KConfigGroup tablesGroup(d->config->group("Tables")); 0371 const int defaultMaxLengthForTextFields = tablesGroup.readEntry("DefaultMaxLengthForTextFields", int(-1)); 0372 if (defaultMaxLengthForTextFields >= 0) { 0373 KDbField::setDefaultMaxLength(defaultMaxLengthForTextFields); 0374 } 0375 // --- /global config 0376 } 0377 0378 KexiMainWindow::~KexiMainWindow() 0379 { 0380 d->forceWindowClosing = true; 0381 closeProject(); 0382 delete d; 0383 Kexi::deleteGlobalObjects(); 0384 } 0385 0386 KexiProject *KexiMainWindow::project() 0387 { 0388 return d->prj; 0389 } 0390 0391 QList<QAction*> KexiMainWindow::allActions() const 0392 { 0393 return actionCollection()->actions(); 0394 } 0395 0396 KActionCollection *KexiMainWindow::actionCollection() const 0397 { 0398 return d->actionCollection; 0399 } 0400 0401 KexiWindow* KexiMainWindow::currentWindow() const 0402 { 0403 if (!d->objectViewWidget || !d->objectViewWidget->tabWidget()) { 0404 return 0; 0405 } 0406 return windowForTab(d->objectViewWidget->tabWidget()->currentIndex()); 0407 } 0408 0409 KexiWindow* KexiMainWindow::windowForTab(int tabIndex) const 0410 { 0411 if (!d->objectViewWidget || !d->objectViewWidget->tabWidget()) 0412 return 0; 0413 return d->objectViewWidget->tabWidget()->window(tabIndex); 0414 } 0415 0416 void KexiMainWindow::setupMainMenuActionShortcut(QAction * action) 0417 { 0418 if (!action->shortcut().isEmpty()) { 0419 //foreach(const QKeySequence &shortcut, action->shortcuts()) { 0420 //(void)new KexiMainMenuActionShortcut(shortcut, action, this); 0421 //} 0422 } 0423 } 0424 0425 static void addThreeDotsToActionText(QAction* action) 0426 { 0427 action->setText(xi18nc("Action name with three dots...", "%1...", action->text())); 0428 } 0429 0430 QAction * KexiMainWindow::addAction(const char *name, const QIcon &icon, const QString& text, 0431 const char *shortcut) 0432 { 0433 QAction *action = icon.isNull() ? new QAction(text, this) : new QAction(icon, text, this); 0434 actionCollection()->addAction(name, action); 0435 if (shortcut) { 0436 action->setShortcut(QKeySequence(shortcut)); 0437 action->setShortcutContext(Qt::ApplicationShortcut); 0438 //QShortcut *s = new QShortcut(action->shortcut(), this); 0439 //connect(s, SIGNAL(activated()), action, SLOT(trigger())); 0440 } 0441 return action; 0442 } 0443 0444 QAction * KexiMainWindow::addAction(const char *name, const QString& text, const char *shortcut) 0445 { 0446 return addAction(name, QIcon(), text, shortcut); 0447 } 0448 0449 void KexiMainWindow::setupActions() 0450 { 0451 KActionCollection *ac = actionCollection(); 0452 0453 // PROJECT MENU 0454 QAction *action; 0455 0456 ac->addAction("project_new", 0457 action = new KexiMenuWidgetAction(KStandardAction::New, this)); 0458 action->setText(xi18n("&New Project...")); 0459 action->setShortcuts(KStandardShortcut::openNew()); 0460 action->setToolTip(xi18n("Create a new project")); 0461 action->setWhatsThis( 0462 xi18n("Creates a new project. Currently opened project is not affected.")); 0463 connect(action, SIGNAL(triggered()), this, SLOT(slotProjectNew())); 0464 setupMainMenuActionShortcut(action); 0465 0466 ac->addAction("project_open", 0467 action = new KexiMenuWidgetAction(KStandardAction::Open, this)); 0468 action->setText(xi18n("&Open Project...")); 0469 action->setIcon(koIcon("project-open")); 0470 action->setToolTip(xi18n("Open an existing project")); 0471 action->setWhatsThis( 0472 xi18n("Opens an existing project. Currently opened project is not affected.")); 0473 connect(action, SIGNAL(triggered()), this, SLOT(slotProjectOpen())); 0474 setupMainMenuActionShortcut(action); 0475 0476 ac->addAction("project_open_recent", 0477 action = KStandardAction::openRecent(this, SLOT(slotProjectOpen()), this)); 0478 action->setToolTip(xi18n("Open a project that was recently opened.")); 0479 action->setWhatsThis(xi18n("Opens a project that was recently opened.")); 0480 0481 { 0482 ac->addAction("project_welcome", 0483 action = d->action_project_welcome = new KexiMenuWidgetAction( 0484 QIcon(), xi18n("Welcome"), this)); 0485 addThreeDotsToActionText(action); 0486 connect(action, SIGNAL(triggered()), this, SLOT(slotProjectWelcome())); 0487 setupMainMenuActionShortcut(action); 0488 action->setToolTip(xi18n("Show Welcome page")); 0489 action->setWhatsThis( 0490 xi18n("Shows Welcome page with list of recently opened projects and other information. ")); 0491 } 0492 0493 ac->addAction("project_save", 0494 d->action_save = KStandardAction::save(this, SLOT(slotProjectSave()), this)); 0495 d->action_save->setToolTip(xi18n("Save object changes")); 0496 d->action_save->setWhatsThis(xi18n("Saves object changes from currently selected window.")); 0497 setupMainMenuActionShortcut(d->action_save); 0498 0499 d->action_save_as = addAction("project_saveas", koIcon("document-save-as"), 0500 xi18n("Save &As...")); 0501 d->action_save_as->setToolTip(xi18n("Save object as")); 0502 d->action_save_as->setWhatsThis( 0503 xi18n("Saves object from currently selected window under a new name (within the same project).")); 0504 connect(d->action_save_as, SIGNAL(triggered()), this, SLOT(slotProjectSaveAs())); 0505 0506 #ifdef KEXI_SHOW_UNIMPLEMENTED 0507 ac->addAction("project_properties", 0508 action = d->action_project_properties = new KexiMenuWidgetAction( 0509 koIcon("document-properties"), futureI18n("Project Properties"), this)); 0510 connect(action, SIGNAL(triggered()), this, SLOT(slotProjectProperties())); 0511 setupMainMenuActionShortcut(action); 0512 #else 0513 d->action_project_properties = d->dummy_action; 0514 #endif 0515 0516 //! @todo replace document-import icon with something other 0517 ac->addAction("project_import_export_send", 0518 action = d->action_project_import_export_send = new KexiMenuWidgetAction( 0519 koIcon("document-import"), xi18n("&Import, Export or Send..."), this)); 0520 action->setToolTip(xi18n("Import, export or send project")); 0521 action->setWhatsThis( 0522 xi18n("Imports, exports or sends project.")); 0523 connect(action, SIGNAL(triggered()), this, SLOT(slotProjectImportExportOrSend())); 0524 setupMainMenuActionShortcut(action); 0525 0526 ac->addAction("project_close", 0527 action = d->action_close = new KexiMenuWidgetAction( 0528 koIcon("project-development-close"), xi18n("&Close Project"), this)); 0529 action->setToolTip(xi18n("Close the current project")); 0530 action->setWhatsThis(xi18n("Closes the current project.")); 0531 connect(action, SIGNAL(triggered()), this, SLOT(slotProjectClose())); 0532 setupMainMenuActionShortcut(action); 0533 0534 ac->addAction("quit", 0535 action = new KexiMenuWidgetAction(KStandardAction::Quit, this)); 0536 connect(action, SIGNAL(triggered()), this, SLOT(slotProjectQuit())); 0537 action->setWhatsThis(xi18nc("@info:whatsthis", "Quits <application>%1</application> application.", 0538 QApplication::applicationDisplayName())); 0539 setupMainMenuActionShortcut(action); 0540 0541 #ifdef KEXI_SHOW_UNIMPLEMENTED 0542 d->action_project_relations = addAction("project_relations", KexiIcon("database-relations"), 0543 futureI18n("&Relationships...")); 0544 d->action_project_relations->setToolTip(futureI18n("Project relationships")); 0545 d->action_project_relations->setWhatsThis(futureI18n("Shows project relationships.")); 0546 connect(d->action_project_relations, SIGNAL(triggered()), 0547 this, SLOT(slotProjectRelations())); 0548 0549 #else 0550 d->action_project_relations = d->dummy_action; 0551 #endif 0552 d->action_tools_import_project = addAction("tools_import_project", KexiIcon("database-import"), 0553 xi18n("&Import Database...")); 0554 d->action_tools_import_project->setToolTip(xi18n("Import entire database as a KEXI project")); 0555 d->action_tools_import_project->setWhatsThis( 0556 xi18n("Imports entire database as a KEXI project.")); 0557 connect(d->action_tools_import_project, SIGNAL(triggered()), 0558 this, SLOT(slotToolsImportProject())); 0559 0560 d->action_tools_data_import = addAction("tools_import_tables", koIcon("document-import"), 0561 xi18n("Import Tables...")); 0562 d->action_tools_data_import->setToolTip(xi18n("Import data from an external source into this project")); 0563 d->action_tools_data_import->setWhatsThis(xi18n("Imports data from an external source into this project.")); 0564 connect(d->action_tools_data_import, SIGNAL(triggered()), this, SLOT(slotToolsImportTables())); 0565 0566 d->action_tools_compact_database = addAction("tools_compact_database", 0567 //! @todo icon 0568 koIcon("application-x-compress"), 0569 xi18n("&Compact Database...")); 0570 d->action_tools_compact_database->setToolTip(xi18n("Compact the current database project")); 0571 d->action_tools_compact_database->setWhatsThis( 0572 xi18n("Compacts the current database project, so it will take less space and work faster.")); 0573 connect(d->action_tools_compact_database, SIGNAL(triggered()), 0574 this, SLOT(slotToolsCompactDatabase())); 0575 0576 if (d->userMode) 0577 d->action_project_import_data_table = 0; 0578 else { 0579 d->action_project_import_data_table = addAction("project_import_data_table", 0580 KexiIcon("document-empty"), 0581 /*! @todo: change to "file_import" with a table or so */ 0582 xi18nc("Import->Table Data From File...", "Import Data From &File...")); 0583 d->action_project_import_data_table->setToolTip(xi18n("Import table data from a file")); 0584 d->action_project_import_data_table->setWhatsThis(xi18n("Imports table data from a file.")); 0585 connect(d->action_project_import_data_table, SIGNAL(triggered()), 0586 this, SLOT(slotProjectImportDataTable())); 0587 } 0588 0589 d->action_project_export_data_table = addAction("project_export_data_table", 0590 KexiIcon("table"), 0591 /*! @todo: change to "file_export" with a table or so */ 0592 xi18nc("Export->Table or Query Data to File...", "Export Data to &File...")); 0593 d->action_project_export_data_table->setToolTip( 0594 xi18n("Export data from the active table or query to a file")); 0595 d->action_project_export_data_table->setWhatsThis( 0596 xi18n("Exports data from the active table or query to a file.")); 0597 connect(d->action_project_export_data_table, SIGNAL(triggered()), 0598 this, SLOT(slotProjectExportDataTable())); 0599 0600 //! @todo new QAction(xi18n("From File..."), "document-open", 0, 0601 //! this, SLOT(slotImportFile()), actionCollection(), "project_import_file"); 0602 //! @todo new QAction(xi18n("From Server..."), "network-server-database", 0, 0603 //! this, SLOT(slotImportServer()), actionCollection(), "project_import_server"); 0604 0605 #ifdef KEXI_SHOW_UNIMPLEMENTED 0606 ac->addAction("project_print", 0607 d->action_project_print = KStandardAction::print(this, SLOT(slotProjectPrint()), this)); 0608 d->action_project_print->setToolTip(futureI18n("Print data from the active table or query")); 0609 d->action_project_print->setWhatsThis(futureI18n("Prints data from the active table or query.")); 0610 0611 ac->addAction("project_print_preview", 0612 d->action_project_print_preview = KStandardAction::printPreview( 0613 this, SLOT(slotProjectPrintPreview()), this)); 0614 d->action_project_print_preview->setToolTip( 0615 futureI18n("Show print preview for the active table or query")); 0616 d->action_project_print_preview->setWhatsThis( 0617 futureI18n("Shows print preview for the active table or query.")); 0618 0619 d->action_project_print_setup = addAction("project_print_setup", 0620 koIcon("configure"), futureI18n("Print Set&up...")); //!< @todo document-page-setup could be a better icon 0621 d->action_project_print_setup->setToolTip( 0622 futureI18n("Show print setup for the active table or query")); 0623 d->action_project_print_setup->setWhatsThis( 0624 futureI18n("Shows print setup for the active table or query.")); 0625 connect(d->action_project_print_setup, SIGNAL(triggered()), 0626 this, SLOT(slotProjectPageSetup())); 0627 #else 0628 d->action_project_print = d->dummy_action; 0629 d->action_project_print_preview = d->dummy_action; 0630 d->action_project_print_setup = d->dummy_action; 0631 #endif 0632 0633 //EDIT MENU 0634 d->action_edit_cut = createSharedAction(KStandardAction::Cut); 0635 d->action_edit_copy = createSharedAction(KStandardAction::Copy); 0636 d->action_edit_paste = createSharedAction(KStandardAction::Paste); 0637 0638 if (d->userMode) 0639 d->action_edit_paste_special_data_table = 0; 0640 else { 0641 d->action_edit_paste_special_data_table = addAction( 0642 "edit_paste_special_data_table", 0643 d->action_edit_paste->icon(), xi18nc("Paste Special->As Data &Table...", "Paste Special...")); 0644 d->action_edit_paste_special_data_table->setToolTip( 0645 xi18n("Paste clipboard data as a table")); 0646 d->action_edit_paste_special_data_table->setWhatsThis( 0647 xi18n("Pastes clipboard data as a table.")); 0648 connect(d->action_edit_paste_special_data_table, SIGNAL(triggered()), 0649 this, SLOT(slotEditPasteSpecialDataTable())); 0650 } 0651 0652 d->action_edit_copy_special_data_table = addAction( 0653 "edit_copy_special_data_table", 0654 KexiIcon("table"), xi18nc("Copy Special->Table or Query Data...", "Copy Special...")); 0655 d->action_edit_copy_special_data_table->setToolTip( 0656 xi18n("Copy selected table or query data to clipboard")); 0657 d->action_edit_copy_special_data_table->setWhatsThis( 0658 xi18n("Copies selected table or query data to clipboard.")); 0659 connect(d->action_edit_copy_special_data_table, SIGNAL(triggered()), 0660 this, SLOT(slotEditCopySpecialDataTable())); 0661 0662 d->action_edit_undo = createSharedAction(KStandardAction::Undo); 0663 d->action_edit_undo->setWhatsThis(xi18n("Reverts the most recent editing action.")); 0664 d->action_edit_redo = createSharedAction(KStandardAction::Redo); 0665 d->action_edit_redo->setWhatsThis(xi18n("Reverts the most recent undo action.")); 0666 0667 ac->addAction("edit_find", 0668 d->action_edit_find = KStandardAction::find( 0669 this, SLOT(slotEditFind()), this)); 0670 d->action_edit_find->setToolTip(xi18n("Find text")); 0671 d->action_edit_find->setWhatsThis(xi18n("Looks up the first occurrence of a piece of text.")); 0672 ac->addAction("edit_findnext", 0673 d->action_edit_findnext = KStandardAction::findNext( 0674 this, SLOT(slotEditFindNext()), this)); 0675 ac->addAction("edit_findprevious", 0676 d->action_edit_findprev = KStandardAction::findPrev( 0677 this, SLOT(slotEditFindPrevious()), this)); 0678 ac->addAction("edit_replace", 0679 d->action_edit_replace = KStandardAction::replace( 0680 this, SLOT(slotEditReplace()), this)); 0681 d->action_edit_replace_all = addAction("edit_replace_all", xi18n("Replace All")); 0682 0683 d->action_edit_select_all = createSharedAction(KStandardAction::SelectAll); 0684 0685 d->action_edit_delete = createSharedAction(xi18n("&Delete"), koIconName("edit-delete"), 0686 QKeySequence(), "edit_delete"); 0687 d->action_edit_delete->setToolTip(xi18n("Delete selected object")); 0688 d->action_edit_delete->setWhatsThis(xi18n("Deletes currently selected object.")); 0689 0690 d->action_edit_delete_row = createSharedAction(xi18n("Delete Record"), KexiIconName("edit-table-delete-row"), 0691 QKeySequence(Qt::CTRL + Qt::Key_Delete), "edit_delete_row"); 0692 d->action_edit_delete_row->setToolTip(xi18n("Delete the current record")); 0693 d->action_edit_delete_row->setWhatsThis(xi18n("Deletes the current record.")); 0694 0695 d->action_edit_clear_table = createSharedAction(xi18n("Clear Table Contents..."), 0696 KexiIconName("edit-table-clear"), QKeySequence(), "edit_clear_table"); 0697 d->action_edit_clear_table->setToolTip(xi18n("Clear table contents")); 0698 d->action_edit_clear_table->setWhatsThis(xi18n("Clears table contents.")); 0699 setActionVolatile(d->action_edit_clear_table, true); 0700 0701 d->action_edit_edititem = createSharedAction(xi18n("Edit Item"), QString(), 0702 QKeySequence(), /* CONFLICT in TV: Qt::Key_F2, */ 0703 "edit_edititem"); 0704 d->action_edit_edititem->setToolTip(xi18n("Edit currently selected item")); 0705 d->action_edit_edititem->setWhatsThis(xi18n("Edits currently selected item.")); 0706 0707 d->action_edit_insert_empty_row = createSharedAction(xi18n("&Insert Empty Row"), 0708 KexiIconName("edit-table-insert-row"), QKeySequence(Qt::SHIFT | Qt::CTRL | Qt::Key_Insert), 0709 "edit_insert_empty_row"); 0710 setActionVolatile(d->action_edit_insert_empty_row, true); 0711 d->action_edit_insert_empty_row->setToolTip(xi18n("Insert one empty row above")); 0712 d->action_edit_insert_empty_row->setWhatsThis( 0713 xi18n("Inserts one empty row above currently selected table row.")); 0714 0715 //VIEW MENU 0716 /* UNUSED, see KexiToggleViewModeAction 0717 if (!d->userMode) { 0718 d->action_view_mode = new QActionGroup(this); 0719 ac->addAction( "view_data_mode", 0720 d->action_view_data_mode = new KToggleAction( 0721 KexiIcon("data-view"), xi18n("&Data View"), d->action_view_mode) ); 0722 // d->action_view_data_mode->setObjectName("view_data_mode"); 0723 d->action_view_data_mode->setShortcut(QKeySequence("F6")); 0724 //d->action_view_data_mode->setExclusiveGroup("view_mode"); 0725 d->action_view_data_mode->setToolTip(xi18n("Switch to data view")); 0726 d->action_view_data_mode->setWhatsThis(xi18n("Switches to data view.")); 0727 d->actions_for_view_modes.insert( Kexi::DataViewMode, d->action_view_data_mode ); 0728 connect(d->action_view_data_mode, SIGNAL(triggered()), 0729 this, SLOT(slotViewDataMode())); 0730 } 0731 else { 0732 d->action_view_mode = 0; 0733 d->action_view_data_mode = 0; 0734 } 0735 0736 if (!d->userMode) { 0737 ac->addAction( "view_design_mode", 0738 d->action_view_design_mode = new KToggleAction( 0739 KexiIcon("design-view"), xi18n("D&esign View"), d->action_view_mode) ); 0740 // d->action_view_design_mode->setObjectName("view_design_mode"); 0741 d->action_view_design_mode->setShortcut(QKeySequence("F7")); 0742 //d->action_view_design_mode->setExclusiveGroup("view_mode"); 0743 d->action_view_design_mode->setToolTip(xi18n("Switch to design view")); 0744 d->action_view_design_mode->setWhatsThis(xi18n("Switches to design view.")); 0745 d->actions_for_view_modes.insert( Kexi::DesignViewMode, d->action_view_design_mode ); 0746 connect(d->action_view_design_mode, SIGNAL(triggered()), 0747 this, SLOT(slotViewDesignMode())); 0748 } 0749 else 0750 d->action_view_design_mode = 0; 0751 0752 if (!d->userMode) { 0753 ac->addAction( "view_text_mode", 0754 d->action_view_text_mode = new KToggleAction( 0755 KexiIcon("sql-view"), xi18n("&Text View"), d->action_view_mode) ); 0756 d->action_view_text_mode->setObjectName("view_text_mode"); 0757 d->action_view_text_mode->setShortcut(QKeySequence("F8")); 0758 //d->action_view_text_mode->setExclusiveGroup("view_mode"); 0759 d->action_view_text_mode->setToolTip(xi18n("Switch to text view")); 0760 d->action_view_text_mode->setWhatsThis(xi18n("Switches to text view.")); 0761 d->actions_for_view_modes.insert( Kexi::TextViewMode, d->action_view_text_mode ); 0762 connect(d->action_view_text_mode, SIGNAL(triggered()), 0763 this, SLOT(slotViewTextMode())); 0764 } 0765 else 0766 d->action_view_text_mode = 0; 0767 */ 0768 if (d->isProjectNavigatorVisible) { 0769 ac->addAction("view_navigator", 0770 d->action_show_nav = new KToggleAction(xi18n("Show Project Navigator"), this)); 0771 d->action_show_nav->setChecked(true); 0772 d->action_show_nav->setShortcut(QKeySequence("Alt+0")); 0773 d->action_show_nav->setToolTip(xi18n("Show the Project Navigator pane")); 0774 d->action_show_nav->setWhatsThis(xi18n("Shows the Project Navigator pane.")); 0775 connect(d->action_show_nav, SIGNAL(triggered()), 0776 this, SLOT(slotToggleProjectNavigator())); 0777 } else { 0778 d->action_show_nav = 0; 0779 } 0780 0781 if (d->isProjectNavigatorVisible) { 0782 // Shortcut taken from "Activate Projects pane" https://doc.qt.io/qtcreator/creator-keyboard-shortcuts.html 0783 d->action_activate_nav = addAction("activate_navigator", 0784 xi18n("Activate Project Navigator"), 0785 "Alt+X"); 0786 d->action_activate_nav->setToolTip(xi18n("Activate the Project Navigator pane")); 0787 d->action_activate_nav->setWhatsThis(xi18n("Activates the Project Navigator pane. If it is hidden, shows it first.")); 0788 connect(d->action_activate_nav, SIGNAL(triggered()), 0789 this, SLOT(slotActivateNavigator())); 0790 } else { 0791 d->action_activate_nav = 0; 0792 } 0793 0794 d->action_activate_mainarea = addAction("activate_mainarea", 0795 xi18n("Activate main area") 0796 // , "Alt+2"? 0797 //! @todo activate_mainarea: pressing Esc in project nav or propeditor should move back to the main area 0798 ); 0799 d->action_activate_mainarea->setToolTip(xi18n("Activate the main area")); 0800 d->action_activate_mainarea->setWhatsThis(xi18n("Activates the main area.")); 0801 connect(d->action_activate_mainarea, SIGNAL(triggered()), 0802 this, SLOT(slotActivateMainArea())); 0803 0804 //! @todo windows with "_3" prefix have conflicting auto shortcut set to Alt+3 -> remove that! 0805 if (!d->userMode) { 0806 ac->addAction("view_propeditor", 0807 d->action_show_propeditor = new KToggleAction(xi18n("Show Property Pane"), this)); 0808 d->action_show_propeditor->setShortcut(QKeySequence("Alt+3")); 0809 d->action_show_propeditor->setToolTip(xi18n("Show the Property pane")); 0810 d->action_show_propeditor->setWhatsThis(xi18n("Shows the Property pane.")); 0811 connect(d->action_show_propeditor, SIGNAL(triggered()), 0812 this, SLOT(slotTogglePropertyEditor())); 0813 } else { 0814 d->action_show_propeditor = 0; 0815 } 0816 0817 if (!d->userMode) { 0818 d->action_activate_propeditor = addAction("activate_propeditor", 0819 xi18n("Activate Property Pane"), "Alt+-"); 0820 d->action_activate_propeditor->setToolTip(xi18n("Activate the Property pane")); 0821 d->action_activate_propeditor->setWhatsThis(xi18n("Activates the Property pane. If it is hidden, shows it first.")); 0822 connect(d->action_activate_propeditor, SIGNAL(triggered()), 0823 this, SLOT(slotActivatePropertyPane())); 0824 } else { 0825 d->action_activate_propeditor = 0; 0826 } 0827 0828 d->action_tools_locate = addAction("tools_locate", 0829 xi18n("Locate..."), "Ctrl+K"); 0830 d->action_tools_locate->setToolTip(xi18n("Switch to Global Locate box")); 0831 d->action_tools_locate->setWhatsThis(xi18n("Switches to Global Locate box.")); 0832 // (connection is added elsewhere) 0833 0834 //DATA MENU 0835 d->action_data_save_row = createSharedAction(xi18n("&Accept"), koIconName("dialog-ok"), 0836 QKeySequence(Qt::SHIFT + Qt::Key_Return), "data_save_row"); 0837 d->action_data_save_row->setToolTip(xi18n("Accept changes made to the current record")); 0838 d->action_data_save_row->setWhatsThis(xi18n("Accepts changes made to the current record.")); 0839 //temp. disable because of problems with volatile actions setActionVolatile( d->action_data_save_row, true ); 0840 0841 d->action_data_cancel_row_changes = createSharedAction(xi18n("&Cancel"), 0842 koIconName("dialog-cancel"), QKeySequence(Qt::Key_Escape), "data_cancel_row_changes"); 0843 d->action_data_cancel_row_changes->setToolTip( 0844 xi18n("Cancel changes made to the current record")); 0845 d->action_data_cancel_row_changes->setWhatsThis( 0846 xi18n("Cancels changes made to the current record.")); 0847 //temp. disable because of problems with volatile actions setActionVolatile( d->action_data_cancel_row_changes, true ); 0848 0849 d->action_data_execute = createSharedAction( 0850 xi18n("&Execute"), koIconName("media-playback-start"), QKeySequence(), "data_execute"); 0851 //! @todo d->action_data_execute->setToolTip(xi18n("")); 0852 //! @todo d->action_data_execute->setWhatsThis(xi18n("")); 0853 0854 #ifdef KEXI_SHOW_UNIMPLEMENTED 0855 action = createSharedAction(futureI18n("&Filter"), koIconName("view-filter"), QKeySequence(), "data_filter"); 0856 setActionVolatile(action, true); 0857 #endif 0858 //! @todo action->setToolTip(xi18n("")); 0859 //! @todo action->setWhatsThis(xi18n("")); 0860 0861 // - record-navigation related actions 0862 createSharedAction(KexiRecordNavigator::Actions::moveToFirstRecord(), QKeySequence(), "data_go_to_first_record"); 0863 createSharedAction(KexiRecordNavigator::Actions::moveToPreviousRecord(), QKeySequence(), "data_go_to_previous_record"); 0864 createSharedAction(KexiRecordNavigator::Actions::moveToNextRecord(), QKeySequence(), "data_go_to_next_record"); 0865 createSharedAction(KexiRecordNavigator::Actions::moveToLastRecord(), QKeySequence(), "data_go_to_last_record"); 0866 createSharedAction(KexiRecordNavigator::Actions::moveToNewRecord(), QKeySequence(), "data_go_to_new_record"); 0867 0868 //FORMAT MENU 0869 #ifdef KEXI_SHOW_UNIMPLEMENTED 0870 d->action_format_font = createSharedAction(xi18n("&Font..."), koIconName("fonts-package"), 0871 QKeySequence(), "format_font"); 0872 d->action_format_font->setToolTip(xi18n("Change font for selected object")); 0873 d->action_format_font->setWhatsThis(xi18n("Changes font for selected object.")); 0874 #else 0875 d->action_format_font = d->dummy_action; 0876 #endif 0877 0878 //TOOLS MENU 0879 0880 //WINDOW MENU 0881 // additional 'Window' menu items 0882 d->action_window_next = addAction("window_next", xi18n("&Next Window"), "Alt+Right"); 0883 d->action_window_next->setToolTip(xi18n("Next window")); 0884 d->action_window_next->setWhatsThis(xi18n("Switches to the next window.")); 0885 connect(d->action_window_next, SIGNAL(triggered()), this, SLOT(activateNextWindow())); 0886 0887 d->action_window_previous = addAction("window_previous", xi18n("&Previous Window"), "Alt+Left"); 0888 d->action_window_previous->setToolTip(xi18n("Previous window")); 0889 d->action_window_previous->setWhatsThis(xi18n("Switches to the previous window.")); 0890 connect(d->action_window_previous, SIGNAL(triggered()), this, SLOT(activatePreviousWindow())); 0891 0892 d->action_close_tab = addAction("close_tab", koIcon("tab-close"), xi18n("&Close Tab"), "Ctrl+W"); 0893 d->action_close_tab->setToolTip(xi18n("Close the current tab")); 0894 d->action_close_tab->setWhatsThis(xi18n("Closes the current tab.")); 0895 connect(d->action_close_tab, SIGNAL(triggered()), this, SLOT(closeCurrentWindow())); 0896 0897 d->action_close_all_tabs = addAction("close_all_tabs", QIcon(), xi18n("Cl&ose All Tabs")); 0898 d->action_close_all_tabs->setToolTip(xi18n("Close all tabs")); 0899 d->action_close_all_tabs->setWhatsThis(xi18n("Closes all tabs.")); 0900 connect(d->action_close_all_tabs, SIGNAL(triggered()), this, SLOT(closeAllWindows())); 0901 0902 d->action_tab_next = addAction("tab_next", koIcon("go-next"), 0903 KStandardShortcut::label(KStandardShortcut::TabNext)); 0904 d->action_tab_next->setWhatsThis(KStandardShortcut::whatsThis(KStandardShortcut::TabNext)); 0905 d->action_tab_next->setShortcuts(KStandardShortcut::shortcut(KStandardShortcut::TabNext)); 0906 connect(d->action_tab_next, &QAction::triggered, this, &KexiMainWindow::activateNextTab); 0907 0908 d->action_tab_previous = addAction("tab_previous", koIcon("go-previous"), 0909 KStandardShortcut::label(KStandardShortcut::TabPrev)); 0910 d->action_tab_previous->setWhatsThis(KStandardShortcut::whatsThis(KStandardShortcut::TabPrev)); 0911 d->action_tab_previous->setShortcuts(KStandardShortcut::shortcut(KStandardShortcut::TabPrev)); 0912 connect(d->action_tab_previous, &QAction::triggered, this, &KexiMainWindow::activatePreviousTab); 0913 0914 d->action_window_fullscreen = KStandardAction::fullScreen(this, SLOT(toggleFullScreen(bool)), this, ac); 0915 ac->addAction("full_screen", d->action_window_fullscreen); 0916 0917 //SETTINGS MENU 0918 //! @todo put 'configure keys' into settings view 0919 0920 #ifdef KEXI_SHOW_UNIMPLEMENTED 0921 //! @todo toolbars configuration will be handled in a special way 0922 #endif 0923 0924 #ifdef KEXI_MACROS_SUPPORT 0925 Kexi::tempShowMacros() = true; 0926 #else 0927 Kexi::tempShowMacros() = false; 0928 #endif 0929 0930 #ifdef KEXI_SCRIPTS_SUPPORT 0931 Kexi::tempShowScripts() = true; 0932 #else 0933 Kexi::tempShowScripts() = false; 0934 #endif 0935 0936 #ifdef KEXI_SHOW_UNIMPLEMENTED 0937 //! @todo implement settings window in a specific way 0938 ac->addAction("settings", 0939 action = d->action_settings = new KexiMenuWidgetAction( 0940 KStandardAction::Preferences, this)); 0941 action->setObjectName("settings"); 0942 //action->setText(futureI18n("Settings...")); 0943 action->setToolTip(futureI18n("Show KEXI settings")); 0944 action->setWhatsThis(futureI18n("Shows KEXI settings.")); 0945 connect(action, SIGNAL(triggered()), this, SLOT(slotSettings())); 0946 setupMainMenuActionShortcut(action); 0947 #else 0948 d->action_settings = d->dummy_action; 0949 #endif 0950 0951 //! @todo reenable 'tip of the day' later 0952 #if 0 0953 KStandardAction::tipOfDay(this, SLOT(slotTipOfTheDayAction()), actionCollection()) 0954 ->setWhatsThis(xi18n("This shows useful tips on the use of this application.")); 0955 #endif 0956 0957 // ----- declare action categories, so form's "assign action to button" 0958 // (and macros in the future) will be able to recognize category 0959 // of actions and filter them ----------------------------------- 0960 //! @todo shouldn't we move this to core? 0961 Kexi::ActionCategories *acat = Kexi::actionCategories(); 0962 acat->addAction("data_execute", Kexi::PartItemActionCategory); 0963 0964 //! @todo unused for now 0965 acat->addWindowAction("data_filter", 0966 KexiPart::TableObjectType, KexiPart::QueryObjectType, KexiPart::FormObjectType); 0967 0968 acat->addWindowAction("data_save_row", 0969 KexiPart::TableObjectType, KexiPart::QueryObjectType, KexiPart::FormObjectType); 0970 0971 acat->addWindowAction("data_cancel_row_changes", 0972 KexiPart::TableObjectType, KexiPart::QueryObjectType, KexiPart::FormObjectType); 0973 0974 acat->addWindowAction("delete_table_row", 0975 KexiPart::TableObjectType, KexiPart::QueryObjectType, KexiPart::FormObjectType); 0976 0977 //! @todo support this in KexiPart::FormObjectType as well 0978 acat->addWindowAction("data_sort_az", 0979 KexiPart::TableObjectType, KexiPart::QueryObjectType); 0980 0981 //! @todo support this in KexiPart::FormObjectType as well 0982 acat->addWindowAction("data_sort_za", 0983 KexiPart::TableObjectType, KexiPart::QueryObjectType); 0984 0985 //! @todo support this in KexiPart::FormObjectType as well 0986 acat->addWindowAction("edit_clear_table", 0987 KexiPart::TableObjectType, KexiPart::QueryObjectType); 0988 0989 //! @todo support this in KexiPart::FormObjectType as well 0990 acat->addWindowAction("edit_copy_special_data_table", 0991 KexiPart::TableObjectType, KexiPart::QueryObjectType); 0992 0993 //! @todo support this in FormObjectType as well 0994 acat->addWindowAction("project_export_data_table", 0995 KexiPart::TableObjectType, KexiPart::QueryObjectType); 0996 0997 // GlobalActions, etc. 0998 acat->addAction("edit_copy", Kexi::GlobalActionCategory | Kexi::PartItemActionCategory); 0999 1000 acat->addAction("edit_cut", Kexi::GlobalActionCategory | Kexi::PartItemActionCategory); 1001 1002 acat->addAction("edit_paste", Kexi::GlobalActionCategory | Kexi::PartItemActionCategory); 1003 1004 acat->addAction("edit_delete", Kexi::GlobalActionCategory | Kexi::PartItemActionCategory | Kexi::WindowActionCategory, 1005 KexiPart::TableObjectType, KexiPart::QueryObjectType, KexiPart::FormObjectType); 1006 1007 acat->addAction("edit_delete_row", Kexi::GlobalActionCategory | Kexi::WindowActionCategory, 1008 KexiPart::TableObjectType, KexiPart::QueryObjectType, KexiPart::FormObjectType); 1009 1010 acat->addAction("edit_edititem", Kexi::PartItemActionCategory | Kexi::WindowActionCategory, 1011 KexiPart::TableObjectType, KexiPart::QueryObjectType); 1012 1013 acat->addAction("edit_find", Kexi::GlobalActionCategory | Kexi::WindowActionCategory, 1014 KexiPart::TableObjectType, KexiPart::QueryObjectType, KexiPart::FormObjectType); 1015 1016 acat->addAction("edit_findnext", Kexi::GlobalActionCategory | Kexi::WindowActionCategory, 1017 KexiPart::TableObjectType, KexiPart::QueryObjectType, KexiPart::FormObjectType); 1018 1019 acat->addAction("edit_findprevious", Kexi::GlobalActionCategory | Kexi::WindowActionCategory, 1020 KexiPart::TableObjectType, KexiPart::QueryObjectType, KexiPart::FormObjectType); 1021 1022 acat->addAction("edit_replace", Kexi::GlobalActionCategory | Kexi::WindowActionCategory, 1023 KexiPart::TableObjectType, KexiPart::QueryObjectType, KexiPart::FormObjectType); 1024 1025 acat->addAction("edit_paste_special_data_table", Kexi::GlobalActionCategory); 1026 1027 acat->addAction("help_about_app", Kexi::GlobalActionCategory); 1028 1029 acat->addAction("help_about_kde", Kexi::GlobalActionCategory); 1030 1031 acat->addAction("help_contents", Kexi::GlobalActionCategory); 1032 1033 acat->addAction("help_report_bug", Kexi::GlobalActionCategory); 1034 1035 acat->addAction("help_whats_this", Kexi::GlobalActionCategory); 1036 1037 acat->addAction("help_donate", Kexi::GlobalActionCategory); // disabled for now 1038 1039 acat->addAction("switch_application_language", Kexi::GlobalActionCategory); 1040 1041 acat->addAction("options_configure_keybinding", Kexi::GlobalActionCategory); 1042 1043 acat->addAction("project_close", Kexi::GlobalActionCategory); 1044 1045 acat->addAction("project_import_data_table", Kexi::GlobalActionCategory); 1046 1047 acat->addAction("project_new", Kexi::GlobalActionCategory); 1048 1049 acat->addAction("project_open", Kexi::GlobalActionCategory); 1050 1051 #ifdef KEXI_QUICK_PRINTING_SUPPORT 1052 //! @todo support this in FormObjectType, ReportObjectType as well as others 1053 acat->addAction("project_print", Kexi::WindowActionCategory, 1054 KexiPart::TableObjectType, KexiPart::QueryObjectType); 1055 1056 //! @todo support this in FormObjectType, ReportObjectType as well as others 1057 acat->addAction("project_print_preview", Kexi::WindowActionCategory, 1058 KexiPart::TableObjectType, KexiPart::QueryObjectType); 1059 1060 //! @todo support this in FormObjectType, ReportObjectType as well as others 1061 acat->addAction("project_print_setup", Kexi::WindowActionCategory, 1062 KexiPart::TableObjectType, KexiPart::QueryObjectType); 1063 #endif 1064 1065 acat->addAction("quit", Kexi::GlobalActionCategory); 1066 1067 acat->addAction("tools_compact_database", Kexi::GlobalActionCategory); 1068 1069 acat->addAction("tools_import_project", Kexi::GlobalActionCategory); 1070 1071 acat->addAction("tools_import_tables", Kexi::GlobalActionCategory); 1072 1073 acat->addAction("view_data_mode", Kexi::GlobalActionCategory); 1074 1075 acat->addAction("view_design_mode", Kexi::GlobalActionCategory); 1076 1077 acat->addAction("view_text_mode", Kexi::GlobalActionCategory); 1078 1079 acat->addAction("view_mainarea", Kexi::GlobalActionCategory); 1080 1081 acat->addAction("view_navigator", Kexi::GlobalActionCategory); 1082 1083 acat->addAction("activate_navigator", Kexi::GlobalActionCategory); 1084 1085 acat->addAction("view_propeditor", Kexi::GlobalActionCategory); 1086 1087 acat->addAction("activate_mainarea", Kexi::GlobalActionCategory); 1088 1089 acat->addAction("activate_propeditor", Kexi::GlobalActionCategory); 1090 1091 acat->addAction("close_tab", Kexi::GlobalActionCategory | Kexi::WindowActionCategory); 1092 acat->setAllObjectTypesSupported("close_tab", true); 1093 1094 acat->addAction("close_all_tabs", Kexi::GlobalActionCategory | Kexi::WindowActionCategory); 1095 acat->setAllObjectTypesSupported("close_all_tabs", true); 1096 1097 acat->addAction("tab_next", Kexi::GlobalActionCategory); 1098 1099 acat->addAction("tab_previous", Kexi::GlobalActionCategory); 1100 1101 acat->addAction("full_screen", Kexi::GlobalActionCategory); 1102 1103 //skipped - design view only 1104 acat->addAction("format_font", Kexi::NoActionCategory); 1105 acat->addAction("project_save", Kexi::NoActionCategory); 1106 acat->addAction("edit_insert_empty_row", Kexi::NoActionCategory); 1107 //! @todo support this in KexiPart::TableObjectType, KexiPart::QueryObjectType later 1108 acat->addAction("edit_select_all", Kexi::NoActionCategory); 1109 //! @todo support this in KexiPart::TableObjectType, KexiPart::QueryObjectType, KexiPart::FormObjectType later 1110 acat->addAction("edit_redo", Kexi::NoActionCategory); 1111 //! @todo support this in KexiPart::TableObjectType, KexiPart::QueryObjectType, KexiPart::FormObjectType later 1112 acat->addAction("edit_undo", Kexi::NoActionCategory); 1113 1114 //record-navigation related actions 1115 acat->addAction("data_go_to_first_record", Kexi::WindowActionCategory, 1116 KexiPart::TableObjectType, KexiPart::QueryObjectType, KexiPart::FormObjectType); 1117 acat->addAction("data_go_to_previous_record", Kexi::WindowActionCategory, 1118 KexiPart::TableObjectType, KexiPart::QueryObjectType, KexiPart::FormObjectType); 1119 acat->addAction("data_go_to_next_record", Kexi::WindowActionCategory, 1120 KexiPart::TableObjectType, KexiPart::QueryObjectType, KexiPart::FormObjectType); 1121 acat->addAction("data_go_to_last_record", Kexi::WindowActionCategory, 1122 KexiPart::TableObjectType, KexiPart::QueryObjectType, KexiPart::FormObjectType); 1123 acat->addAction("data_go_to_new_record", Kexi::WindowActionCategory, 1124 KexiPart::TableObjectType, KexiPart::QueryObjectType, KexiPart::FormObjectType); 1125 1126 //skipped - internal: 1127 acat->addAction("tablepart_create", Kexi::NoActionCategory); 1128 acat->addAction("querypart_create", Kexi::NoActionCategory); 1129 acat->addAction("formpart_create", Kexi::NoActionCategory); 1130 acat->addAction("reportpart_create", Kexi::NoActionCategory); 1131 acat->addAction("macropart_create", Kexi::NoActionCategory); 1132 acat->addAction("scriptpart_create", Kexi::NoActionCategory); 1133 } 1134 1135 void KexiMainWindow::setupMainMenu() 1136 { 1137 KActionCollection *ac = actionCollection(); 1138 QMenuBar *menu = menuBar(); 1139 { 1140 QMenu *fileMenu = menu->addMenu(xi18n("&File")); 1141 if (!d->userMode) { 1142 d->addAction(fileMenu, "project_new"); 1143 fileMenu->addSeparator(); 1144 d->addAction(fileMenu, "project_open"); 1145 d->addAction(fileMenu, "project_open_recent"); 1146 fileMenu->addSeparator(); 1147 } 1148 fileMenu->addAction(d->action_save); 1149 if (!d->userMode) { 1150 fileMenu->addAction(d->action_save_as); 1151 } 1152 fileMenu->addSeparator(); 1153 if (!d->userMode) { 1154 fileMenu->addAction(d->action_tools_import_project); 1155 fileMenu->addSeparator(); 1156 } 1157 #ifdef KEXI_SHOW_UNIMPLEMENTED 1158 fileMenu->addAction(d->action_project_print); 1159 fileMenu->addAction(d->action_project_print_preview); 1160 fileMenu->addAction(d->action_project_print_setup); 1161 fileMenu->addSeparator(); 1162 #endif 1163 #ifdef KEXI_SHOW_UNIMPLEMENTED 1164 fileMenu->addAction(d->action_project_properties); 1165 fileMenu->addSeparator(); 1166 #endif 1167 fileMenu->addAction(d->action_close_tab); 1168 fileMenu->addAction(d->action_close_all_tabs); 1169 if (!d->userMode) { 1170 fileMenu->addAction(d->action_close); 1171 } 1172 fileMenu->addSeparator(); 1173 d->addAction(fileMenu, "quit"); 1174 } 1175 { 1176 QMenu *editMenu = menu->addMenu(xi18n("&Edit")); 1177 editMenu->addAction(d->action_edit_undo); 1178 editMenu->addAction(d->action_edit_redo); 1179 editMenu->addSeparator(); 1180 editMenu->addAction(d->action_edit_cut); 1181 editMenu->addAction(d->action_edit_copy); 1182 editMenu->addAction(d->action_edit_copy_special_data_table); 1183 editMenu->addAction(d->action_edit_paste); 1184 if (!d->userMode) { 1185 editMenu->addAction(d->action_edit_paste_special_data_table); 1186 } 1187 editMenu->addSeparator(); 1188 editMenu->addAction(d->action_edit_select_all); 1189 editMenu->addSeparator(); 1190 { 1191 QMenu *findReplaceMenu = editMenu->addMenu(xi18n("&Find/Replace")); 1192 findReplaceMenu->addAction(d->action_edit_find); 1193 findReplaceMenu->addAction(d->action_edit_findnext); 1194 findReplaceMenu->addAction(d->action_edit_findprev); 1195 #ifdef KEXI_SHOW_UNIMPLEMENTED 1196 findReplaceMenu->addSeparator(); 1197 findReplaceMenu->addAction(d->action_edit_replace); 1198 findReplaceMenu->addAction(d->action_edit_replace_all); 1199 #endif 1200 } 1201 editMenu->addSeparator(); 1202 editMenu->addAction(d->action_edit_delete); 1203 // in local toolbar already: editMenu->addAction(d->action_data_save_row); 1204 // in local toolbar already: editMenu->addAction(d->action_data_cancel_row_changes); 1205 //TODO move to local menu: editMenu->addAction(d->action_edit_edititem); 1206 //TODO move to local menu: editMenu->addAction(d->action_edit_insert_empty_row); 1207 //TODO move to local menu: editMenu->addAction(d->action_data_execute); 1208 //editMenu->addSeparator(); 1209 //TODO move to local menu: editMenu->addAction(d->action_edit_delete); 1210 //TODO move to local menu: editMenu->addAction(d->action_edit_delete_row); 1211 //in local menu already editMenu->addAction(d->action_edit_clear_table); 1212 } 1213 #ifdef KEXI_SHOW_UNIMPLEMENTED 1214 { 1215 QMenu *formatMenu = menu->addMenu(xi18n("F&ormat")); 1216 formatMenu->addAction(d->action_format_font); 1217 } 1218 #endif 1219 { 1220 QMenu *dataMenu = menu->addMenu(xi18n("&Data")); 1221 if (!d->userMode) { 1222 dataMenu->addAction(d->action_project_import_data_table); 1223 dataMenu->addAction(d->action_tools_data_import); 1224 dataMenu->addSeparator(); 1225 } 1226 dataMenu->addAction(d->action_project_export_data_table); 1227 } 1228 { 1229 QMenu *toolsMenu = menu->addMenu(xi18n("&Tools")); 1230 toolsMenu->addAction(d->action_tools_locate); 1231 toolsMenu->addSeparator(); 1232 #ifdef KEXI_SHOW_UNIMPLEMENTED 1233 toolsMenu->addAction(d->action_project_relations); 1234 #endif 1235 toolsMenu->addAction(d->action_tools_compact_database); 1236 } 1237 { 1238 QMenu *settingsMenu = menu->addMenu(xi18n("&Settings")); 1239 settingsMenu->addAction(d->action_window_fullscreen); 1240 settingsMenu->addSeparator(); 1241 #ifdef KEXI_SHOW_UNIMPLEMENTED 1242 settingsMenu->addAction(d->action_settings); 1243 #endif 1244 } 1245 { 1246 QMenu *windowMenu = menu->addMenu(xi18n("&Window")); 1247 windowMenu->addAction(d->action_tab_next); 1248 windowMenu->addAction(d->action_tab_previous); 1249 windowMenu->addSeparator(); 1250 windowMenu->addAction(d->action_show_nav); 1251 windowMenu->addAction(d->action_show_propeditor); 1252 } 1253 { 1254 // add help menu actions... (KexiTabbedToolBar depends on them) 1255 KHelpMenu *helpMenu = new KHelpMenu(this, KAboutData::applicationData(), 1256 true/*showWhatsThis*/); 1257 QAction* help_report_bug_action = helpMenu->action(KHelpMenu::menuReportBug); 1258 ac->addAction(help_report_bug_action->objectName(), help_report_bug_action); 1259 QObject::disconnect(help_report_bug_action, 0, 0, 0); 1260 QObject::connect(help_report_bug_action, &QAction::triggered, this, &KexiMainWindow::slotReportBug); 1261 help_report_bug_action->setText(xi18nc("Report a bug or wish for KEXI application", "Report a &Bug or Wish...")); 1262 help_report_bug_action->setIcon(koIcon("tools-report-bug")); // good icon for toolbar 1263 help_report_bug_action->setWhatsThis(xi18n("Files a bug or wish for KEXI application.")); 1264 QAction* help_whats_this_action = helpMenu->action(KHelpMenu::menuWhatsThis); 1265 ac->addAction(help_whats_this_action->objectName(), help_whats_this_action); 1266 help_whats_this_action->setWhatsThis(xi18n("Activates a \"What's This?\" tool.")); 1267 QAction* help_contents_action = helpMenu->action(KHelpMenu::menuHelpContents); 1268 ac->addAction(help_contents_action->objectName(), help_contents_action); 1269 help_contents_action->setText(xi18n("Help")); 1270 help_contents_action->setWhatsThis(xi18n("Shows KEXI Handbook.")); 1271 QAction* help_about_app_action = helpMenu->action(KHelpMenu::menuAboutApp); 1272 ac->addAction(help_about_app_action->objectName(), help_about_app_action); 1273 help_about_app_action->setWhatsThis(xi18n("Shows information about KEXI application.")); 1274 QAction* help_about_kde_action = helpMenu->action(KHelpMenu::menuAboutKDE); 1275 ac->addAction(help_about_kde_action->objectName(), help_about_kde_action); 1276 help_about_kde_action->setWhatsThis(xi18n("Shows information about KDE.")); 1277 menu->addMenu(helpMenu->menu()); 1278 } 1279 } 1280 1281 void KexiMainWindow::invalidateActions() 1282 { 1283 invalidateProjectWideActions(); 1284 invalidateSharedActions(); 1285 } 1286 1287 void KexiMainWindow::invalidateSharedActions(QObject *o) 1288 { 1289 //! @todo enabling is more complex... 1290 /* d->action_edit_cut->setEnabled(true); 1291 d->action_edit_copy->setEnabled(true); 1292 d->action_edit_paste->setEnabled(true);*/ 1293 1294 if (!o) 1295 o = focusWindow(); 1296 KexiSharedActionHost::invalidateSharedActions(o); 1297 } 1298 1299 void KexiMainWindow::invalidateSharedActions() 1300 { 1301 invalidateSharedActions(0); 1302 } 1303 1304 // unused, I think 1305 void KexiMainWindow::invalidateSharedActionsLater() 1306 { 1307 QTimer::singleShot(1, this, SLOT(invalidateSharedActions())); 1308 } 1309 1310 void KexiMainWindow::invalidateProjectWideActions() 1311 { 1312 const bool has_window = currentWindow(); 1313 const bool window_dirty = currentWindow() && currentWindow()->isDirty(); 1314 const bool readOnly = d->prj && d->prj->dbConnection() && d->prj->dbConnection()->options()->isReadOnly(); 1315 1316 //PROJECT MENU 1317 d->action_save->setEnabled(has_window && window_dirty && !readOnly); 1318 d->action_save_as->setEnabled(has_window && !readOnly); 1319 d->action_project_properties->setEnabled(d->prj); 1320 d->action_close->setEnabled(d->prj); 1321 d->action_project_relations->setEnabled(d->prj); 1322 if (d->objectViewWidget) { 1323 d->action_close_tab->setEnabled(has_window); 1324 d->action_close_all_tabs->setEnabled(has_window); 1325 } 1326 1327 //DATA MENU 1328 if (d->action_project_import_data_table) 1329 d->action_project_import_data_table->setEnabled(d->prj && !readOnly); 1330 if (d->action_tools_data_import) 1331 d->action_tools_data_import->setEnabled(d->prj && !readOnly); 1332 d->action_project_export_data_table->setEnabled( 1333 currentWindow() && currentWindow()->part()->info()->isDataExportSupported()); 1334 if (d->action_edit_paste_special_data_table) 1335 d->action_edit_paste_special_data_table->setEnabled(d->prj && !readOnly); 1336 1337 #ifdef KEXI_SHOW_UNIMPLEMENTED 1338 const bool printingActionsEnabled = 1339 currentWindow() && currentWindow()->part()->info()->isPrintingSupported() 1340 && !currentWindow()->neverSaved(); 1341 d->action_project_print->setEnabled(printingActionsEnabled); 1342 d->action_project_print_preview->setEnabled(printingActionsEnabled); 1343 d->action_project_print_setup->setEnabled(printingActionsEnabled); 1344 #endif 1345 1346 //EDIT MENU 1347 //! @todo "copy special" is currently enabled only for data view mode; 1348 //! what about allowing it to enable in design view for "kexi/table" ? 1349 if (currentWindow() && currentWindow()->currentViewMode() == Kexi::DataViewMode) { 1350 KexiPart::Info *activePartInfo = currentWindow()->part()->info(); 1351 d->action_edit_copy_special_data_table->setEnabled( 1352 activePartInfo ? activePartInfo->isDataExportSupported() : false); 1353 } else { 1354 d->action_edit_copy_special_data_table->setEnabled(false); 1355 } 1356 d->action_edit_find->setEnabled(d->prj); 1357 1358 //VIEW MENU 1359 if (d->action_show_nav) 1360 d->action_show_nav->setEnabled(d->prj); 1361 d->action_activate_mainarea->setEnabled(d->prj); 1362 1363 //CREATE MENU 1364 if (d->tabbedToolBar && d->tabbedToolBar->createWidgetToolBar()) 1365 d->tabbedToolBar->createWidgetToolBar()->setEnabled(d->prj); 1366 1367 // DATA MENU 1368 1369 // WINDOW MENU 1370 if (d->objectViewWidget) { 1371 d->action_tab_next->setEnabled(d->objectViewWidget->tabWidget()->count() > 1); 1372 d->action_tab_previous->setEnabled(d->objectViewWidget->tabWidget()->count() > 1); 1373 } 1374 1375 //TOOLS MENU 1376 // "compact db" supported if there's no db or the current db supports compacting and is opened r/w: 1377 d->action_tools_compact_database->setEnabled( 1378 //! @todo Support compacting of non-opened projects 1379 /*!d->prj 1380 ||*/ (!readOnly && d->prj && d->prj->dbConnection() 1381 && (d->prj->dbConnection()->driver()->features() & KDbDriver::CompactingDatabaseSupported)) 1382 ); 1383 1384 //DOCKS 1385 if (d->objectViewWidget && d->objectViewWidget->projectNavigator()) { 1386 d->objectViewWidget->projectNavigator()->setEnabled(d->prj); 1387 } 1388 if (d->objectViewWidget && d->objectViewWidget->propertyPane()) { 1389 d->objectViewWidget->propertyPane()->setEnabled(d->prj); 1390 } 1391 } 1392 1393 tristate KexiMainWindow::startup() 1394 { 1395 tristate result = true; 1396 switch (KexiStartupHandler::global()->action()) { 1397 case KexiStartupHandler::CreateBlankProject: 1398 d->updatePropEditorVisibility(Kexi::NoViewMode); 1399 break; 1400 #ifdef KEXI_PROJECT_TEMPLATES 1401 case KexiStartupHandler::CreateFromTemplate: 1402 result = createProjectFromTemplate(*KexiStartupHandler::global()->projectData()); 1403 break; 1404 #endif 1405 case KexiStartupHandler::OpenProject: 1406 result = openProject(*KexiStartupHandler::global()->projectData()); 1407 break; 1408 case KexiStartupHandler::ImportProject: 1409 result = showProjectMigrationWizard( 1410 KexiStartupHandler::global()->importActionData().mimeType, 1411 KexiStartupHandler::global()->importActionData().fileName 1412 ); 1413 break; 1414 case KexiStartupHandler::ShowWelcomeScreen: 1415 //! @todo show welcome screen as soon as is available 1416 QTimer::singleShot(100, this, SLOT(slotProjectWelcome())); 1417 break; 1418 default: 1419 d->updatePropEditorVisibility(Kexi::NoViewMode); 1420 } 1421 return result; 1422 } 1423 1424 static QString internalReason(const KDbResult &result) 1425 { 1426 const QString msg = result.message(); 1427 if (msg.isEmpty()) { 1428 return QString(); 1429 } 1430 return xi18n("<br/>(reason: <i>%1</i>)", msg); 1431 } 1432 1433 tristate KexiMainWindow::openProject(const KexiProjectData& projectData) 1434 { 1435 //qDebug() << projectData; 1436 QScopedPointer<KexiProject> prj(createKexiProjectObject(projectData)); 1437 if (~KexiDBPasswordDialog::getPasswordIfNeeded(prj->data()->connectionData(), this)) { 1438 return cancelled; 1439 } 1440 bool incompatibleWithKexi; 1441 tristate res = prj->open(&incompatibleWithKexi); 1442 1443 if (prj->data()->connectionData()->isPasswordNeeded()) { 1444 // password was supplied in this session, and shouldn't be stored or reused afterwards, 1445 // so let's remove it 1446 prj->data()->connectionData()->setPassword(QString()); 1447 } 1448 1449 if (~res) { 1450 return cancelled; 1451 } 1452 else if (!res) { 1453 if (incompatibleWithKexi) { 1454 if (KMessageBox::Yes == KMessageBox::questionYesNo(this, 1455 xi18nc("@info (don't add tags around %1, it's done already)", 1456 "Database project %1 does not appear to have been created using " 1457 "<application>%2</application>.<nl/>" 1458 "Do you want to import it as a new KEXI project?", 1459 projectData.infoString(), QApplication::applicationDisplayName()), 1460 QString(), KGuiItem(xi18nc("@action:button Import Database", "&Import..."), KexiIconName("database-import")), 1461 KStandardGuiItem::cancel())) 1462 { 1463 const bool anotherProjectAlreadyOpened = prj; 1464 tristate res = showProjectMigrationWizard("application/x-kexi-connectiondata", 1465 projectData.databaseName(), *projectData.connectionData()); 1466 1467 if (!anotherProjectAlreadyOpened) //the project could have been opened within this instance 1468 return res; 1469 1470 //always return cancelled because even if migration succeeded, new Kexi instance 1471 //will be started if user wanted to open the imported db 1472 return cancelled; 1473 } 1474 return cancelled; 1475 } 1476 return false; 1477 } 1478 1479 // success 1480 d->prj = prj.take(); 1481 d->modeSelector->setCurrentMode(Kexi::EditGlobalMode); 1482 d->prj->data()->setLastOpened(QDateTime::currentDateTime()); 1483 Kexi::recentProjects()->addProjectData(*d->prj->data()); 1484 updateReadOnlyState(); 1485 invalidateActions(); 1486 setMessagesEnabled(false); 1487 1488 QTimer::singleShot(1, this, SLOT(slotAutoOpenObjectsLater())); 1489 if (d->tabbedToolBar) { 1490 d->tabbedToolBar->showTab("create");// not needed since create toolbar already shows toolbar! move when kexi starts 1491 d->tabbedToolBar->hideTab("form");//temporalily until createToolbar is split 1492 d->tabbedToolBar->hideTab("report");//temporalily until createToolbar is split 1493 1494 // make sure any tab is activated 1495 d->tabbedToolBar->setCurrentTab(0); 1496 } 1497 return true; 1498 } 1499 1500 tristate KexiMainWindow::openProject(const KexiProjectData& data, const QString& shortcutPath, 1501 bool *opened) 1502 { 1503 if (!shortcutPath.isEmpty() && d->prj) { 1504 const tristate result = openProjectInExternalKexiInstance( 1505 shortcutPath, QString(), QString()); 1506 if (result == true) { 1507 *opened = true; 1508 } 1509 return result; 1510 } 1511 return openProject(data); 1512 } 1513 1514 tristate KexiMainWindow::createProjectFromTemplate(const KexiProjectData& projectData) 1515 { 1516 Q_UNUSED(projectData); 1517 #ifdef KEXI_PROJECT_TEMPLATES 1518 QStringList mimetypes; 1519 mimetypes.append(KDb::defaultFileBasedDriverMimeType()); 1520 QString fname; 1521 //! @todo KEXI3 add equivalent of kfiledialog:/// 1522 const QString startDir("kfiledialog:///OpenExistingOrCreateNewProject"/*as in KexiNewProjectWizard*/); 1523 const QString caption(xi18nc("@window:title", "Select New Project's Location")); 1524 1525 while (true) { 1526 if (fname.isEmpty() && 1527 !projectData.connectionData()->databaseName().isEmpty()) { 1528 //propose filename from db template name 1529 fname = projectData.connectionData()->databaseName(); 1530 } 1531 const bool specialDir = fname.isEmpty(); 1532 qDebug() << fname << "............."; 1533 QFileDialog dlg(specialDir ? QUrl(startDir) : QUrl(), 1534 QString(), this); 1535 dlg.setModal(true); 1536 dlg.setMimeFilter(mimetypes); 1537 if (!specialDir) 1538 dlg.selectUrl(QUrl::fromLocalFile(fname); // may also be a filename 1539 dlg.setFileMode(QFileDialog::ExistingFile); 1540 dlg.setFileMode(QFileDialog::AcceptOpen); 1541 dlg.setWindowTitle(caption); 1542 if (QDialog::Accepted != dlg.exec()) { 1543 return cancelled; 1544 } 1545 if (dlg.selectedFiles().isEmpty()) { 1546 return cancelled; 1547 } 1548 fname = dlg.selectedFiles().first(); 1549 if (fname.isEmpty()) { 1550 return cancelled; 1551 } 1552 if (KexiUtils::askForFileOverwriting(fname, this)) { 1553 break; 1554 } 1555 } 1556 1557 QFile sourceFile(projectData.connectionData()->fileName()); 1558 if (!sourceFile.copy(fname)) { 1559 //! @todo show error from with QFile::FileError 1560 return false; 1561 } 1562 1563 return openProject(fname, 0, QString(), projectData.autoopenObjects/*copy*/); 1564 #else 1565 return false; 1566 #endif 1567 } 1568 1569 void KexiMainWindow::updateReadOnlyState() 1570 { 1571 const bool readOnly = d->prj && d->prj->dbConnection() && d->prj->dbConnection()->options()->isReadOnly(); 1572 //! @todo KEXI3 show read-only flag in the GUI because we have no statusbar 1573 if (d->objectViewWidget && d->objectViewWidget->projectNavigator()) { 1574 d->objectViewWidget->projectNavigator()->setReadOnly(readOnly); 1575 } 1576 1577 // update "insert ....." actions for every part 1578 KexiPart::PartInfoList *plist = Kexi::partManager().infoList(); 1579 if (plist) { 1580 foreach(KexiPart::Info *info, *plist) { 1581 QAction *a = info->newObjectAction(); 1582 if (a) 1583 a->setEnabled(!readOnly); 1584 } 1585 } 1586 } 1587 1588 void KexiMainWindow::slotAutoOpenObjectsLater() 1589 { 1590 QString not_found_msg; 1591 bool openingCancelled; 1592 //ok, now open "autoopen: objects 1593 if (d->prj) { 1594 for (const KexiProjectData::ObjectInfo &info : d->prj->data()->autoopenObjects) { 1595 KexiPart::Info *i = Kexi::partManager().infoForPluginId(info.value("type")); 1596 if (!i) { 1597 not_found_msg += "<li>"; 1598 if (!info.value("name").isEmpty()) { 1599 not_found_msg += (QString("\"") + info.value("name") + "\" - "); 1600 } 1601 if (info.value("action") == "new") { 1602 not_found_msg += xi18n("cannot create object - unknown object type \"%1\"", 1603 info.value("type")); 1604 } else { 1605 not_found_msg += xi18n("unknown object type \"%1\"", info.value("type")); 1606 } 1607 not_found_msg += internalReason(Kexi::partManager().result()) + "<br></li>"; 1608 continue; 1609 } 1610 // * NEW 1611 if (info.value("action") == "new") { 1612 if (!newObject(i, &openingCancelled) && !openingCancelled) { 1613 not_found_msg += "<li>"; 1614 not_found_msg 1615 += (xi18n("cannot create object of type \"%1\"", info.value("type")) 1616 + internalReason(d->prj->result()) + "<br></li>"); 1617 } else { 1618 d->wasAutoOpen = true; 1619 } 1620 continue; 1621 } 1622 1623 KexiPart::Item *item = d->prj->item(i, info.value("name")); 1624 if (!item) { 1625 QString taskName; 1626 if (info.value("action") == "execute") { 1627 taskName = xi18nc("\"executing object\" action", "executing"); 1628 #ifdef KEXI_QUICK_PRINTING_SUPPORT 1629 } else if (info->value("action") == "print-preview") { 1630 taskName = futureI18n("making print preview for"); 1631 } else if (info->value("action") == "print") { 1632 taskName = futureI18n("printing"); 1633 #endif 1634 } else { 1635 taskName = xi18n("opening"); 1636 } 1637 1638 not_found_msg += (QString("<li>") + taskName + " \"" + info.value("name") + "\" - "); 1639 if ("table" == info.value("type").toLower()) { 1640 not_found_msg += xi18n("table not found"); 1641 } else if ("query" == info.value("type").toLower()) { 1642 not_found_msg += xi18n("query not found"); 1643 } else if ("macro" == info.value("type").toLower()) { 1644 not_found_msg += xi18n("macro not found"); 1645 } else if ("script" == info.value("type").toLower()) { 1646 not_found_msg += xi18n("script not found"); 1647 } else { 1648 not_found_msg += xi18n("object not found"); 1649 } 1650 not_found_msg += (internalReason(d->prj->result()) + "<br></li>"); 1651 continue; 1652 } 1653 // * EXECUTE, PRINT, PRINT PREVIEW 1654 if (info.value("action") == "execute") { 1655 tristate res = executeItem(item); 1656 if (false == res) { 1657 not_found_msg += (QString("<li>\"") + info.value("name") + "\" - " 1658 + xi18n("cannot execute object") 1659 + internalReason(d->prj->result()) + "<br></li>"); 1660 } 1661 continue; 1662 } 1663 #ifdef KEXI_QUICK_PRINTING_SUPPORT 1664 else if (info.value("action") == "print") { 1665 tristate res = printItem(item); 1666 if (false == res) { 1667 not_found_msg += (QString("<li>\"") + info.value("name") + "\" - " + futureI18n("cannot print object") + 1668 internalReason(d->prj->result()) + "<br></li>"); 1669 } 1670 continue; 1671 } 1672 else if (info.value("action") == "print-preview") { 1673 tristate res = printPreviewForItem(item); 1674 if (false == res) { 1675 not_found_msg += (QString("<li>\"") + info.value("name") + "\" - " + futureI18n("cannot make print preview of object") + 1676 internalReason(d->prj->result()) + "<br></li>"); 1677 } 1678 continue; 1679 } 1680 #endif 1681 1682 Kexi::ViewMode viewMode; 1683 if (info.value("action") == "open") { 1684 viewMode = Kexi::DataViewMode; 1685 } else if (info.value("action") == "design") { 1686 viewMode = Kexi::DesignViewMode; 1687 } else if (info.value("action") == "edittext") { 1688 viewMode = Kexi::TextViewMode; 1689 } else { 1690 continue; //sanity 1691 } 1692 1693 QString openObjectMessage; 1694 if (!openObject(item, viewMode, &openingCancelled, 0, &openObjectMessage) 1695 && (!openingCancelled || !openObjectMessage.isEmpty())) 1696 { 1697 not_found_msg += (QString("<li>\"") + info.value("name") + "\" - "); 1698 if (openObjectMessage.isEmpty()) { 1699 not_found_msg += xi18n("cannot open object"); 1700 } else { 1701 not_found_msg += openObjectMessage; 1702 } 1703 not_found_msg += internalReason(d->prj->result()) + "<br></li>"; 1704 continue; 1705 } else { 1706 d->wasAutoOpen = true; 1707 } 1708 } 1709 } 1710 setMessagesEnabled(true); 1711 1712 if (!not_found_msg.isEmpty()) { 1713 showErrorMessage(xi18n("You have requested selected objects to be automatically opened " 1714 "or processed on startup. Several objects cannot be opened or processed."), 1715 QString("<ul>%1</ul>").arg(not_found_msg)); 1716 } 1717 d->updatePropEditorVisibility(currentWindow() ? currentWindow()->currentViewMode() : Kexi::NoViewMode); 1718 #if defined(KDOCKWIDGET_P) 1719 if (d->propEditor) { 1720 KDockWidget *dw = (KDockWidget *)d->propEditorTabWidget->parentWidget(); 1721 KDockSplitter *ds = (KDockSplitter *)dw->parentWidget(); 1722 if (ds) 1723 ds->setSeparatorPosInPercent(d->config->readEntry("RightDockPosition", 80/* % */)); 1724 } 1725 #endif 1726 1727 updateAppCaption(); 1728 if (d->tabbedToolBar) { 1729 d->tabbedToolBar->hideMainMenu(); 1730 } 1731 1732 qApp->processEvents(); 1733 emit projectOpened(); 1734 } 1735 1736 tristate KexiMainWindow::closeProject() 1737 { 1738 if (d->tabbedToolBar) 1739 d->tabbedToolBar->hideMainMenu(); 1740 1741 #ifndef KEXI_NO_PENDING_DIALOGS 1742 if (d->pendingWindowsExist()) { 1743 qDebug() << "pendingWindowsExist..."; 1744 d->actionToExecuteWhenPendingJobsAreFinished = Private::CloseProjectAction; 1745 return cancelled; 1746 } 1747 #endif 1748 1749 //only save nav. visibility setting if there is project opened 1750 d->saveSettingsForShowProjectNavigator = d->prj && d->isProjectNavigatorVisible; 1751 1752 if (!d->prj) 1753 return true; 1754 1755 { 1756 // make sure the project can be closed 1757 bool cancel = false; 1758 emit acceptProjectClosingRequested(&cancel); 1759 if (cancel) 1760 return cancelled; 1761 } 1762 1763 d->windowExistedBeforeCloseProject = currentWindow(); 1764 1765 #if defined(KDOCKWIDGET_P) 1766 //remember docks position - will be used on storeSettings() 1767 if (d->propEditor) { 1768 KDockWidget *dw = (KDockWidget *)d->propEditorTabWidget->parentWidget(); 1769 KDockSplitter *ds = (KDockSplitter *)dw->parentWidget(); 1770 if (ds) 1771 d->propEditorDockSeparatorPos = ds->separatorPosInPercent(); 1772 } 1773 if (d->nav) { 1774 if (d->propEditor) { 1775 //! @todo KEXI3 if (d->openedWindowsCount() == 0) 1776 //! @todo KEXI3 makeWidgetDockVisible(d->propEditorTabWidget); 1777 KDockWidget *dw = (KDockWidget *)d->propEditorTabWidget->parentWidget(); 1778 KDockSplitter *ds = (KDockSplitter *)dw->parentWidget(); 1779 if (ds) 1780 ds->setSeparatorPosInPercent(80); 1781 } 1782 1783 KDockWidget *dw = (KDockWidget *)d->nav->parentWidget(); 1784 KDockSplitter *ds = (KDockSplitter *)dw->parentWidget(); 1785 int dwWidth = dw->width(); 1786 if (ds) { 1787 if (d->openedWindowsCount() != 0 && d->propEditorTabWidget && d->propEditorTabWidget->isVisible()) { 1788 d->navDockSeparatorPos = ds->separatorPosInPercent(); 1789 } 1790 else { 1791 d->navDockSeparatorPos = (100 * dwWidth) / width(); 1792 } 1793 } 1794 } 1795 #endif 1796 1797 //close each window, optionally asking if user wants to close (if data changed) 1798 while (currentWindow()) { 1799 tristate res = closeWindow(currentWindow()); 1800 if (!res || ~res) 1801 return res; 1802 } 1803 1804 // now we will close for sure 1805 emit beforeProjectClosing(); 1806 1807 if (!d->prj->closeConnection()) 1808 return false; 1809 1810 if (d->objectViewWidget && d->objectViewWidget->projectNavigator()) { 1811 d->navWasVisibleBeforeProjectClosing = d->objectViewWidget->projectNavigator()->isVisible(); 1812 d->setProjectNavigatorVisible(false); 1813 d->objectViewWidget->projectNavigator()->setProject(0); 1814 //slotProjectNavigatorVisibilityChanged(true); // hide side tab 1815 } 1816 1817 if (d->objectViewWidget && d->objectViewWidget->propertyPane()) { 1818 d->objectViewWidget->propertyPane()->hide(); 1819 d->action_show_propeditor->setChecked(false); 1820 } 1821 d->clearWindows(); //sanity! 1822 delete d->prj; 1823 d->prj = 0; 1824 1825 updateReadOnlyState(); 1826 invalidateActions(); 1827 updateAppCaption(); 1828 if (d->userMode) { 1829 d->modeSelector->setCurrentMode(Kexi::WelcomeGlobalMode); 1830 } 1831 1832 emit projectClosed(); 1833 return true; 1834 } 1835 1836 void KexiMainWindow::setupContextHelp() 1837 { 1838 #ifdef KEXI_SHOW_CONTEXT_HELP 1839 d->ctxHelp = new KexiContextHelp(d->mainWidget, this); 1840 //! @todo 1841 /* 1842 d->ctxHelp->setContextHelp(xi18n("Welcome"),xi18n("The <B>KEXI team</B> wishes you a lot of productive work, " 1843 "with this product. <BR><HR><BR>If you have found a <B>bug</B> or have a <B>feature</B> request, please don't " 1844 "hesitate to report it at our <A href=\"http://www.kexi-project.org/cgi-bin/bug.pl\"> issue " 1845 "tracking system </A>.<BR><HR><BR>If you would like to <B>join</B> our effort, the <B>development</B> documentation " 1846 "at <A href=\"http://www.kexi-project.org\">www.kexi-project.org</A> is a good starting point."),0); 1847 */ 1848 addToolWindow(d->ctxHelp, KDockWidget::DockBottom | KDockWidget::DockLeft, getMainDockWidget(), 20); 1849 #endif 1850 } 1851 1852 void KexiMainWindow::setupMainWidget() 1853 { 1854 QWidget *centralWidget = new QWidget; 1855 setCentralWidget(centralWidget); 1856 1857 QVBoxLayout *vlyr = new QVBoxLayout(centralWidget); 1858 vlyr->setContentsMargins(0, 0, 0, 0); 1859 vlyr->setSpacing(0); 1860 1861 if (d->isMainMenuVisible) { 1862 QWidget *tabbedToolBarContainer = new QWidget(this); 1863 vlyr->addWidget(tabbedToolBarContainer); 1864 QVBoxLayout *tabbedToolBarContainerLyr = new QVBoxLayout(tabbedToolBarContainer); 1865 tabbedToolBarContainerLyr->setSpacing(0); 1866 tabbedToolBarContainerLyr->setContentsMargins( 1867 KexiUtils::marginHint() / 2, KexiUtils::marginHint() / 2, 1868 KexiUtils::marginHint() / 2, KexiUtils::marginHint() / 2); 1869 1870 d->tabbedToolBar = new KexiTabbedToolBar(tabbedToolBarContainer); 1871 Q_ASSERT(d->action_tools_locate); 1872 connect(d->action_tools_locate, SIGNAL(triggered()), 1873 d->tabbedToolBar, SLOT(activateSearchLineEdit())); 1874 tabbedToolBarContainerLyr->addWidget(d->tabbedToolBar); 1875 d->tabbedToolBar->hideTab("form"); //temporarily until createToolbar is split 1876 d->tabbedToolBar->hideTab("report"); //temporarily until createToolbar is split 1877 } 1878 else { 1879 d->tabbedToolBar = 0; 1880 } 1881 1882 QWidget *mainWidgetContainer = new QWidget(); 1883 vlyr->addWidget(mainWidgetContainer, 1); 1884 QHBoxLayout *mainWidgetContainerLyr = new QHBoxLayout(mainWidgetContainer); 1885 mainWidgetContainerLyr->setContentsMargins(0, 0, 0, 0); 1886 mainWidgetContainerLyr->setSpacing(0); 1887 1888 d->modeSelector = new KexiGlobalViewModeSelector; 1889 connect(d->modeSelector, &KexiGlobalViewModeSelector::currentModeChanged, 1890 this, &KexiMainWindow::slotCurrentModeChanged); 1891 mainWidgetContainerLyr->addWidget(d->modeSelector); 1892 if (d->userMode) { 1893 d->modeSelector->hide(); 1894 } 1895 1896 d->globalViewStack = new QStackedWidget; 1897 mainWidgetContainerLyr->addWidget(d->globalViewStack, 1); 1898 } 1899 1900 //void KexiMainWindow::slotSetProjectNavigatorVisible(bool set) 1901 //{ 1902 // if (d->navDockWidget) 1903 // d->navDockWidget->setVisible(set); 1904 //} 1905 1906 //void KexiMainWindow::slotSetPropertyEditorVisible(bool set) 1907 //{ 1908 // if (d->propEditorDockWidget) 1909 // d->propEditorDockWidget->setVisible(set); 1910 //} 1911 1912 //void KexiMainWindow::slotProjectNavigatorVisibilityChanged(bool visible) 1913 //{ 1914 // d->setTabBarVisible(KMultiTabBar::Left, PROJECT_NAVIGATOR_TABBAR_ID, 1915 // d->navDockWidget, !visible); 1916 //} 1917 1918 //void KexiMainWindow::slotPropertyEditorVisibilityChanged(bool visible) 1919 //{ 1920 // if (!d->enable_slotPropertyEditorVisibilityChanged) 1921 // return; 1922 // d->setPropertyEditorTabBarVisible(!visible); 1923 // if (!visible) 1924 // d->propertyEditorCollapsed = true; 1925 //} 1926 1927 /* 1928 void KexiMainWindow::slotMultiTabBarTabClicked(int id) 1929 { 1930 if (id == PROJECT_NAVIGATOR_TABBAR_ID) { 1931 slotProjectNavigatorVisibilityChanged(true); 1932 d->navDockWidget->show(); 1933 } 1934 else if (id == PROPERTY_EDITOR_TABBAR_ID) { 1935 slotPropertyEditorVisibilityChanged(true); 1936 d->propEditorDockWidget->show(); 1937 d->propertyEditorCollapsed = false; 1938 } 1939 } 1940 1941 static Qt::DockWidgetArea applyRightToLeftToDockArea(Qt::DockWidgetArea area) 1942 { 1943 if (QApplication::layoutDirection() == Qt::RightToLeft) { 1944 if (area == Qt::LeftDockWidgetArea) { 1945 return Qt::RightDockWidgetArea; 1946 } 1947 else if (area == Qt::RightDockWidgetArea) { 1948 return Qt::LeftDockWidgetArea; 1949 } 1950 } 1951 return area; 1952 }*/ 1953 1954 void KexiMainWindow::setupObjectView() 1955 { 1956 if (d->objectViewWidget) { 1957 return; 1958 } 1959 KexiObjectViewWidget::Flags flags; 1960 if (d->isProjectNavigatorVisible) { 1961 flags |= KexiObjectViewWidget::ProjectNavigatorEnabled; 1962 } 1963 if (!d->userMode) { 1964 flags |= KexiObjectViewWidget::PropertyPaneEnabled; 1965 } 1966 d->objectViewWidget = new KexiObjectViewWidget(flags); 1967 connect(d->objectViewWidget, &KexiObjectViewWidget::activeWindowChanged, 1968 this, &KexiMainWindow::activeWindowChanged); 1969 connect(d->objectViewWidget, &KexiObjectViewWidget::closeWindowRequested, 1970 this, &KexiMainWindow::closeWindowForTab); 1971 connect(d->objectViewWidget, &KexiObjectViewWidget::closeAllWindowsRequested, 1972 this, &KexiMainWindow::closeAllWindows); 1973 connect(d->objectViewWidget, &KexiObjectViewWidget::projectNavigatorAnimationFinished, 1974 this, &KexiMainWindow::slotProjectNavigatorVisibilityChanged); 1975 slotProjectNavigatorVisibilityChanged(d->objectViewWidget->projectNavigator()); 1976 1977 // Restore settings 1978 //! @todo FIX LAYOUT PROBLEMS 1979 KConfigGroup propertyEditorGroup(d->config->group("PropertyEditor")); 1980 QFont f(KexiStyle::propertyPane().font()); 1981 const qreal pointSizeF = propertyEditorGroup.readEntry("FontPointSize", -1.0f); // points are more accurate 1982 if (pointSizeF > 0.0) { 1983 f.setPointSizeF(pointSizeF); 1984 } else { 1985 const int pixelSize = propertyEditorGroup.readEntry("FontSize", -1); // compatibility with Kexi 2.x 1986 if (pixelSize > 0) { 1987 f.setPixelSize(pixelSize); 1988 } 1989 } 1990 if (d->objectViewWidget->propertyPane()) { 1991 d->objectViewWidget->propertyPane()->setFont(f); 1992 1993 KConfigGroup mainWindowGroup(d->config->group("MainWindow")); 1994 const QSize projectNavigatorSize = mainWindowGroup.readEntry<QSize>("ProjectNavigatorSize", QSize()); 1995 const QSize propertyEditorSize = mainWindowGroup.readEntry<QSize>("PropertyEditorSize", QSize()); 1996 d->objectViewWidget->setSidebarWidths(projectNavigatorSize.isValid() ? projectNavigatorSize.width() : -1, 1997 propertyEditorSize.isValid() ? propertyEditorSize.width() : -1); 1998 } 1999 2000 d->globalViewStack->addWidget(d->objectViewWidget); 2001 KexiProjectNavigator* navigator = d->objectViewWidget->projectNavigator(); 2002 if (navigator) { 2003 //connect(d->navDockWidget, SIGNAL(visibilityChanged(bool)), 2004 // this, SLOT(slotProjectNavigatorVisibilityChanged(bool))); 2005 2006 //Nav2 Signals 2007 connect(navigator, SIGNAL(openItem(KexiPart::Item*,Kexi::ViewMode)), 2008 this, SLOT(openObject(KexiPart::Item*,Kexi::ViewMode))); 2009 connect(navigator, SIGNAL(openOrActivateItem(KexiPart::Item*,Kexi::ViewMode)), 2010 this, SLOT(openObjectFromNavigator(KexiPart::Item*,Kexi::ViewMode))); 2011 connect(navigator, SIGNAL(newItem(KexiPart::Info*)), 2012 this, SLOT(newObject(KexiPart::Info*))); 2013 connect(navigator, SIGNAL(removeItem(KexiPart::Item*)), 2014 this, SLOT(removeObject(KexiPart::Item*))); 2015 connect(navigator->model(), SIGNAL(renameItem(KexiPart::Item*,QString,bool*)), 2016 this, SLOT(renameObject(KexiPart::Item*,QString,bool*))); 2017 connect(navigator->model(), SIGNAL(changeItemCaption(KexiPart::Item*,QString,bool*)), 2018 this, SLOT(setObjectCaption(KexiPart::Item*,QString,bool*))); 2019 connect(navigator, SIGNAL(executeItem(KexiPart::Item*)), 2020 this, SLOT(executeItem(KexiPart::Item*))); 2021 connect(navigator, SIGNAL(exportItemToClipboardAsDataTable(KexiPart::Item*)), 2022 this, SLOT(copyItemToClipboardAsDataTable(KexiPart::Item*))); 2023 connect(navigator, SIGNAL(exportItemToFileAsDataTable(KexiPart::Item*)), 2024 this, SLOT(exportItemAsDataTable(KexiPart::Item*))); 2025 #ifdef KEXI_QUICK_PRINTING_SUPPORT 2026 connect(navigator, SIGNAL(printItem(KexiPart::Item*)), 2027 this, SLOT(printItem(KexiPart::Item*))); 2028 connect(navigator, SIGNAL(pageSetupForItem(KexiPart::Item*)), 2029 this, SLOT(showPageSetupForItem(KexiPart::Item*))); 2030 #endif 2031 connect(navigator, SIGNAL(selectionChanged(KexiPart::Item*)), 2032 this, SLOT(slotPartItemSelectedInNavigator(KexiPart::Item*))); 2033 } 2034 2035 if (navigator) { 2036 if (d->prj) { 2037 connect(d->prj, SIGNAL(newItemStored(KexiPart::Item*)), 2038 navigator->model(), SLOT(slotAddItem(KexiPart::Item*))); 2039 connect(d->prj, SIGNAL(itemRemoved(KexiPart::Item)), 2040 navigator->model(), SLOT(slotRemoveItem(KexiPart::Item))); 2041 navigator->setFocus(); 2042 } 2043 2044 /*if (d->forceShowProjectNavigatorOnCreation) { 2045 slotShowNavigator(); 2046 d->forceShowProjectNavigatorOnCreation = false; 2047 } else if (d->forceHideProjectNavigatorOnCreation) { 2048 d->forceHideProjectNavigatorOnCreation = false; 2049 }*/ 2050 } 2051 2052 invalidateActions(); 2053 } 2054 2055 void KexiMainWindow::updateObjectView() 2056 { 2057 setupObjectView(); 2058 2059 if (d->prj && d->prj->isConnected()) { 2060 KexiProjectNavigator* navigator = d->objectViewWidget->projectNavigator(); 2061 if (navigator && !navigator->model()->project()) { 2062 QString partManagerErrorMessages; 2063 navigator->setProject(d->prj, QString()/*all classes*/, &partManagerErrorMessages); 2064 if (partManagerErrorMessages.isEmpty()) { 2065 d->setProjectNavigatorVisible(true); 2066 } else { 2067 showWarningContinueMessage(partManagerErrorMessages, QString(), 2068 "ShowWarningsRelatedToPluginsLoading"); 2069 } 2070 } 2071 } 2072 } 2073 2074 void KexiMainWindow::slotLastActions() 2075 { 2076 } 2077 2078 void KexiMainWindow::slotPartLoaded(KexiPart::Part* p) 2079 { 2080 if (!p) 2081 return; 2082 p->createGUIClients(); 2083 } 2084 2085 void KexiMainWindow::updateAppCaption() 2086 { 2087 //! @todo allow to set custom "static" app caption 2088 2089 d->appCaptionPrefix.clear(); 2090 if (d->prj && d->prj->data()) {//add project name 2091 d->appCaptionPrefix = d->prj->data()->caption(); 2092 if (d->appCaptionPrefix.isEmpty()) { 2093 d->appCaptionPrefix = d->prj->data()->databaseName(); 2094 } 2095 if (d->prj->dbConnection()->options()->isReadOnly()) { 2096 d->appCaptionPrefix = xi18nc("<project-name> (read only)", "%1 (read only)", d->appCaptionPrefix); 2097 } 2098 } 2099 2100 setWindowTitle(d->appCaptionPrefix); 2101 } 2102 2103 bool KexiMainWindow::queryClose() 2104 { 2105 #ifndef KEXI_NO_PENDING_DIALOGS 2106 if (d->pendingWindowsExist()) { 2107 qDebug() << "pendingWindowsExist..."; 2108 d->actionToExecuteWhenPendingJobsAreFinished = Private::QuitAction; 2109 return false; 2110 } 2111 #endif 2112 const tristate res = closeProject(); 2113 if (~res) 2114 return false; 2115 2116 if (res == true) 2117 storeSettings(); 2118 2119 if (! ~res) { 2120 Kexi::deleteGlobalObjects(); 2121 qApp->quit(); 2122 } 2123 return ! ~res; 2124 } 2125 2126 void KexiMainWindow::closeEvent(QCloseEvent *ev) 2127 { 2128 if (queryClose()) { 2129 ev->accept(); 2130 } else { 2131 ev->ignore(); 2132 } 2133 } 2134 2135 void KexiMainWindow::resizeEvent(QResizeEvent *e) 2136 { 2137 QMainWindow::resizeEvent(e); 2138 //qDebug() << "===" << e->size() << size() << isVisible(); 2139 } 2140 2141 static const QSize KEXI_MIN_WINDOW_SIZE(1024, 768); 2142 2143 void 2144 KexiMainWindow::restoreSettings() 2145 { 2146 KConfigGroup mainWindowGroup(d->config->group("MainWindow")); 2147 const bool maximize = mainWindowGroup.readEntry("Maximized", false); 2148 const QRect geometry(mainWindowGroup.readEntry("Geometry", QRect())); 2149 if (geometry.isValid()) 2150 setGeometry(geometry); 2151 else if (maximize) 2152 setWindowState(windowState() | Qt::WindowMaximized); 2153 else { 2154 QRect desk = QApplication::desktop()->screenGeometry( 2155 QApplication::desktop()->screenNumber(this)); 2156 if (desk.width() <= KEXI_MIN_WINDOW_SIZE.width() 2157 || desk.height() <= KEXI_MIN_WINDOW_SIZE.height()) 2158 { 2159 setWindowState(windowState() | Qt::WindowMaximized); 2160 } else { 2161 resize(KEXI_MIN_WINDOW_SIZE); 2162 } 2163 } 2164 } 2165 2166 void 2167 KexiMainWindow::storeSettings() 2168 { 2169 //qDebug(); 2170 KConfigGroup mainWindowGroup(d->config->group("MainWindow")); 2171 2172 if (isMaximized()) { 2173 mainWindowGroup.writeEntry("Maximized", true); 2174 mainWindowGroup.deleteEntry("Geometry"); 2175 } else { 2176 mainWindowGroup.deleteEntry("Maximized"); 2177 mainWindowGroup.writeEntry("Geometry", geometry()); 2178 } 2179 2180 if (d->objectViewWidget) { 2181 int projectNavigatorWidth; 2182 int propertyEditorWidth; 2183 d->objectViewWidget->getSidebarWidths(&projectNavigatorWidth, &propertyEditorWidth); 2184 if (projectNavigatorWidth > 0) { 2185 mainWindowGroup.writeEntry("ProjectNavigatorSize", QSize(projectNavigatorWidth, 1)); 2186 } 2187 if (propertyEditorWidth > 0) { 2188 mainWindowGroup.writeEntry("PropertyEditorSize", QSize(propertyEditorWidth, 1)); 2189 } 2190 } 2191 d->config->sync(); 2192 } 2193 2194 void 2195 KexiMainWindow::registerChild(KexiWindow *window) 2196 { 2197 //qDebug(); 2198 connect(window, SIGNAL(dirtyChanged(KexiWindow*)), this, SLOT(slotDirtyFlagChanged(KexiWindow*))); 2199 2200 if (window->id() != -1) { 2201 d->insertWindow(window); 2202 } 2203 //qDebug() << "ID=" << window->id(); 2204 } 2205 2206 void KexiMainWindow::updateCustomPropertyPanelTabs(KexiWindow *prevWindow, 2207 Kexi::ViewMode prevViewMode) 2208 { 2209 updateCustomPropertyPanelTabs( 2210 prevWindow ? prevWindow->part() : 0, 2211 prevWindow ? prevWindow->currentViewMode() : prevViewMode, 2212 currentWindow() ? currentWindow()->part() : 0, 2213 currentWindow() ? currentWindow()->currentViewMode() : Kexi::NoViewMode 2214 ); 2215 } 2216 2217 void KexiMainWindow::updateCustomPropertyPanelTabs( 2218 KexiPart::Part *prevWindowPart, Kexi::ViewMode prevViewMode, 2219 KexiPart::Part *curWindowPart, Kexi::ViewMode curViewMode) 2220 { 2221 if (!d->objectViewWidget || !d->objectViewWidget->propertyPane()) 2222 return; 2223 2224 if ( !curWindowPart 2225 || (/*prevWindowPart &&*/ curWindowPart 2226 && (prevWindowPart != curWindowPart || prevViewMode != curViewMode) 2227 ) 2228 ) 2229 { 2230 #ifdef __GNUC__ 2231 #warning TODO KexiMainWindow::updateCustomPropertyPanelTabs() 2232 #else 2233 #pragma WARNING(TODO KexiMainWindow::updateCustomPropertyPanelTabs()) 2234 #endif 2235 #if 0 2236 if (d->partForPreviouslySetupPropertyPanelTabs) { 2237 //remember current page number for this part 2238 if (( prevViewMode == Kexi::DesignViewMode 2239 && static_cast<KexiPart::Part*>(d->partForPreviouslySetupPropertyPanelTabs) != curWindowPart) //part changed 2240 || curViewMode != Kexi::DesignViewMode) 2241 { //..or switching to other view mode 2242 d->recentlySelectedPropertyPanelPages.insert( 2243 d->partForPreviouslySetupPropertyPanelTabs, 2244 d->objectViewWidget->propertyPane()->currentIndex()); 2245 } 2246 } 2247 2248 //delete old custom tabs (other than 'property' tab) 2249 const int count = d->objectViewWidget->propertyEditorTabWidget()->count(); 2250 for (int i = 1; i < count; i++) 2251 d->objectViewWidget->propertyEditorTabWidget()->removeTab(1); 2252 #endif 2253 } 2254 2255 //don't change anything if part is not switched nor view mode changed 2256 if ((!prevWindowPart && !curWindowPart) 2257 || (prevWindowPart == curWindowPart && prevViewMode == curViewMode) 2258 || (curWindowPart && curViewMode != Kexi::DesignViewMode)) 2259 { 2260 //new part for 'previously setup tabs' 2261 d->partForPreviouslySetupPropertyPanelTabs = curWindowPart; 2262 return; 2263 } 2264 2265 if (curWindowPart) { 2266 //recreate custom tabs 2267 d->objectViewWidget->propertyPane()->removeAllSections(); 2268 curWindowPart->setupPropertyPane(d->objectViewWidget->propertyPane()); 2269 2270 #ifdef __GNUC__ 2271 #warning TODO KexiMainWindow::updateCustomPropertyPanelTabs() 2272 #else 2273 #pragma WARNING(TODO KexiMainWindow::updateCustomPropertyPanelTabs()) 2274 #endif 2275 #if 0 2276 //restore current page number for this part 2277 if (d->recentlySelectedPropertyPanelPages.contains(curWindowPart)) { 2278 d->objectViewWidget->propertyEditorTabWidget()->setCurrentIndex( 2279 d->recentlySelectedPropertyPanelPages[ curWindowPart ] 2280 ); 2281 } 2282 #endif 2283 } 2284 //#endif 2285 //new part for 'previously setup tabs' 2286 d->partForPreviouslySetupPropertyPanelTabs = curWindowPart; 2287 } 2288 2289 void KexiMainWindow::activeWindowChanged(KexiWindow *window, KexiWindow *prevWindow) 2290 { 2291 //qDebug() << "to=" << (window ? window->windowTitle() : "<none>"); 2292 bool windowChanged = prevWindow != window; 2293 2294 if (windowChanged) { 2295 if (prevWindow) { 2296 //inform previously activated dialog about deactivation 2297 prevWindow->deactivate(); 2298 } 2299 } 2300 2301 updateCustomPropertyPanelTabs(prevWindow, prevWindow ? prevWindow->currentViewMode() : Kexi::NoViewMode); 2302 2303 // inform the current view of the new dialog about property switching 2304 // (this will also call KexiMainWindow::propertySetSwitched() to update the current property editor's set 2305 if (windowChanged && currentWindow()) 2306 currentWindow()->selectedView()->propertySetSwitched(); 2307 2308 if (windowChanged) { 2309 if (currentWindow() && currentWindow()->currentViewMode() != 0 && window) { 2310 setCurrentMode(viewModeToGlobal(currentWindow()->currentViewMode())); 2311 2312 //on opening new dialog it can be 0; we don't want this 2313 d->updatePropEditorVisibility(currentWindow()->currentViewMode()); 2314 2315 restoreDesignTabIfNeeded(window->partItem()->pluginId(), window->currentViewMode(), 2316 prevWindow ? prevWindow->partItem()->identifier() : 0); 2317 activateDesignTabIfNeeded(window->partItem()->pluginId(), 2318 window->currentViewMode()); 2319 } 2320 } 2321 2322 invalidateActions(); 2323 d->updateFindDialogContents(); 2324 if (window) 2325 window->setFocus(); 2326 } 2327 2328 bool 2329 KexiMainWindow::activateWindow(int id) 2330 { 2331 #ifndef KEXI_NO_PENDING_DIALOGS 2332 Private::PendingJobType pendingType; 2333 return activateWindow(*d->openedWindowFor(id, pendingType)); 2334 #else 2335 return activateWindow(*d->openedWindowFor(id)); 2336 #endif 2337 } 2338 2339 bool 2340 KexiMainWindow::activateWindow(KexiWindow& window) 2341 { 2342 //qDebug(); 2343 2344 d->focus_before_popup = &window; 2345 d->objectViewWidget->tabWidget()->setCurrentWidget(window.parentWidget()/*container*/); 2346 window.activate(); 2347 return true; 2348 } 2349 2350 void KexiMainWindow::activateNextWindow() 2351 { 2352 // Case 1: go to next assistant page 2353 KexiAssistantPage *page = d->visibleMainMenuWidgetPage(); 2354 if (page) { 2355 page->next(); 2356 return; 2357 } 2358 // Case 2: go to next tab 2359 activateNextTab(); 2360 } 2361 2362 void KexiMainWindow::activatePreviousWindow() 2363 { 2364 // Case 1: go to previous assistant page 2365 KexiAssistantPage *page = d->visibleMainMenuWidgetPage(); 2366 if (page) { 2367 page->tryBack(); 2368 return; 2369 } 2370 // Case 2: go to previous tab 2371 activatePreviousTab(); 2372 } 2373 2374 void KexiMainWindow::activateNextTab() 2375 { 2376 int index = d->objectViewWidget->tabWidget()->currentIndex() + 1; 2377 if (index >= d->objectViewWidget->tabWidget()->count()) { 2378 index = 0; 2379 } 2380 d->objectViewWidget->tabWidget()->setCurrentIndex(index); 2381 } 2382 2383 void KexiMainWindow::activatePreviousTab() 2384 { 2385 int index = d->objectViewWidget->tabWidget()->currentIndex() - 1; 2386 if (index < 0) { 2387 index = d->objectViewWidget->tabWidget()->count() - 1; 2388 } 2389 d->objectViewWidget->tabWidget()->setCurrentIndex(index); 2390 } 2391 2392 void 2393 KexiMainWindow::slotSettings() 2394 { 2395 if (d->tabbedToolBar) { 2396 d->tabbedToolBar->showMainMenu("settings"); 2397 // dummy 2398 QLabel *dummy = KEXI_UNFINISHED_LABEL(actionCollection()->action("settings")->text()); 2399 d->tabbedToolBar->setMainMenuContent(dummy); 2400 } 2401 } 2402 2403 void 2404 KexiMainWindow::slotConfigureKeys() 2405 { 2406 KShortcutsDialog::configure(actionCollection(), 2407 KShortcutsEditor::LetterShortcutsDisallowed, this); 2408 } 2409 2410 void 2411 KexiMainWindow::slotConfigureToolbars() 2412 { 2413 KEditToolBar edit(actionCollection()); 2414 (void) edit.exec(); 2415 } 2416 2417 void KexiMainWindow::slotProjectNew() 2418 { 2419 createNewProject(); 2420 } 2421 2422 KexiProject* KexiMainWindow::createKexiProjectObject(const KexiProjectData &data) 2423 { 2424 KexiProject *prj = new KexiProject(data, this); 2425 connect(prj, SIGNAL(itemRenamed(KexiPart::Item,QString)), this, SLOT(slotObjectRenamed(KexiPart::Item,QString))); 2426 2427 if (d->objectViewWidget && d->objectViewWidget->projectNavigator()){ 2428 connect(prj, SIGNAL(itemRemoved(KexiPart::Item)), 2429 d->objectViewWidget->projectNavigator()->model(), 2430 SLOT(slotRemoveItem(KexiPart::Item))); 2431 } 2432 return prj; 2433 } 2434 2435 void KexiMainWindow::createNewProject() 2436 { 2437 if (!d->tabbedToolBar) 2438 return; 2439 d->tabbedToolBar->showMainMenu("project_new"); 2440 KexiNewProjectAssistant* assistant = new KexiNewProjectAssistant; 2441 connect(assistant, SIGNAL(createProject(KexiProjectData)), 2442 this, SLOT(createNewProject(KexiProjectData))); 2443 2444 d->tabbedToolBar->setMainMenuContent(assistant); 2445 } 2446 2447 tristate KexiMainWindow::createNewProject(const KexiProjectData &projectData) 2448 { 2449 QScopedPointer<KexiProject> prj(createKexiProjectObject(projectData)); 2450 tristate res = prj->create(true /*overwrite*/); 2451 if (res != true) { 2452 return res; 2453 } 2454 //qDebug() << "new project created ---"; 2455 if (d->prj) { 2456 res = openProjectInExternalKexiInstance( 2457 prj->data()->connectionData()->databaseName(), 2458 prj->data()->connectionData(), 2459 prj->data()->databaseName()); 2460 Kexi::recentProjects()->addProjectData(*prj->data()); 2461 if (d->tabbedToolBar) { 2462 d->tabbedToolBar->hideMainMenu(); 2463 } 2464 return res; 2465 } 2466 if (d->tabbedToolBar) { 2467 d->tabbedToolBar->hideMainMenu(); 2468 } 2469 d->prj = prj.take(); 2470 d->prj->data()->setLastOpened(QDateTime::currentDateTime()); 2471 Kexi::recentProjects()->addProjectData(*d->prj->data()); 2472 d->modeSelector->setCurrentMode(Kexi::EditGlobalMode); 2473 2474 invalidateActions(); 2475 updateAppCaption(); 2476 return true; 2477 } 2478 2479 void KexiMainWindow::slotProjectOpen() 2480 { 2481 if (!d->tabbedToolBar) 2482 return; 2483 d->tabbedToolBar->showMainMenu("project_open"); 2484 KexiOpenProjectAssistant* assistant = new KexiOpenProjectAssistant; 2485 connect(assistant, SIGNAL(openProject(KexiProjectData)), 2486 this, SLOT(openProject(KexiProjectData))); 2487 connect(assistant, SIGNAL(openProject(QString)), 2488 this, SLOT(openProject(QString))); 2489 d->tabbedToolBar->setMainMenuContent(assistant); 2490 } 2491 2492 tristate KexiMainWindow::openProject(const QString& aFileName) 2493 { 2494 return openProject(aFileName, QString(), QString()); 2495 } 2496 2497 tristate KexiMainWindow::openProject(const QString& aFileName, 2498 const QString& fileNameForConnectionData, const QString& dbName) 2499 { 2500 if (d->prj) 2501 return openProjectInExternalKexiInstance(aFileName, fileNameForConnectionData, dbName); 2502 2503 KDbConnectionData *cdata = 0; 2504 if (!fileNameForConnectionData.isEmpty()) { 2505 cdata = Kexi::connset().connectionDataForFileName(fileNameForConnectionData); 2506 if (!cdata) { 2507 qWarning() << "cdata?"; 2508 return false; 2509 } 2510 } 2511 return openProject(aFileName, cdata, dbName); 2512 } 2513 2514 tristate KexiMainWindow::openProject(const QString& aFileName, 2515 KDbConnectionData *cdata, const QString& dbName, 2516 const KexiProjectData::AutoOpenObjects& autoopenObjects) 2517 { 2518 if (d->prj) { 2519 return openProjectInExternalKexiInstance(aFileName, cdata, dbName); 2520 } 2521 2522 KexiProjectData* projectData = 0; 2523 const KexiStartupHandler *h = KexiStartupHandler::global(); 2524 bool readOnly = h->isSet(h->options().readOnly); 2525 bool deleteAfterOpen = false; 2526 if (cdata) { 2527 //server-based project 2528 if (dbName.isEmpty()) {//no database name given, ask user 2529 bool cancel; 2530 projectData = KexiStartupHandler::global()->selectProject(cdata, &cancel, this); 2531 if (cancel) 2532 return cancelled; 2533 } else { 2534 //! @todo caption arg? 2535 projectData = new KexiProjectData(*cdata, dbName); 2536 deleteAfterOpen = true; 2537 } 2538 } else { 2539 if (aFileName.isEmpty()) { 2540 qWarning() << "aFileName.isEmpty()"; 2541 return false; 2542 } 2543 //file-based project 2544 //qDebug() << "Project File:" << aFileName; 2545 KDbConnectionData fileConnData; 2546 fileConnData.setDatabaseName(aFileName); 2547 QString detectedDriverId; 2548 int detectOptions = 0; 2549 if (readOnly) { 2550 detectOptions |= KexiStartupHandler::OpenReadOnly; 2551 } 2552 KexiStartupData::Import importActionData; 2553 bool forceReadOnly; 2554 const tristate res = KexiStartupHandler::detectActionForFile( 2555 &importActionData, &detectedDriverId, fileConnData.driverId(), 2556 aFileName, this, detectOptions, &forceReadOnly); 2557 if (forceReadOnly) { 2558 readOnly = true; 2559 } 2560 if (true != res) 2561 return res; 2562 2563 if (importActionData) { //importing requested 2564 return showProjectMigrationWizard(importActionData.mimeType, importActionData.fileName); 2565 } 2566 fileConnData.setDriverId(detectedDriverId); 2567 2568 if (fileConnData.driverId().isEmpty()) 2569 return false; 2570 2571 //opening requested 2572 projectData = new KexiProjectData(fileConnData); 2573 deleteAfterOpen = true; 2574 } 2575 if (!projectData) 2576 return false; 2577 projectData->setReadOnly(readOnly); 2578 projectData->autoopenObjects = autoopenObjects; 2579 const tristate res = openProject(*projectData); 2580 if (deleteAfterOpen) //projectData object has been copied 2581 delete projectData; 2582 return res; 2583 } 2584 2585 tristate KexiMainWindow::openProjectInExternalKexiInstance(const QString& aFileName, 2586 KDbConnectionData *cdata, const QString& dbName) 2587 { 2588 QString fileNameForConnectionData; 2589 if (aFileName.isEmpty()) { //try .kexic file 2590 if (cdata) 2591 fileNameForConnectionData = Kexi::connset().fileNameForConnectionData(*cdata); 2592 } 2593 return openProjectInExternalKexiInstance(aFileName, fileNameForConnectionData, dbName); 2594 } 2595 2596 tristate KexiMainWindow::openProjectInExternalKexiInstance(const QString& aFileName, 2597 const QString& fileNameForConnectionData, const QString& dbName) 2598 { 2599 QString fileName(aFileName); 2600 QStringList args; 2601 2602 // open a file-based project or a server connection provided as a .kexic file 2603 // (we have no other simple way to provide the startup data to a new process) 2604 if (fileName.isEmpty()) { //try .kexic file 2605 if (!fileNameForConnectionData.isEmpty()) 2606 args << "--skip-conn-dialog"; //user does not expect conn. dialog to be shown here 2607 2608 if (dbName.isEmpty()) { //use 'kexi --skip-conn-dialog file.kexic' 2609 fileName = fileNameForConnectionData; 2610 } else { //use 'kexi --skip-conn-dialog --connection file.kexic dbName' 2611 if (fileNameForConnectionData.isEmpty()) { 2612 qWarning() << "fileNameForConnectionData?"; 2613 return false; 2614 } 2615 args << "--connection" << fileNameForConnectionData; 2616 fileName = dbName; 2617 } 2618 } 2619 if (fileName.isEmpty()) { 2620 qWarning() << "fileName?"; 2621 return false; 2622 } 2623 //! @todo use KRun 2624 //! @todo untested 2625 //Can arguments be supplied to KRun like is used here? AP 2626 args << fileName; 2627 const bool ok = QProcess::startDetached( 2628 qApp->applicationFilePath(), args, 2629 QFileInfo(fileName).absoluteDir().absolutePath()); 2630 if (!ok) { 2631 d->showStartProcessMsg(args); 2632 } 2633 if (d->tabbedToolBar) { 2634 d->tabbedToolBar->hideMainMenu(); 2635 } 2636 return ok; 2637 } 2638 2639 void KexiMainWindow::slotProjectWelcome() 2640 { 2641 if (!d->tabbedToolBar) 2642 return; 2643 d->tabbedToolBar->showMainMenu("project_welcome"); 2644 KexiWelcomeAssistant* assistant = new KexiWelcomeAssistant( 2645 Kexi::recentProjects(), this); 2646 connect(assistant, SIGNAL(openProject(KexiProjectData,QString,bool*)), 2647 this, SLOT(openProject(KexiProjectData,QString,bool*))); 2648 d->tabbedToolBar->setMainMenuContent(assistant); 2649 } 2650 2651 void 2652 KexiMainWindow::slotProjectSave() 2653 { 2654 if (!currentWindow() || currentWindow()->currentViewMode() == Kexi::DataViewMode) { 2655 return; 2656 } 2657 saveObject(currentWindow()); 2658 updateAppCaption(); 2659 invalidateActions(); 2660 } 2661 2662 void 2663 KexiMainWindow::slotProjectSaveAs() 2664 { 2665 if (!currentWindow() || currentWindow()->currentViewMode() == Kexi::DataViewMode) { 2666 return; 2667 } 2668 saveObject(currentWindow(), QString(), SaveObjectAs); 2669 updateAppCaption(); 2670 invalidateActions(); 2671 } 2672 2673 void 2674 KexiMainWindow::slotProjectPrint() 2675 { 2676 #ifdef KEXI_QUICK_PRINTING_SUPPORT 2677 if (currentWindow() && currentWindow()->partItem()) 2678 printItem(currentWindow()->partItem()); 2679 #endif 2680 } 2681 2682 void 2683 KexiMainWindow::slotProjectPrintPreview() 2684 { 2685 #ifdef KEXI_QUICK_PRINTING_SUPPORT 2686 if (currentWindow() && currentWindow()->partItem()) 2687 printPreviewForItem(currentWindow()->partItem()); 2688 #endif 2689 } 2690 2691 void 2692 KexiMainWindow::slotProjectPageSetup() 2693 { 2694 #ifdef KEXI_QUICK_PRINTING_SUPPORT 2695 if (currentWindow() && currentWindow()->partItem()) 2696 showPageSetupForItem(currentWindow()->partItem()); 2697 #endif 2698 } 2699 2700 void KexiMainWindow::slotProjectExportDataTable() 2701 { 2702 if (currentWindow() && currentWindow()->partItem()) 2703 exportItemAsDataTable(currentWindow()->partItem()); 2704 } 2705 2706 void KexiMainWindow::slotProjectProperties() 2707 { 2708 if (!d->tabbedToolBar) 2709 return; 2710 d->tabbedToolBar->showMainMenu("project_properties"); 2711 // dummy 2712 QLabel *dummy = KEXI_UNFINISHED_LABEL(actionCollection()->action("project_properties")->text()); 2713 d->tabbedToolBar->setMainMenuContent(dummy); 2714 //! @todo load the implementation not the ui :) 2715 // ProjectSettingsUI u(this); 2716 // u.exec(); 2717 } 2718 2719 void KexiMainWindow::slotProjectImportExportOrSend() 2720 { 2721 if (!d->tabbedToolBar) 2722 return; 2723 d->tabbedToolBar->showMainMenu("project_import_export_send"); 2724 KexiImportExportAssistant* assistant = new KexiImportExportAssistant( 2725 d->action_project_import_export_send, 2726 d->action_tools_import_project); 2727 connect(assistant, SIGNAL(importProject()), this, SLOT(slotToolsImportProject())); 2728 d->tabbedToolBar->setMainMenuContent(assistant); 2729 } 2730 2731 void 2732 KexiMainWindow::slotProjectClose() 2733 { 2734 closeProject(); 2735 } 2736 2737 void KexiMainWindow::slotProjectRelations() 2738 { 2739 if (!d->prj) 2740 return; 2741 KexiWindow *w = KexiInternalPart::createKexiWindowInstance("org.kexi-project.relations", this); 2742 if (w) { 2743 activateWindow(*w); 2744 } 2745 } 2746 2747 void KexiMainWindow::slotImportFile() 2748 { 2749 KEXI_UNFINISHED("Import: " + xi18n("From File...")); 2750 } 2751 2752 void KexiMainWindow::slotImportServer() 2753 { 2754 KEXI_UNFINISHED("Import: " + xi18n("From Server...")); 2755 } 2756 2757 void 2758 KexiMainWindow::slotProjectQuit() 2759 { 2760 if (~ closeProject()) 2761 return; 2762 close(); 2763 } 2764 2765 void KexiMainWindow::slotActivateNavigator() 2766 { 2767 if (!d->objectViewWidget || !d->objectViewWidget->projectNavigator()) { 2768 return; 2769 } 2770 d->objectViewWidget->projectNavigator()->setFocus(); 2771 } 2772 2773 void KexiMainWindow::slotActivateMainArea() 2774 { 2775 if (currentWindow()) 2776 currentWindow()->setFocus(); 2777 } 2778 2779 void KexiMainWindow::slotActivatePropertyPane() 2780 { 2781 if (!d->objectViewWidget || !d->objectViewWidget->propertyPane()) { 2782 return; 2783 } 2784 2785 d->objectViewWidget->propertyPane()->setFocus(); 2786 // if (d->objectViewWidget->propertyPane()->currentWidget()) { 2787 // d->objectViewWidget->propertyPane()->currentWidget()->setFocus(); 2788 // } 2789 } 2790 2791 void KexiMainWindow::slotToggleProjectNavigator() 2792 { 2793 if (d->objectViewWidget && d->objectViewWidget->projectNavigator()) { 2794 d->setProjectNavigatorVisible(!d->objectViewWidget->projectNavigator()->isVisible(), Private::ShowAnimated); 2795 } 2796 } 2797 2798 void KexiMainWindow::slotTogglePropertyEditor() 2799 { 2800 if (d->objectViewWidget && d->objectViewWidget->propertyPane()) { 2801 d->objectViewWidget->setPropertyPaneVisible(!d->objectViewWidget->propertyPane()->isVisible()); 2802 } 2803 } 2804 2805 tristate KexiMainWindow::switchToViewMode(KexiWindow& window, Kexi::ViewMode viewMode) 2806 { 2807 const Kexi::ViewMode prevViewMode = currentWindow()->currentViewMode(); 2808 if (prevViewMode == viewMode) 2809 return true; 2810 if (!activateWindow(window)) 2811 return false; 2812 if (!currentWindow()) { 2813 return false; 2814 } 2815 if (&window != currentWindow()) 2816 return false; 2817 if (!currentWindow()->supportsViewMode(viewMode)) { 2818 showErrorMessage(xi18nc("@info", 2819 "Selected view is not supported for <resource>%1</resource> object.", 2820 currentWindow()->partItem()->name()), 2821 xi18nc("@info", 2822 "Selected view (%1) is not supported by this object type (%2).", 2823 Kexi::nameForViewMode(viewMode), 2824 currentWindow()->part()->info()->name())); 2825 return false; 2826 } 2827 setCurrentMode(viewModeToGlobal(viewMode)); 2828 2829 updateCustomPropertyPanelTabs(currentWindow()->part(), prevViewMode, 2830 currentWindow()->part(), viewMode); 2831 tristate res = currentWindow()->switchToViewMode(viewMode); 2832 if (!res) { 2833 updateCustomPropertyPanelTabs(0, Kexi::NoViewMode); //revert 2834 showErrorMessage(xi18n("Switching to other view failed (%1).", 2835 Kexi::nameForViewMode(viewMode)), currentWindow()); 2836 return false; 2837 } 2838 if (~res) { 2839 updateCustomPropertyPanelTabs(0, Kexi::NoViewMode); //revert 2840 return cancelled; 2841 } 2842 2843 activateWindow(window); 2844 2845 invalidateSharedActions(); 2846 invalidateProjectWideActions(); 2847 d->updateFindDialogContents(); 2848 d->updatePropEditorVisibility(viewMode); 2849 QString origTabToActivate; 2850 if (viewMode == Kexi::DesignViewMode) { 2851 // Save the orig tab: we want to back to design tab 2852 // when user moved to data view and then immediately to design view. 2853 origTabToActivate = d->tabsToActivateOnShow.value(currentWindow()->partItem()->identifier()); 2854 } 2855 restoreDesignTabIfNeeded(currentWindow()->partItem()->pluginId(), viewMode, 2856 currentWindow()->partItem()->identifier()); 2857 if (viewMode == Kexi::DesignViewMode) { 2858 activateDesignTab(currentWindow()->partItem()->pluginId()); 2859 // Restore the saved tab to the orig one. restoreDesignTabIfNeeded() saved tools tab probably. 2860 d->tabsToActivateOnShow.insert(currentWindow()->partItem()->identifier(), origTabToActivate); 2861 } 2862 2863 return true; 2864 } 2865 2866 void KexiMainWindow::slotViewDataMode() 2867 { 2868 if (currentWindow()) 2869 switchToViewMode(*currentWindow(), Kexi::DataViewMode); 2870 } 2871 2872 void KexiMainWindow::slotViewDesignMode() 2873 { 2874 if (currentWindow()) 2875 switchToViewMode(*currentWindow(), Kexi::DesignViewMode); 2876 } 2877 2878 void KexiMainWindow::slotViewTextMode() 2879 { 2880 if (currentWindow()) 2881 switchToViewMode(*currentWindow(), Kexi::TextViewMode); 2882 } 2883 2884 //! Used to control if we're not Saving-As object under the original name 2885 class SaveAsObjectNameValidator : public KexiNameDialogValidator 2886 { 2887 public: 2888 explicit SaveAsObjectNameValidator(const QString &originalObjectName) 2889 : m_originalObjectName(originalObjectName) 2890 { 2891 } 2892 virtual bool validate(KexiNameDialog *dialog) const override { 2893 if (dialog->widget()->nameText() == m_originalObjectName) { 2894 KMessageBox::information(dialog, 2895 xi18nc("Could not save object under the original name.", 2896 "Could not save under the original name.")); 2897 return false; 2898 } 2899 return true; 2900 } 2901 private: 2902 QString m_originalObjectName; 2903 }; 2904 2905 tristate KexiMainWindow::getNewObjectInfo( 2906 KexiPart::Item *partItem, const QString &originalName, KexiPart::Part *part, 2907 bool allowOverwriting, bool *overwriteNeeded, const QString& messageWhenAskingForName) 2908 { 2909 //data was never saved in the past -we need to create a new object at the backend 2910 KexiPart::Info *info = part->info(); 2911 if (!d->nameDialog) { 2912 d->nameDialog = new KexiNameDialog( 2913 messageWhenAskingForName, this); 2914 //check if that name is allowed 2915 d->nameDialog->widget()->addNameSubvalidator( 2916 new KDbObjectNameValidator(project()->dbConnection()->driver())); 2917 d->nameDialog->buttonBox()->button(QDialogButtonBox::Ok)->setText(xi18nc("@action:button Save object", "Save")); 2918 } else { 2919 d->nameDialog->widget()->setMessageText(messageWhenAskingForName); 2920 } 2921 d->nameDialog->widget()->setCaptionText(partItem->caption()); 2922 d->nameDialog->widget()->setNameText(partItem->name()); 2923 d->nameDialog->setWindowTitle(xi18nc("@title:window", "Save Object As")); 2924 d->nameDialog->setDialogIcon(info->iconName()); 2925 d->nameDialog->setAllowOverwriting(allowOverwriting); 2926 if (!originalName.isEmpty()) { 2927 d->nameDialog->setValidator(new SaveAsObjectNameValidator(originalName)); 2928 } 2929 if (d->nameDialog->execAndCheckIfObjectExists(*project(), *part, overwriteNeeded) 2930 != QDialog::Accepted) 2931 { 2932 return cancelled; 2933 } 2934 2935 // close window of object that will be overwritten 2936 if (*overwriteNeeded) { 2937 KexiPart::Item* overwrittenItem = project()->item(info, d->nameDialog->widget()->nameText()); 2938 if (overwrittenItem) { 2939 KexiWindow * openedWindow = d->openedWindowFor(overwrittenItem->identifier()); 2940 if (openedWindow) { 2941 const tristate res = closeWindow(openedWindow); 2942 if (res != true) { 2943 return res; 2944 } 2945 } 2946 } 2947 } 2948 2949 //update name and caption 2950 partItem->setName(d->nameDialog->widget()->nameText()); 2951 partItem->setCaption(d->nameDialog->widget()->captionText()); 2952 return true; 2953 } 2954 2955 //! Used to delete part item on exit from block 2956 class PartItemDeleter : public QScopedPointer<KexiPart::Item> 2957 { 2958 public: 2959 explicit PartItemDeleter(KexiProject *prj) : m_prj(prj) {} 2960 ~PartItemDeleter() { 2961 if (!isNull()) { 2962 m_prj->deleteUnstoredItem(take()); 2963 } 2964 } 2965 private: 2966 KexiProject *m_prj; 2967 }; 2968 2969 static void showSavingObjectFailedErrorMessage(KexiMainWindow *wnd, KexiPart::Item *item) 2970 { 2971 wnd->showErrorMessage( 2972 xi18nc("@info Saving object failed", 2973 "Saving <resource>%1</resource> object failed.", item->name()), 2974 wnd->currentWindow()); 2975 } 2976 2977 tristate KexiMainWindow::saveObject(KexiWindow *window, const QString& messageWhenAskingForName, 2978 SaveObjectOptions options) 2979 { 2980 tristate res; 2981 bool saveAs = options & SaveObjectAs; 2982 if (!saveAs && !window->neverSaved()) { 2983 //data was saved in the past -just save again 2984 res = window->storeData(options & DoNotAsk); 2985 if (!res) { 2986 showSavingObjectFailedErrorMessage(this, window->partItem()); 2987 } 2988 return res; 2989 } 2990 if (saveAs && window->neverSaved()) { 2991 //if never saved, saveAs == save 2992 saveAs = false; 2993 } 2994 2995 const int oldItemID = window->partItem()->identifier(); 2996 2997 KexiPart::Item *partItem; 2998 KexiView::StoreNewDataOptions storeNewDataOptions; 2999 PartItemDeleter itemDeleter(d->prj); 3000 if (saveAs) { 3001 partItem = d->prj->createPartItem(window->part()); 3002 if (!partItem) { 3003 //! @todo error 3004 return false; 3005 } 3006 itemDeleter.reset(partItem); 3007 } 3008 else { 3009 partItem = window->partItem(); 3010 } 3011 3012 bool overwriteNeeded; 3013 res = getNewObjectInfo(partItem, saveAs ? window->partItem()->name() : QString(), 3014 window->part(), true /*allowOverwriting*/, 3015 &overwriteNeeded, messageWhenAskingForName); 3016 if (res != true) 3017 return res; 3018 if (overwriteNeeded) { 3019 storeNewDataOptions |= KexiView::OverwriteExistingData; 3020 } 3021 3022 if (saveAs) { 3023 res = window->storeDataAs(partItem, storeNewDataOptions); 3024 } 3025 else { 3026 res = window->storeNewData(storeNewDataOptions); 3027 } 3028 3029 if (~res) 3030 return cancelled; 3031 if (!res) { 3032 showSavingObjectFailedErrorMessage(this, partItem); 3033 return false; 3034 } 3035 3036 d->updateWindowId(window, oldItemID); 3037 invalidateProjectWideActions(); 3038 itemDeleter.take(); 3039 return true; 3040 } 3041 3042 tristate KexiMainWindow::closeWindow(KexiWindow *window) 3043 { 3044 return closeWindow(window ? window : currentWindow(), true); 3045 } 3046 3047 tristate KexiMainWindow::closeCurrentWindow() 3048 { 3049 return closeWindow(0); 3050 } 3051 3052 tristate KexiMainWindow::closeWindowForTab(int tabIndex) 3053 { 3054 KexiWindow* window = windowForTab(tabIndex); 3055 if (!window) 3056 return false; 3057 return closeWindow(window); 3058 } 3059 3060 tristate KexiMainWindow::closeAllWindows() 3061 { 3062 if (!d->objectViewWidget || !d->objectViewWidget->tabWidget()) 3063 return true; 3064 QList<KexiWindow*> windowList; 3065 for (int i = 0; i < d->objectViewWidget->tabWidget()->count(); ++i) { 3066 KexiWindow *window = windowForTab(i); 3067 if (window) { 3068 windowList.append(window); 3069 } 3070 } 3071 tristate alternateResult = true; 3072 for (KexiWindow *window : windowList) { 3073 const tristate result = closeWindow(window); 3074 if (~result) { 3075 return result; 3076 } 3077 if (result == false) { 3078 alternateResult = false; 3079 } 3080 } 3081 return alternateResult; 3082 } 3083 3084 tristate KexiMainWindow::closeWindow(KexiWindow *window, bool layoutTaskBar, bool doNotSaveChanges) 3085 { 3086 //! @todo KEXI3 KexiMainWindow::closeWindow() 3087 ///@note Q_UNUSED layoutTaskBar 3088 Q_UNUSED(layoutTaskBar); 3089 3090 if (!window) 3091 return true; 3092 if (d->insideCloseWindow) 3093 return true; 3094 3095 const int previousItemId = window->partItem()->identifier(); 3096 3097 #ifndef KEXI_NO_PENDING_DIALOGS 3098 d->addItemToPendingWindows(window->partItem(), Private::WindowClosingJob); 3099 #endif 3100 3101 d->insideCloseWindow = true; 3102 3103 if (window == currentWindow() && !window->isAttached()) { 3104 if (d->propertyEditor()) { 3105 // ah, closing detached window - better switch off property buffer right now... 3106 d->propertySet = 0; 3107 d->propertyEditor()->changeSet(0); 3108 } 3109 } 3110 3111 bool remove_on_closing = window->partItem() ? window->partItem()->neverSaved() : false; 3112 if (window->isDirty() && !d->forceWindowClosing && !doNotSaveChanges) { 3113 //more accurate tool tips and what's this 3114 KGuiItem saveChanges(KStandardGuiItem::save()); 3115 saveChanges.setToolTip(xi18n("Save changes")); 3116 saveChanges.setWhatsThis( 3117 xi18nc("@info", "Saves all recent changes made in <resource>%1</resource> object.", 3118 window->partItem()->name())); 3119 KGuiItem discardChanges(KStandardGuiItem::discard()); 3120 discardChanges.setWhatsThis( 3121 xi18nc("@info", "Discards all recent changes made in <resource>%1</resource> object.", 3122 window->partItem()->name())); 3123 3124 //dialog's data is dirty: 3125 //--adidional message, e.g. table designer will return 3126 // "Note: This table is already filled with data which will be removed." 3127 // if the window is in design view mode. 3128 const KLocalizedString additionalMessage( 3129 window->part()->i18nMessage(":additional message before saving design", window)); 3130 QString additionalMessageString; 3131 if (!additionalMessage.isEmpty()) 3132 additionalMessageString = additionalMessage.toString(); 3133 3134 if (additionalMessageString.startsWith(':')) 3135 additionalMessageString.clear(); 3136 if (!additionalMessageString.isEmpty()) 3137 additionalMessageString = "<p>" + additionalMessageString + "</p>"; 3138 3139 const KMessageBox::ButtonCode questionRes = KMessageBox::warningYesNoCancel(this, 3140 "<p>" 3141 + window->part()->i18nMessage("Design of object <resource>%1</resource> has been modified.", window) 3142 .subs(window->partItem()->name()).toString() 3143 + "</p><p>" + xi18n("Do you want to save changes?") + "</p>" 3144 + additionalMessageString /*may be empty*/, 3145 QString(), 3146 saveChanges, 3147 discardChanges); 3148 if (questionRes == KMessageBox::Cancel) { 3149 #ifndef KEXI_NO_PENDING_DIALOGS 3150 d->removePendingWindow(window->id()); 3151 #endif 3152 d->insideCloseWindow = false; 3153 d->windowsToClose.clear(); //give up with 'close all' 3154 return cancelled; 3155 } 3156 if (questionRes == KMessageBox::Yes) { 3157 //save it 3158 tristate res = saveObject(window, QString(), DoNotAsk); 3159 if (!res || ~res) { 3160 //! @todo show error info; (retry/ignore/cancel) 3161 #ifndef KEXI_NO_PENDING_DIALOGS 3162 d->removePendingWindow(window->id()); 3163 #endif 3164 d->insideCloseWindow = false; 3165 d->windowsToClose.clear(); //give up with 'close all' 3166 return res; 3167 } 3168 remove_on_closing = false; 3169 } 3170 } 3171 3172 const int window_id = window->id(); //remember now, because removeObject() can destruct partitem object 3173 if (remove_on_closing) { 3174 //we won't save this object, and it was never saved -remove it 3175 if (!removeObject(window->partItem(), true)) { 3176 #ifndef KEXI_NO_PENDING_DIALOGS 3177 d->removePendingWindow(window->id()); 3178 #endif 3179 //msg? 3180 //! @todo ask if we'd continue and return true/false 3181 d->insideCloseWindow = false; 3182 d->windowsToClose.clear(); //give up with 'close all' 3183 return false; 3184 } 3185 } else { 3186 //not dirty now 3187 if (d->objectViewWidget && d->objectViewWidget->projectNavigator()) { 3188 d->objectViewWidget->projectNavigator()->updateItemName(*window->partItem(), false); 3189 } 3190 } 3191 3192 hideDesignTab(previousItemId, QString()); 3193 3194 d->removeWindow(window_id); 3195 d->setWindowContainerExistsFor(window->partItem()->identifier(), false); 3196 QWidget *windowContainer = window->parentWidget(); 3197 d->objectViewWidget->tabWidget()->removeTab( 3198 d->objectViewWidget->tabWidget()->indexOf(windowContainer)); 3199 3200 #ifdef KEXI_QUICK_PRINTING_SUPPORT 3201 //also remove from 'print setup dialogs' cache, if needed 3202 int printedObjectID = 0; 3203 if (d->pageSetupWindowItemID2dataItemID_map.contains(window_id)) 3204 printedObjectID = d->pageSetupWindowItemID2dataItemID_map[ window_id ]; 3205 d->pageSetupWindows.remove(printedObjectID); 3206 #endif 3207 3208 delete windowContainer; 3209 3210 //focus navigator if nothing else available 3211 if (d->openedWindowsCount() == 0) { 3212 if (d->objectViewWidget && d->objectViewWidget->projectNavigator()) { 3213 d->objectViewWidget->projectNavigator()->setFocus(); 3214 } 3215 d->updatePropEditorVisibility(Kexi::NoViewMode); 3216 } 3217 3218 invalidateActions(); 3219 d->insideCloseWindow = false; 3220 if (!d->windowsToClose.isEmpty()) {//continue 'close all' 3221 KexiWindow* w = d->windowsToClose.takeAt(0); 3222 closeWindow(w, true); 3223 } 3224 3225 #ifndef KEXI_NO_PENDING_DIALOGS 3226 d->removePendingWindow(window_id); 3227 3228 //perform pending global action that was suspended: 3229 if (!d->pendingWindowsExist()) { 3230 d->executeActionWhenPendingJobsAreFinished(); 3231 } 3232 #endif 3233 //d->objectViewWidget->slotCurrentTabIndexChanged(d->objectViewWidget->tabWidget()->currentIndex()); 3234 showDesignTabIfNeeded(0); 3235 3236 if (currentWindow()) { 3237 restoreDesignTabIfNeeded(currentWindow()->partItem()->pluginId(), 3238 currentWindow()->currentViewMode(), 3239 0); 3240 } 3241 d->tabsToActivateOnShow.remove(previousItemId); 3242 return true; 3243 } 3244 3245 QWidget* KexiMainWindow::findWindow(QWidget *w) 3246 { 3247 while (w && !acceptsSharedActions(w)) { 3248 if (w == d->objectViewWidget->propertyPane()) { 3249 return currentWindow(); 3250 } 3251 w = w->parentWidget(); 3252 } 3253 return w; 3254 } 3255 3256 KexiWindow* KexiMainWindow::openedWindowFor(int identifier) 3257 { 3258 return d->openedWindowFor(identifier); 3259 } 3260 3261 KexiWindow* KexiMainWindow::openedWindowFor(const KexiPart::Item* item) 3262 { 3263 return item ? openedWindowFor(item->identifier()) : 0; 3264 } 3265 3266 KDbQuerySchema* KexiMainWindow::unsavedQuery(int queryId) 3267 { 3268 KexiWindow * queryWindow = openedWindowFor(queryId); 3269 if (!queryWindow || !queryWindow->isDirty()) { 3270 return 0; 3271 } 3272 3273 return queryWindow->part()->currentQuery(queryWindow->viewForMode(Kexi::DataViewMode)); 3274 } 3275 3276 QList<QVariant> KexiMainWindow::currentParametersForQuery(int queryId) const 3277 { 3278 KexiWindow *queryWindow = d->openedWindowFor(queryId); 3279 if (!queryWindow) { 3280 return QList<QVariant>(); 3281 } 3282 3283 KexiView *view = queryWindow->viewForMode(Kexi::DataViewMode); 3284 if (!view) { 3285 return QList<QVariant>(); 3286 } 3287 3288 return view->currentParameters(); 3289 } 3290 3291 bool KexiMainWindow::acceptsSharedActions(QObject *w) 3292 { 3293 return w->inherits("KexiWindow") || w->inherits("KexiView"); 3294 } 3295 3296 bool KexiMainWindow::openingAllowed(KexiPart::Item* item, Kexi::ViewMode viewMode, QString* errorMessage) 3297 { 3298 //qDebug() << viewMode; 3299 //! @todo this can be more complex once we deliver ACLs... 3300 if (!d->userMode) 3301 return true; 3302 KexiPart::Part * part = Kexi::partManager().partForPluginId(item->pluginId()); 3303 if (!part) { 3304 if (errorMessage) { 3305 *errorMessage = Kexi::partManager().result().message(); 3306 } 3307 } 3308 //qDebug() << part << item->pluginId(); 3309 //if (part) 3310 // qDebug() << item->pluginId() << part->info()->supportedUserViewModes(); 3311 return part && (part->info()->supportedUserViewModes() & viewMode); 3312 } 3313 3314 KexiWindow * 3315 KexiMainWindow::openObject(const QString& pluginId, const QString& name, 3316 Kexi::ViewMode viewMode, bool *openingCancelled, QMap<QString, QVariant>* staticObjectArgs) 3317 { 3318 KexiPart::Item *item = d->prj->itemForPluginId(pluginId, name); 3319 if (!item) 3320 return 0; 3321 return openObject(item, viewMode, openingCancelled, staticObjectArgs); 3322 } 3323 3324 KexiWindow * 3325 KexiMainWindow::openObject(KexiPart::Item* item, Kexi::ViewMode viewMode, bool *openingCancelled, 3326 QMap<QString, QVariant>* staticObjectArgs, QString* errorMessage) 3327 { 3328 Q_ASSERT(openingCancelled); 3329 if (!d->prj || !item) { 3330 return 0; 3331 } 3332 3333 if (!openingAllowed(item, viewMode, errorMessage)) { 3334 if (errorMessage) 3335 *errorMessage = xi18nc( 3336 "opening is not allowed in \"data view/design view/text view\" mode", 3337 "opening is not allowed in \"%1\" mode", Kexi::nameForViewMode(viewMode)); 3338 *openingCancelled = true; 3339 return 0; 3340 } 3341 //qDebug() << d->prj << item; 3342 3343 KexiWindow *prevWindow = currentWindow(); 3344 3345 KexiUtils::WaitCursor wait; 3346 #ifndef KEXI_NO_PENDING_DIALOGS 3347 Private::PendingJobType pendingType; 3348 KexiWindow *window = d->openedWindowFor(item, pendingType); 3349 if (pendingType != Private::NoJob) { 3350 *openingCancelled = true; 3351 return 0; 3352 } 3353 #else 3354 KexiWindow *window = openedWindowFor(item); 3355 #endif 3356 int previousItemId = currentWindow() ? currentWindow()->partItem()->identifier() : 0; 3357 *openingCancelled = false; 3358 3359 bool alreadyOpened = false; 3360 QWidget *windowContainer = 0; 3361 3362 if (window) { 3363 if (viewMode != window->currentViewMode()) { 3364 if (true != switchToViewMode(*window, viewMode)) 3365 return 0; 3366 } else 3367 activateWindow(*window); 3368 alreadyOpened = true; 3369 } else { 3370 if (d->windowContainerExistsFor(item->identifier())) { 3371 // window not yet present but window container exists: return 0 and wait 3372 return 0; 3373 } 3374 KexiPart::Part *part = Kexi::partManager().partForPluginId(item->pluginId()); 3375 d->updatePropEditorVisibility(viewMode, part ? part->info() : 0); 3376 //update tabs before opening 3377 updateCustomPropertyPanelTabs(currentWindow() ? currentWindow()->part() : 0, 3378 currentWindow() ? currentWindow()->currentViewMode() : Kexi::NoViewMode, 3379 part, viewMode); 3380 3381 const int tabIndex = d->objectViewWidget->tabWidget()->addEmptyContainerTab( 3382 part ? part->info()->icon() : koIcon("object"), 3383 KexiWindow::windowTitleForItem(*item)); 3384 // open new tab earlier 3385 d->setWindowContainerExistsFor(item->identifier(), true); 3386 d->objectViewWidget->tabWidget()->setTabToolTip(tabIndex, KexiPart::fullCaptionForItem(item, part)); 3387 QString whatsThisText; 3388 if (part) { 3389 whatsThisText = xi18nc("@info", 3390 "Tab for <resource>%1</resource> (%2).", 3391 item->captionOrName(), part->info()->name()); 3392 } 3393 else { 3394 whatsThisText = xi18nc("@info", 3395 "Tab for <resource>%1</resource>.", item->captionOrName()); 3396 } 3397 d->objectViewWidget->tabWidget()->setTabWhatsThis(tabIndex, whatsThisText); 3398 d->objectViewWidget->tabWidget()->setCurrentIndex(tabIndex); 3399 3400 #ifndef KEXI_NO_PENDING_DIALOGS 3401 d->addItemToPendingWindows(item, Private::WindowOpeningJob); 3402 #endif 3403 windowContainer = d->objectViewWidget->tabWidget()->widget(tabIndex); 3404 window = d->prj->openObject(windowContainer, item, viewMode, staticObjectArgs); 3405 if (window) { 3406 d->objectViewWidget->tabWidget()->setWindowForTab(tabIndex, window); 3407 // update text and icon 3408 d->objectViewWidget->tabWidget()->setTabText(tabIndex, window->windowTitle()); 3409 d->objectViewWidget->tabWidget()->setTabIcon(tabIndex, window->windowIcon()); 3410 } 3411 } 3412 3413 if (!window || !activateWindow(*window)) { 3414 #ifndef KEXI_NO_PENDING_DIALOGS 3415 d->removePendingWindow(item->identifier()); 3416 #endif 3417 d->setWindowContainerExistsFor(item->identifier(), false); 3418 d->objectViewWidget->tabWidget()->removeTab( 3419 d->objectViewWidget->tabWidget()->indexOf(windowContainer)); 3420 delete windowContainer; 3421 updateCustomPropertyPanelTabs(0, Kexi::NoViewMode); //revert 3422 //! @todo add error msg... 3423 return 0; 3424 } 3425 3426 if (viewMode != window->currentViewMode()) 3427 invalidateSharedActions(); 3428 3429 #ifndef KEXI_NO_PENDING_DIALOGS 3430 d->removePendingWindow(window->id()); 3431 3432 //perform pending global action that was suspended: 3433 if (!d->pendingWindowsExist()) { 3434 d->executeActionWhenPendingJobsAreFinished(); 3435 } 3436 #endif 3437 if (window && !alreadyOpened) { 3438 // Call switchToViewMode() and propertySetSwitched() again here because 3439 // this is the time when then new window is the current one - previous call did nothing. 3440 switchToViewMode(*window, window->currentViewMode()); 3441 currentWindow()->selectedView()->propertySetSwitched(); 3442 } 3443 invalidateProjectWideActions(); 3444 restoreDesignTabIfNeeded(item->pluginId(), viewMode, previousItemId); 3445 activateDesignTabIfNeeded(item->pluginId(), viewMode); 3446 QString origTabToActivate; 3447 if (prevWindow) { 3448 // Save the orig tab for prevWindow that was stored in the restoreDesignTabIfNeeded() call above 3449 origTabToActivate = d->tabsToActivateOnShow.value(prevWindow->partItem()->identifier()); 3450 } 3451 activeWindowChanged(window, prevWindow); 3452 if (prevWindow) { 3453 // Restore the orig tab 3454 d->tabsToActivateOnShow.insert(prevWindow->partItem()->identifier(), origTabToActivate); 3455 } 3456 return window; 3457 } 3458 3459 KexiWindow * 3460 KexiMainWindow::openObjectFromNavigator(KexiPart::Item* item, Kexi::ViewMode viewMode) 3461 { 3462 bool openingCancelled; 3463 return openObjectFromNavigator(item, viewMode, &openingCancelled); 3464 } 3465 3466 KexiWindow * 3467 KexiMainWindow::openObjectFromNavigator(KexiPart::Item* item, Kexi::ViewMode viewMode, 3468 bool *openingCancelled) 3469 { 3470 Q_ASSERT(openingCancelled); 3471 if (!openingAllowed(item, viewMode)) { 3472 *openingCancelled = true; 3473 return 0; 3474 } 3475 if (!d->prj || !item) 3476 return 0; 3477 #ifndef KEXI_NO_PENDING_DIALOGS 3478 Private::PendingJobType pendingType; 3479 KexiWindow *window = d->openedWindowFor(item, pendingType); 3480 if (pendingType != Private::NoJob) { 3481 *openingCancelled = true; 3482 return 0; 3483 } 3484 #else 3485 KexiWindow *window = openedWindowFor(item); 3486 #endif 3487 *openingCancelled = false; 3488 if (window) { 3489 if (activateWindow(*window)) { 3490 return window; 3491 } 3492 } 3493 //if DataViewMode is not supported, try Design, then Text mode (currently useful for script part) 3494 KexiPart::Part *part = Kexi::partManager().partForPluginId(item->pluginId()); 3495 if (!part) 3496 return 0; 3497 if (viewMode == Kexi::DataViewMode && !(part->info()->supportedViewModes() & Kexi::DataViewMode)) { 3498 if (part->info()->supportedViewModes() & Kexi::DesignViewMode) 3499 return openObjectFromNavigator(item, Kexi::DesignViewMode, openingCancelled); 3500 else if (part->info()->supportedViewModes() & Kexi::TextViewMode) 3501 return openObjectFromNavigator(item, Kexi::TextViewMode, openingCancelled); 3502 } 3503 //do the same as in openObject() 3504 return openObject(item, viewMode, openingCancelled); 3505 } 3506 3507 tristate KexiMainWindow::closeObject(KexiPart::Item* item) 3508 { 3509 #ifndef KEXI_NO_PENDING_DIALOGS 3510 Private::PendingJobType pendingType; 3511 KexiWindow *window = d->openedWindowFor(item, pendingType); 3512 if (pendingType == Private::WindowClosingJob) 3513 return true; 3514 else if (pendingType == Private::WindowOpeningJob) 3515 return cancelled; 3516 #else 3517 KexiWindow *window = openedWindowFor(item); 3518 #endif 3519 if (!window) 3520 return cancelled; 3521 return closeWindow(window); 3522 } 3523 3524 bool KexiMainWindow::newObject(KexiPart::Info *info, bool* openingCancelled) 3525 { 3526 Q_ASSERT(openingCancelled); 3527 if (d->userMode) { 3528 *openingCancelled = true; 3529 return false; 3530 } 3531 *openingCancelled = false; 3532 if (!d->prj || !info) 3533 return false; 3534 KexiPart::Part *part = Kexi::partManager().part(info); 3535 if (!part) 3536 return false; 3537 3538 KexiPart::Item *it = d->prj->createPartItem(info); 3539 if (!it) { 3540 //! @todo error 3541 return false; 3542 } 3543 3544 if (!it->neverSaved()) { //only add stored objects to the browser 3545 d->objectViewWidget->projectNavigator()->model()->slotAddItem(it); 3546 } 3547 Kexi::ViewMode viewMode = (info->supportedViewModes() & Kexi::DesignViewMode) 3548 ? Kexi::DesignViewMode 3549 : Kexi::TextViewMode; 3550 return openObject(it, viewMode, openingCancelled); 3551 } 3552 3553 tristate KexiMainWindow::removeObject(KexiPart::Item *item, bool dontAsk) 3554 { 3555 if (d->userMode) 3556 return cancelled; 3557 if (!d->prj || !item) 3558 return false; 3559 3560 KexiPart::Part *part = Kexi::partManager().partForPluginId(item->pluginId()); 3561 if (!part) 3562 return false; 3563 3564 if (!dontAsk) { 3565 if (KMessageBox::No == KMessageBox::questionYesNo(this, 3566 xi18nc("@info Delete <objecttype> <objectname>?", 3567 "<para>Do you want to permanently delete the following object?<nl/>" 3568 "<nl/>%1 <resource>%2</resource></para>" 3569 "<para><note>If you click <interface>Delete</interface>, " 3570 "you will not be able to undo the deletion.</note></para>", 3571 part->info()->name(), item->name()), 3572 xi18nc("@title:window Delete Object %1.", 3573 "Delete <resource>%1</resource>?", item->name()), 3574 KStandardGuiItem::del(), 3575 KStandardGuiItem::no(), QString(), KMessageBox::Notify | KMessageBox::Dangerous)) 3576 { 3577 return cancelled; 3578 } 3579 } 3580 3581 tristate res = true; 3582 #ifdef KEXI_QUICK_PRINTING_SUPPORT 3583 //also close 'print setup' dialog for this item, if any 3584 KexiWindow * pageSetupWindow = d->pageSetupWindows[ item->identifier()]; 3585 const bool oldInsideCloseWindow = d->insideCloseWindow; 3586 { 3587 d->insideCloseWindow = false; 3588 if (pageSetupWindow) 3589 res = closeWindow(pageSetupWindow); 3590 } 3591 d->insideCloseWindow = oldInsideCloseWindow; 3592 if (!res || ~res) { 3593 return res; 3594 } 3595 #endif 3596 3597 #ifndef KEXI_NO_PENDING_DIALOGS 3598 Private::PendingJobType pendingType; 3599 KexiWindow *window = d->openedWindowFor(item, pendingType); 3600 if (pendingType != Private::NoJob) { 3601 return cancelled; 3602 } 3603 #else 3604 KexiWindow *window = openedWindowFor(item); 3605 #endif 3606 3607 if (window) {//close existing window 3608 const bool tmp = d->forceWindowClosing; 3609 d->forceWindowClosing = true; 3610 res = closeWindow(window); 3611 d->forceWindowClosing = tmp; //restore 3612 if (!res || ~res) { 3613 return res; 3614 } 3615 } 3616 3617 #ifdef KEXI_QUICK_PRINTING_SUPPORT 3618 //in case the dialog is a 'print setup' dialog, also update d->pageSetupWindows 3619 int dataItemID = d->pageSetupWindowItemID2dataItemID_map[item->identifier()]; 3620 d->pageSetupWindowItemID2dataItemID_map.remove(item->identifier()); 3621 d->pageSetupWindows.remove(dataItemID); 3622 #endif 3623 3624 if (!d->prj->removeObject(item)) { 3625 //! @todo better msg 3626 showSorryMessage(xi18n("Could not delete object.")); 3627 return false; 3628 } 3629 return true; 3630 } 3631 3632 void KexiMainWindow::renameObject(KexiPart::Item *item, const QString& _newName, bool *success) 3633 { 3634 Q_ASSERT(success); 3635 if (d->userMode) { 3636 *success = false; 3637 return; 3638 } 3639 QString newName = _newName.trimmed(); 3640 if (newName.isEmpty()) { 3641 showSorryMessage(xi18n("Could not set empty name for this object.")); 3642 *success = false; 3643 return; 3644 } 3645 3646 KexiWindow *window = openedWindowFor(item); 3647 if (window) { 3648 QString msg = xi18nc("@info", 3649 "<para>Before renaming object <resource>%1</resource> it should be closed.</para>" 3650 "<para>Do you want to close it?</para>", 3651 item->name()); 3652 KGuiItem closeAndRenameItem(KStandardGuiItem::closeWindow()); 3653 closeAndRenameItem.setText(xi18n("Close Window and Rename")); 3654 const int r = KMessageBox::questionYesNo(this, msg, QString(), closeAndRenameItem, 3655 KStandardGuiItem::cancel()); 3656 if (r != KMessageBox::Yes) { 3657 *success = false; 3658 return; 3659 } 3660 const tristate closeResult = closeWindow(window); 3661 if (closeResult != true) { 3662 *success = false; 3663 return; 3664 } 3665 } 3666 setMessagesEnabled(false); //to avoid double messages 3667 const bool res = d->prj->renameObject(item, newName); 3668 setMessagesEnabled(true); 3669 if (!res) { 3670 showErrorMessage(xi18nc("@info", "Renaming object <resource>%1</resource> failed.", 3671 newName), d->prj); 3672 *success = false; 3673 return; 3674 } 3675 *success = true; 3676 } 3677 3678 void KexiMainWindow::setObjectCaption(KexiPart::Item *item, const QString& _newCaption, bool *success) 3679 { 3680 Q_ASSERT(success); 3681 if (d->userMode) { 3682 *success = false; 3683 return; 3684 } 3685 QString newCaption = _newCaption.trimmed(); 3686 setMessagesEnabled(false); //to avoid double messages 3687 const bool res = d->prj->setObjectCaption(item, newCaption); 3688 setMessagesEnabled(true); 3689 if (!res) { 3690 showErrorMessage(xi18nc("@info", 3691 "Setting caption for object <resource>%1</resource> failed.", 3692 newCaption), d->prj); 3693 *success = false; 3694 return; 3695 } 3696 *success = true; 3697 } 3698 3699 void KexiMainWindow::slotObjectRenamed(const KexiPart::Item &item, const QString& oldName) 3700 { 3701 Q_UNUSED(oldName); 3702 #ifndef KEXI_NO_PENDING_DIALOGS 3703 Private::PendingJobType pendingType; 3704 KexiWindow *window = d->openedWindowFor(&item, pendingType); 3705 if (pendingType != Private::NoJob) 3706 return; 3707 #else 3708 KexiWindow *window = openedWindowFor(&item); 3709 #endif 3710 if (!window) 3711 return; 3712 3713 //change item 3714 window->updateCaption(); 3715 if (static_cast<KexiWindow*>(currentWindow()) == window)//optionally, update app. caption 3716 updateAppCaption(); 3717 } 3718 3719 void KexiMainWindow::acceptPropertySetEditing() 3720 { 3721 if (d->propertyEditor()) { 3722 d->propertyEditor()->acceptInput(); 3723 } 3724 } 3725 3726 void KexiMainWindow::propertySetSwitched(KexiWindow *window, bool force, 3727 bool preservePrevSelection, bool sortedProperties, const QByteArray& propertyToSelect) 3728 { 3729 KexiWindow* _currentWindow = currentWindow(); 3730 //qDebug() << "currentWindow(): " 3731 // << (_currentWindow ? _currentWindow->windowTitle() : QString("NULL")) 3732 // << "window:" << (window ? window->windowTitle() : QString("NULL")); 3733 if (_currentWindow && _currentWindow != window) { 3734 d->propertySet = 0; //we'll need to move to another prop. set 3735 return; 3736 } 3737 if (d->propertyEditor()) { 3738 KPropertySet *newSet = _currentWindow ? _currentWindow->propertySet() : 0; 3739 if (!newSet || (force || static_cast<KPropertySet*>(d->propertySet) != newSet)) { 3740 d->propertySet = newSet; 3741 if (preservePrevSelection || force) { 3742 KPropertyEditorView::SetOptions options; 3743 if (preservePrevSelection) { 3744 options |= KPropertyEditorView::SetOption::PreservePreviousSelection; 3745 } 3746 if (sortedProperties) { 3747 options |= KPropertyEditorView::SetOption::AlphabeticalOrder; 3748 } 3749 3750 d->objectViewWidget->propertyPane()->changePropertySet( 3751 d->propertySet, propertyToSelect, options, 3752 (_currentWindow && _currentWindow->selectedView()) 3753 ? _currentWindow->selectedView()->textToDisplayForNullSet() 3754 : QString()); 3755 } 3756 } 3757 } 3758 } 3759 3760 void KexiMainWindow::slotDirtyFlagChanged(KexiWindow* window) 3761 { 3762 KexiPart::Item *item = window->partItem(); 3763 //update text in navigator and app. caption 3764 if (!d->userMode) { 3765 d->objectViewWidget->projectNavigator()->updateItemName(*item, window->isDirty()); 3766 } 3767 3768 invalidateActions(); 3769 updateAppCaption(); 3770 d->objectViewWidget->tabWidget()->setTabText( 3771 d->objectViewWidget->tabWidget()->indexOf(window->parentWidget()), 3772 window->windowTitle()); 3773 } 3774 3775 void KexiMainWindow::slotTipOfTheDay() 3776 { 3777 //! @todo 3778 } 3779 3780 void KexiMainWindow::slotReportBug() 3781 { 3782 KexiBugReportDialog bugReport(this); 3783 bugReport.exec(); 3784 } 3785 3786 bool KexiMainWindow::userMode() const 3787 { 3788 return d->userMode; 3789 } 3790 3791 void 3792 KexiMainWindow::setupUserActions() 3793 { 3794 } 3795 3796 void KexiMainWindow::slotToolsImportProject() 3797 { 3798 if (d->tabbedToolBar) 3799 d->tabbedToolBar->hideMainMenu(); 3800 showProjectMigrationWizard(QString(), QString()); 3801 } 3802 3803 void KexiMainWindow::slotToolsImportTables() 3804 { 3805 if (project()) { 3806 QMap<QString, QString> args; 3807 QDialog *dlg = KexiInternalPart::createModalDialogInstance("org.kexi-project.migration", "importtable", this, 0, &args); 3808 if (!dlg) 3809 return; //error msg has been shown by KexiInternalPart 3810 3811 const int result = dlg->exec(); 3812 delete dlg; 3813 if (result != QDialog::Accepted) 3814 return; 3815 3816 QString destinationTableName(args["destinationTableName"]); 3817 if (!destinationTableName.isEmpty()) { 3818 QString pluginId = "org.kexi-project.table"; 3819 bool openingCancelled; 3820 KexiMainWindow::openObject(pluginId, destinationTableName, Kexi::DataViewMode, &openingCancelled); 3821 } 3822 } 3823 } 3824 3825 void KexiMainWindow::slotToolsCompactDatabase() 3826 { 3827 KexiProjectData *data = 0; 3828 KDbDriver *drv = 0; 3829 const bool projectWasOpened = d->prj; 3830 3831 if (!d->prj) { 3832 //! @todo Support compacting of non-opened projects 3833 return; 3834 #if 0 3835 KexiStartupDialog dlg( 3836 KexiStartupDialog::OpenExisting, 0, Kexi::connset(), this); 3837 3838 if (dlg.exec() != QDialog::Accepted) 3839 return; 3840 3841 if (dlg.selectedFile().isEmpty()) { 3842 //! @todo add support for server based if needed? 3843 return; 3844 } 3845 KDbConnectionData cdata; 3846 cdata.setDatabaseName(dlg.selectedFile()); 3847 3848 //detect driver name for the selected file 3849 KexiStartupData::Import detectedImportAction; 3850 QString detectedDriverId; 3851 tristate res = KexiStartupHandler::detectActionForFile( 3852 &detectedImportAction, &detectedDriverId, 3853 QString() /*suggestedDriverId*/, cdata.databaseName(), 0, 3854 KexiStartupHandler::SkipMessages | KexiStartupHandler::ThisIsAProjectFile 3855 | KexiStartupHandler::DontConvert); 3856 3857 if (true == res && !detectedImportAction) { 3858 cdata.setDriverId(detectedDriverId); 3859 drv = Kexi::driverManager().driver(cdata.driverId()); 3860 } 3861 if (!drv || !(drv->features() & KDbDriver::CompactingDatabaseSupported)) { 3862 KMessageBox::information(this, 3863 xi18n("Compacting database file <filename>%1</filename> is not supported.", 3864 QDir::toNativeSeparators(cdata.databaseName()))); 3865 return; 3866 } 3867 data = new KexiProjectData(cdata); 3868 #endif 3869 } else { 3870 //sanity 3871 if (!(d->prj && d->prj->dbConnection() 3872 && (d->prj->dbConnection()->driver()->features() & KDbDriver::CompactingDatabaseSupported))) 3873 return; 3874 3875 KGuiItem yesItem(KStandardGuiItem::cont()); 3876 yesItem.setText(xi18nc("@action:button Compact database", "Compact")); 3877 if (KMessageBox::Yes != KMessageBox::questionYesNo(this, 3878 xi18n("The current project has to be closed before compacting the database. " 3879 "It will be open again after compacting.\n\nDo you want to continue?"), 3880 QString(), yesItem, KStandardGuiItem::cancel())) 3881 { 3882 return; 3883 } 3884 data = new KexiProjectData(*d->prj->data()); // a copy 3885 drv = d->prj->dbConnection()->driver(); 3886 const tristate res = closeProject(); 3887 if (~res || !res) { 3888 delete data; 3889 return; 3890 } 3891 } 3892 3893 if (!drv->adminTools().vacuum(*data->connectionData(), data->databaseName())) { 3894 showErrorMessage(QString(), &drv->adminTools()); 3895 } 3896 3897 if (projectWasOpened) 3898 openProject(*data); 3899 3900 delete data; 3901 } 3902 3903 tristate KexiMainWindow::showProjectMigrationWizard(const QString& mimeType, const QString& databaseName) 3904 { 3905 return d->showProjectMigrationWizard(mimeType, databaseName, 0); 3906 } 3907 3908 tristate KexiMainWindow::showProjectMigrationWizard( 3909 const QString& mimeType, const QString& databaseName, const KDbConnectionData &cdata) 3910 { 3911 return d->showProjectMigrationWizard(mimeType, databaseName, &cdata); 3912 } 3913 3914 tristate KexiMainWindow::executeItem(KexiPart::Item* item) 3915 { 3916 KexiPart::Info *info = item ? Kexi::partManager().infoForPluginId(item->pluginId()) : 0; 3917 if ((! info) || (! info->isExecuteSupported())) 3918 return false; 3919 KexiPart::Part *part = Kexi::partManager().part(info); 3920 if (!part) 3921 return false; 3922 return part->execute(item); 3923 } 3924 3925 void KexiMainWindow::slotProjectImportDataTable() 3926 { 3927 //! @todo allow data appending (it is not possible now) 3928 if (d->userMode) 3929 return; 3930 QMap<QString, QString> args; 3931 args.insert("sourceType", "file"); 3932 QDialog *dlg = KexiInternalPart::createModalDialogInstance( 3933 "org.kexi-project.importexport.csv", "KexiCSVImportDialog", this, 0, &args); 3934 if (!dlg) 3935 return; //error msg has been shown by KexiInternalPart 3936 dlg->exec(); 3937 delete dlg; 3938 } 3939 3940 tristate KexiMainWindow::executeCustomActionForObject(KexiPart::Item* item, 3941 const QString& actionName) 3942 { 3943 if (actionName == "exportToCSV") 3944 return exportItemAsDataTable(item); 3945 else if (actionName == "copyToClipboardAsCSV") 3946 return copyItemToClipboardAsDataTable(item); 3947 3948 qWarning() << "no such action:" << actionName; 3949 return false; 3950 } 3951 3952 tristate KexiMainWindow::exportItemAsDataTable(KexiPart::Item* item) 3953 { 3954 if (!item) 3955 return false; 3956 3957 QMap<QString, QString> args; 3958 3959 if (!checkForDirtyFlagOnExport(item, &args)) { 3960 return false; 3961 } 3962 3963 //! @todo: accept record changes... 3964 args.insert("destinationType", "file"); 3965 args.insert("itemId", QString::number(item->identifier())); 3966 QDialog *dlg = KexiInternalPart::createModalDialogInstance( 3967 "org.kexi-project.importexport.csv", "KexiCSVExportWizard", this, 0, &args); 3968 if (!dlg) 3969 return false; //error msg has been shown by KexiInternalPart 3970 int result = dlg->exec(); 3971 delete dlg; 3972 return result == QDialog::Rejected ? tristate(cancelled) : tristate(true); 3973 } 3974 3975 bool KexiMainWindow::checkForDirtyFlagOnExport(KexiPart::Item *item, QMap<QString, QString> *args) 3976 { 3977 //! @todo: handle tables 3978 if (item->pluginId() != "org.kexi-project.query") { 3979 return true; 3980 } 3981 3982 KexiWindow * itemWindow = openedWindowFor(item); 3983 if (itemWindow && itemWindow->isDirty()) { 3984 tristate result; 3985 if (item->neverSaved()) { 3986 result = true; 3987 } else { 3988 int prevWindowId = 0; 3989 if (!itemWindow->isVisible()) { 3990 prevWindowId = currentWindow()->id(); 3991 activateWindow(itemWindow->id()); 3992 } 3993 result = askOnExportingChangedQuery(item); 3994 3995 if (prevWindowId != 0) { 3996 activateWindow(prevWindowId); 3997 } 3998 } 3999 4000 if (~result) { 4001 return false; 4002 } else if (true == result) { 4003 args->insert("useTempQuery","1"); 4004 } 4005 } 4006 4007 return true; 4008 } 4009 4010 tristate KexiMainWindow::askOnExportingChangedQuery(KexiPart::Item *item) const 4011 { 4012 const KMessageBox::ButtonCode result = KMessageBox::warningYesNoCancel(const_cast<KexiMainWindow*>(this), 4013 xi18nc("@info", "Design of query <resource>%1</resource> that you want to export data" 4014 " from is changed and has not yet been saved. Do you want to use data" 4015 " from the changed query for exporting or from its original (saved)" 4016 " version?", item->captionOrName()), 4017 QString(), 4018 KGuiItem(xi18nc("@action:button Export query data", "Use the Changed Query")), 4019 KGuiItem(xi18nc("@action:button Export query data", "Use the Original Query")), 4020 KStandardGuiItem::cancel(), 4021 QString(), 4022 KMessageBox::Notify | KMessageBox::Dangerous); 4023 if (result == KMessageBox::Yes) { 4024 return true; 4025 } else if (result == KMessageBox::No) { 4026 return false; 4027 } 4028 4029 return cancelled; 4030 } 4031 4032 bool KexiMainWindow::printItem(KexiPart::Item* item, const QString& titleText) 4033 { 4034 //! @todo printItem(item, KexiSimplePrintingSettings::load(), titleText); 4035 Q_UNUSED(item) 4036 Q_UNUSED(titleText) 4037 return false; 4038 } 4039 4040 tristate KexiMainWindow::printItem(KexiPart::Item* item) 4041 { 4042 return printItem(item, QString()); 4043 } 4044 4045 bool KexiMainWindow::printPreviewForItem(KexiPart::Item* item, const QString& titleText, bool reload) 4046 { 4047 //! @todo printPreviewForItem(item, KexiSimplePrintingSettings::load(), titleText, reload); 4048 Q_UNUSED(item) 4049 Q_UNUSED(titleText) 4050 Q_UNUSED(reload) 4051 return false; 4052 } 4053 4054 tristate KexiMainWindow::printPreviewForItem(KexiPart::Item* item) 4055 { 4056 return printPreviewForItem(item, QString(), 4057 //! @todo store cached record data? 4058 true/*reload*/); 4059 } 4060 4061 tristate KexiMainWindow::showPageSetupForItem(KexiPart::Item* item) 4062 { 4063 Q_UNUSED(item) 4064 //! @todo check if changes to this object's design are saved, if not: ask for saving 4065 //! @todo accept record changes... 4066 //! @todo printActionForItem(item, PageSetupForItem); 4067 return false; 4068 } 4069 4070 //! @todo reenable printItem() when ported 4071 #if 0 4072 bool KexiMainWindow::printItem(KexiPart::Item* item, const KexiSimplePrintingSettings& settings, 4073 const QString& titleText) 4074 { 4075 //! @todo: check if changes to this object's design are saved, if not: ask for saving 4076 //! @todo: accept record changes... 4077 KexiSimplePrintingCommand cmd(this, item->identifier()); 4078 //modal 4079 return cmd.print(settings, titleText); 4080 } 4081 4082 bool KexiMainWindow::printPreviewForItem(KexiPart::Item* item, 4083 const KexiSimplePrintingSettings& settings, const QString& titleText, bool reload) 4084 { 4085 //! @todo: check if changes to this object's design are saved, if not: ask for saving 4086 //! @todo: accept record changes... 4087 KexiSimplePrintingCommand* cmd = d->openedCustomObjectsForItem<KexiSimplePrintingCommand>( 4088 item, "KexiSimplePrintingCommand"); 4089 if (!cmd) { 4090 d->addOpenedCustomObjectForItem( 4091 item, 4092 cmd = new KexiSimplePrintingCommand(this, item->identifier()), 4093 "KexiSimplePrintingCommand" 4094 ); 4095 } 4096 return cmd->showPrintPreview(settings, titleText, reload); 4097 } 4098 4099 tristate KexiMainWindow::printActionForItem(KexiPart::Item* item, PrintActionType action) 4100 { 4101 if (!item) 4102 return false; 4103 KexiPart::Info *info = Kexi::partManager().infoForPluginId(item->pluginId()); 4104 if (!info->isPrintingSupported()) 4105 return false; 4106 4107 KexiWindow *printingWindow = d->pageSetupWindows[ item->identifier()]; 4108 if (printingWindow) { 4109 if (!activateWindow(*printingWindow)) 4110 return false; 4111 if (action == PreviewItem || action == PrintItem) { 4112 QTimer::singleShot(0, printingWindow->selectedView(), 4113 (action == PreviewItem) ? SLOT(printPreview()) : SLOT(print())); 4114 } 4115 return true; 4116 } 4117 4118 #ifndef KEXI_NO_PENDING_DIALOGS 4119 Private::PendingJobType pendingType; 4120 KexiWindow *window = d->openedWindowFor(item, pendingType); 4121 if (pendingType != Private::NoJob) 4122 return cancelled; 4123 #else 4124 KexiWindow *window = openedWindowFor(item); 4125 #endif 4126 4127 if (window) { 4128 // accept record changes 4129 QWidget *prevFocusWidget = focusWidget(); 4130 window->setFocus(); 4131 d->action_data_save_row->activate(QAction::Trigger); 4132 if (prevFocusWidget) 4133 prevFocusWidget->setFocus(); 4134 4135 // opened: check if changes made to this dialog are saved, if not: ask for saving 4136 if (window->neverSaved()) //sanity check 4137 return false; 4138 if (window->isDirty()) { 4139 KGuiItem saveChanges(KStandardGuiItem::save()); 4140 saveChanges.setToolTip(futureI18n("Save changes")); 4141 saveChanges.setWhatsThis( 4142 futureI18n("Pressing this button will save all recent changes made in \"%1\" object.", 4143 item->name())); 4144 KGuiItem doNotSave(KStandardGuiItem::no()); 4145 doNotSave.setWhatsThis( 4146 futureI18n("Pressing this button will ignore all unsaved changes made in \"%1\" object.", 4147 window->partItem()->name())); 4148 4149 QString question; 4150 if (action == PrintItem) 4151 question = futureI18n("Do you want to save changes before printing?"); 4152 else if (action == PreviewItem) 4153 question = futureI18n("Do you want to save changes before making print preview?"); 4154 else if (action == PageSetupForItem) 4155 question = futureI18n("Do you want to save changes before showing page setup?"); 4156 else 4157 return false; 4158 4159 const KMessageBox::ButtonCode questionRes = KMessageBox::warningYesNoCancel(this, 4160 "<p>" 4161 + window->part()->i18nMessage("Design of object <resource>%1</resource> has been modified.", window) 4162 .subs(item->name()) 4163 + "</p><p>" + question + "</p>", 4164 QString(), 4165 saveChanges, 4166 doNotSave); 4167 if (KMessageBox::Cancel == questionRes) 4168 return cancelled; 4169 if (KMessageBox::Yes == questionRes) { 4170 tristate savingRes = saveObject(window, QString(), DoNotAsk); 4171 if (true != savingRes) 4172 return savingRes; 4173 } 4174 } 4175 } 4176 KexiPart::Part * printingPart = Kexi::partManager().partForClass("org.kexi-project.simpleprinting"); 4177 if (!printingPart) 4178 printingPart = new KexiSimplePrintingPart(); //hardcoded as there're no .desktop file 4179 KexiPart::Item* printingPartItem = d->prj->createPartItem( 4180 printingPart, item->name() //<-- this will look like "table1 : printing" on the window list 4181 ); 4182 QMap<QString, QVariant> staticObjectArgs; 4183 staticObjectArgs["identifier"] = QString::number(item->identifier()); 4184 if (action == PrintItem) 4185 staticObjectArgs["action"] = "print"; 4186 else if (action == PreviewItem) 4187 staticObjectArgs["action"] = "printPreview"; 4188 else if (action == PageSetupForItem) 4189 staticObjectArgs["action"] = "pageSetup"; 4190 else 4191 return false; 4192 bool openingCancelled; 4193 printingWindow = openObject(printingPartItem, Kexi::DesignViewMode, 4194 &openingCancelled, &staticObjectArgs); 4195 if (openingCancelled) 4196 return cancelled; 4197 if (!printingWindow) //sanity 4198 return false; 4199 d->pageSetupWindows.insert(item->identifier(), printingWindow); 4200 d->pageSetupWindowItemID2dataItemID_map.insert( 4201 printingWindow->partItem()->identifier(), item->identifier()); 4202 4203 return true; 4204 } 4205 #endif 4206 4207 void KexiMainWindow::slotEditCopySpecialDataTable() 4208 { 4209 KexiPart::Item* item = d->objectViewWidget->projectNavigator()->selectedPartItem(); 4210 if (item) 4211 copyItemToClipboardAsDataTable(item); 4212 } 4213 4214 tristate KexiMainWindow::copyItemToClipboardAsDataTable(KexiPart::Item* item) 4215 { 4216 if (!item) 4217 return false; 4218 4219 QMap<QString, QString> args; 4220 4221 if (!checkForDirtyFlagOnExport(item, &args)) { 4222 return false; 4223 } 4224 4225 args.insert("destinationType", "clipboard"); 4226 args.insert("itemId", QString::number(item->identifier())); 4227 QDialog *dlg = KexiInternalPart::createModalDialogInstance( 4228 "org.kexi-project.importexport.csv", "KexiCSVExportWizard", this, 0, &args); 4229 if (!dlg) 4230 return false; //error msg has been shown by KexiInternalPart 4231 const int result = dlg->exec(); 4232 delete dlg; 4233 return result == QDialog::Rejected ? tristate(cancelled) : tristate(true); 4234 } 4235 4236 void KexiMainWindow::slotEditPasteSpecialDataTable() 4237 { 4238 //! @todo allow data appending (it is not possible now) 4239 if (d->userMode) 4240 return; 4241 QMap<QString, QString> args; 4242 args.insert("sourceType", "clipboard"); 4243 QDialog *dlg = KexiInternalPart::createModalDialogInstance( 4244 "org.kexi-project.importexport.csv", "KexiCSVImportDialog", this, 0, &args); 4245 if (!dlg) 4246 return; //error msg has been shown by KexiInternalPart 4247 dlg->exec(); 4248 delete dlg; 4249 } 4250 4251 void KexiMainWindow::slotEditFind() 4252 { 4253 KexiSearchAndReplaceViewInterface* iface = d->currentViewSupportingSearchAndReplaceInterface(); 4254 if (!iface) 4255 return; 4256 d->updateFindDialogContents(true/*create if does not exist*/); 4257 d->findDialog()->setReplaceMode(false); 4258 4259 d->findDialog()->show(); 4260 d->findDialog()->activateWindow(); 4261 d->findDialog()->raise(); 4262 } 4263 4264 void KexiMainWindow::slotEditFind(bool next) 4265 { 4266 KexiSearchAndReplaceViewInterface* iface = d->currentViewSupportingSearchAndReplaceInterface(); 4267 if (!iface) 4268 return; 4269 tristate res = iface->find( 4270 d->findDialog()->valueToFind(), d->findDialog()->options(), next); 4271 if (~res) 4272 return; 4273 d->findDialog()->updateMessage(true == res); 4274 //! @todo result 4275 } 4276 4277 void KexiMainWindow::slotEditFindNext() 4278 { 4279 slotEditFind(true); 4280 } 4281 4282 void KexiMainWindow::slotEditFindPrevious() 4283 { 4284 slotEditFind(false); 4285 } 4286 4287 void KexiMainWindow::slotEditReplace() 4288 { 4289 KexiSearchAndReplaceViewInterface* iface = d->currentViewSupportingSearchAndReplaceInterface(); 4290 if (!iface) 4291 return; 4292 d->updateFindDialogContents(true/*create if does not exist*/); 4293 d->findDialog()->setReplaceMode(true); 4294 //! @todo slotEditReplace() 4295 d->findDialog()->show(); 4296 d->findDialog()->activateWindow(); 4297 } 4298 4299 void KexiMainWindow::slotEditReplaceNext() 4300 { 4301 slotEditReplace(false); 4302 } 4303 4304 void KexiMainWindow::slotEditReplace(bool all) 4305 { 4306 KexiSearchAndReplaceViewInterface* iface = d->currentViewSupportingSearchAndReplaceInterface(); 4307 if (!iface) 4308 return; 4309 //! @todo add question: "Do you want to replace every occurrence of \"%1\" with \"%2\"? 4310 //! You won't be able to undo this." + "Do not ask again". 4311 tristate res = iface->findNextAndReplace( 4312 d->findDialog()->valueToFind(), d->findDialog()->valueToReplaceWith(), 4313 d->findDialog()->options(), all); 4314 d->findDialog()->updateMessage(true == res); 4315 //! @todo result 4316 } 4317 4318 void KexiMainWindow::slotEditReplaceAll() 4319 { 4320 slotEditReplace(true); 4321 } 4322 4323 void KexiMainWindow::highlightObject(const QString& pluginId, const QString& name) 4324 { 4325 if (!d->prj) 4326 return; 4327 KexiPart::Item *item = d->prj->itemForPluginId(pluginId, name); 4328 if (!item) 4329 return; 4330 if (d->objectViewWidget && d->objectViewWidget->projectNavigator()) { 4331 d->setProjectNavigatorVisible(true, Private::ShowAnimated); 4332 d->objectViewWidget->projectNavigator()->selectItem(*item); 4333 } 4334 } 4335 4336 void KexiMainWindow::slotPartItemSelectedInNavigator(KexiPart::Item* item) 4337 { 4338 Q_UNUSED(item); 4339 } 4340 4341 KToolBar *KexiMainWindow::toolBar(const QString& name) const 4342 { 4343 return d->tabbedToolBar ? d->tabbedToolBar->toolBar(name) : 0; 4344 } 4345 4346 void KexiMainWindow::appendWidgetToToolbar(const QString& name, QWidget* widget) 4347 { 4348 if (d->tabbedToolBar) 4349 d->tabbedToolBar->appendWidgetToToolbar(name, widget); 4350 } 4351 4352 void KexiMainWindow::setWidgetVisibleInToolbar(QWidget* widget, bool visible) 4353 { 4354 if (d->tabbedToolBar) 4355 d->tabbedToolBar->setWidgetVisibleInToolbar(widget, visible); 4356 } 4357 4358 void KexiMainWindow::addToolBarAction(const QString& toolBarName, QAction *action) 4359 { 4360 if (d->tabbedToolBar) 4361 d->tabbedToolBar->addAction(toolBarName, action); 4362 } 4363 4364 void KexiMainWindow::updatePropertyEditorInfoLabel() 4365 { 4366 if (d->objectViewWidget && d->objectViewWidget->propertyPane()) { 4367 d->objectViewWidget->propertyPane()->updateInfoLabelForPropertySet( 4368 (currentWindow() && currentWindow()->selectedView()) 4369 ? currentWindow()->selectedView()->textToDisplayForNullSet() 4370 : QString()); 4371 } 4372 } 4373 4374 void KexiMainWindow::beginPropertyPaneUpdate() 4375 { 4376 if (d->propertyPaneAnimation) { 4377 d->propertyPaneAnimation->hide(); 4378 d->propertyPaneAnimation->deleteLater(); 4379 } 4380 d->propertyPaneAnimation = new KexiFadeWidgetEffect(d->objectViewWidget->propertyPane()); 4381 } 4382 4383 void KexiMainWindow::endPropertyPaneUpdate() 4384 { 4385 if (d->propertyPaneAnimation) { 4386 d->objectViewWidget->propertyPane()->repaint(); 4387 d->propertyPaneAnimation->start(150); 4388 } 4389 } 4390 4391 void KexiMainWindow::addSearchableModel(KexiSearchableModel *model) 4392 { 4393 if (d->tabbedToolBar) { 4394 d->tabbedToolBar->addSearchableModel(model); 4395 } 4396 } 4397 4398 void KexiMainWindow::removeSearchableModel(KexiSearchableModel *model) 4399 { 4400 if (d->tabbedToolBar) { 4401 d->tabbedToolBar->removeSearchableModel(model); 4402 } 4403 } 4404 4405 void KexiMainWindow::setReasonableDialogSize(QDialog *dialog) 4406 { 4407 dialog->setMinimumSize(600, 400); 4408 dialog->resize(size() * 0.8); 4409 } 4410 4411 void KexiMainWindow::restoreDesignTabAndActivateIfNeeded(const QString &tabName) 4412 { 4413 if (!d->tabbedToolBar) { 4414 return; 4415 } 4416 d->tabbedToolBar->showTab(tabName); 4417 if (currentWindow() && currentWindow()->partItem() 4418 && currentWindow()->partItem()->identifier() != 0) // for unstored items id can be < 0 4419 { 4420 const QString tabToActivate = d->tabsToActivateOnShow.value( 4421 currentWindow()->partItem()->identifier()); 4422 //qDebug() << "tabToActivate:" << tabToActivate << "tabName:" << tabName; 4423 if (tabToActivate == tabName) { 4424 d->tabbedToolBar->setCurrentTab(tabToActivate); 4425 } 4426 } 4427 } 4428 4429 void KexiMainWindow::restoreDesignTabIfNeeded(const QString &pluginId, Kexi::ViewMode viewMode, 4430 int previousItemId) 4431 { 4432 //qDebug() << pluginId << viewMode << previousItemId; 4433 if (viewMode == Kexi::DesignViewMode) { 4434 switch (d->prj->typeIdForPluginId(pluginId)) { 4435 case KexiPart::FormObjectType: { 4436 hideDesignTab(previousItemId, "org.kexi-project.report"); 4437 restoreDesignTabAndActivateIfNeeded("form"); 4438 break; 4439 } 4440 case KexiPart::ReportObjectType: { 4441 hideDesignTab(previousItemId, "org.kexi-project.form"); 4442 restoreDesignTabAndActivateIfNeeded("report"); 4443 break; 4444 } 4445 default: 4446 hideDesignTab(previousItemId); 4447 } 4448 } 4449 else { 4450 hideDesignTab(previousItemId); 4451 } 4452 } 4453 4454 void KexiMainWindow::activateDesignTab(const QString &pluginId) 4455 { 4456 if (!d->tabbedToolBar) { 4457 return; 4458 } 4459 switch (d->prj->typeIdForPluginId(pluginId)) { 4460 case KexiPart::FormObjectType: 4461 d->tabbedToolBar->setCurrentTab("form"); 4462 break; 4463 case KexiPart::ReportObjectType: 4464 d->tabbedToolBar->setCurrentTab("report"); 4465 break; 4466 default:; 4467 } 4468 } 4469 4470 void KexiMainWindow::activateDesignTabIfNeeded(const QString &pluginId, Kexi::ViewMode viewMode) 4471 { 4472 if (!d->tabbedToolBar) { 4473 return; 4474 } 4475 const QString tabToActivate = d->tabsToActivateOnShow.value(currentWindow()->partItem()->identifier()); 4476 //qDebug() << pluginId << viewMode << tabToActivate; 4477 4478 if (viewMode == Kexi::DesignViewMode && tabToActivate.isEmpty()) { 4479 activateDesignTab(pluginId); 4480 } 4481 else { 4482 d->tabbedToolBar->setCurrentTab(tabToActivate); 4483 } 4484 } 4485 4486 void KexiMainWindow::hideDesignTab(int itemId, const QString &pluginId) 4487 { 4488 if (!d->tabbedToolBar) { 4489 return; 4490 } 4491 //qDebug() << itemId << pluginId; 4492 if ( itemId > 0 4493 && d->tabbedToolBar->currentWidget()) 4494 { 4495 const QString currentTab = d->tabbedToolBar->currentWidget()->objectName(); 4496 //qDebug() << "d->tabsToActivateOnShow.insert" << itemId << currentTab; 4497 d->tabsToActivateOnShow.insert(itemId, currentTab); 4498 } 4499 switch (d->prj->typeIdForPluginId(pluginId)) { 4500 case KexiPart::FormObjectType: 4501 d->tabbedToolBar->hideTab("form"); 4502 break; 4503 case KexiPart::ReportObjectType: 4504 d->tabbedToolBar->hideTab("report"); 4505 break; 4506 default: 4507 d->tabbedToolBar->hideTab("form"); 4508 d->tabbedToolBar->hideTab("report"); 4509 } 4510 } 4511 4512 void KexiMainWindow::showDesignTabIfNeeded(int previousItemId) 4513 { 4514 if (d->insideCloseWindow && d->tabbedToolBar) 4515 return; 4516 if (currentWindow()) { 4517 restoreDesignTabIfNeeded(currentWindow()->partItem()->pluginId(), 4518 currentWindow()->currentViewMode(), previousItemId); 4519 } else { 4520 hideDesignTab(previousItemId); 4521 } 4522 } 4523 4524 KexiUserFeedbackAgent* KexiMainWindow::userFeedbackAgent() const 4525 { 4526 return &d->userFeedback; 4527 } 4528 4529 KexiMigrateManagerInterface* KexiMainWindow::migrateManager() 4530 { 4531 if (!d->migrateManager) { 4532 d->migrateManager = dynamic_cast<KexiMigrateManagerInterface*>( 4533 KexiInternalPart::createObjectInstance( 4534 "org.kexi-project.migration", "manager", this, this, nullptr)); 4535 } 4536 return d->migrateManager; 4537 } 4538 4539 void KexiMainWindow::toggleFullScreen(bool isFullScreen) 4540 { 4541 if (d->tabbedToolBar) { 4542 static bool isTabbarRolledDown; 4543 if (isFullScreen) { 4544 isTabbarRolledDown = !d->tabbedToolBar->isRolledUp(); 4545 if (isTabbarRolledDown) { 4546 d->tabbedToolBar->toggleRollDown(); 4547 } 4548 } else { 4549 if (isTabbarRolledDown && d->tabbedToolBar->isRolledUp()) { 4550 d->tabbedToolBar->toggleRollDown(); 4551 } 4552 } 4553 } 4554 const Qt::WindowStates s = windowState() & Qt::WindowMaximized; 4555 if (isFullScreen) { 4556 setWindowState(windowState() | Qt::WindowFullScreen | s); 4557 } else { 4558 setWindowState((windowState() & ~Qt::WindowFullScreen)); 4559 showMaximized(); 4560 } 4561 } 4562 4563 Kexi::GlobalViewMode KexiMainWindow::currentMode() const 4564 { 4565 return d->modeSelector->currentMode(); 4566 } 4567 4568 void KexiMainWindow::setCurrentMode(Kexi::GlobalViewMode mode) 4569 { 4570 d->modeSelector->setCurrentMode(mode); 4571 } 4572 4573 void KexiMainWindow::slotCurrentModeChanged(Kexi::GlobalViewMode previousMode) 4574 { 4575 const Kexi::ViewMode viewMode = currentWindow() 4576 ? currentWindow()->currentViewMode() : Kexi::NoViewMode; 4577 switch (d->modeSelector->currentMode()) { 4578 case Kexi::WelcomeGlobalMode: 4579 break; 4580 case Kexi::ProjectGlobalMode: 4581 break; 4582 case Kexi::EditGlobalMode: 4583 updateObjectView(); 4584 d->globalViewStack->setCurrentWidget(d->objectViewWidget); 4585 if (viewMode == Kexi::DesignViewMode || viewMode == Kexi::TextViewMode) { 4586 if (true != switchToViewMode(*currentWindow(), Kexi::DataViewMode)) { 4587 setCurrentMode(previousMode); 4588 } 4589 } 4590 break; 4591 case Kexi::DesignGlobalMode: 4592 updateObjectView(); 4593 d->globalViewStack->setCurrentWidget(d->objectViewWidget); 4594 if (viewMode == Kexi::DataViewMode) { 4595 Kexi::ViewMode newViewMode; 4596 if (currentWindow()->supportsViewMode(Kexi::TextViewMode) 4597 && d->modeSelector->keyboardModifiers() == Qt::CTRL) 4598 { 4599 newViewMode = Kexi::TextViewMode; 4600 } else { 4601 newViewMode = Kexi::DesignViewMode; 4602 } 4603 if (true != switchToViewMode(*currentWindow(), newViewMode)) { 4604 setCurrentMode(previousMode); 4605 } 4606 } 4607 break; 4608 case Kexi::HelpGlobalMode: 4609 break; 4610 case Kexi::NoGlobalMode: 4611 break; 4612 } 4613 } 4614 4615 void KexiMainWindow::slotProjectNavigatorVisibilityChanged(bool visible) 4616 { 4617 if (d->objectViewWidget && d->objectViewWidget->projectNavigator()) { 4618 d->modeSelector->setArrowColor(visible 4619 ? d->objectViewWidget->projectNavigator()->palette().color(QPalette::Window) 4620 : d->objectViewWidget->tabWidget()->palette().color(QPalette::Window)); 4621 } 4622 }