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