00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020 #include "KexiStartup.h"
00021 #ifdef Q_WS_WIN
00022 # include "KexiStartup_p_win.h"
00023 #else
00024 # include "KexiStartup_p.h"
00025 #endif
00026
00027 #include "kexiproject.h"
00028 #include "kexiprojectdata.h"
00029 #include "kexiprojectset.h"
00030 #include "kexiguimsghandler.h"
00031
00032 #include <kexidb/driver.h>
00033 #include <kexidb/drivermanager.h>
00034 #include "KexiStartupDialog.h"
00035 #include "KexiConnSelector.h"
00036 #include "KexiProjectSelectorBase.h"
00037 #include "KexiProjectSelector.h"
00038 #include "KexiNewProjectWizard.h"
00039 #include <kexidbconnectionwidget.h>
00040 #include <kexidbshortcutfile.h>
00041
00042 #include <kdebug.h>
00043 #include <klocale.h>
00044 #include <kmimetype.h>
00045 #include <kmessagebox.h>
00046 #include <kcmdlineargs.h>
00047 #include <kdeversion.h>
00048 #include <kprogress.h>
00049 #include <ktextedit.h>
00050 #include <kstaticdeleter.h>
00051 #include <kuser.h>
00052
00053 #include <unistd.h>
00054
00055 #include <qcstring.h>
00056 #include <qapplication.h>
00057 #include <qlayout.h>
00058
00059 namespace Kexi {
00060 static KStaticDeleter<KexiStartupHandler> Kexi_startupHandlerDeleter;
00061 KexiStartupHandler* _startupHandler = 0;
00062
00063 KexiStartupHandler& startupHandler()
00064 {
00065 if (!_startupHandler)
00066 Kexi_startupHandlerDeleter.setObject( _startupHandler, new KexiStartupHandler() );
00067 return *_startupHandler;
00068 }
00069 }
00070
00071
00072
00074 class KexiStartupHandlerPrivate
00075 {
00076 public:
00077 KexiStartupHandlerPrivate()
00078 : passwordDialog(0)
00079 , shortcutFile(0), connShortcutFile(0), connDialog(0), startupDialog(0)
00080 {
00081 }
00082
00083 ~KexiStartupHandlerPrivate()
00084 {
00085 delete passwordDialog;
00086 delete connDialog;
00087 delete startupDialog;
00088 }
00089
00090 KexiDBPasswordDialog* passwordDialog;
00091
00092 KexiDBShortcutFile *shortcutFile;
00093 KexiDBConnShortcutFile *connShortcutFile;
00094 KexiDBConnectionDialog *connDialog;
00095 QString shortcutFileGroupKey;
00096 KexiStartupDialog *startupDialog;
00097 };
00098
00099
00100
00101 static bool stripQuotes(const QString &item, QString &name)
00102 {
00103 if (item.left(1)=="\"" && item.right(1)=="\"") {
00104 name = item.mid(1, item.length()-2);
00105 return true;
00106 }
00107 name = item;
00108 return false;
00109 }
00110
00111 void updateProgressBar(KProgressDialog *pd, char *buffer, int buflen)
00112 {
00113 char *p = buffer;
00114 QCString line(80);
00115 for (int i=0; i<buflen; i++, p++) {
00116 if ((i==0 || buffer[i-1]=='\n') && buffer[i]=='%') {
00117 bool ok;
00118 int j=0;
00119
00120 ++i;
00121 line="";
00122 for (;i<buflen && *p>='0' && *p<='9'; j++, i++, p++)
00123 line+=QChar(*p);
00124 --i; --p;
00125 int percent = line.toInt(&ok);
00126 if (ok && percent>=0 && percent<=100 && pd->progressBar()->progress()<percent) {
00127
00128 pd->progressBar()->setProgress(percent);
00129 qApp->processEvents(100);
00130 }
00131 }
00132 }
00133 }
00134
00135
00136
00137 KexiDBPasswordDialog::KexiDBPasswordDialog(QWidget *parent, KexiDB::ConnectionData& cdata, bool showDetailsButton)
00138 : KPasswordDialog( KPasswordDialog::Password, false,
00139 showDetailsButton ? (int)KDialogBase::User1 : 0, parent )
00140 , m_cdata(&cdata)
00141 , m_showConnectionDetailsRequested(false)
00142 {
00143 QString msg = "<H2>" + i18n("Opening database") + "</H2><p>"
00144 + i18n("Please enter the password.") + "</p>";
00145
00146
00147
00148
00149 QString srv = cdata.serverInfoString(false);
00150 if (srv.isEmpty() || srv.lower()=="localhost")
00151 srv = i18n("local database server");
00152
00153 msg += ("</p><p>"+i18n("Database server: %1").arg(QString("<nobr>")+srv+"</nobr>")+"</p>");
00154
00155 QString usr;
00156 if (cdata.userName.isEmpty())
00157 usr = i18n("unspecified user", "(unspecified)");
00158 else
00159 usr = cdata.userName;
00160
00161 msg += ("<p>"+i18n("Username: %1").arg(usr)+"</p>");
00162
00163 setPrompt( msg );
00164 if (showDetailsButton) {
00165 connect( this, SIGNAL(user1Clicked()),
00166 this, SLOT(slotShowConnectionDetails()) );
00167 setButtonText(KDialogBase::User1, i18n("&Details")+ " >>");
00168 }
00169 setButtonOK(KGuiItem(i18n("&Open"), "fileopen"));
00170 }
00171
00172 KexiDBPasswordDialog::~KexiDBPasswordDialog()
00173 {
00174 }
00175
00176 void KexiDBPasswordDialog::done(int r)
00177 {
00178 if (r == QDialog::Accepted) {
00179 m_cdata->password = QString::fromLatin1(password());
00180 }
00181
00182
00183
00184
00185
00186
00187 KPasswordDialog::done(r);
00188 }
00189
00190 void KexiDBPasswordDialog::slotShowConnectionDetails()
00191 {
00192 m_showConnectionDetailsRequested = true;
00193 close();
00194 }
00195
00196
00197 KexiStartupHandler::KexiStartupHandler()
00198 : QObject(0,"KexiStartupHandler")
00199 , KexiStartupData()
00200 , d( new KexiStartupHandlerPrivate() )
00201 {
00202 }
00203
00204 KexiStartupHandler::~KexiStartupHandler()
00205 {
00206 delete d;
00207 }
00208
00209 bool KexiStartupHandler::getAutoopenObjects(KCmdLineArgs *args, const QCString &action_name)
00210 {
00211 QCStringList list = args->getOptionList(action_name);
00212 QCStringList::ConstIterator it;
00213 bool atLeastOneFound = false;
00214 for ( it = list.constBegin(); it!=list.constEnd(); ++it) {
00215 QString type_name, obj_name, item=*it;
00216 int idx;
00217 bool name_required = true;
00218 if (action_name=="new") {
00219 obj_name = "";
00220 stripQuotes(item, type_name);
00221 name_required = false;
00222 }
00223 else {
00224 QString defaultType;
00225 if (action_name=="execute")
00226 defaultType = "macro";
00227 else
00228 defaultType = "table";
00229
00230
00231 if (stripQuotes(item, obj_name)) {
00232 type_name = defaultType;
00233 }
00234 else if ((idx = item.find(':'))!=-1) {
00235
00236 type_name = item.left(idx).lower();
00237 obj_name = item.mid(idx+1);
00238
00239 if (obj_name.left(1)=="\"" && obj_name.right(1)=="\"")
00240 obj_name = obj_name.mid(1, obj_name.length()-2);
00241 }
00242 else {
00243
00244 obj_name = item;
00245 type_name = defaultType;
00246 }
00247 }
00248 if (type_name.isEmpty())
00249 continue;
00250 if (name_required && obj_name.isEmpty())
00251 continue;
00252
00253 KexiProjectData::ObjectInfo info;
00254 info["name"]=obj_name;
00255 info["type"]=type_name;
00256 info["action"]=action_name;
00257
00258 atLeastOneFound = true;
00259 if (projectData())
00260 projectData()->autoopenObjects.append( info );
00261 else
00262 return true;
00263 }
00264 return atLeastOneFound;
00265 }
00266
00267 tristate KexiStartupHandler::init(int , char ** )
00268 {
00269 m_action = DoNothing;
00270
00271 KCmdLineArgs *args = KCmdLineArgs::parsedArgs(0);
00272 if (!args)
00273 return true;
00274
00275 KexiDB::ConnectionData cdata;
00276
00277 const QString connectionShortcutFileName( args->getOption("connection") );
00278 if (!connectionShortcutFileName.isEmpty()) {
00279 KexiDBConnShortcutFile connectionShortcut( connectionShortcutFileName );
00280 if (!connectionShortcut.loadConnectionData(cdata)) {
00283 KMessageBox::sorry( 0, "<qt>"
00284 +i18n("Could not read connection information from connection shortcut "
00285 "file <nobr>\"%1\"</nobr>.<br><br>Check whether the file has valid contents.")
00286 .arg(QDir::convertSeparators(connectionShortcut.fileName())));
00287 return false;
00288 }
00289 }
00290
00291 if (!args->getOption("dbdriver").isEmpty())
00292 cdata.driverName = args->getOption("dbdriver");
00293
00294 QString fileType( args->getOption("type").lower() );
00295 if (args->count()>0 && (!fileType.isEmpty() && fileType!="project" && fileType!="shortcut" && fileType!="connection")) {
00296 KMessageBox::sorry( 0,
00297 i18n("You have specified invalid argument (\"%1\") for \"type\" command-line option.")
00298 .arg(fileType));
00299 return false;
00300 }
00301
00302
00303
00304 if (!args->getOption("host").isEmpty())
00305 cdata.hostName = args->getOption("host");
00306 if (!args->getOption("local-socket").isEmpty())
00307 cdata.localSocketFileName = args->getOption("local-socket");
00308 if (!args->getOption("user").isEmpty())
00309 cdata.userName = args->getOption("user");
00310
00311 bool fileDriverSelected;
00312 if (cdata.driverName.isEmpty())
00313 fileDriverSelected = true;
00314 else {
00315 KexiDB::DriverManager dm;
00316 KexiDB::Driver::Info dinfo = dm.driverInfo(cdata.driverName);
00317 if (dinfo.name.isEmpty()) {
00318
00319 KMessageBox::sorry(0, dm.errorMsg());
00320 return false;
00321 }
00322 fileDriverSelected = dinfo.fileBased;
00323 }
00324 bool projectFileExists = false;
00325
00326
00327
00328
00329
00330
00331
00332
00333
00334
00335
00336
00337
00338
00339
00340
00341
00342
00343
00344 const QString portStr = args->getOption("port");
00345 if (!portStr.isEmpty()) {
00346 bool ok;
00347 const int p = portStr.toInt(&ok);
00348 if (ok && p > 0)
00349 cdata.port = p;
00350 else {
00351 KMessageBox::sorry( 0,
00352 i18n("You have specified invalid port number \"%1\"."));
00353 return false;
00354 }
00355 }
00356
00357 m_forcedUserMode = args->isSet("user-mode");
00358 m_forcedDesignMode = args->isSet("design-mode");
00359 m_isProjectNavigatorVisible = args->isSet("show-navigator");
00360 bool createDB = args->isSet("createdb");
00361 const bool alsoOpenDB = args->isSet("create-opendb");
00362 if (alsoOpenDB)
00363 createDB = true;
00364 const bool dropDB = args->isSet("dropdb");
00365 const bool openExisting = !createDB && !dropDB;
00366 const bool readOnly = args->isSet("readonly");
00367 const QString couldnotMsg = QString::fromLatin1("\n")
00368 +i18n("Could not start Kexi application this way.");
00369
00370 if (createDB && dropDB) {
00371 KMessageBox::sorry( 0, i18n(
00372 "You have used both \"createdb\" and \"dropdb\" startup options.")+couldnotMsg);
00373 return false;
00374 };
00375
00376 if (createDB || dropDB) {
00377 if (args->count()<1) {
00378 KMessageBox::sorry( 0, i18n("No project name specified.") );
00379 return false;
00380 }
00381 m_action = Exit;
00382 }
00383
00384
00385
00386 if (!fileDriverSelected && !cdata.driverName.isEmpty() && cdata.password.isEmpty()) {
00387
00388 if (cdata.password.isEmpty()) {
00389 delete d->passwordDialog;
00390 d->passwordDialog = new KexiDBPasswordDialog(0, cdata, true);
00391
00392
00393 const int ret = d->passwordDialog->exec();
00394 if (d->passwordDialog->showConnectionDetailsRequested() || ret == QDialog::Accepted) {
00395
00396
00397
00398
00399 } else {
00400 m_action = Exit;
00401 return true;
00402 }
00403 }
00404 }
00405
00406
00407
00408
00409
00410
00411 if (m_forcedUserMode && m_forcedDesignMode) {
00412 KMessageBox::sorry( 0, i18n(
00413 "You have used both \"user-mode\" and \"design-mode\" startup options.")+couldnotMsg);
00414 return false;
00415 }
00416
00417
00418 if (args->count()>=1) {
00419 QString prjName;
00420 QString fileName;
00421 if (fileDriverSelected) {
00422 fileName = QFile::decodeName(args->arg(0));
00423 }
00424 else {
00425 prjName = QString::fromLocal8Bit(args->arg(0));
00426 }
00427
00428 if (fileDriverSelected) {
00429 QFileInfo finfo(fileName);
00430 prjName = finfo.fileName();
00431 cdata.setFileName( finfo.absFilePath() );
00432 projectFileExists = finfo.exists();
00433
00434 if (dropDB && !projectFileExists) {
00435 KMessageBox::sorry(0,
00436 i18n("Could not remove project.\nThe file \"%1\" does not exist.")
00437 .arg(QDir::convertSeparators(cdata.dbFileName())));
00438 return 0;
00439 }
00440 }
00441
00442 if (createDB) {
00443 if (cdata.driverName.isEmpty())
00444 cdata.driverName = KexiDB::Driver::defaultFileBasedDriverName();
00445 m_projectData = new KexiProjectData(cdata, prjName);
00446 }
00447 else {
00448 if (fileDriverSelected) {
00449 int detectOptions = 0;
00450 if (fileType=="project")
00451 detectOptions |= ThisIsAProjectFile;
00452 else if (fileType=="shortcut")
00453 detectOptions |= ThisIsAShortcutToAProjectFile;
00454 else if (fileType=="connection")
00455 detectOptions |= ThisIsAShortcutToAConnectionData;
00456
00457 if (dropDB)
00458 detectOptions |= DontConvert;
00459
00460 QString detectedDriverName;
00461 const tristate res = detectActionForFile( m_importActionData, detectedDriverName,
00462 cdata.driverName, cdata.fileName(), 0, detectOptions );
00463 if (true != res)
00464 return res;
00465
00466 if (m_importActionData) {
00467 m_action = ImportProject;
00468 return true;
00469 }
00470
00471
00472 cdata.driverName = detectedDriverName;
00473 if (cdata.driverName=="shortcut") {
00474
00475 d->shortcutFile = new KexiDBShortcutFile(cdata.fileName());
00476 m_projectData = new KexiProjectData();
00477 if (!d->shortcutFile->loadProjectData(*m_projectData, &d->shortcutFileGroupKey)) {
00478 KMessageBox::sorry(0, i18n("Could not open shortcut file\n\"%1\".")
00479 .arg(QDir::convertSeparators(cdata.fileName())));
00480 delete m_projectData;
00481 m_projectData = 0;
00482 delete d->shortcutFile;
00483 d->shortcutFile = 0;
00484 return false;
00485 }
00486 d->connDialog = new KexiDBConnectionDialog(
00487 *m_projectData, d->shortcutFile->fileName());
00488 connect(d->connDialog, SIGNAL(saveChanges()),
00489 this, SLOT(slotSaveShortcutFileChanges()));
00490 int res = d->connDialog->exec();
00491 if (res == QDialog::Accepted) {
00492
00493 *m_projectData = d->connDialog->currentProjectData();
00494 }
00495
00496 delete d->connDialog;
00497 d->connDialog = 0;
00498 delete d->shortcutFile;
00499 d->shortcutFile = 0;
00500
00501 if (res == QDialog::Rejected) {
00502 delete m_projectData;
00503 m_projectData = 0;
00504 return cancelled;
00505 }
00506 }
00507 else if (cdata.driverName=="connection") {
00508
00509 d->connShortcutFile = new KexiDBConnShortcutFile(cdata.fileName());
00510 if (!d->connShortcutFile->loadConnectionData(cdata, &d->shortcutFileGroupKey)) {
00511 KMessageBox::sorry(0, i18n("Could not open connection data file\n\"%1\".")
00512 .arg(QDir::convertSeparators(cdata.fileName())));
00513 delete d->connShortcutFile;
00514 d->connShortcutFile = 0;
00515 return false;
00516 }
00517 bool cancel = false;
00518 const bool showConnectionDialog = !args->isSet("skip-conn-dialog");
00519 while (true) {
00520 if (showConnectionDialog) {
00521
00522 if (!d->connDialog) {
00523 d->connDialog = new KexiDBConnectionDialog(
00524 cdata, d->connShortcutFile->fileName());
00525 connect(d->connDialog, SIGNAL(saveChanges()),
00526 this, SLOT(slotSaveShortcutFileChanges()));
00527 }
00528 const int res = d->connDialog->exec();
00529 if (res == QDialog::Accepted) {
00530
00531 cdata = *d->connDialog->currentProjectData().constConnectionData();
00532 }
00533 else {
00534 cancel = true;
00535 break;
00536 }
00537 }
00538 m_projectData = selectProject(&cdata, cancel);
00539 if (m_projectData || cancel || !showConnectionDialog)
00540 break;
00541 }
00542
00543 delete d->connShortcutFile;
00544 d->connShortcutFile = 0;
00545 delete d->connDialog;
00546 d->connDialog = 0;
00547
00548 if (cancel)
00549 return cancelled;
00550 }
00551 else
00552 m_projectData = new KexiProjectData(cdata, prjName);
00553 }
00554 else
00555 m_projectData = new KexiProjectData(cdata, prjName);
00556
00557 }
00558
00559
00560 }
00561 if (args->count()>1) {
00562
00563 }
00564
00565
00566 if (d->passwordDialog && d->passwordDialog->showConnectionDetailsRequested()) {
00567 d->connDialog = new KexiDBConnectionDialog(*m_projectData);
00568
00569
00570 int res = d->connDialog->exec();
00571
00572 if (res == QDialog::Accepted) {
00573
00574 *m_projectData = d->connDialog->currentProjectData();
00575 }
00576
00577 delete d->connDialog;
00578 d->connDialog = 0;
00579
00580 if (res == QDialog::Rejected) {
00581 delete m_projectData;
00582 m_projectData = 0;
00583 return cancelled;
00584 }
00585 }
00586
00587
00588 const bool atLeastOneAOOFound = getAutoopenObjects(args, "open")
00589 || getAutoopenObjects(args, "design")
00590 || getAutoopenObjects(args, "edittext")
00591 || getAutoopenObjects(args, "execute")
00592 || getAutoopenObjects(args, "new")
00593 || getAutoopenObjects(args, "print")
00594 || getAutoopenObjects(args, "print-preview");
00595
00596 if (atLeastOneAOOFound && !openExisting) {
00597 KMessageBox::information( 0,
00598 i18n("You have specified a few database objects to be opened automatically, "
00599 "using startup options.\n"
00600 "These options will be ignored because it is not available while creating "
00601 "or dropping projects."));
00602 }
00603
00604 if (createDB) {
00605 bool creationNancelled;
00606 KexiGUIMessageHandler gui;
00607 KexiProject *prj = KexiProject::createBlankProject(creationNancelled, projectData(), &gui);
00608 bool ok = prj!=0;
00609 delete prj;
00610 if (creationNancelled)
00611 return cancelled;
00612 if (!alsoOpenDB) {
00613 if (ok) {
00614 KMessageBox::information( 0, i18n("Project \"%1\" created successfully.")
00615 .arg( QDir::convertSeparators(projectData()->databaseName()) ));
00616 }
00617 return ok;
00618 }
00619 }
00620 else if (dropDB) {
00621 KexiGUIMessageHandler gui;
00622 tristate res = KexiProject::dropProject(projectData(), &gui, false);
00623 if (res==true)
00624 KMessageBox::information( 0, i18n("Project \"%1\" dropped successfully.")
00625 .arg( QDir::convertSeparators(projectData()->databaseName()) ));
00626 return res!=false;
00627 }
00628
00629
00630
00631
00632
00633
00634
00635
00636
00637 if (!m_projectData) {
00638 cdata = KexiDB::ConnectionData();
00639
00640 if (args->isSet("skip-startup-dialog") || !KexiStartupDialog::shouldBeShown())
00641 return true;
00642
00643 if (!d->startupDialog) {
00644
00645 d->startupDialog = new KexiStartupDialog(
00646 KexiStartupDialog::Everything, KexiStartupDialog::CheckBoxDoNotShowAgain,
00647 Kexi::connset(), Kexi::recentProjects(), 0, "KexiStartupDialog");
00648 }
00649 if (d->startupDialog->exec()!=QDialog::Accepted)
00650 return true;
00651
00652 const int r = d->startupDialog->result();
00653 if (r == KexiStartupDialog::CreateBlankResult) {
00654 m_action = CreateBlankProject;
00655 return true;
00656 }
00657 else if (r == KexiStartupDialog::ImportResult) {
00658 m_action = ImportProject;
00659 return true;
00660 }
00661 else if (r == KexiStartupDialog::CreateFromTemplateResult) {
00662 const QString selFile( d->startupDialog->selectedFileName() );
00663 cdata.setFileName( selFile );
00664 QString detectedDriverName;
00665 const tristate res = detectActionForFile( m_importActionData, detectedDriverName,
00666 cdata.driverName, selFile );
00667 if (true != res)
00668 return res;
00669 if (m_importActionData || detectedDriverName.isEmpty())
00670 return false;
00671 cdata.driverName = detectedDriverName;
00672 m_projectData = new KexiProjectData(cdata, selFile);
00673 m_projectData->autoopenObjects = d->startupDialog->autoopenObjects();
00674 m_action = CreateFromTemplate;
00675 return true;
00676 }
00677 else if (r == KexiStartupDialog::OpenExistingResult) {
00678
00679 const QString selFile( d->startupDialog->selectedFileName() );
00680 if (!selFile.isEmpty()) {
00681
00682
00683 cdata.setFileName( selFile );
00684 QString detectedDriverName;
00685 const tristate res = detectActionForFile( m_importActionData, detectedDriverName,
00686 cdata.driverName, selFile );
00687 if (true != res)
00688 return res;
00689 if (m_importActionData) {
00690 m_action = ImportProject;
00691 return true;
00692 }
00693
00694 if (detectedDriverName.isEmpty())
00695 return false;
00696 cdata.driverName = detectedDriverName;
00697 m_projectData = new KexiProjectData(cdata, selFile);
00698 }
00699 else if (d->startupDialog->selectedExistingConnection()) {
00700
00701
00702 KexiDB::ConnectionData *cdata = d->startupDialog->selectedExistingConnection();
00703
00704 bool cancelled;
00705 m_projectData = selectProject( cdata, cancelled );
00706 if (!m_projectData && !cancelled || cancelled) {
00707
00708 return init(0, 0);
00709 }
00710
00711 delete d->startupDialog;
00712 d->startupDialog = 0;
00713 }
00714 }
00715 else if (r==KexiStartupDialog::OpenRecentResult) {
00716
00717 const KexiProjectData *data = d->startupDialog->selectedProjectData();
00718 if (data) {
00719
00720
00721 }
00723 return data!=0;
00724 }
00725
00726 if (!m_projectData)
00727 return true;
00728 }
00729
00730 if (m_projectData && (openExisting || (createDB && alsoOpenDB))) {
00731 m_projectData->setReadOnly( readOnly );
00732 m_action = OpenProject;
00733 }
00734
00735
00736
00737 return true;
00738 }
00739
00740 tristate KexiStartupHandler::detectActionForFile(
00741 KexiStartupData::Import& detectedImportAction, QString& detectedDriverName,
00742 const QString& _suggestedDriverName, const QString &dbFileName, QWidget *parent, int options )
00743 {
00744 detectedImportAction = KexiStartupData::Import();
00745 QString suggestedDriverName(_suggestedDriverName);
00746 detectedDriverName = QString::null;
00747 QFileInfo finfo(dbFileName);
00748 if (dbFileName.isEmpty() || !finfo.isReadable()) {
00749 if (!(options & SkipMessages))
00750 KMessageBox::sorry(parent, i18n("<p>Could not open project.</p>")
00751 +i18n("<p>The file <nobr>\"%1\"</nobr> does not exist or is not readable.</p>")
00752 .arg(QDir::convertSeparators(dbFileName))
00753 +i18n("Check the file's permissions and whether it is already opened "
00754 "and locked by another application."));
00755 return false;
00756 }
00757
00758 KMimeType::Ptr ptr;
00759 QString mimename;
00760
00761 const bool thisIsShortcut = (options & ThisIsAShortcutToAProjectFile)
00762 || (options & ThisIsAShortcutToAConnectionData);
00763
00764 if ((options & ThisIsAProjectFile) || !thisIsShortcut) {
00765
00766 ptr = KMimeType::findByFileContent(dbFileName);
00767 mimename = ptr.data()->name();
00768 kdDebug() << "KexiStartupHandler::detectActionForFile(): found mime is: "
00769 << mimename << endl;
00770 if (mimename.isEmpty() || mimename=="application/octet-stream" || mimename=="text/plain") {
00771
00772 ptr = KMimeType::findByURL(dbFileName);
00773 mimename = ptr.data()->name();
00774 }
00775 }
00776 if (mimename.isEmpty() || mimename=="application/octet-stream") {
00777
00778 QFile f(dbFileName);
00779 if (!f.open(IO_ReadOnly)) {
00780
00781 if (!(options & SkipMessages))
00782 KMessageBox::sorry(parent, i18n("<p>Could not open project.</p>")
00783 +i18n("<p>The file <nobr>\"%1\"</nobr> is not readable.</p>")
00784 .arg(QDir::convertSeparators(dbFileName))
00785 +i18n("Check the file's permissions and whether it is already opened "
00786 "and locked by another application."));
00787 return false;
00788 }
00789 }
00790 if ((options & ThisIsAShortcutToAProjectFile) || mimename=="application/x-kexiproject-shortcut") {
00791 detectedDriverName = "shortcut";
00792 return true;
00793 }
00794
00795 if ((options & ThisIsAShortcutToAConnectionData) || mimename=="application/x-kexi-connectiondata") {
00796 detectedDriverName = "connection";
00797 return true;
00798 }
00799
00802 if (ptr.data()) {
00803 if (mimename=="application/x-msaccess") {
00804 if ((options & SkipMessages) || KMessageBox::Yes != KMessageBox::questionYesNo(
00805 parent, i18n("\"%1\" is an external file of type:\n\"%2\".\n"
00806 "Do you want to import the file as a Kexi project?")
00807 .arg(QDir::convertSeparators(dbFileName)).arg(ptr.data()->comment()),
00808 i18n("Open External File"), KGuiItem(i18n("Import...")), KStdGuiItem::cancel() ) )
00809 {
00810 return cancelled;
00811 }
00812 detectedImportAction.mimeType = mimename;
00813 detectedImportAction.fileName = dbFileName;
00814 return true;
00815 }
00816 }
00817
00818 if (!finfo.isWritable()) {
00820 }
00821
00822
00823 QString tmpDriverName = Kexi::driverManager().lookupByMime(mimename).latin1();
00824
00825 bool useDetectedDriver = suggestedDriverName.isEmpty() || suggestedDriverName.lower()==detectedDriverName.lower();
00826 if (!useDetectedDriver) {
00827 int res = KMessageBox::Yes;
00828 if (!(options & SkipMessages))
00829 res = KMessageBox::warningYesNoCancel(parent, i18n(
00830 "The project file \"%1\" is recognized as compatible with \"%2\" database driver, "
00831 "while you have asked for \"%3\" database driver to be used.\n"
00832 "Do you want to use \"%4\" database driver?")
00833 .arg(QDir::convertSeparators(dbFileName))
00834 .arg(tmpDriverName).arg(suggestedDriverName).arg(tmpDriverName));
00835 if (KMessageBox::Yes == res)
00836 useDetectedDriver = true;
00837 else if (KMessageBox::Cancel == res)
00838 return cancelled;
00839 }
00840 if (useDetectedDriver) {
00841 detectedDriverName = tmpDriverName;
00842 }
00843 else {
00844 detectedDriverName = suggestedDriverName;
00845 }
00846
00847
00848 const QString newFileFormat = "SQLite3";
00849 if (!(options & DontConvert || options & SkipMessages)
00850 && detectedDriverName.lower()=="sqlite2" && detectedDriverName.lower()!=suggestedDriverName.lower()
00851 && KMessageBox::Yes == KMessageBox::questionYesNo(parent, i18n(
00852 "Previous version of database file format (\"%1\") is detected in the \"%2\" "
00853 "project file.\nDo you want to convert the project to a new \"%3\" format (recommended)?")
00854 .arg(detectedDriverName).arg(QDir::convertSeparators(dbFileName)).arg(newFileFormat)) )
00855 {
00856
00857 SQLite2ToSQLite3Migration migr( finfo.absFilePath() );
00858 tristate res = migr.run();
00859
00860 if (!res) {
00861
00862 KMessageBox::sorry(parent, i18n(
00863 "Failed to convert project file \"%1\" to a new \"%2\" format.\n"
00864 "The file format remains unchanged.")
00865 .arg(QDir::convertSeparators(dbFileName)).arg(newFileFormat) );
00866
00867 }
00868 if (res==true)
00869 detectedDriverName = newFileFormat;
00870 }
00871
00872 if (detectedDriverName.isEmpty()) {
00873 QString possibleProblemsInfoMsg( Kexi::driverManager().possibleProblemsInfoMsg() );
00874 if (!possibleProblemsInfoMsg.isEmpty()) {
00875 possibleProblemsInfoMsg.prepend(QString::fromLatin1("<p>")+i18n("Possible problems:"));
00876 possibleProblemsInfoMsg += QString::fromLatin1("</p>");
00877 }
00878 if (!(options & SkipMessages))
00879 KMessageBox::detailedSorry(parent,
00880 i18n( "The file \"%1\" is not recognized as being supported by Kexi.")
00881 .arg(QDir::convertSeparators(dbFileName)),
00882 QString::fromLatin1("<p>")
00883 +i18n("Database driver for this file type not found.\nDetected MIME type: %1")
00884 .arg(mimename)
00885 +(ptr.data()->comment().isEmpty()
00886 ? QString::fromLatin1(".") : QString::fromLatin1(" (%1).").arg(ptr.data()->comment()))
00887 +QString::fromLatin1("</p>")
00888 +possibleProblemsInfoMsg);
00889 return false;
00890 }
00891 return true;
00892 }
00893
00894 KexiProjectData*
00895 KexiStartupHandler::selectProject(KexiDB::ConnectionData *cdata, bool& cancelled, QWidget *parent)
00896 {
00897 clearStatus();
00898 cancelled = false;
00899 if (!cdata)
00900 return 0;
00901 if (!cdata->savePassword && cdata->password.isEmpty()) {
00902 if (!d->passwordDialog)
00903 d->passwordDialog = new KexiDBPasswordDialog(0, *cdata, false);
00904 const int ret = d->passwordDialog->exec();
00905 if (d->passwordDialog->showConnectionDetailsRequested() || ret == QDialog::Accepted) {
00906
00907 } else {
00908 cancelled = true;
00909 return 0;
00910 }
00911 }
00912 KexiProjectData* projectData = 0;
00913
00914 KexiProjectSelectorDialog prjdlg( parent, "prjdlg", cdata, true, false );
00915 if (!prjdlg.projectSet() || prjdlg.projectSet()->error()) {
00916 KexiGUIMessageHandler msgh;
00917 if (prjdlg.projectSet())
00918 msgh.showErrorMessage(prjdlg.projectSet(),
00919 i18n("Could not load list of available projects for <b>%1</b> database server.")
00920 .arg(cdata->serverInfoString(true)));
00921 else
00922 msgh.showErrorMessage(
00923 i18n("Could not load list of available projects for <b>%1</b> database server.")
00924 .arg(cdata->serverInfoString(true)));
00925
00926
00927 return 0;
00928 }
00929 if (prjdlg.exec()!=QDialog::Accepted) {
00930 cancelled = true;
00931 return 0;
00932 }
00933 if (prjdlg.selectedProjectData()) {
00934
00935 projectData = new KexiProjectData(*prjdlg.selectedProjectData());
00936 }
00937 return projectData;
00938 }
00939
00940 void KexiStartupHandler::slotSaveShortcutFileChanges()
00941 {
00942 bool ok = true;
00943 if (d->shortcutFile)
00944 ok = d->shortcutFile->saveProjectData(d->connDialog->currentProjectData(),
00945 d->connDialog->savePasswordOptionSelected(),
00946 &d->shortcutFileGroupKey );
00947 else if (d->connShortcutFile)
00948 ok = d->connShortcutFile->saveConnectionData(
00949 *d->connDialog->currentProjectData().connectionData(),
00950 d->connDialog->savePasswordOptionSelected(),
00951 &d->shortcutFileGroupKey );
00952
00953 if (!ok) {
00954 KMessageBox::sorry(0, i18n("Failed saving connection data to\n\"%1\" file.")
00955 .arg(QDir::convertSeparators(d->shortcutFile->fileName())));
00956 }
00957 }
00958
00959
00960
00961
00962
00963
00964
00965 #include "KexiStartup.moc"