summaryrefslogtreecommitdiffstats
path: root/kexi/main/startup/KexiStartup.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'kexi/main/startup/KexiStartup.cpp')
-rw-r--r--kexi/main/startup/KexiStartup.cpp965
1 files changed, 965 insertions, 0 deletions
diff --git a/kexi/main/startup/KexiStartup.cpp b/kexi/main/startup/KexiStartup.cpp
new file mode 100644
index 00000000..19ae8d28
--- /dev/null
+++ b/kexi/main/startup/KexiStartup.cpp
@@ -0,0 +1,965 @@
+/* This file is part of the KDE project
+ Copyright (C) 2003-2007 Jaroslaw Staniek <js@iidea.pl>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+*/
+
+#include "KexiStartup.h"
+#ifdef Q_WS_WIN
+# include "KexiStartup_p_win.h"
+#else
+# include "KexiStartup_p.h"
+#endif
+
+#include "kexiproject.h"
+#include "kexiprojectdata.h"
+#include "kexiprojectset.h"
+#include "kexiguimsghandler.h"
+
+#include <kexidb/driver.h>
+#include <kexidb/drivermanager.h>
+#include "KexiStartupDialog.h"
+#include "KexiConnSelector.h"
+#include "KexiProjectSelectorBase.h"
+#include "KexiProjectSelector.h"
+#include "KexiNewProjectWizard.h"
+#include <kexidbconnectionwidget.h>
+#include <kexidbshortcutfile.h>
+
+#include <kdebug.h>
+#include <klocale.h>
+#include <kmimetype.h>
+#include <kmessagebox.h>
+#include <kcmdlineargs.h>
+#include <kdeversion.h>
+#include <kprogress.h>
+#include <ktextedit.h>
+#include <kstaticdeleter.h>
+#include <kuser.h>
+
+#include <unistd.h>
+
+#include <qcstring.h>
+#include <qapplication.h>
+#include <qlayout.h>
+
+namespace Kexi {
+ static KStaticDeleter<KexiStartupHandler> Kexi_startupHandlerDeleter;
+ KexiStartupHandler* _startupHandler = 0;
+
+ KexiStartupHandler& startupHandler()
+ {
+ if (!_startupHandler)
+ Kexi_startupHandlerDeleter.setObject( _startupHandler, new KexiStartupHandler() );
+ return *_startupHandler;
+ }
+}
+
+//---------------------------------
+
+//! @internal
+class KexiStartupHandlerPrivate
+{
+ public:
+ KexiStartupHandlerPrivate()
+ : passwordDialog(0)//, showConnectionDetailsExecuted(false)
+ , shortcutFile(0), connShortcutFile(0), connDialog(0), startupDialog(0)
+ {
+ }
+
+ ~KexiStartupHandlerPrivate()
+ {
+ delete passwordDialog;
+ delete connDialog;
+ delete startupDialog;
+ }
+
+ KexiDBPasswordDialog* passwordDialog;
+// bool showConnectionDetailsExecuted : 1;
+ KexiDBShortcutFile *shortcutFile;
+ KexiDBConnShortcutFile *connShortcutFile;
+ KexiDBConnectionDialog *connDialog;
+ QString shortcutFileGroupKey;
+ KexiStartupDialog *startupDialog;
+};
+
+//---------------------------------
+
+static bool stripQuotes(const QString &item, QString &name)
+{
+ if (item.left(1)=="\"" && item.right(1)=="\"") {
+ name = item.mid(1, item.length()-2);
+ return true;
+ }
+ name = item;
+ return false;
+}
+
+void updateProgressBar(KProgressDialog *pd, char *buffer, int buflen)
+{
+ char *p = buffer;
+ QCString line(80);
+ for (int i=0; i<buflen; i++, p++) {
+ if ((i==0 || buffer[i-1]=='\n') && buffer[i]=='%') {
+ bool ok;
+ int j=0;
+// char *q=++p;
+ ++i;
+ line="";
+ for (;i<buflen && *p>='0' && *p<='9'; j++, i++, p++)
+ line+=QChar(*p);
+ --i; --p;
+ int percent = line.toInt(&ok);
+ if (ok && percent>=0 && percent<=100 && pd->progressBar()->progress()<percent) {
+// kdDebug() << percent << endl;
+ pd->progressBar()->setProgress(percent);
+ qApp->processEvents(100);
+ }
+ }
+ }
+}
+
+//---------------------------------
+
+KexiDBPasswordDialog::KexiDBPasswordDialog(QWidget *parent, KexiDB::ConnectionData& cdata, bool showDetailsButton)
+ : KPasswordDialog( KPasswordDialog::Password, false/*keep*/,
+ showDetailsButton ? (int)KDialogBase::User1 : 0, parent )
+ , m_cdata(&cdata)
+ , m_showConnectionDetailsRequested(false)
+{
+ QString msg = "<H2>" + i18n("Opening database") + "</H2><p>"
+ + i18n("Please enter the password.") + "</p>";
+/* msg += cdata.userName.isEmpty() ?
+ "<p>"+i18n("Please enter the password.")
+ : "<p>"+i18n("Please enter the password for user.").arg("<b>"+cdata.userName+"</b>");*/
+
+ QString srv = cdata.serverInfoString(false);
+ if (srv.isEmpty() || srv.lower()=="localhost")
+ srv = i18n("local database server");
+
+ msg += ("</p><p>"+i18n("Database server: %1").arg(QString("<nobr>")+srv+"</nobr>")+"</p>");
+
+ QString usr;
+ if (cdata.userName.isEmpty())
+ usr = i18n("unspecified user", "(unspecified)");
+ else
+ usr = cdata.userName;
+
+ msg += ("<p>"+i18n("Username: %1").arg(usr)+"</p>");
+
+ setPrompt( msg );
+ if (showDetailsButton) {
+ connect( this, SIGNAL(user1Clicked()),
+ this, SLOT(slotShowConnectionDetails()) );
+ setButtonText(KDialogBase::User1, i18n("&Details")+ " >>");
+ }
+ setButtonOK(KGuiItem(i18n("&Open"), "fileopen"));
+}
+
+KexiDBPasswordDialog::~KexiDBPasswordDialog()
+{
+}
+
+void KexiDBPasswordDialog::done(int r)
+{
+ if (r == QDialog::Accepted) {
+ m_cdata->password = QString::fromLatin1(password());
+ }
+// if (d->showConnectionDetailsExecuted || ret == QDialog::Accepted) {
+/* } else {
+ m_action = Exit;
+ return true;
+ }
+ }*/
+ KPasswordDialog::done(r);
+}
+
+void KexiDBPasswordDialog::slotShowConnectionDetails()
+{
+ m_showConnectionDetailsRequested = true;
+ close();
+}
+
+//---------------------------------
+KexiStartupHandler::KexiStartupHandler()
+ : QObject(0,"KexiStartupHandler")
+ , KexiStartupData()
+ , d( new KexiStartupHandlerPrivate() )
+{
+}
+
+KexiStartupHandler::~KexiStartupHandler()
+{
+ delete d;
+}
+
+bool KexiStartupHandler::getAutoopenObjects(KCmdLineArgs *args, const QCString &action_name)
+{
+ QCStringList list = args->getOptionList(action_name);
+ QCStringList::ConstIterator it;
+ bool atLeastOneFound = false;
+ for ( it = list.constBegin(); it!=list.constEnd(); ++it) {
+ QString type_name, obj_name, item=*it;
+ int idx;
+ bool name_required = true;
+ if (action_name=="new") {
+ obj_name = "";
+ stripQuotes(item, type_name);
+ name_required = false;
+ }
+ else {//open, design, text...
+ QString defaultType;
+ if (action_name=="execute")
+ defaultType = "macro";
+ else
+ defaultType = "table";
+
+ //option with " " (set default type)
+ if (stripQuotes(item, obj_name)) {
+ type_name = defaultType;
+ }
+ else if ((idx = item.find(':'))!=-1) {
+ //option with type name specified:
+ type_name = item.left(idx).lower();
+ obj_name = item.mid(idx+1);
+ //optional: remove ""
+ if (obj_name.left(1)=="\"" && obj_name.right(1)=="\"")
+ obj_name = obj_name.mid(1, obj_name.length()-2);
+ }
+ else {
+ //just obj. name: set default type name
+ obj_name = item;
+ type_name = defaultType;
+ }
+ }
+ if (type_name.isEmpty())
+ continue;
+ if (name_required && obj_name.isEmpty())
+ continue;
+
+ KexiProjectData::ObjectInfo info;
+ info["name"]=obj_name;
+ info["type"]=type_name;
+ info["action"]=action_name;
+ //ok, now add info for this object
+ atLeastOneFound = true;
+ if (projectData())
+ projectData()->autoopenObjects.append( info );
+ else
+ return true; //no need to find more because we do not have projectData() anyway
+ } //for
+ return atLeastOneFound;
+}
+
+tristate KexiStartupHandler::init(int /*argc*/, char ** /*argv*/)
+{
+ m_action = DoNothing;
+// d->showConnectionDetailsExecuted = false;
+ KCmdLineArgs *args = KCmdLineArgs::parsedArgs(0);
+ if (!args)
+ return true;
+
+ KexiDB::ConnectionData cdata;
+
+ const QString connectionShortcutFileName( args->getOption("connection") );
+ if (!connectionShortcutFileName.isEmpty()) {
+ KexiDBConnShortcutFile connectionShortcut( connectionShortcutFileName );
+ if (!connectionShortcut.loadConnectionData(cdata)) {
+//! @todo Show error message from KexiDBConnShortcutFile when there's one implemented.
+//! For we're displaying generic error msg.
+ KMessageBox::sorry( 0, "<qt>"
+ +i18n("Could not read connection information from connection shortcut "
+ "file <nobr>\"%1\"</nobr>.<br><br>Check whether the file has valid contents.")
+ .arg(QDir::convertSeparators(connectionShortcut.fileName())));
+ return false;
+ }
+ }
+
+ if (!args->getOption("dbdriver").isEmpty())
+ cdata.driverName = args->getOption("dbdriver");
+
+ QString fileType( args->getOption("type").lower() );
+ if (args->count()>0 && (!fileType.isEmpty() && fileType!="project" && fileType!="shortcut" && fileType!="connection")) {
+ KMessageBox::sorry( 0,
+ i18n("You have specified invalid argument (\"%1\") for \"type\" command-line option.")
+ .arg(fileType));
+ return false;
+ }
+
+// if (cdata.driverName.isEmpty())
+// cdata.driverName = KexiDB::Driver::defaultFileBasedDriverName();
+ if (!args->getOption("host").isEmpty())
+ cdata.hostName = args->getOption("host");
+ if (!args->getOption("local-socket").isEmpty())
+ cdata.localSocketFileName = args->getOption("local-socket");
+ if (!args->getOption("user").isEmpty())
+ cdata.userName = args->getOption("user");
+// cdata.password = args->getOption("password");
+ bool fileDriverSelected;
+ if (cdata.driverName.isEmpty())
+ fileDriverSelected = true;
+ else {
+ KexiDB::DriverManager dm;
+ KexiDB::Driver::Info dinfo = dm.driverInfo(cdata.driverName);
+ if (dinfo.name.isEmpty()) {
+ //driver name provided explicitly, but not found
+ KMessageBox::sorry(0, dm.errorMsg());
+ return false;
+ }
+ fileDriverSelected = dinfo.fileBased;
+ }
+ bool projectFileExists = false;
+
+ //obfuscate the password, if present
+//removed
+/*
+ for (int i=1; i<(argc-1); i++) {
+ if (qstrcmp("--password",argv[i])==0
+ || qstrcmp("-password",argv[i])==0)
+ {
+ QCString pwd(argv[i+1]);
+ if (!pwd.isEmpty()) {
+ pwd.fill(' ');
+ pwd[0]='x';
+ qstrcpy(argv[i+1], (const char*)pwd);
+ }
+ break;
+ }
+ }
+ */
+
+ const QString portStr = args->getOption("port");
+ if (!portStr.isEmpty()) {
+ bool ok;
+ const int p = portStr.toInt(&ok);
+ if (ok && p > 0)
+ cdata.port = p;
+ else {
+ KMessageBox::sorry( 0,
+ i18n("You have specified invalid port number \"%1\"."));
+ return false;
+ }
+ }
+
+ m_forcedUserMode = args->isSet("user-mode");
+ m_forcedDesignMode = args->isSet("design-mode");
+ m_isProjectNavigatorVisible = args->isSet("show-navigator");
+ bool createDB = args->isSet("createdb");
+ const bool alsoOpenDB = args->isSet("create-opendb");
+ if (alsoOpenDB)
+ createDB = true;
+ const bool dropDB = args->isSet("dropdb");
+ const bool openExisting = !createDB && !dropDB;
+ const bool readOnly = args->isSet("readonly");
+ const QString couldnotMsg = QString::fromLatin1("\n")
+ +i18n("Could not start Kexi application this way.");
+
+ if (createDB && dropDB) {
+ KMessageBox::sorry( 0, i18n(
+ "You have used both \"createdb\" and \"dropdb\" startup options.")+couldnotMsg);
+ return false;
+ };
+
+ if (createDB || dropDB) {
+ if (args->count()<1) {
+ KMessageBox::sorry( 0, i18n("No project name specified.") );
+ return false;
+ }
+ m_action = Exit;
+ }
+
+//TODO: add option for non-gui; integrate with KWallet;
+// move to static KexiProject method
+ if (!fileDriverSelected && !cdata.driverName.isEmpty() && cdata.password.isEmpty()) {
+
+ if (cdata.password.isEmpty()) {
+ delete d->passwordDialog;
+ d->passwordDialog = new KexiDBPasswordDialog(0, cdata, true);
+// connect( d->passwordDialog, SIGNAL(user1Clicked()),
+// this, SLOT(slotShowConnectionDetails()) );
+ const int ret = d->passwordDialog->exec();
+ if (d->passwordDialog->showConnectionDetailsRequested() || ret == QDialog::Accepted) {
+// if ( ret == QDialog::Accepted ) {
+ // if (QDialog::Accepted == KPasswordDialog::getPassword(pwd, msg)) {
+//moved cdata.password = QString(pwd);
+// }
+ } else {
+ m_action = Exit;
+ return true;
+ }
+ }
+ }
+
+/* kdDebug() << "ARGC==" << args->count() << endl;
+ for (int i=0;i<args->count();i++) {
+ kdDebug() << "ARG" <<i<< "= " << args->arg(i) <<endl;
+ }*/
+
+ if (m_forcedUserMode && m_forcedDesignMode) {
+ KMessageBox::sorry( 0, i18n(
+ "You have used both \"user-mode\" and \"design-mode\" startup options.")+couldnotMsg);
+ return false;
+ }
+
+ //database filenames, shortcut filenames or db names on a server
+ if (args->count()>=1) {
+ QString prjName;
+ QString fileName;
+ if (fileDriverSelected) {
+ fileName = QFile::decodeName(args->arg(0));
+ }
+ else {
+ prjName = QString::fromLocal8Bit(args->arg(0));
+ }
+
+ if (fileDriverSelected) {
+ QFileInfo finfo(fileName);
+ prjName = finfo.fileName(); //filename only, to avoid messy names like when Kexi is started with "../../db" arg
+ cdata.setFileName( finfo.absFilePath() );
+ projectFileExists = finfo.exists();
+
+ if (dropDB && !projectFileExists) {
+ KMessageBox::sorry(0,
+ i18n("Could not remove project.\nThe file \"%1\" does not exist.")
+ .arg(QDir::convertSeparators(cdata.dbFileName())));
+ return 0;
+ }
+ }
+
+ if (createDB) {
+ if (cdata.driverName.isEmpty())
+ cdata.driverName = KexiDB::Driver::defaultFileBasedDriverName();
+ m_projectData = new KexiProjectData(cdata, prjName); //dummy
+ }
+ else {
+ if (fileDriverSelected) {
+ int detectOptions = 0;
+ if (fileType=="project")
+ detectOptions |= ThisIsAProjectFile;
+ else if (fileType=="shortcut")
+ detectOptions |= ThisIsAShortcutToAProjectFile;
+ else if (fileType=="connection")
+ detectOptions |= ThisIsAShortcutToAConnectionData;
+
+ if (dropDB)
+ detectOptions |= DontConvert;
+
+ QString detectedDriverName;
+ const tristate res = detectActionForFile( m_importActionData, detectedDriverName,
+ cdata.driverName, cdata.fileName(), 0, detectOptions );
+ if (true != res)
+ return res;
+
+ if (m_importActionData) { //importing action
+ m_action = ImportProject;
+ return true;
+ }
+
+ //opening action
+ cdata.driverName = detectedDriverName;
+ if (cdata.driverName=="shortcut") {
+ //get information for a shortcut file
+ d->shortcutFile = new KexiDBShortcutFile(cdata.fileName());
+ m_projectData = new KexiProjectData();
+ if (!d->shortcutFile->loadProjectData(*m_projectData, &d->shortcutFileGroupKey)) {
+ KMessageBox::sorry(0, i18n("Could not open shortcut file\n\"%1\".")
+ .arg(QDir::convertSeparators(cdata.fileName())));
+ delete m_projectData;
+ m_projectData = 0;
+ delete d->shortcutFile;
+ d->shortcutFile = 0;
+ return false;
+ }
+ d->connDialog = new KexiDBConnectionDialog(
+ *m_projectData, d->shortcutFile->fileName());
+ connect(d->connDialog, SIGNAL(saveChanges()),
+ this, SLOT(slotSaveShortcutFileChanges()));
+ int res = d->connDialog->exec();
+ if (res == QDialog::Accepted) {
+ //get (possibly changed) prj data
+ *m_projectData = d->connDialog->currentProjectData();
+ }
+
+ delete d->connDialog;
+ d->connDialog = 0;
+ delete d->shortcutFile;
+ d->shortcutFile = 0;
+
+ if (res == QDialog::Rejected) {
+ delete m_projectData;
+ m_projectData = 0;
+ return cancelled;
+ }
+ }
+ else if (cdata.driverName=="connection") {
+ //get information for a connection file
+ d->connShortcutFile = new KexiDBConnShortcutFile(cdata.fileName());
+ if (!d->connShortcutFile->loadConnectionData(cdata, &d->shortcutFileGroupKey)) {
+ KMessageBox::sorry(0, i18n("Could not open connection data file\n\"%1\".")
+ .arg(QDir::convertSeparators(cdata.fileName())));
+ delete d->connShortcutFile;
+ d->connShortcutFile = 0;
+ return false;
+ }
+ bool cancel = false;
+ const bool showConnectionDialog = !args->isSet("skip-conn-dialog");
+ while (true) {
+ if (showConnectionDialog) {
+ //show connection dialog, so user can change parameters
+ if (!d->connDialog) {
+ d->connDialog = new KexiDBConnectionDialog(
+ cdata, d->connShortcutFile->fileName());
+ connect(d->connDialog, SIGNAL(saveChanges()),
+ this, SLOT(slotSaveShortcutFileChanges()));
+ }
+ const int res = d->connDialog->exec();
+ if (res == QDialog::Accepted) {
+ //get (possibly changed) prj data
+ cdata = *d->connDialog->currentProjectData().constConnectionData();
+ }
+ else {
+ cancel = true;
+ break;
+ }
+ }
+ m_projectData = selectProject(&cdata, cancel);
+ if (m_projectData || cancel || !showConnectionDialog)
+ break;
+ }
+
+ delete d->connShortcutFile;
+ d->connShortcutFile = 0;
+ delete d->connDialog;
+ d->connDialog = 0;
+
+ if (cancel)
+ return cancelled;
+ }
+ else
+ m_projectData = new KexiProjectData(cdata, prjName);
+ }
+ else
+ m_projectData = new KexiProjectData(cdata, prjName);
+
+ }
+// if (!m_projectData)
+// return false;
+ }
+ if (args->count()>1) {
+ //TODO: KRun another Kexi instances
+ }
+
+ //let's show connection details, user asked for that in the "password dialog"
+ if (d->passwordDialog && d->passwordDialog->showConnectionDetailsRequested()) {
+ d->connDialog = new KexiDBConnectionDialog(*m_projectData);
+// connect(d->connDialog->tabWidget->mainWidget, SIGNAL(saveChanges()),
+// this, SLOT(slotSaveShortcutFileChanges()));
+ int res = d->connDialog->exec();
+
+ if (res == QDialog::Accepted) {
+ //get (possibly changed) prj data
+ *m_projectData = d->connDialog->currentProjectData();
+ }
+
+ delete d->connDialog;
+ d->connDialog = 0;
+
+ if (res == QDialog::Rejected) {
+ delete m_projectData;
+ m_projectData = 0;
+ return cancelled;
+ }
+ }
+
+ //---autoopen objects:
+ const bool atLeastOneAOOFound = getAutoopenObjects(args, "open")
+ || getAutoopenObjects(args, "design")
+ || getAutoopenObjects(args, "edittext")
+ || getAutoopenObjects(args, "execute")
+ || getAutoopenObjects(args, "new")
+ || getAutoopenObjects(args, "print")
+ || getAutoopenObjects(args, "print-preview");
+
+ if (atLeastOneAOOFound && !openExisting) {
+ KMessageBox::information( 0,
+ i18n("You have specified a few database objects to be opened automatically, "
+ "using startup options.\n"
+ "These options will be ignored because it is not available while creating "
+ "or dropping projects."));
+ }
+
+ if (createDB) {
+ bool creationNancelled;
+ KexiGUIMessageHandler gui;
+ KexiProject *prj = KexiProject::createBlankProject(creationNancelled, projectData(), &gui);
+ bool ok = prj!=0;
+ delete prj;
+ if (creationNancelled)
+ return cancelled;
+ if (!alsoOpenDB) {
+ if (ok) {
+ KMessageBox::information( 0, i18n("Project \"%1\" created successfully.")
+ .arg( QDir::convertSeparators(projectData()->databaseName()) ));
+ }
+ return ok;
+ }
+ }
+ else if (dropDB) {
+ KexiGUIMessageHandler gui;
+ tristate res = KexiProject::dropProject(projectData(), &gui, false/*ask*/);
+ if (res==true)
+ KMessageBox::information( 0, i18n("Project \"%1\" dropped successfully.")
+ .arg( QDir::convertSeparators(projectData()->databaseName()) ));
+ return res!=false;
+ }
+
+ //------
+
+/* if (m_forcedFinalMode || (m_projectData && projectData->finalMode())) {
+ //TODO: maybe also auto allow to open objects...
+ KexiMainWindowImpl::initFinal(m_projectData);
+ return;
+ }*/
+
+ if (!m_projectData) {
+ cdata = KexiDB::ConnectionData(); //clear
+
+ if (args->isSet("skip-startup-dialog") || !KexiStartupDialog::shouldBeShown())
+ return true;
+
+ if (!d->startupDialog) {
+ //create d->startupDialog for reuse because it can be used again after conn err.
+ d->startupDialog = new KexiStartupDialog(
+ KexiStartupDialog::Everything, KexiStartupDialog::CheckBoxDoNotShowAgain,
+ Kexi::connset(), Kexi::recentProjects(), 0, "KexiStartupDialog");
+ }
+ if (d->startupDialog->exec()!=QDialog::Accepted)
+ return true;
+
+ const int r = d->startupDialog->result();
+ if (r == KexiStartupDialog::CreateBlankResult) {
+ m_action = CreateBlankProject;
+ return true;
+ }
+ else if (r == KexiStartupDialog::ImportResult) {
+ m_action = ImportProject;
+ return true;
+ }
+ else if (r == KexiStartupDialog::CreateFromTemplateResult) {
+ const QString selFile( d->startupDialog->selectedFileName() );
+ cdata.setFileName( selFile );
+ QString detectedDriverName;
+ const tristate res = detectActionForFile( m_importActionData, detectedDriverName,
+ cdata.driverName, selFile );
+ if (true != res)
+ return res;
+ if (m_importActionData || detectedDriverName.isEmpty())
+ return false;
+ cdata.driverName = detectedDriverName;
+ m_projectData = new KexiProjectData(cdata, selFile);
+ m_projectData->autoopenObjects = d->startupDialog->autoopenObjects();
+ m_action = CreateFromTemplate;
+ return true;
+ }
+ else if (r == KexiStartupDialog::OpenExistingResult) {
+// kdDebug() << "Existing project --------" << endl;
+ const QString selFile( d->startupDialog->selectedFileName() );
+ if (!selFile.isEmpty()) {
+ //file-based project
+// kdDebug() << "Project File: " << selFile << endl;
+ cdata.setFileName( selFile );
+ QString detectedDriverName;
+ const tristate res = detectActionForFile( m_importActionData, detectedDriverName,
+ cdata.driverName, selFile );
+ if (true != res)
+ return res;
+ if (m_importActionData) { //importing action
+ m_action = ImportProject;
+ return true;
+ }
+
+ if (detectedDriverName.isEmpty())
+ return false;
+ cdata.driverName = detectedDriverName;
+ m_projectData = new KexiProjectData(cdata, selFile);
+ }
+ else if (d->startupDialog->selectedExistingConnection()) {
+// kdDebug() << "Existing connection: " <<
+// d->startupDialog->selectedExistingConnection()->serverInfoString() << endl;
+ KexiDB::ConnectionData *cdata = d->startupDialog->selectedExistingConnection();
+ //ok, now we will try to show projects for this connection to the user
+ bool cancelled;
+ m_projectData = selectProject( cdata, cancelled );
+ if (!m_projectData && !cancelled || cancelled) {
+ //try again
+ return init(0, 0);
+ }
+ //not needed anymore
+ delete d->startupDialog;
+ d->startupDialog = 0;
+ }
+ }
+ else if (r==KexiStartupDialog::OpenRecentResult) {
+// kdDebug() << "Recent project --------" << endl;
+ const KexiProjectData *data = d->startupDialog->selectedProjectData();
+ if (data) {
+// kdDebug() << "Selected project: database=" << data->databaseName()
+// << " connection=" << data->constConnectionData()->serverInfoString() << endl;
+ }
+//! @todo
+ return data!=0;
+ }
+
+ if (!m_projectData)
+ return true;
+ }
+
+ if (m_projectData && (openExisting || (createDB && alsoOpenDB))) {
+ m_projectData->setReadOnly( readOnly );
+ m_action = OpenProject;
+ }
+ //show if wasn't show yet
+// importantInfo(true);
+
+ return true;
+}
+
+tristate KexiStartupHandler::detectActionForFile(
+ KexiStartupData::Import& detectedImportAction, QString& detectedDriverName,
+ const QString& _suggestedDriverName, const QString &dbFileName, QWidget *parent, int options )
+{
+ detectedImportAction = KexiStartupData::Import(); //clear
+ QString suggestedDriverName(_suggestedDriverName); //safe
+ detectedDriverName = QString::null;
+ QFileInfo finfo(dbFileName);
+ if (dbFileName.isEmpty() || !finfo.isReadable()) {
+ if (!(options & SkipMessages))
+ KMessageBox::sorry(parent, i18n("<p>Could not open project.</p>")
+ +i18n("<p>The file <nobr>\"%1\"</nobr> does not exist or is not readable.</p>")
+ .arg(QDir::convertSeparators(dbFileName))
+ +i18n("Check the file's permissions and whether it is already opened "
+ "and locked by another application."));
+ return false;
+ }
+
+ KMimeType::Ptr ptr;
+ QString mimename;
+
+ const bool thisIsShortcut = (options & ThisIsAShortcutToAProjectFile)
+ || (options & ThisIsAShortcutToAConnectionData);
+
+ if ((options & ThisIsAProjectFile) || !thisIsShortcut) {
+ //try this detection if "project file" mode is forced or no type is forced:
+ ptr = KMimeType::findByFileContent(dbFileName);
+ mimename = ptr.data()->name();
+ kdDebug() << "KexiStartupHandler::detectActionForFile(): found mime is: "
+ << mimename << endl;
+ if (mimename.isEmpty() || mimename=="application/octet-stream" || mimename=="text/plain") {
+ //try by URL:
+ ptr = KMimeType::findByURL(dbFileName);
+ mimename = ptr.data()->name();
+ }
+ }
+ if (mimename.isEmpty() || mimename=="application/octet-stream") {
+ // perhaps the file is locked
+ QFile f(dbFileName);
+ if (!f.open(IO_ReadOnly)) {
+ // BTW: similar error msg is provided in SQLiteConnection::drv_useDatabase()
+ if (!(options & SkipMessages))
+ KMessageBox::sorry(parent, i18n("<p>Could not open project.</p>")
+ +i18n("<p>The file <nobr>\"%1\"</nobr> is not readable.</p>")
+ .arg(QDir::convertSeparators(dbFileName))
+ +i18n("Check the file's permissions and whether it is already opened "
+ "and locked by another application."));
+ return false;
+ }
+ }
+ if ((options & ThisIsAShortcutToAProjectFile) || mimename=="application/x-kexiproject-shortcut") {
+ detectedDriverName = "shortcut";
+ return true;
+ }
+
+ if ((options & ThisIsAShortcutToAConnectionData) || mimename=="application/x-kexi-connectiondata") {
+ detectedDriverName = "connection";
+ return true;
+ }
+
+ //! @todo rather check this using migration drivers'
+ //! X-KexiSupportedMimeTypes [strlist] property
+ if (ptr.data()) {
+ if (mimename=="application/x-msaccess") {
+ if ((options & SkipMessages) || KMessageBox::Yes != KMessageBox::questionYesNo(
+ parent, i18n("\"%1\" is an external file of type:\n\"%2\".\n"
+ "Do you want to import the file as a Kexi project?")
+ .arg(QDir::convertSeparators(dbFileName)).arg(ptr.data()->comment()),
+ i18n("Open External File"), KGuiItem(i18n("Import...")), KStdGuiItem::cancel() ) )
+ {
+ return cancelled;
+ }
+ detectedImportAction.mimeType = mimename;
+ detectedImportAction.fileName = dbFileName;
+ return true;
+ }
+ }
+
+ if (!finfo.isWritable()) {
+ //! @todo if file is ro: change project mode (but do not care if we're jsut importing)
+ }
+
+ // "application/x-kexiproject-sqlite", etc.:
+ QString tmpDriverName = Kexi::driverManager().lookupByMime(mimename).latin1();
+//@todo What about trying to reuse KOFFICE FILTER CHAINS here?
+ bool useDetectedDriver = suggestedDriverName.isEmpty() || suggestedDriverName.lower()==detectedDriverName.lower();
+ if (!useDetectedDriver) {
+ int res = KMessageBox::Yes;
+ if (!(options & SkipMessages))
+ res = KMessageBox::warningYesNoCancel(parent, i18n(
+ "The project file \"%1\" is recognized as compatible with \"%2\" database driver, "
+ "while you have asked for \"%3\" database driver to be used.\n"
+ "Do you want to use \"%4\" database driver?")
+ .arg(QDir::convertSeparators(dbFileName))
+ .arg(tmpDriverName).arg(suggestedDriverName).arg(tmpDriverName));
+ if (KMessageBox::Yes == res)
+ useDetectedDriver = true;
+ else if (KMessageBox::Cancel == res)
+ return cancelled;
+ }
+ if (useDetectedDriver) {
+ detectedDriverName = tmpDriverName;
+ }
+ else {//use suggested driver
+ detectedDriverName = suggestedDriverName;
+ }
+// kdDebug() << "KexiStartupHandler::detectActionForFile(): driver name: " << detectedDriverName << endl;
+//hardcoded for convenience:
+ const QString newFileFormat = "SQLite3";
+ if (!(options & DontConvert || options & SkipMessages)
+ && detectedDriverName.lower()=="sqlite2" && detectedDriverName.lower()!=suggestedDriverName.lower()
+ && KMessageBox::Yes == KMessageBox::questionYesNo(parent, i18n(
+ "Previous version of database file format (\"%1\") is detected in the \"%2\" "
+ "project file.\nDo you want to convert the project to a new \"%3\" format (recommended)?")
+ .arg(detectedDriverName).arg(QDir::convertSeparators(dbFileName)).arg(newFileFormat)) )
+ {
+// SQLite2ToSQLite3Migration *migr = new
+ SQLite2ToSQLite3Migration migr( finfo.absFilePath() );
+ tristate res = migr.run();
+// kdDebug() << "--- migr.run() END ---" <<endl;
+ if (!res) {
+ //TODO msg
+ KMessageBox::sorry(parent, i18n(
+ "Failed to convert project file \"%1\" to a new \"%2\" format.\n"
+ "The file format remains unchanged.")
+ .arg(QDir::convertSeparators(dbFileName)).arg(newFileFormat) );
+ //continue...
+ }
+ if (res==true)
+ detectedDriverName = newFileFormat;
+ }
+// action.driverName = detectedDriverName;
+ if (detectedDriverName.isEmpty()) {
+ QString possibleProblemsInfoMsg( Kexi::driverManager().possibleProblemsInfoMsg() );
+ if (!possibleProblemsInfoMsg.isEmpty()) {
+ possibleProblemsInfoMsg.prepend(QString::fromLatin1("<p>")+i18n("Possible problems:"));
+ possibleProblemsInfoMsg += QString::fromLatin1("</p>");
+ }
+ if (!(options & SkipMessages))
+ KMessageBox::detailedSorry(parent,
+ i18n( "The file \"%1\" is not recognized as being supported by Kexi.")
+ .arg(QDir::convertSeparators(dbFileName)),
+ QString::fromLatin1("<p>")
+ +i18n("Database driver for this file type not found.\nDetected MIME type: %1")
+ .arg(mimename)
+ +(ptr.data()->comment().isEmpty()
+ ? QString::fromLatin1(".") : QString::fromLatin1(" (%1).").arg(ptr.data()->comment()))
+ +QString::fromLatin1("</p>")
+ +possibleProblemsInfoMsg);
+ return false;
+ }
+ return true;
+}
+
+KexiProjectData*
+KexiStartupHandler::selectProject(KexiDB::ConnectionData *cdata, bool& cancelled, QWidget *parent)
+{
+ clearStatus();
+ cancelled = false;
+ if (!cdata)
+ return 0;
+ if (!cdata->savePassword && cdata->password.isEmpty()) {
+ if (!d->passwordDialog)
+ d->passwordDialog = new KexiDBPasswordDialog(0, *cdata, false);
+ const int ret = d->passwordDialog->exec();
+ if (d->passwordDialog->showConnectionDetailsRequested() || ret == QDialog::Accepted) {
+
+ } else {
+ cancelled = true;
+ return 0;
+ }
+ }
+ KexiProjectData* projectData = 0;
+ //dialog for selecting a project
+ KexiProjectSelectorDialog prjdlg( parent, "prjdlg", cdata, true, false );
+ if (!prjdlg.projectSet() || prjdlg.projectSet()->error()) {
+ KexiGUIMessageHandler msgh;
+ if (prjdlg.projectSet())
+ msgh.showErrorMessage(prjdlg.projectSet(),
+ i18n("Could not load list of available projects for <b>%1</b> database server.")
+ .arg(cdata->serverInfoString(true)));
+ else
+ msgh.showErrorMessage(
+ i18n("Could not load list of available projects for <b>%1</b> database server.")
+ .arg(cdata->serverInfoString(true)));
+// setStatus(i18n("Could not load list of available projects for database server \"%1\"")
+// .arg(cdata->serverInfoString(true)), prjdlg.projectSet()->errorMsg());
+ return 0;
+ }
+ if (prjdlg.exec()!=QDialog::Accepted) {
+ cancelled = true;
+ return 0;
+ }
+ if (prjdlg.selectedProjectData()) {
+ //deep copy
+ projectData = new KexiProjectData(*prjdlg.selectedProjectData());
+ }
+ return projectData;
+}
+
+void KexiStartupHandler::slotSaveShortcutFileChanges()
+{
+ bool ok = true;
+ if (d->shortcutFile)
+ ok = d->shortcutFile->saveProjectData(d->connDialog->currentProjectData(),
+ d->connDialog->savePasswordOptionSelected(),
+ &d->shortcutFileGroupKey );
+ else if (d->connShortcutFile)
+ ok = d->connShortcutFile->saveConnectionData(
+ *d->connDialog->currentProjectData().connectionData(),
+ d->connDialog->savePasswordOptionSelected(),
+ &d->shortcutFileGroupKey );
+
+ if (!ok) {
+ KMessageBox::sorry(0, i18n("Failed saving connection data to\n\"%1\" file.")
+ .arg(QDir::convertSeparators(d->shortcutFile->fileName())));
+ }
+}
+
+/*void KexiStartupHandler::slotShowConnectionDetails()
+{
+ d->passwordDialog->close();
+ d->showConnectionDetailsExecuted = true;
+}*/
+
+#include "KexiStartup.moc"