00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021 #include <qfile.h>
00022 #include <qapplication.h>
00023 #include <qdom.h>
00024
00025 #include <kmimetype.h>
00026 #include <kdebug.h>
00027 #include <klocale.h>
00028
00029 #include <kexiutils/identifier.h>
00030
00031 #include <kexidb/connection.h>
00032 #include <kexidb/cursor.h>
00033 #include <kexidb/driver.h>
00034 #include <kexidb/drivermanager.h>
00035 #include <kexidb/utils.h>
00036 #include <kexidb/parser/parser.h>
00037 #include <kexidb/msghandler.h>
00038 #include <kexidb/dbproperties.h>
00039 #include <kexiutils/utils.h>
00040
00041 #include "kexiproject.h"
00042 #include "kexipartmanager.h"
00043 #include "kexipartitem.h"
00044 #include "kexipartinfo.h"
00045 #include "kexipart.h"
00046 #include "kexidialogbase.h"
00047 #include "kexi.h"
00048 #include "keximainwindow.h"
00049 #include "kexiblobbuffer.h"
00050 #include "kexiguimsghandler.h"
00051
00052 #include <assert.h>
00053
00054 class KexiProject::Private
00055 {
00056 public:
00057 Private()
00058 : data(0)
00059 , itemDictsCache(199)
00060 , unstoredItems(199)
00061 , tempPartItemID_Counter(-1)
00062 , sqlParser(0)
00063 , versionMajor(0)
00064 , versionMinor(0)
00065 , final(false)
00066 {
00067 itemDictsCache.setAutoDelete(true);
00068 unstoredItems.setAutoDelete(true);
00069 }
00070 ~Private() {
00071 delete data;
00072 data=0;
00073 delete sqlParser;
00074 }
00075
00076 QGuardedPtr<KexiDB::Connection> connection;
00077 QGuardedPtr<KexiProjectData> data;
00078
00079 QString error_title;
00080
00082 QIntDict<KexiPart::ItemDict> itemDictsCache;
00083
00084 QPtrDict<KexiPart::Item> unstoredItems;
00085 int tempPartItemID_Counter;
00086
00087 KexiDB::Parser* sqlParser;
00088
00089 int versionMajor;
00090 int versionMinor;
00091 bool final : 1;
00092 };
00093
00094
00095
00096
00097
00098
00099
00100
00101
00102
00103
00104
00105
00106
00107
00108
00109
00110
00111
00112
00113
00114
00115 KexiProject::KexiProject(KexiProjectData *pdata, KexiDB::MessageHandler* handler)
00116 : QObject(), Object(handler)
00117 , d(new Private())
00118 {
00119 d->data = pdata;
00121 Kexi::partManager().lookup();
00122 }
00123
00124 KexiProject::KexiProject(KexiProjectData *pdata, KexiDB::MessageHandler* handler,
00125 KexiDB::Connection* conn)
00126 : QObject(), Object(handler)
00127 , d(new Private())
00128 {
00129 d->data = pdata;
00130 if (d->data->connectionData() == d->connection->data())
00131 d->connection = conn;
00132 else
00133 kdWarning() << "KexiProject::KexiProject(): passed connection's data ("
00134 << conn->data()->serverInfoString() << ") is not compatible with project's conn. data ("
00135 << d->data->connectionData()->serverInfoString() << ")" << endl;
00137 Kexi::partManager().lookup();
00138 }
00139
00140 KexiProject::~KexiProject()
00141 {
00142 closeConnection();
00143 delete d;
00144 }
00145
00146 KexiDB::Connection *KexiProject::dbConnection() const
00147 {
00148 return d->connection;
00149 }
00150
00151 KexiProjectData* KexiProject::data() const
00152 {
00153 return d->data;
00154 }
00155
00156 bool KexiProject::final() const
00157 {
00158 return d->final;
00159 }
00160
00161 void KexiProject::setFinal(bool set)
00162 {
00163 d->final = set;
00164 }
00165
00166 int KexiProject::versionMajor() const
00167 {
00168 return d->versionMajor;
00169 }
00170
00171 int KexiProject::versionMinor() const
00172 {
00173 return d->versionMinor;
00174 }
00175
00176 tristate
00177 KexiProject::open(bool &incompatibleWithKexi)
00178 {
00179 return openInternal(&incompatibleWithKexi);
00180 }
00181
00182 tristate
00183 KexiProject::open()
00184 {
00185 return openInternal(0);
00186 }
00187
00188 tristate
00189 KexiProject::openInternal(bool *incompatibleWithKexi)
00190 {
00191 if (incompatibleWithKexi)
00192 *incompatibleWithKexi = false;
00193 kdDebug() << "KexiProject::open(): " << d->data->databaseName() <<" "<< d->data->connectionData()->driverName << endl;
00194 KexiDB::MessageTitle et(this,
00195 i18n("Could not open project \"%1\".").arg(d->data->databaseName()));
00196
00197 if (!createConnection()) {
00198 kdDebug() << "KexiProject::open(): !createConnection()" << endl;
00199 return false;
00200 }
00201 bool cancel = false;
00202 KexiGUIMessageHandler msgHandler;
00203 if (!d->connection->useDatabase(d->data->databaseName(), true, &cancel, &msgHandler))
00204 {
00205 if (cancel) {
00206 return cancelled;
00207 }
00208 kdDebug() << "KexiProject::open(): !d->connection->useDatabase() "
00209 << d->data->databaseName() <<" "<< d->data->connectionData()->driverName << endl;
00210
00211 if (d->connection->errorNum() == ERR_NO_DB_PROPERTY) {
00212 if (incompatibleWithKexi)
00213 *incompatibleWithKexi = true;
00214 closeConnection();
00215 return false;
00216 }
00217
00218 setError(d->connection);
00219 closeConnection();
00220 return false;
00221 }
00222
00223 if (!initProject())
00224 return false;
00225
00226 return createInternalStructures(true);
00227 }
00228
00229 tristate
00230 KexiProject::create(bool forceOverwrite)
00231 {
00232 KexiDB::MessageTitle et(this,
00233 i18n("Could not create project \"%1\".").arg(d->data->databaseName()));
00234
00235 if (!createConnection())
00236 return false;
00237 if (!checkWritable())
00238 return false;
00239 if (d->connection->databaseExists( d->data->databaseName() )) {
00240 if (!forceOverwrite)
00241 return cancelled;
00242 if (!d->connection->dropDatabase( d->data->databaseName() )) {
00243 setError(d->connection);
00244 closeConnection();
00245 return false;
00246 }
00247 kdDebug() << "--- DB '" << d->data->databaseName() << "' dropped ---"<< endl;
00248 }
00249 if (!d->connection->createDatabase( d->data->databaseName() )) {
00250 setError(d->connection);
00251 closeConnection();
00252 return false;
00253 }
00254 kdDebug() << "--- DB '" << d->data->databaseName() << "' created ---"<< endl;
00255
00256 if (!d->connection->useDatabase(d->data->databaseName()))
00257 {
00258 kdDebug() << "--- DB '" << d->data->databaseName() << "' USE ERROR ---"<< endl;
00259 setError(d->connection);
00260 closeConnection();
00261 return false;
00262 }
00263 kdDebug() << "--- DB '" << d->data->databaseName() << "' used ---"<< endl;
00264
00265
00266 KexiDB::Transaction trans = d->connection->beginTransaction();
00267 if (trans.isNull())
00268 return false;
00269
00270 if (!createInternalStructures(false))
00271 return false;
00272
00273
00275 KexiDB::DatabaseProperties &props = d->connection->databaseProperties();
00276 if (!props.setValue("kexiproject_major_ver", d->versionMajor)
00277 || !props.setCaption("kexiproject_major_ver", i18n("Project major version"))
00278 || !props.setValue("kexiproject_minor_ver", d->versionMinor)
00279 || !props.setCaption("kexiproject_minor_ver", i18n("Project minor version"))
00280 || !props.setValue("project_caption", d->data->caption())
00281 || !props.setCaption("project_caption", i18n("Project caption"))
00282 || !props.setValue("project_desc", d->data->description())
00283 || !props.setCaption("project_desc", i18n("Project description")) )
00284 return false;
00285
00286
00287
00288
00289
00290
00291
00292
00293
00294
00295
00296
00297 if (trans.active() && !d->connection->commitTransaction(trans))
00298 return false;
00299
00300
00301 return initProject();
00302 }
00303
00304 bool KexiProject::createInternalStructures(bool insideTransaction)
00305 {
00306 KexiDB::TransactionGuard tg;
00307 if (insideTransaction) {
00308 tg.setTransaction( d->connection->beginTransaction() );
00309 if (tg.transaction().isNull())
00310 return false;
00311 }
00312
00313
00314
00315 KexiDB::DatabaseProperties &props = d->connection->databaseProperties();
00316 bool ok;
00317 int storedMajorVersion = props.value("kexiproject_major_ver").toInt(&ok);
00318 if (!ok)
00319 storedMajorVersion = 0;
00320 int storedMinorVersion = props.value("kexiproject_minor_ver").toInt(&ok);
00321 if (!ok)
00322 storedMinorVersion = 1;
00323
00324 bool containsKexi__blobsTable = d->connection->drv_containsTable("kexi__blobs");
00325
00327 if (storedMajorVersion<=0) {
00328 d->versionMajor = KEXIPROJECT_VERSION_MAJOR;
00329 d->versionMinor = KEXIPROJECT_VERSION_MINOR;
00330
00331
00332 if (!props.setValue("kexiproject_major_ver", d->versionMajor)
00333 || !props.setCaption("kexiproject_major_ver", i18n("Project major version"))
00334 || !props.setValue("kexiproject_minor_ver", d->versionMinor)
00335 || !props.setCaption("kexiproject_minor_ver", i18n("Project minor version")) ) {
00336 return false;
00337 }
00338
00339
00340 if (containsKexi__blobsTable) {
00341 if (!d->connection->executeSQL(QString::fromLatin1("DROP TABLE kexi__blobs")))
00342 return false;
00343 containsKexi__blobsTable = false;
00344 }
00345 }
00346 if (storedMajorVersion!=d->versionMajor || storedMajorVersion!=d->versionMinor) {
00348 d->versionMajor = storedMajorVersion;
00349 d->versionMinor = storedMinorVersion;
00350 }
00351
00352 KexiDB::InternalTableSchema *t_blobs = new KexiDB::InternalTableSchema("kexi__blobs");
00353 t_blobs->addField( new KexiDB::Field("o_id", KexiDB::Field::Integer,
00354 KexiDB::Field::PrimaryKey | KexiDB::Field::AutoInc, KexiDB::Field::Unsigned) )
00355 .addField( new KexiDB::Field("o_data", KexiDB::Field::BLOB) )
00356 .addField( new KexiDB::Field("o_name", KexiDB::Field::Text ) )
00357 .addField( new KexiDB::Field("o_caption", KexiDB::Field::Text ) )
00358 .addField( new KexiDB::Field("o_mime", KexiDB::Field::Text, KexiDB::Field::NotNull) )
00359 .addField( new KexiDB::Field("o_folder_id",
00360 KexiDB::Field::Integer, 0, KexiDB::Field::Unsigned)
00361
00362
00363 );
00364
00365
00366 if (containsKexi__blobsTable) {
00368 d->connection->insertInternalTableSchema(t_blobs);
00369 }
00370 else {
00371
00372 if (!d->connection->createTable( t_blobs, true )) {
00373 delete t_blobs;
00374 return false;
00375 }
00376 }
00377
00378
00379
00380 KexiDB::InternalTableSchema *t_parts = new KexiDB::InternalTableSchema("kexi__parts");
00381 t_parts->addField(
00382 new KexiDB::Field("p_id", KexiDB::Field::Integer, KexiDB::Field::PrimaryKey | KexiDB::Field::AutoInc, KexiDB::Field::Unsigned)
00383 )
00384 .addField( new KexiDB::Field("p_name", KexiDB::Field::Text) )
00385 .addField( new KexiDB::Field("p_mime", KexiDB::Field::Text ) )
00386 .addField( new KexiDB::Field("p_url", KexiDB::Field::Text ) );
00387
00388 bool containsKexi__partsTable = d->connection->drv_containsTable("kexi__parts");
00389 bool partsTableOk = true;
00390 if (containsKexi__partsTable) {
00392 d->connection->insertInternalTableSchema(t_parts);
00393 }
00394 else {
00395 partsTableOk = d->connection->createTable( t_parts, true );
00396
00397 KexiDB::FieldList *fl = t_parts->subList("p_id", "p_name", "p_mime", "p_url");
00398 if (partsTableOk)
00399 partsTableOk = d->connection->insertRecord(*fl, QVariant(1), QVariant("Tables"),
00400 QVariant("kexi/table"), QVariant("http://koffice.org/kexi/"));
00401
00402 if (partsTableOk)
00403 partsTableOk = d->connection->insertRecord(*fl, QVariant(2), QVariant("Queries"),
00404 QVariant("kexi/query"), QVariant("http://koffice.org/kexi/"));
00405 }
00406
00407 if (!partsTableOk) {
00408 delete t_parts;
00409 return false;
00410 }
00411
00412 if (insideTransaction) {
00413 if (tg.transaction().active() && !tg.commit())
00414 return false;
00415 }
00416 return true;
00417 }
00418
00419 bool
00420 KexiProject::createConnection()
00421 {
00422 if (d->connection)
00423 return true;
00424
00425 clearError();
00426
00427 KexiDB::MessageTitle et(this);
00428
00429 KexiDB::Driver *driver = Kexi::driverManager().driver(d->data->connectionData()->driverName);
00430 if(!driver) {
00431 setError(&Kexi::driverManager());
00432 return false;
00433 }
00434
00435 d->connection = driver->createConnection(*d->data->connectionData());
00436 if (!d->connection)
00437 {
00438 kdDebug() << "KexiProject::open(): uuups failed " << driver->errorMsg() << endl;
00439 setError(driver);
00440 return false;
00441 }
00442
00443 if (!d->connection->connect())
00444 {
00445 setError(d->connection);
00446 kdDebug() << "KexiProject::createConnection(): error connecting: " << (d->connection ? d->connection->errorMsg() : QString::null) << endl;
00447 closeConnection();
00448 return false;
00449 }
00450
00451
00453 KexiBLOBBuffer::setConnection(d->connection);
00454 return true;
00455 }
00456
00457
00458 void
00459 KexiProject::closeConnection()
00460 {
00461 if (!d->connection)
00462 return;
00463
00464 delete d->connection;
00465 d->connection = 0;
00466 }
00467
00468 bool
00469 KexiProject::initProject()
00470 {
00471
00472 kdDebug() << "KexiProject::open(): checking project parts..." << endl;
00473
00474 if (!Kexi::partManager().checkProject(d->connection)) {
00475 setError(Kexi::partManager().error() ? (KexiDB::Object*)&Kexi::partManager() : (KexiDB::Connection*)d->connection);
00476 return false;
00477 }
00478
00479
00480 KexiDB::DatabaseProperties &props = d->connection->databaseProperties();
00481 QString str( props.value("project_caption").toString() );
00482 if (!str.isEmpty())
00483 d->data->setCaption( str );
00484 str = props.value("project_desc").toString();
00485 if (!str.isEmpty())
00486 d->data->setDescription( str );
00487
00488
00489
00490
00491
00492
00493
00494 return true;
00495 }
00496
00497 bool
00498 KexiProject::isConnected()
00499 {
00500 if(d->connection && d->connection->isDatabaseUsed())
00501 return true;
00502
00503 return false;
00504 }
00505
00506 KexiPart::ItemDict*
00507 KexiProject::items(KexiPart::Info *i)
00508 {
00509 kdDebug() << "KexiProject::items()" << endl;
00510 if(!i || !isConnected())
00511 return 0;
00512
00513
00514 KexiPart::ItemDict *dict = d->itemDictsCache[ i->projectPartID() ];
00515 if (dict)
00516 return dict;
00517
00518 KexiDB::Cursor *cursor = d->connection->executeQuery(
00519 "SELECT o_id, o_name, o_caption FROM kexi__objects WHERE o_type = "
00520 + QString::number(i->projectPartID()));
00521
00522 if(!cursor)
00523 return 0;
00524
00525 dict = new KexiPart::ItemDict(1009);
00526 dict->setAutoDelete(true);
00527
00528 for(cursor->moveFirst(); !cursor->eof(); cursor->moveNext())
00529 {
00530 KexiPart::Item *it = new KexiPart::Item();
00531 bool ok;
00532 int ident = cursor->value(0).toInt(&ok);
00533 QString objName( cursor->value(1).toString() );
00534
00535 if ( ok && (ident>0) && !d->connection->isInternalTableSchema(objName)
00536 && KexiUtils::isIdentifier(objName) )
00537 {
00538 it->setIdentifier(ident);
00539 it->setMimeType(i->mimeType());
00540 it->setName(objName);
00541 it->setCaption(cursor->value(2).toString());
00542 }
00543 dict->insert(it->identifier(), it);
00544
00545 }
00546
00547 d->connection->deleteCursor(cursor);
00548
00549 d->itemDictsCache.insert( i->projectPartID(), dict );
00550 return dict;
00551 }
00552
00553 KexiPart::ItemDict*
00554 KexiProject::itemsForMimeType(const QCString &mimeType)
00555 {
00556 KexiPart::Info *info = Kexi::partManager().infoForMimeType(mimeType);
00557 return items(info);
00558 }
00559
00560 void
00561 KexiProject::getSortedItems(KexiPart::ItemList& list, KexiPart::Info *i)
00562 {
00563 list.clear();
00564 KexiPart::ItemDict* dict = items(i);
00565 if (!dict)
00566 return;
00567 for (KexiPart::ItemDictIterator it(*dict); it.current(); ++it)
00568 list.append(it.current());
00569 }
00570
00571 void
00572 KexiProject::getSortedItemsForMimeType(KexiPart::ItemList& list, const QCString &mimeType)
00573 {
00574 KexiPart::Info *info = Kexi::partManager().infoForMimeType(mimeType);
00575 getSortedItems(list, info);
00576 }
00577
00578 void
00579 KexiProject::addStoredItem(KexiPart::Info *info, KexiPart::Item *item)
00580 {
00581 if (!info || !item)
00582 return;
00583 KexiPart::ItemDict *dict = items(info);
00584 item->setNeverSaved( false );
00585 d->unstoredItems.take(item);
00586 dict->insert( item->identifier(), item );
00587
00588 emit newItemStored(*item);
00589 }
00590
00591 KexiPart::Item*
00592 KexiProject::itemForMimeType(const QCString &mimeType, const QString &name)
00593 {
00594 KexiPart::ItemDict *dict = itemsForMimeType(mimeType);
00595 if (!dict)
00596 return 0;
00597 const QString l_name = name.lower();
00598 for (KexiPart::ItemDictIterator it( *dict ); it.current(); ++it) {
00599 if (it.current()->name().lower()==l_name)
00600 return it.current();
00601 }
00602 return 0;
00603 }
00604
00605 KexiPart::Item*
00606 KexiProject::item(KexiPart::Info *i, const QString &name)
00607 {
00608 KexiPart::ItemDict *dict = items(i);
00609 if (!dict)
00610 return 0;
00611 const QString l_name = name.lower();
00612 for (KexiPart::ItemDictIterator it( *dict ); it.current(); ++it) {
00613 if (it.current()->name().lower()==l_name)
00614 return it.current();
00615 }
00616 return 0;
00617 }
00618
00619 KexiPart::Item*
00620 KexiProject::item(int identifier)
00621 {
00622 KexiPart::ItemDict *dict;
00623 for (QIntDictIterator<KexiPart::ItemDict> it(d->itemDictsCache); (dict = it.current()); ++it) {
00624 KexiPart::Item *item = dict->find(identifier);
00625 if (item)
00626 return item;
00627 }
00628 return 0;
00629 }
00630
00631
00632
00633
00634
00635
00636
00637
00638
00639
00640
00641
00642
00643
00644
00645
00646
00647
00648
00649
00650
00651
00652
00653
00654
00655
00656
00657
00658
00659
00660
00661
00662
00663
00664
00665
00666
00667
00668
00669
00670
00671
00672 KexiPart::Part *KexiProject::findPartFor(KexiPart::Item& item)
00673 {
00674 clearError();
00675 KexiDB::MessageTitle et(this);
00676 KexiPart::Part *part = Kexi::partManager().partForMimeType(item.mimeType());
00677 if (!part)
00678 setError(&Kexi::partManager());
00679 return part;
00680 }
00681
00682 KexiDialogBase* KexiProject::openObject(KexiMainWindow *wnd, KexiPart::Item& item,
00683 int viewMode, QMap<QString,QString>* staticObjectArgs)
00684 {
00685 clearError();
00686 KexiDB::MessageTitle et(this);
00687 KexiPart::Part *part = findPartFor(item);
00688 if (!part)
00689 return 0;
00690 KexiDialogBase *dlg = part->openInstance(wnd, item, viewMode, staticObjectArgs);
00691 if (!dlg) {
00692 if (part->lastOperationStatus().error())
00693 setError(i18n("Opening object \"%1\" failed.").arg(item.name())+"<br>"
00694 +part->lastOperationStatus().message,
00695 part->lastOperationStatus().description);
00696 return 0;
00697 }
00698 return dlg;
00699 }
00700
00701 KexiDialogBase* KexiProject::openObject(KexiMainWindow *wnd, const QCString &mimeType,
00702 const QString& name, int viewMode)
00703 {
00704 KexiPart::Item *it = itemForMimeType(mimeType, name);
00705 return it ? openObject(wnd, *it, viewMode) : 0;
00706 }
00707
00708 bool KexiProject::checkWritable()
00709 {
00710 if (!d->connection->isReadOnly())
00711 return true;
00712 setError(futureI18n("This project is opened as read only."));
00713 return false;
00714 }
00715
00716 bool KexiProject::removeObject(KexiMainWindow *wnd, KexiPart::Item& item)
00717 {
00718 clearError();
00719 KexiDB::MessageTitle et(this);
00720 if (!checkWritable())
00721 return false;
00722 KexiPart::Part *part = findPartFor(item);
00723 if (!part)
00724 return false;
00725 if (!item.neverSaved() && !part->remove(wnd, item)) {
00726
00727 return false;
00728 }
00729 if (!item.neverSaved()) {
00730 KexiDB::TransactionGuard tg( *d->connection );
00731 if (!tg.transaction().active()) {
00732 setError(d->connection);
00733 return false;
00734 }
00735 if (!d->connection->removeObject( item.identifier() )) {
00736 setError(d->connection);
00737 return false;
00738 }
00739 if (!tg.commit()) {
00740 setError(d->connection);
00741 return false;
00742 }
00743 }
00744 emit itemRemoved(item);
00745
00746
00747 if (part->info()) {
00748 KexiPart::ItemDict *dict = d->itemDictsCache[ part->info()->projectPartID() ];
00749 if (!(dict && dict->remove( item.identifier() )))
00750 d->unstoredItems.remove(&item);
00751 }
00752 return true;
00753 }
00754
00755 bool KexiProject::renameObject( KexiMainWindow *wnd, KexiPart::Item& item, const QString& _newName )
00756 {
00757 KexiUtils::WaitCursor wait;
00758 clearError();
00759 QString newName = _newName.stripWhiteSpace();
00760 {
00761 KexiDB::MessageTitle et(this);
00762 if (newName.isEmpty()) {
00763 setError( i18n("Could not set empty name for this object.") );
00764 return false;
00765 }
00766 if (this->itemForMimeType(item.mimeType(), newName)!=0) {
00767 setError( i18n("Could not use this name. Object with name \"%1\" already exists.")
00768 .arg(newName) );
00769 return false;
00770 }
00771 }
00772
00773 KexiDB::MessageTitle et(this,
00774 i18n("Could not rename object \"%1\".").arg(item.name()) );
00775 if (!checkWritable())
00776 return false;
00777 KexiPart::Part *part = findPartFor(item);
00778 if (!part)
00779 return false;
00780 KexiDB::TransactionGuard tg( *d->connection );
00781 if (!tg.transaction().active()) {
00782 setError(d->connection);
00783 return false;
00784 }
00785 if (!part->rename(wnd, item, newName)) {
00786 setError(part->lastOperationStatus().message, part->lastOperationStatus().description);
00787 return false;
00788 }
00789 if (!d->connection->executeSQL( "update kexi__objects set o_name="
00790 + d->connection->driver()->valueToSQL( KexiDB::Field::Text, newName )
00791 + " where o_id=" + QString::number(item.identifier()) )) {
00792 setError(d->connection);
00793 return false;
00794 }
00795 if (!tg.commit()) {
00796 setError(d->connection);
00797 return false;
00798 }
00799 QCString oldName( item.name().latin1() );
00800 item.setName( newName );
00801 emit itemRenamed(item, oldName);
00802 return true;
00803 }
00804
00805 KexiPart::Item* KexiProject::createPartItem(KexiPart::Info *info, const QString& suggestedCaption)
00806 {
00807 clearError();
00808 KexiDB::MessageTitle et(this);
00809 KexiPart::Part *part = Kexi::partManager().part(info);
00810 if (!part) {
00811 setError(&Kexi::partManager());
00812 return 0;
00813 }
00814
00815 KexiPart::ItemDict *dict = items(info);
00816
00817
00818 int n;
00819 QString new_name;
00820 QString base_name;
00821 if (suggestedCaption.isEmpty()) {
00822 n = 1;
00823 base_name = part->instanceName();
00824 }
00825 else {
00826 n = 0;
00827 base_name = KexiUtils::string2Identifier(suggestedCaption).lower();
00828 }
00829 base_name = KexiUtils::string2Identifier(base_name).lower();
00830 KexiPart::ItemDictIterator it(*dict);
00831 QPtrDictIterator<KexiPart::Item> itUnstored(d->unstoredItems);
00832 do {
00833 new_name = base_name;
00834 if (n>=1)
00835 new_name += QString::number(n);
00836 for (it.toFirst(); it.current(); ++it) {
00837 if (it.current()->name().lower()==new_name)
00838 break;
00839 }
00840 if ( it.current() ) {
00841 n++;
00842 continue;
00843 }
00844 for (itUnstored.toFirst(); itUnstored.current(); ++itUnstored) {
00845 if (itUnstored.current()->name().lower()==new_name)
00846 break;
00847 }
00848 if ( !itUnstored.current() )
00849 break;
00850 n++;
00851 } while (n<1000);
00852
00853 if (n>=1000)
00854 return 0;
00855
00856 QString new_caption( suggestedCaption.isEmpty() ? part->instanceCaption() : suggestedCaption);
00857 if (n>=1)
00858 new_caption += QString::number(n);
00859
00860 KexiPart::Item *item = new KexiPart::Item();
00861 item->setIdentifier( --d->tempPartItemID_Counter );
00862 item->setMimeType(info->mimeType());
00863 item->setName(new_name);
00864 item->setCaption(new_caption);
00865 item->setNeverSaved(true);
00866 d->unstoredItems.insert(item, item);
00867 return item;
00868 }
00869
00870 KexiPart::Item* KexiProject::createPartItem(KexiPart::Part *part, const QString& suggestedCaption)
00871 {
00872 return createPartItem(part->info(), suggestedCaption);
00873 }
00874
00875 void KexiProject::deleteUnstoredItem(KexiPart::Item *item)
00876 {
00877 if (!item)
00878 return;
00879 d->unstoredItems.remove(item);
00880 }
00881
00882 KexiDB::Parser* KexiProject::sqlParser()
00883 {
00884 if (!d->sqlParser) {
00885 if (!d->connection)
00886 return 0;
00887 d->sqlParser = new KexiDB::Parser(d->connection);
00888 }
00889 return d->sqlParser;
00890 }
00891
00892 static const QString warningNoUndo = i18n("Warning: entire project's data will be removed.");
00893
00894
00895 KexiProject*
00896 KexiProject::createBlankProject(bool &cancelled, KexiProjectData* data,
00897 KexiDB::MessageHandler* handler)
00898 {
00899 cancelled = false;
00900 KexiProject *prj = new KexiProject( new KexiProjectData(*data), handler );
00901
00902 bool ok = true;
00903 tristate res = prj->create(false);
00904 if (~res) {
00906 if (KMessageBox::Yes != KMessageBox::warningYesNo(0, "<qt>"+i18n(
00907 "The project %1 already exists.\n"
00908 "Do you want to replace it with a new, blank one?")
00909 .arg(prj->data()->infoString())+"\n"+warningNoUndo+"</qt>",
00910 QString::null, KGuiItem(i18n("Replace")), KStdGuiItem::cancel() ))
00911
00912 {
00913 delete prj;
00914 cancelled = true;
00915 return 0;
00916 }
00917 res = prj->create(true);
00918 }
00919 ok = res;
00920 if (!ok) {
00921 delete prj;
00922 return 0;
00923 }
00924 kdDebug() << "KexiProject::createBlankProject(): new project created --- " << endl;
00925
00926
00927 return prj;
00928 }
00929
00930
00931 tristate KexiProject::dropProject(KexiProjectData* data,
00932 KexiDB::MessageHandler* handler, bool dontAsk)
00933 {
00934 if (!dontAsk && KMessageBox::Yes != KMessageBox::warningYesNo(0,
00935 i18n("Do you want to drop the project \"%1\"?").arg(data->objectName())+"\n"+warningNoUndo ))
00936 return cancelled;
00937
00938 KexiProject prj( new KexiProjectData(*data), handler );
00939 if (!prj.open())
00940 return false;
00941
00942 if (prj.dbConnection()->isReadOnly()) {
00943 handler->showErrorMessage(
00944 futureI18n("Could not drop this project. Database connection project is opened as read only."));
00945 return false;
00946 }
00947
00948 return prj.dbConnection()->dropDatabase();
00949 }
00950
00951
00952
00953
00954
00955
00956
00957
00958
00959
00960
00961
00962
00963
00964
00965
00966
00967
00968
00969
00970 #include "kexiproject.moc"