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) {
00213 if ( !d->data->connectionData()->driverName.lower().startsWith("sqlite")) {
00215 if (incompatibleWithKexi)
00216 *incompatibleWithKexi = true;
00217 }
00218 else
00219 setError(d->connection);
00220 closeConnection();
00221 return false;
00222 }
00223
00224 setError(d->connection);
00225 closeConnection();
00226 return false;
00227 }
00228
00229 if (!initProject())
00230 return false;
00231
00232 return createInternalStructures(true);
00233 }
00234
00235 tristate
00236 KexiProject::create(bool forceOverwrite)
00237 {
00238 KexiDB::MessageTitle et(this,
00239 i18n("Could not create project \"%1\".").arg(d->data->databaseName()));
00240
00241 if (!createConnection())
00242 return false;
00243 if (!checkWritable())
00244 return false;
00245 if (d->connection->databaseExists( d->data->databaseName() )) {
00246 if (!forceOverwrite)
00247 return cancelled;
00248 if (!d->connection->dropDatabase( d->data->databaseName() )) {
00249 setError(d->connection);
00250 closeConnection();
00251 return false;
00252 }
00253 kdDebug() << "--- DB '" << d->data->databaseName() << "' dropped ---"<< endl;
00254 }
00255 if (!d->connection->createDatabase( d->data->databaseName() )) {
00256 setError(d->connection);
00257 closeConnection();
00258 return false;
00259 }
00260 kdDebug() << "--- DB '" << d->data->databaseName() << "' created ---"<< endl;
00261
00262 if (!d->connection->useDatabase(d->data->databaseName()))
00263 {
00264 kdDebug() << "--- DB '" << d->data->databaseName() << "' USE ERROR ---"<< endl;
00265 setError(d->connection);
00266 closeConnection();
00267 return false;
00268 }
00269 kdDebug() << "--- DB '" << d->data->databaseName() << "' used ---"<< endl;
00270
00271
00272 KexiDB::Transaction trans = d->connection->beginTransaction();
00273 if (trans.isNull())
00274 return false;
00275
00276 if (!createInternalStructures(false))
00277 return false;
00278
00279
00281 KexiDB::DatabaseProperties &props = d->connection->databaseProperties();
00282 if (!props.setValue("kexiproject_major_ver", d->versionMajor)
00283 || !props.setCaption("kexiproject_major_ver", i18n("Project major version"))
00284 || !props.setValue("kexiproject_minor_ver", d->versionMinor)
00285 || !props.setCaption("kexiproject_minor_ver", i18n("Project minor version"))
00286 || !props.setValue("project_caption", d->data->caption())
00287 || !props.setCaption("project_caption", i18n("Project caption"))
00288 || !props.setValue("project_desc", d->data->description())
00289 || !props.setCaption("project_desc", i18n("Project description")) )
00290 return false;
00291
00292
00293
00294
00295
00296
00297
00298
00299
00300
00301
00302
00303 if (trans.active() && !d->connection->commitTransaction(trans))
00304 return false;
00305
00306
00307 return initProject();
00308 }
00309
00310 bool KexiProject::createInternalStructures(bool insideTransaction)
00311 {
00312 KexiDB::TransactionGuard tg;
00313 if (insideTransaction) {
00314 tg.setTransaction( d->connection->beginTransaction() );
00315 if (tg.transaction().isNull())
00316 return false;
00317 }
00318
00319
00320
00321 KexiDB::DatabaseProperties &props = d->connection->databaseProperties();
00322 bool ok;
00323 int storedMajorVersion = props.value("kexiproject_major_ver").toInt(&ok);
00324 if (!ok)
00325 storedMajorVersion = 0;
00326 int storedMinorVersion = props.value("kexiproject_minor_ver").toInt(&ok);
00327 if (!ok)
00328 storedMinorVersion = 1;
00329
00330 bool containsKexi__blobsTable = d->connection->drv_containsTable("kexi__blobs");
00331
00333 if (storedMajorVersion<=0) {
00334 d->versionMajor = KEXIPROJECT_VERSION_MAJOR;
00335 d->versionMinor = KEXIPROJECT_VERSION_MINOR;
00336
00337
00338 if (!props.setValue("kexiproject_major_ver", d->versionMajor)
00339 || !props.setCaption("kexiproject_major_ver", i18n("Project major version"))
00340 || !props.setValue("kexiproject_minor_ver", d->versionMinor)
00341 || !props.setCaption("kexiproject_minor_ver", i18n("Project minor version")) ) {
00342 return false;
00343 }
00344
00345
00346 if (containsKexi__blobsTable) {
00347 if (!d->connection->executeSQL(QString::fromLatin1("DROP TABLE kexi__blobs")))
00348 return false;
00349 containsKexi__blobsTable = false;
00350 }
00351 }
00352 if (storedMajorVersion!=d->versionMajor || storedMajorVersion!=d->versionMinor) {
00354 d->versionMajor = storedMajorVersion;
00355 d->versionMinor = storedMinorVersion;
00356 }
00357
00358 KexiDB::InternalTableSchema *t_blobs = new KexiDB::InternalTableSchema("kexi__blobs");
00359 t_blobs->addField( new KexiDB::Field("o_id", KexiDB::Field::Integer,
00360 KexiDB::Field::PrimaryKey | KexiDB::Field::AutoInc, KexiDB::Field::Unsigned) )
00361 .addField( new KexiDB::Field("o_data", KexiDB::Field::BLOB) )
00362 .addField( new KexiDB::Field("o_name", KexiDB::Field::Text ) )
00363 .addField( new KexiDB::Field("o_caption", KexiDB::Field::Text ) )
00364 .addField( new KexiDB::Field("o_mime", KexiDB::Field::Text, KexiDB::Field::NotNull) )
00365 .addField( new KexiDB::Field("o_folder_id",
00366 KexiDB::Field::Integer, 0, KexiDB::Field::Unsigned)
00367
00368
00369 );
00370
00371
00372 if (containsKexi__blobsTable) {
00374 d->connection->insertInternalTableSchema(t_blobs);
00375 }
00376 else {
00377
00378 if (!d->connection->createTable( t_blobs, true )) {
00379 delete t_blobs;
00380 return false;
00381 }
00382 }
00383
00384
00385
00386 KexiDB::InternalTableSchema *t_parts = new KexiDB::InternalTableSchema("kexi__parts");
00387 t_parts->addField(
00388 new KexiDB::Field("p_id", KexiDB::Field::Integer, KexiDB::Field::PrimaryKey | KexiDB::Field::AutoInc, KexiDB::Field::Unsigned)
00389 )
00390 .addField( new KexiDB::Field("p_name", KexiDB::Field::Text) )
00391 .addField( new KexiDB::Field("p_mime", KexiDB::Field::Text ) )
00392 .addField( new KexiDB::Field("p_url", KexiDB::Field::Text ) );
00393
00394 bool containsKexi__partsTable = d->connection->drv_containsTable("kexi__parts");
00395 bool partsTableOk = true;
00396 if (containsKexi__partsTable) {
00398 d->connection->insertInternalTableSchema(t_parts);
00399 }
00400 else {
00401 partsTableOk = d->connection->createTable( t_parts, true );
00402
00403 KexiDB::FieldList *fl = t_parts->subList("p_id", "p_name", "p_mime", "p_url");
00404 if (partsTableOk)
00405 partsTableOk = d->connection->insertRecord(*fl, QVariant(1), QVariant("Tables"),
00406 QVariant("kexi/table"), QVariant("http://koffice.org/kexi/"));
00407
00408 if (partsTableOk)
00409 partsTableOk = d->connection->insertRecord(*fl, QVariant(2), QVariant("Queries"),
00410 QVariant("kexi/query"), QVariant("http://koffice.org/kexi/"));
00411 }
00412
00413 if (!partsTableOk) {
00414 delete t_parts;
00415 return false;
00416 }
00417
00418 if (insideTransaction) {
00419 if (tg.transaction().active() && !tg.commit())
00420 return false;
00421 }
00422 return true;
00423 }
00424
00425 bool
00426 KexiProject::createConnection()
00427 {
00428 if (d->connection)
00429 return true;
00430
00431 clearError();
00432
00433 KexiDB::MessageTitle et(this);
00434
00435 KexiDB::Driver *driver = Kexi::driverManager().driver(d->data->connectionData()->driverName);
00436 if(!driver) {
00437 setError(&Kexi::driverManager());
00438 return false;
00439 }
00440
00441 int connectionOptions = 0;
00442 if (d->data->isReadOnly())
00443 connectionOptions |= KexiDB::Driver::ReadOnlyConnection;
00444 d->connection = driver->createConnection(*d->data->connectionData(), connectionOptions);
00445 if (!d->connection)
00446 {
00447 kdDebug() << "KexiProject::open(): uuups failed " << driver->errorMsg() << endl;
00448 setError(driver);
00449 return false;
00450 }
00451
00452 if (!d->connection->connect())
00453 {
00454 setError(d->connection);
00455 kdDebug() << "KexiProject::createConnection(): error connecting: " << (d->connection ? d->connection->errorMsg() : QString::null) << endl;
00456 closeConnection();
00457 return false;
00458 }
00459
00460
00462 KexiBLOBBuffer::setConnection(d->connection);
00463 return true;
00464 }
00465
00466
00467 bool
00468 KexiProject::closeConnection()
00469 {
00470 if (!d->connection)
00471 return true;
00472
00473 if (!d->connection->disconnect()) {
00474 setError(d->connection);
00475 return false;
00476 }
00477
00478 delete d->connection;
00479 d->connection = 0;
00480 return true;
00481 }
00482
00483 bool
00484 KexiProject::initProject()
00485 {
00486
00487 kdDebug() << "KexiProject::open(): checking project parts..." << endl;
00488
00489 if (!Kexi::partManager().checkProject(d->connection)) {
00490 setError(Kexi::partManager().error() ? (KexiDB::Object*)&Kexi::partManager() : (KexiDB::Connection*)d->connection);
00491 return false;
00492 }
00493
00494
00495 KexiDB::DatabaseProperties &props = d->connection->databaseProperties();
00496 QString str( props.value("project_caption").toString() );
00497 if (!str.isEmpty())
00498 d->data->setCaption( str );
00499 str = props.value("project_desc").toString();
00500 if (!str.isEmpty())
00501 d->data->setDescription( str );
00502
00503
00504
00505
00506
00507
00508
00509 return true;
00510 }
00511
00512 bool
00513 KexiProject::isConnected()
00514 {
00515 if(d->connection && d->connection->isDatabaseUsed())
00516 return true;
00517
00518 return false;
00519 }
00520
00521 KexiPart::ItemDict*
00522 KexiProject::items(KexiPart::Info *i)
00523 {
00524 kdDebug() << "KexiProject::items()" << endl;
00525 if(!i || !isConnected())
00526 return 0;
00527
00528
00529 KexiPart::ItemDict *dict = d->itemDictsCache[ i->projectPartID() ];
00530 if (dict)
00531 return dict;
00532
00533 KexiDB::Cursor *cursor = d->connection->executeQuery(
00534 "SELECT o_id, o_name, o_caption FROM kexi__objects WHERE o_type = "
00535 + QString::number(i->projectPartID()));
00536
00537 if(!cursor)
00538 return 0;
00539
00540 dict = new KexiPart::ItemDict(1009);
00541 dict->setAutoDelete(true);
00542
00543 for(cursor->moveFirst(); !cursor->eof(); cursor->moveNext())
00544 {
00545 KexiPart::Item *it = new KexiPart::Item();
00546 bool ok;
00547 int ident = cursor->value(0).toInt(&ok);
00548 QString objName( cursor->value(1).toString() );
00549
00550 if ( ok && (ident>0) && !d->connection->isInternalTableSchema(objName)
00551 && KexiUtils::isIdentifier(objName) )
00552 {
00553 it->setIdentifier(ident);
00554 it->setMimeType(i->mimeType());
00555 it->setName(objName);
00556 it->setCaption(cursor->value(2).toString());
00557 }
00558 dict->insert(it->identifier(), it);
00559
00560 }
00561
00562 d->connection->deleteCursor(cursor);
00563
00564 d->itemDictsCache.insert( i->projectPartID(), dict );
00565 return dict;
00566 }
00567
00568 KexiPart::ItemDict*
00569 KexiProject::itemsForMimeType(const QCString &mimeType)
00570 {
00571 KexiPart::Info *info = Kexi::partManager().infoForMimeType(mimeType);
00572 return items(info);
00573 }
00574
00575 void
00576 KexiProject::getSortedItems(KexiPart::ItemList& list, KexiPart::Info *i)
00577 {
00578 list.clear();
00579 KexiPart::ItemDict* dict = items(i);
00580 if (!dict)
00581 return;
00582 for (KexiPart::ItemDictIterator it(*dict); it.current(); ++it)
00583 list.append(it.current());
00584 }
00585
00586 void
00587 KexiProject::getSortedItemsForMimeType(KexiPart::ItemList& list, const QCString &mimeType)
00588 {
00589 KexiPart::Info *info = Kexi::partManager().infoForMimeType(mimeType);
00590 getSortedItems(list, info);
00591 }
00592
00593 void
00594 KexiProject::addStoredItem(KexiPart::Info *info, KexiPart::Item *item)
00595 {
00596 if (!info || !item)
00597 return;
00598 KexiPart::ItemDict *dict = items(info);
00599 item->setNeverSaved( false );
00600 d->unstoredItems.take(item);
00601 dict->insert( item->identifier(), item );
00602
00603 emit newItemStored(*item);
00604 }
00605
00606 KexiPart::Item*
00607 KexiProject::itemForMimeType(const QCString &mimeType, const QString &name)
00608 {
00609 KexiPart::ItemDict *dict = itemsForMimeType(mimeType);
00610 if (!dict)
00611 return 0;
00612 const QString l_name = name.lower();
00613 for (KexiPart::ItemDictIterator it( *dict ); it.current(); ++it) {
00614 if (it.current()->name().lower()==l_name)
00615 return it.current();
00616 }
00617 return 0;
00618 }
00619
00620 KexiPart::Item*
00621 KexiProject::item(KexiPart::Info *i, const QString &name)
00622 {
00623 KexiPart::ItemDict *dict = items(i);
00624 if (!dict)
00625 return 0;
00626 const QString l_name = name.lower();
00627 for (KexiPart::ItemDictIterator it( *dict ); it.current(); ++it) {
00628 if (it.current()->name().lower()==l_name)
00629 return it.current();
00630 }
00631 return 0;
00632 }
00633
00634 KexiPart::Item*
00635 KexiProject::item(int identifier)
00636 {
00637 KexiPart::ItemDict *dict;
00638 for (QIntDictIterator<KexiPart::ItemDict> it(d->itemDictsCache); (dict = it.current()); ++it) {
00639 KexiPart::Item *item = dict->find(identifier);
00640 if (item)
00641 return item;
00642 }
00643 return 0;
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
00673
00674
00675
00676
00677
00678
00679
00680
00681
00682
00683
00684
00685
00686
00687 KexiPart::Part *KexiProject::findPartFor(KexiPart::Item& item)
00688 {
00689 clearError();
00690 KexiDB::MessageTitle et(this);
00691 KexiPart::Part *part = Kexi::partManager().partForMimeType(item.mimeType());
00692 if (!part)
00693 setError(&Kexi::partManager());
00694 return part;
00695 }
00696
00697 KexiDialogBase* KexiProject::openObject(KexiMainWindow *wnd, KexiPart::Item& item,
00698 int viewMode, QMap<QString,QString>* staticObjectArgs)
00699 {
00700 clearError();
00701 KexiDB::MessageTitle et(this);
00702 KexiPart::Part *part = findPartFor(item);
00703 if (!part)
00704 return 0;
00705 KexiDialogBase *dlg = part->openInstance(wnd, item, viewMode, staticObjectArgs);
00706 if (!dlg) {
00707 if (part->lastOperationStatus().error())
00708 setError(i18n("Opening object \"%1\" failed.").arg(item.name())+"<br>"
00709 +part->lastOperationStatus().message,
00710 part->lastOperationStatus().description);
00711 return 0;
00712 }
00713 return dlg;
00714 }
00715
00716 KexiDialogBase* KexiProject::openObject(KexiMainWindow *wnd, const QCString &mimeType,
00717 const QString& name, int viewMode)
00718 {
00719 KexiPart::Item *it = itemForMimeType(mimeType, name);
00720 return it ? openObject(wnd, *it, viewMode) : 0;
00721 }
00722
00723 bool KexiProject::checkWritable()
00724 {
00725 if (!d->connection->isReadOnly())
00726 return true;
00727 setError(i18n("This project is opened as read only."));
00728 return false;
00729 }
00730
00731 bool KexiProject::removeObject(KexiMainWindow *wnd, KexiPart::Item& item)
00732 {
00733 clearError();
00734 KexiDB::MessageTitle et(this);
00735 if (!checkWritable())
00736 return false;
00737 KexiPart::Part *part = findPartFor(item);
00738 if (!part)
00739 return false;
00740 if (!item.neverSaved() && !part->remove(wnd, item)) {
00741
00742 return false;
00743 }
00744 if (!item.neverSaved()) {
00745 KexiDB::TransactionGuard tg( *d->connection );
00746 if (!tg.transaction().active()) {
00747 setError(d->connection);
00748 return false;
00749 }
00750 if (!d->connection->removeObject( item.identifier() )) {
00751 setError(d->connection);
00752 return false;
00753 }
00754 if (!tg.commit()) {
00755 setError(d->connection);
00756 return false;
00757 }
00758 }
00759 emit itemRemoved(item);
00760
00761
00762 if (part->info()) {
00763 KexiPart::ItemDict *dict = d->itemDictsCache[ part->info()->projectPartID() ];
00764 if (!(dict && dict->remove( item.identifier() )))
00765 d->unstoredItems.remove(&item);
00766 }
00767 return true;
00768 }
00769
00770 bool KexiProject::renameObject( KexiMainWindow *wnd, KexiPart::Item& item, const QString& _newName )
00771 {
00772 KexiUtils::WaitCursor wait;
00773 clearError();
00774 QString newName = _newName.stripWhiteSpace();
00775 {
00776 KexiDB::MessageTitle et(this);
00777 if (newName.isEmpty()) {
00778 setError( i18n("Could not set empty name for this object.") );
00779 return false;
00780 }
00781 if (this->itemForMimeType(item.mimeType(), newName)!=0) {
00782 setError( i18n("Could not use this name. Object with name \"%1\" already exists.")
00783 .arg(newName) );
00784 return false;
00785 }
00786 }
00787
00788 KexiDB::MessageTitle et(this,
00789 i18n("Could not rename object \"%1\".").arg(item.name()) );
00790 if (!checkWritable())
00791 return false;
00792 KexiPart::Part *part = findPartFor(item);
00793 if (!part)
00794 return false;
00795 KexiDB::TransactionGuard tg( *d->connection );
00796 if (!tg.transaction().active()) {
00797 setError(d->connection);
00798 return false;
00799 }
00800 if (!part->rename(wnd, item, newName)) {
00801 setError(part->lastOperationStatus().message, part->lastOperationStatus().description);
00802 return false;
00803 }
00804 if (!d->connection->executeSQL( "update kexi__objects set o_name="
00805 + d->connection->driver()->valueToSQL( KexiDB::Field::Text, newName )
00806 + " where o_id=" + QString::number(item.identifier()) )) {
00807 setError(d->connection);
00808 return false;
00809 }
00810 if (!tg.commit()) {
00811 setError(d->connection);
00812 return false;
00813 }
00814 QCString oldName( item.name().latin1() );
00815 item.setName( newName );
00816 emit itemRenamed(item, oldName);
00817 return true;
00818 }
00819
00820 KexiPart::Item* KexiProject::createPartItem(KexiPart::Info *info, const QString& suggestedCaption)
00821 {
00822 clearError();
00823 KexiDB::MessageTitle et(this);
00824 KexiPart::Part *part = Kexi::partManager().part(info);
00825 if (!part) {
00826 setError(&Kexi::partManager());
00827 return 0;
00828 }
00829
00830 KexiPart::ItemDict *dict = items(info);
00831
00832
00833 int n;
00834 QString new_name;
00835 QString base_name;
00836 if (suggestedCaption.isEmpty()) {
00837 n = 1;
00838 base_name = part->instanceName();
00839 }
00840 else {
00841 n = 0;
00842 base_name = KexiUtils::string2Identifier(suggestedCaption).lower();
00843 }
00844 base_name = KexiUtils::string2Identifier(base_name).lower();
00845 KexiPart::ItemDictIterator it(*dict);
00846 QPtrDictIterator<KexiPart::Item> itUnstored(d->unstoredItems);
00847 do {
00848 new_name = base_name;
00849 if (n>=1)
00850 new_name += QString::number(n);
00851 for (it.toFirst(); it.current(); ++it) {
00852 if (it.current()->name().lower()==new_name)
00853 break;
00854 }
00855 if ( it.current() ) {
00856 n++;
00857 continue;
00858 }
00859 for (itUnstored.toFirst(); itUnstored.current(); ++itUnstored) {
00860 if (itUnstored.current()->name().lower()==new_name)
00861 break;
00862 }
00863 if ( !itUnstored.current() )
00864 break;
00865 n++;
00866 } while (n<1000);
00867
00868 if (n>=1000)
00869 return 0;
00870
00871 QString new_caption( suggestedCaption.isEmpty() ? part->instanceCaption() : suggestedCaption);
00872 if (n>=1)
00873 new_caption += QString::number(n);
00874
00875 KexiPart::Item *item = new KexiPart::Item();
00876 item->setIdentifier( --d->tempPartItemID_Counter );
00877 item->setMimeType(info->mimeType());
00878 item->setName(new_name);
00879 item->setCaption(new_caption);
00880 item->setNeverSaved(true);
00881 d->unstoredItems.insert(item, item);
00882 return item;
00883 }
00884
00885 KexiPart::Item* KexiProject::createPartItem(KexiPart::Part *part, const QString& suggestedCaption)
00886 {
00887 return createPartItem(part->info(), suggestedCaption);
00888 }
00889
00890 void KexiProject::deleteUnstoredItem(KexiPart::Item *item)
00891 {
00892 if (!item)
00893 return;
00894 d->unstoredItems.remove(item);
00895 }
00896
00897 KexiDB::Parser* KexiProject::sqlParser()
00898 {
00899 if (!d->sqlParser) {
00900 if (!d->connection)
00901 return 0;
00902 d->sqlParser = new KexiDB::Parser(d->connection);
00903 }
00904 return d->sqlParser;
00905 }
00906
00907 static const QString warningNoUndo = i18n("Warning: entire project's data will be removed.");
00908
00909
00910 KexiProject*
00911 KexiProject::createBlankProject(bool &cancelled, KexiProjectData* data,
00912 KexiDB::MessageHandler* handler)
00913 {
00914 cancelled = false;
00915 KexiProject *prj = new KexiProject( new KexiProjectData(*data), handler );
00916
00917 tristate res = prj->create(false);
00918 if (~res) {
00920 if (KMessageBox::Yes != KMessageBox::warningYesNo(0, "<qt>"+i18n(
00921 "The project %1 already exists.\n"
00922 "Do you want to replace it with a new, blank one?")
00923 .arg(prj->data()->infoString())+"\n"+warningNoUndo+"</qt>",
00924 QString::null, KGuiItem(i18n("Replace")), KStdGuiItem::cancel() ))
00925
00926 {
00927 delete prj;
00928 cancelled = true;
00929 return 0;
00930 }
00931 res = prj->create(true);
00932 }
00933 if (res != true) {
00934 delete prj;
00935 return 0;
00936 }
00937 kdDebug() << "KexiProject::createBlankProject(): new project created --- " << endl;
00938
00939
00940 return prj;
00941 }
00942
00943
00944 tristate KexiProject::dropProject(KexiProjectData* data,
00945 KexiDB::MessageHandler* handler, bool dontAsk)
00946 {
00947 if (!dontAsk && KMessageBox::Yes != KMessageBox::warningYesNo(0,
00948 i18n("Do you want to drop the project \"%1\"?").arg(data->objectName())+"\n"+warningNoUndo ))
00949 return cancelled;
00950
00951 KexiProject prj( new KexiProjectData(*data), handler );
00952 if (!prj.open())
00953 return false;
00954
00955 if (prj.dbConnection()->isReadOnly()) {
00956 handler->showErrorMessage(
00957 i18n("Could not drop this project. Database connection for this project has been opened as read only."));
00958 return false;
00959 }
00960
00961 return prj.dbConnection()->dropDatabase();
00962 }
00963
00964
00965
00966
00967
00968
00969
00970
00971
00972
00973
00974
00975
00976
00977
00978
00979
00980
00981
00982
00983 #include "kexiproject.moc"