You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
966 lines
30 KiB
966 lines
30 KiB
/* 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 TQ_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 <tdelocale.h>
|
|
#include <kmimetype.h>
|
|
#include <tdemessagebox.h>
|
|
#include <tdecmdlineargs.h>
|
|
#include <tdeversion.h>
|
|
#include <kprogress.h>
|
|
#include <ktextedit.h>
|
|
#include <kstaticdeleter.h>
|
|
#include <kuser.h>
|
|
|
|
#include <unistd.h>
|
|
|
|
#include <tqcstring.h>
|
|
#include <tqapplication.h>
|
|
#include <tqlayout.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;
|
|
TQString shortcutFileGroupKey;
|
|
KexiStartupDialog *startupDialog;
|
|
};
|
|
|
|
//---------------------------------
|
|
|
|
static bool stripQuotes(const TQString &item, TQString &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;
|
|
TQCString 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+=TQChar(*p).latin1();
|
|
--i; --p;
|
|
int percent = line.toInt(&ok);
|
|
if (ok && percent>=0 && percent<=100 && pd->progressBar()->progress()<percent) {
|
|
// kdDebug() << percent << endl;
|
|
pd->progressBar()->setProgress(percent);
|
|
tqApp->processEvents(100);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
//---------------------------------
|
|
|
|
KexiDBPasswordDialog::KexiDBPasswordDialog(TQWidget *parent, KexiDB::ConnectionData& cdata, bool showDetailsButton)
|
|
: KPasswordDialog( KPasswordDialog::Password, false/*keep*/,
|
|
showDetailsButton ? (int)KDialogBase::User1 : 0, parent )
|
|
, m_cdata(&cdata)
|
|
, m_showConnectionDetailsRequested(false)
|
|
{
|
|
TQString 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>");*/
|
|
|
|
TQString srv = cdata.serverInfoString(false);
|
|
if (srv.isEmpty() || srv.lower()=="localhost")
|
|
srv = i18n("local database server");
|
|
|
|
msg += ("</p><p>"+i18n("Database server: %1").arg(TQString("<nobr>")+srv+"</nobr>")+"</p>");
|
|
|
|
TQString 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, TQT_SIGNAL(user1Clicked()),
|
|
this, TQT_SLOT(slotShowConnectionDetails()) );
|
|
setButtonText(KDialogBase::User1, i18n("&Details")+ " >>");
|
|
}
|
|
setButtonOK(KGuiItem(i18n("&Open"), "fileopen"));
|
|
}
|
|
|
|
KexiDBPasswordDialog::~KexiDBPasswordDialog()
|
|
{
|
|
}
|
|
|
|
void KexiDBPasswordDialog::done(int r)
|
|
{
|
|
if (r == TQDialog::Accepted) {
|
|
m_cdata->password = TQString::fromLatin1(password());
|
|
}
|
|
// if (d->showConnectionDetailsExecuted || ret == TQDialog::Accepted) {
|
|
/* } else {
|
|
m_action = Exit;
|
|
return true;
|
|
}
|
|
}*/
|
|
KPasswordDialog::done(r);
|
|
}
|
|
|
|
void KexiDBPasswordDialog::slotShowConnectionDetails()
|
|
{
|
|
m_showConnectionDetailsRequested = true;
|
|
close();
|
|
}
|
|
|
|
//---------------------------------
|
|
KexiStartupHandler::KexiStartupHandler()
|
|
: TQObject(0,"KexiStartupHandler")
|
|
, KexiStartupData()
|
|
, d( new KexiStartupHandlerPrivate() )
|
|
{
|
|
}
|
|
|
|
KexiStartupHandler::~KexiStartupHandler()
|
|
{
|
|
delete d;
|
|
}
|
|
|
|
bool KexiStartupHandler::getAutoopenObjects(TDECmdLineArgs *args, const TQCString &action_name)
|
|
{
|
|
QCStringList list = args->getOptionList(action_name);
|
|
QCStringList::ConstIterator it;
|
|
bool atLeastOneFound = false;
|
|
for ( it = list.constBegin(); it!=list.constEnd(); ++it) {
|
|
TQString 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...
|
|
TQString 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;
|
|
TDECmdLineArgs *args = TDECmdLineArgs::parsedArgs(0);
|
|
if (!args)
|
|
return true;
|
|
|
|
KexiDB::ConnectionData cdata;
|
|
|
|
const TQString 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(TQDir::convertSeparators(connectionShortcut.fileName())));
|
|
return false;
|
|
}
|
|
}
|
|
|
|
if (!args->getOption("dbdriver").isEmpty())
|
|
cdata.driverName = args->getOption("dbdriver");
|
|
|
|
TQString 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)
|
|
{
|
|
TQCString pwd(argv[i+1]);
|
|
if (!pwd.isEmpty()) {
|
|
pwd.fill(' ');
|
|
pwd[0]='x';
|
|
qstrcpy(argv[i+1], (const char*)pwd);
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
*/
|
|
|
|
const TQString 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 TQString couldnotMsg = TQString::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, TQT_SIGNAL(user1Clicked()),
|
|
// this, TQT_SLOT(slotShowConnectionDetails()) );
|
|
const int ret = d->passwordDialog->exec();
|
|
if (d->passwordDialog->showConnectionDetailsRequested() || ret == TQDialog::Accepted) {
|
|
// if ( ret == TQDialog::Accepted ) {
|
|
// if (TQDialog::Accepted == KPasswordDialog::getPassword(pwd, msg)) {
|
|
//moved cdata.password = TQString(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) {
|
|
TQString prjName;
|
|
TQString fileName;
|
|
if (fileDriverSelected) {
|
|
fileName = TQFile::decodeName(args->arg(0));
|
|
}
|
|
else {
|
|
prjName = TQString::fromLocal8Bit(args->arg(0));
|
|
}
|
|
|
|
if (fileDriverSelected) {
|
|
TQFileInfo 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(TQDir::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;
|
|
|
|
TQString 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(TQDir::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, TQT_SIGNAL(saveChanges()),
|
|
this, TQT_SLOT(slotSaveShortcutFileChanges()));
|
|
int res = d->connDialog->exec();
|
|
if (res == TQDialog::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 == TQDialog::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(TQDir::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, TQT_SIGNAL(saveChanges()),
|
|
this, TQT_SLOT(slotSaveShortcutFileChanges()));
|
|
}
|
|
const int res = d->connDialog->exec();
|
|
if (res == TQDialog::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, TQT_SIGNAL(saveChanges()),
|
|
// this, TQT_SLOT(slotSaveShortcutFileChanges()));
|
|
int res = d->connDialog->exec();
|
|
|
|
if (res == TQDialog::Accepted) {
|
|
//get (possibly changed) prj data
|
|
*m_projectData = d->connDialog->currentProjectData();
|
|
}
|
|
|
|
delete d->connDialog;
|
|
d->connDialog = 0;
|
|
|
|
if (res == TQDialog::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( TQDir::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( TQDir::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()!=TQDialog::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 TQString selFile( d->startupDialog->selectedFileName() );
|
|
cdata.setFileName( selFile );
|
|
TQString 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 TQString selFile( d->startupDialog->selectedFileName() );
|
|
if (!selFile.isEmpty()) {
|
|
//file-based project
|
|
// kdDebug() << "Project File: " << selFile << endl;
|
|
cdata.setFileName( selFile );
|
|
TQString 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, TQString& detectedDriverName,
|
|
const TQString& _suggestedDriverName, const TQString &dbFileName, TQWidget *parent, int options )
|
|
{
|
|
detectedImportAction = KexiStartupData::Import(); //clear
|
|
TQString suggestedDriverName(_suggestedDriverName); //safe
|
|
detectedDriverName = TQString();
|
|
TQFileInfo 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(TQDir::convertSeparators(dbFileName))
|
|
+i18n("Check the file's permissions and whether it is already opened "
|
|
"and locked by another application."));
|
|
return false;
|
|
}
|
|
|
|
KMimeType::Ptr ptr;
|
|
TQString 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
|
|
TQFile 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(TQDir::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(TQDir::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.:
|
|
TQString 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(TQDir::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 TQString 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(TQDir::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(TQDir::convertSeparators(dbFileName)).arg(newFileFormat) );
|
|
//continue...
|
|
}
|
|
if (res==true)
|
|
detectedDriverName = newFileFormat;
|
|
}
|
|
// action.driverName = detectedDriverName;
|
|
if (detectedDriverName.isEmpty()) {
|
|
TQString possibleProblemsInfoMsg( Kexi::driverManager().possibleProblemsInfoMsg() );
|
|
if (!possibleProblemsInfoMsg.isEmpty()) {
|
|
possibleProblemsInfoMsg.prepend(TQString::fromLatin1("<p>")+i18n("Possible problems:"));
|
|
possibleProblemsInfoMsg += TQString::fromLatin1("</p>");
|
|
}
|
|
if (!(options & SkipMessages))
|
|
KMessageBox::detailedSorry(parent,
|
|
i18n( "The file \"%1\" is not recognized as being supported by Kexi.")
|
|
.arg(TQDir::convertSeparators(dbFileName)),
|
|
TQString::fromLatin1("<p>")
|
|
+i18n("Database driver for this file type not found.\nDetected MIME type: %1")
|
|
.arg(mimename)
|
|
+(ptr.data()->comment().isEmpty()
|
|
? TQString::fromLatin1(".") : TQString::fromLatin1(" (%1).").arg(ptr.data()->comment()))
|
|
+TQString::fromLatin1("</p>")
|
|
+possibleProblemsInfoMsg);
|
|
return false;
|
|
}
|
|
return true;
|
|
}
|
|
|
|
KexiProjectData*
|
|
KexiStartupHandler::selectProject(KexiDB::ConnectionData *cdata, bool& cancelled, TQWidget *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 == TQDialog::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()!=TQDialog::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(TQDir::convertSeparators(d->shortcutFile->fileName())));
|
|
}
|
|
}
|
|
|
|
/*void KexiStartupHandler::slotShowConnectionDetails()
|
|
{
|
|
d->passwordDialog->close();
|
|
d->showConnectionDetailsExecuted = true;
|
|
}*/
|
|
|
|
#include "KexiStartup.moc"
|