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 d->connection = driver->createConnection(*d->data->connectionData());
00442 if (!d->connection)
00443 {
00444 kdDebug() << "KexiProject::open(): uuups failed " << driver->errorMsg() << endl;
00445 setError(driver);
00446 return false;
00447 }
00448
00449 if (!d->connection->connect())
00450 {
00451 setError(d->connection);
00452 kdDebug() << "KexiProject::createConnection(): error connecting: " << (d->connection ? d->connection->errorMsg() : QString::null) << endl;
00453 closeConnection();
00454 return false;
00455 }
00456
00457
00459 KexiBLOBBuffer::setConnection(d->connection);
00460 return true;
00461 }
00462
00463
00464 void
00465 KexiProject::closeConnection()
00466 {
00467 if (!d->connection)
00468 return;
00469
00470 delete d->connection;
00471 d->connection = 0;
00472 }
00473
00474 bool
00475 KexiProject::initProject()
00476 {
00477
00478 kdDebug() << "KexiProject::open(): checking project parts..." << endl;
00479
00480 if (!Kexi::partManager().checkProject(d->connection)) {
00481 setError(Kexi::partManager().error() ? (KexiDB::Object*)&Kexi::partManager() : (KexiDB::Connection*)d->connection);
00482 return false;
00483 }
00484
00485
00486 KexiDB::DatabaseProperties &props = d->connection->databaseProperties();
00487 QString str( props.value("project_caption").toString() );
00488 if (!str.isEmpty())
00489 d->data->setCaption( str );
00490 str = props.value("project_desc").toString();
00491 if (!str.isEmpty())
00492 d->data->setDescription( str );
00493
00494
00495
00496
00497
00498
00499
00500 return true;
00501 }
00502
00503 bool
00504 KexiProject::isConnected()
00505 {
00506 if(d->connection && d->connection->isDatabaseUsed())
00507 return true;
00508
00509 return false;
00510 }
00511
00512 KexiPart::ItemDict*
00513 KexiProject::items(KexiPart::Info *i)
00514 {
00515 kdDebug() << "KexiProject::items()" << endl;
00516 if(!i || !isConnected())
00517 return 0;
00518
00519
00520 KexiPart::ItemDict *dict = d->itemDictsCache[ i->projectPartID() ];
00521 if (dict)
00522 return dict;
00523
00524 KexiDB::Cursor *cursor = d->connection->executeQuery(
00525 "SELECT o_id, o_name, o_caption FROM kexi__objects WHERE o_type = "
00526 + QString::number(i->projectPartID()));
00527
00528 if(!cursor)
00529 return 0;
00530
00531 dict = new KexiPart::ItemDict(1009);
00532 dict->setAutoDelete(true);
00533
00534 for(cursor->moveFirst(); !cursor->eof(); cursor->moveNext())
00535 {
00536 KexiPart::Item *it = new KexiPart::Item();
00537 bool ok;
00538 int ident = cursor->value(0).toInt(&ok);
00539 QString objName( cursor->value(1).toString() );
00540
00541 if ( ok && (ident>0) && !d->connection->isInternalTableSchema(objName)
00542 && KexiUtils::isIdentifier(objName) )
00543 {
00544 it->setIdentifier(ident);
00545 it->setMimeType(i->mimeType());
00546 it->setName(objName);
00547 it->setCaption(cursor->value(2).toString());
00548 }
00549 dict->insert(it->identifier(), it);
00550
00551 }
00552
00553 d->connection->deleteCursor(cursor);
00554
00555 d->itemDictsCache.insert( i->projectPartID(), dict );
00556 return dict;
00557 }
00558
00559 KexiPart::ItemDict*
00560 KexiProject::itemsForMimeType(const QCString &mimeType)
00561 {
00562 KexiPart::Info *info = Kexi::partManager().infoForMimeType(mimeType);
00563 return items(info);
00564 }
00565
00566 void
00567 KexiProject::getSortedItems(KexiPart::ItemList& list, KexiPart::Info *i)
00568 {
00569 list.clear();
00570 KexiPart::ItemDict* dict = items(i);
00571 if (!dict)
00572 return;
00573 for (KexiPart::ItemDictIterator it(*dict); it.current(); ++it)
00574 list.append(it.current());
00575 }
00576
00577 void
00578 KexiProject::getSortedItemsForMimeType(KexiPart::ItemList& list, const QCString &mimeType)
00579 {
00580 KexiPart::Info *info = Kexi::partManager().infoForMimeType(mimeType);
00581 getSortedItems(list, info);
00582 }
00583
00584 void
00585 KexiProject::addStoredItem(KexiPart::Info *info, KexiPart::Item *item)
00586 {
00587 if (!info || !item)
00588 return;
00589 KexiPart::ItemDict *dict = items(info);
00590 item->setNeverSaved( false );
00591 d->unstoredItems.take(item);
00592 dict->insert( item->identifier(), item );
00593
00594 emit newItemStored(*item);
00595 }
00596
00597 KexiPart::Item*
00598 KexiProject::itemForMimeType(const QCString &mimeType, const QString &name)
00599 {
00600 KexiPart::ItemDict *dict = itemsForMimeType(mimeType);
00601 if (!dict)
00602 return 0;
00603 const QString l_name = name.lower();
00604 for (KexiPart::ItemDictIterator it( *dict ); it.current(); ++it) {
00605 if (it.current()->name().lower()==l_name)
00606 return it.current();
00607 }
00608 return 0;
00609 }
00610
00611 KexiPart::Item*
00612 KexiProject::item(KexiPart::Info *i, const QString &name)
00613 {
00614 KexiPart::ItemDict *dict = items(i);
00615 if (!dict)
00616 return 0;
00617 const QString l_name = name.lower();
00618 for (KexiPart::ItemDictIterator it( *dict ); it.current(); ++it) {
00619 if (it.current()->name().lower()==l_name)
00620 return it.current();
00621 }
00622 return 0;
00623 }
00624
00625 KexiPart::Item*
00626 KexiProject::item(int identifier)
00627 {
00628 KexiPart::ItemDict *dict;
00629 for (QIntDictIterator<KexiPart::ItemDict> it(d->itemDictsCache); (dict = it.current()); ++it) {
00630 KexiPart::Item *item = dict->find(identifier);
00631 if (item)
00632 return item;
00633 }
00634 return 0;
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
00673
00674
00675
00676
00677
00678 KexiPart::Part *KexiProject::findPartFor(KexiPart::Item& item)
00679 {
00680 clearError();
00681 KexiDB::MessageTitle et(this);
00682 KexiPart::Part *part = Kexi::partManager().partForMimeType(item.mimeType());
00683 if (!part)
00684 setError(&Kexi::partManager());
00685 return part;
00686 }
00687
00688 KexiDialogBase* KexiProject::openObject(KexiMainWindow *wnd, KexiPart::Item& item,
00689 int viewMode, QMap<QString,QString>* staticObjectArgs)
00690 {
00691 clearError();
00692 KexiDB::MessageTitle et(this);
00693 KexiPart::Part *part = findPartFor(item);
00694 if (!part)
00695 return 0;
00696 KexiDialogBase *dlg = part->openInstance(wnd, item, viewMode, staticObjectArgs);
00697 if (!dlg) {
00698 if (part->lastOperationStatus().error())
00699 setError(i18n("Opening object \"%1\" failed.").arg(item.name())+"<br>"
00700 +part->lastOperationStatus().message,
00701 part->lastOperationStatus().description);
00702 return 0;
00703 }
00704 return dlg;
00705 }
00706
00707 KexiDialogBase* KexiProject::openObject(KexiMainWindow *wnd, const QCString &mimeType,
00708 const QString& name, int viewMode)
00709 {
00710 KexiPart::Item *it = itemForMimeType(mimeType, name);
00711 return it ? openObject(wnd, *it, viewMode) : 0;
00712 }
00713
00714 bool KexiProject::checkWritable()
00715 {
00716 if (!d->connection->isReadOnly())
00717 return true;
00718 setError(futureI18n("This project is opened as read only."));
00719 return false;
00720 }
00721
00722 bool KexiProject::removeObject(KexiMainWindow *wnd, KexiPart::Item& item)
00723 {
00724 clearError();
00725 KexiDB::MessageTitle et(this);
00726 if (!checkWritable())
00727 return false;
00728 KexiPart::Part *part = findPartFor(item);
00729 if (!part)
00730 return false;
00731 if (!item.neverSaved() && !part->remove(wnd, item)) {
00732
00733 return false;
00734 }
00735 if (!item.neverSaved()) {
00736 KexiDB::TransactionGuard tg( *d->connection );
00737 if (!tg.transaction().active()) {
00738 setError(d->connection);
00739 return false;
00740 }
00741 if (!d->connection->removeObject( item.identifier() )) {
00742 setError(d->connection);
00743 return false;
00744 }
00745 if (!tg.commit()) {
00746 setError(d->connection);
00747 return false;
00748 }
00749 }
00750 emit itemRemoved(item);
00751
00752
00753 if (part->info()) {
00754 KexiPart::ItemDict *dict = d->itemDictsCache[ part->info()->projectPartID() ];
00755 if (!(dict && dict->remove( item.identifier() )))
00756 d->unstoredItems.remove(&item);
00757 }
00758 return true;
00759 }
00760
00761 bool KexiProject::renameObject( KexiMainWindow *wnd, KexiPart::Item& item, const QString& _newName )
00762 {
00763 KexiUtils::WaitCursor wait;
00764 clearError();
00765 QString newName = _newName.stripWhiteSpace();
00766 {
00767 KexiDB::MessageTitle et(this);
00768 if (newName.isEmpty()) {
00769 setError( i18n("Could not set empty name for this object.") );
00770 return false;
00771 }
00772 if (this->itemForMimeType(item.mimeType(), newName)!=0) {
00773 setError( i18n("Could not use this name. Object with name \"%1\" already exists.")
00774 .arg(newName) );
00775 return false;
00776 }
00777 }
00778
00779 KexiDB::MessageTitle et(this,
00780 i18n("Could not rename object \"%1\".").arg(item.name()) );
00781 if (!checkWritable())
00782 return false;
00783 KexiPart::Part *part = findPartFor(item);
00784 if (!part)
00785 return false;
00786 KexiDB::TransactionGuard tg( *d->connection );
00787 if (!tg.transaction().active()) {
00788 setError(d->connection);
00789 return false;
00790 }
00791 if (!part->rename(wnd, item, newName)) {
00792 setError(part->lastOperationStatus().message, part->lastOperationStatus().description);
00793 return false;
00794 }
00795 if (!d->connection->executeSQL( "update kexi__objects set o_name="
00796 + d->connection->driver()->valueToSQL( KexiDB::Field::Text, newName )
00797 + " where o_id=" + QString::number(item.identifier()) )) {
00798 setError(d->connection);
00799 return false;
00800 }
00801 if (!tg.commit()) {
00802 setError(d->connection);
00803 return false;
00804 }
00805 QCString oldName( item.name().latin1() );
00806 item.setName( newName );
00807 emit itemRenamed(item, oldName);
00808 return true;
00809 }
00810
00811 KexiPart::Item* KexiProject::createPartItem(KexiPart::Info *info, const QString& suggestedCaption)
00812 {
00813 clearError();
00814 KexiDB::MessageTitle et(this);
00815 KexiPart::Part *part = Kexi::partManager().part(info);
00816 if (!part) {
00817 setError(&Kexi::partManager());
00818 return 0;
00819 }
00820
00821 KexiPart::ItemDict *dict = items(info);
00822
00823
00824 int n;
00825 QString new_name;
00826 QString base_name;
00827 if (suggestedCaption.isEmpty()) {
00828 n = 1;
00829 base_name = part->instanceName();
00830 }
00831 else {
00832 n = 0;
00833 base_name = KexiUtils::string2Identifier(suggestedCaption).lower();
00834 }
00835 base_name = KexiUtils::string2Identifier(base_name).lower();
00836 KexiPart::ItemDictIterator it(*dict);
00837 QPtrDictIterator<KexiPart::Item> itUnstored(d->unstoredItems);
00838 do {
00839 new_name = base_name;
00840 if (n>=1)
00841 new_name += QString::number(n);
00842 for (it.toFirst(); it.current(); ++it) {
00843 if (it.current()->name().lower()==new_name)
00844 break;
00845 }
00846 if ( it.current() ) {
00847 n++;
00848 continue;
00849 }
00850 for (itUnstored.toFirst(); itUnstored.current(); ++itUnstored) {
00851 if (itUnstored.current()->name().lower()==new_name)
00852 break;
00853 }
00854 if ( !itUnstored.current() )
00855 break;
00856 n++;
00857 } while (n<1000);
00858
00859 if (n>=1000)
00860 return 0;
00861
00862 QString new_caption( suggestedCaption.isEmpty() ? part->instanceCaption() : suggestedCaption);
00863 if (n>=1)
00864 new_caption += QString::number(n);
00865
00866 KexiPart::Item *item = new KexiPart::Item();
00867 item->setIdentifier( --d->tempPartItemID_Counter );
00868 item->setMimeType(info->mimeType());
00869 item->setName(new_name);
00870 item->setCaption(new_caption);
00871 item->setNeverSaved(true);
00872 d->unstoredItems.insert(item, item);
00873 return item;
00874 }
00875
00876 KexiPart::Item* KexiProject::createPartItem(KexiPart::Part *part, const QString& suggestedCaption)
00877 {
00878 return createPartItem(part->info(), suggestedCaption);
00879 }
00880
00881 void KexiProject::deleteUnstoredItem(KexiPart::Item *item)
00882 {
00883 if (!item)
00884 return;
00885 d->unstoredItems.remove(item);
00886 }
00887
00888 KexiDB::Parser* KexiProject::sqlParser()
00889 {
00890 if (!d->sqlParser) {
00891 if (!d->connection)
00892 return 0;
00893 d->sqlParser = new KexiDB::Parser(d->connection);
00894 }
00895 return d->sqlParser;
00896 }
00897
00898 static const QString warningNoUndo = i18n("Warning: entire project's data will be removed.");
00899
00900
00901 KexiProject*
00902 KexiProject::createBlankProject(bool &cancelled, KexiProjectData* data,
00903 KexiDB::MessageHandler* handler)
00904 {
00905 cancelled = false;
00906 KexiProject *prj = new KexiProject( new KexiProjectData(*data), handler );
00907
00908 bool ok = true;
00909 tristate res = prj->create(false);
00910 if (~res) {
00912 if (KMessageBox::Yes != KMessageBox::warningYesNo(0, "<qt>"+i18n(
00913 "The project %1 already exists.\n"
00914 "Do you want to replace it with a new, blank one?")
00915 .arg(prj->data()->infoString())+"\n"+warningNoUndo+"</qt>",
00916 QString::null, KGuiItem(i18n("Replace")), KStdGuiItem::cancel() ))
00917
00918 {
00919 delete prj;
00920 cancelled = true;
00921 return 0;
00922 }
00923 res = prj->create(true);
00924 }
00925 ok = res;
00926 if (!ok) {
00927 delete prj;
00928 return 0;
00929 }
00930 kdDebug() << "KexiProject::createBlankProject(): new project created --- " << endl;
00931
00932
00933 return prj;
00934 }
00935
00936
00937 tristate KexiProject::dropProject(KexiProjectData* data,
00938 KexiDB::MessageHandler* handler, bool dontAsk)
00939 {
00940 if (!dontAsk && KMessageBox::Yes != KMessageBox::warningYesNo(0,
00941 i18n("Do you want to drop the project \"%1\"?").arg(data->objectName())+"\n"+warningNoUndo ))
00942 return cancelled;
00943
00944 KexiProject prj( new KexiProjectData(*data), handler );
00945 if (!prj.open())
00946 return false;
00947
00948 if (prj.dbConnection()->isReadOnly()) {
00949 handler->showErrorMessage(
00950 futureI18n("Could not drop this project. Database connection project is opened as read only."));
00951 return false;
00952 }
00953
00954 return prj.dbConnection()->dropDatabase();
00955 }
00956
00957
00958
00959
00960
00961
00962
00963
00964
00965
00966
00967
00968
00969
00970
00971
00972
00973
00974
00975
00976 #include "kexiproject.moc"