File indexing completed on 2024-05-12 16:39:39
0001 /* This file is part of the KDE project 0002 Copyright (C) 2003 Lucijan Busch <lucijan@kde.org> 0003 Copyright (C) 2003-2019 Jarosław Staniek <staniek@kde.org> 0004 0005 This library is free software; you can redistribute it and/or 0006 modify it under the terms of the GNU Library General Public 0007 License as published by the Free Software Foundation; either 0008 version 2 of the License, or (at your option) any later version. 0009 0010 This library is distributed in the hope that it will be useful, 0011 but WITHOUT ANY WARRANTY; without even the implied warranty of 0012 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 0013 Library General Public License for more details. 0014 0015 You should have received a copy of the GNU Library General Public License 0016 along with this library; see the file COPYING.LIB. If not, write to 0017 the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, 0018 * Boston, MA 02110-1301, USA. 0019 */ 0020 0021 #ifndef KEXIPROJECT_H 0022 #define KEXIPROJECT_H 0023 0024 #include <QObject> 0025 0026 #include <KDbTristate> 0027 #include <KDbObject> 0028 #include <KDbResult> 0029 0030 #include "kexiprojectdata.h" 0031 #include "kexipartitem.h" 0032 #include "kexi.h" 0033 0034 #include <KDbTableOrQuerySchema> 0035 0036 /*! KexiProject implementation version. 0037 It is altered after every change: 0038 - major number is increased after KexiProject storage format change, 0039 - minor is increased after adding binary-incompatible change. 0040 Use KexiProject::versionMajor() and KexiProject::versionMinor() to get real project's version. 0041 */ 0042 0043 #define KEXIPROJECT_VERSION_MAJOR 1 0044 #define KEXIPROJECT_VERSION_MINOR 0 0045 0046 class QFileInfo; 0047 class KDbConnection; 0048 class KDbParser; 0049 class KexiMainWindow; 0050 class KexiWindow; 0051 0052 namespace KexiPart 0053 { 0054 class Part; 0055 class Info; 0056 0057 struct MissingPart { 0058 QString name; 0059 QString id; 0060 }; 0061 typedef QList<MissingPart> MissingPartsList; 0062 } 0063 0064 /** 0065 * @brief A single project's controller and data structure. 0066 * It contains data connection, state, etc. 0067 */ 0068 class KEXICORE_EXPORT KexiProject : public QObject, public KDbObject, public KDbResultable 0069 { 0070 Q_OBJECT 0071 0072 public: 0073 /*! Constructor 1. Creates a new object using \a pdata. 0074 \a handler can be provided to receive error messages during 0075 entire KexiProject object's lifetime. */ 0076 explicit KexiProject(const KexiProjectData& pdata, KDbMessageHandler* handler = 0); 0077 0078 /*! Constructor 2. Like above but sets predefined connections \a conn. 0079 The connection should be created using the same connection data 0080 as pdata->connectionData(). The connection will become owned by created KexiProject 0081 object, so do not destroy it. */ 0082 KexiProject(const KexiProjectData& pdata, KDbMessageHandler* handler, 0083 KDbConnection* conn); 0084 0085 ~KexiProject(); 0086 0087 /*! \return major version of KexiProject object. 0088 This information is retrieved from database when existing project is opened. */ 0089 int versionMajor() const; 0090 0091 /*! \return minor version of KexiProject object. 0092 @see versionMajor() */ 0093 int versionMinor() const; 0094 0095 /*! Opens existing project using project data. 0096 \return true on success */ 0097 tristate open(); 0098 0099 /*! Like open(). 0100 \return true on success. 0101 Additional \a incompatibleWithKexi, is set to false on failure when 0102 connection for the project was successfully started bu the project 0103 is probably not compatible with Kexi - no valid "kexidb_major_ver" 0104 value in "kexi__db" table. 0105 This is often the case for native server-based databases. 0106 If so, Kexi application can propose importing the database 0107 or linking it to parent project (the latter isn't yet implemented). 0108 For other types of errors the variable is set to true. */ 0109 tristate open(bool *incompatibleWithKexi); 0110 0111 /*! Creates new, empty project using project data. 0112 If \a forceOverwrite is true, existing database project is silently overwritten. 0113 KDbConnection is created (accessible then with KexiProject::dbConnection()). 0114 0115 Since KexiProject inherits KDbObject, it is possible to get error message 0116 and other information on error. 0117 0118 \return true on success, false on failure, and cancelled when database exists 0119 but \a forceOverwrite is false. */ 0120 tristate create(bool forceOverwrite = false); 0121 0122 /** 0123 * @return true if a we are connected to a database 0124 */ 0125 bool isConnected(); 0126 0127 /** 0128 * @return internal numeric type identifier for plugin ID @a pluginId. 0129 * -1 is returned if the ID is unknown. 0130 * While the plugin IDs are unique strings like "org.kexi-project.table", 0131 * the type identifiers are specific to the given physically stored project 0132 * because sets of plugins can differ from between various Kexi installations 0133 * and configurations. 0134 * @see pluginIdForTypeId() 0135 */ 0136 int typeIdForPluginId(const QString &pluginId) const; 0137 0138 /** 0139 * @return plugin ID for a numeric type ID @a typeId. 0140 * Empty string is returned if the plugin ID is unknown. 0141 * @see typeIdForPluginId() 0142 */ 0143 QString pluginIdForTypeId(int typeId) const; 0144 0145 /** 0146 * Returns table or query type for given plugin ID 0147 * 0148 * - KDbTableOrQuerySchema::Type::Table for "org.kexi-project.table" 0149 * - KDbTableOrQuerySchema::Type::Query for "org.kexi-project.query" 0150 * 0151 * @a ok must not be @c nullptr. For "org.kexi-project.table" or "org.kexi-project.query" plugin 0152 * ID *ok is set to @c true, for other IDs it is set to @c false and 0153 * KDbTableOrQuerySchema::Type::Table is returned. 0154 */ 0155 static KDbTableOrQuerySchema::Type pluginIdToTableOrQueryType(const QString &pluginId, 0156 bool *ok); 0157 0158 /** 0159 * @return all items of a type \a i in this project 0160 */ 0161 KexiPart::ItemDict* items(KexiPart::Info *i); 0162 0163 /** 0164 * @return all items of a plugin ID \a pluginId in this project 0165 * It is a convenience function. 0166 */ 0167 KexiPart::ItemDict* itemsForPluginId(const QString &pluginId); 0168 0169 /** 0170 * Puts a list of items of a type \a i in this project into \a list. 0171 * You can then sort this list using ItemList::sort(). 0172 */ 0173 void getSortedItems(KexiPart::ItemList *list, KexiPart::Info *i); 0174 0175 /** 0176 * Puts a sorted list of items that use a plugin ID \a pluginId into \a list. 0177 * You can then sort this list using KexiPart::ItemList::sort(). 0178 */ 0179 void getSortedItemsForPluginId(KexiPart::ItemList *list, const QString &pluginId); 0180 0181 /** 0182 * @return item corresponding with plugin ID \a pluginId and name \a name 0183 */ 0184 KexiPart::Item* itemForPluginId(const QString &pluginId, const QString &name); 0185 0186 /** 0187 * @return item of type \a i and name \a name 0188 */ 0189 KexiPart::Item* item(KexiPart::Info *i, const QString &name); 0190 0191 /** 0192 * @return item for \a identifier 0193 */ 0194 KexiPart::Item* item(int identifier); 0195 0196 /** 0197 * @return the database connection associated with this project 0198 */ 0199 KDbConnection *dbConnection() const; 0200 0201 /** 0202 * @return the project's data 0203 */ 0204 KexiProjectData *data() const; 0205 0206 /*! Opens object pointed by \a item in a view \a viewMode. 0207 \a staticObjectArgs can be passed for static object 0208 (only works when part for this item is of type KexiPart::StaticPart). 0209 The new widget will be a child of \a parent. */ 0210 KexiWindow* openObject(QWidget* parent, KexiPart::Item *item, 0211 Kexi::ViewMode viewMode = Kexi::DataViewMode, 0212 QMap<QString, QVariant>* staticObjectArgs = 0); 0213 0214 //! For convenience 0215 KexiWindow* openObject(QWidget* parent, const QString &pluginId, 0216 const QString& name, Kexi::ViewMode viewMode = Kexi::DataViewMode); 0217 0218 /*! Remove a part instance pointed by \a item. 0219 \return true on success. */ 0220 bool removeObject(KexiPart::Item* item); 0221 0222 /*! Renames a part instance pointed by \a item to a new name \a newName. 0223 \return true on success. */ 0224 bool renameObject(KexiPart::Item* item, const QString& newName); 0225 0226 /*! Renames a part instance pointed by \a item to a new name \a newName. 0227 \return true on success. */ 0228 bool setObjectCaption(KexiPart::Item* item, const QString& newCaption); 0229 0230 /*! Creates part item for given part \a info. 0231 Newly item will not be saved to the backend but stored in memory only 0232 (owned by project), and marked as "neverSaved" (see KexiPart::Item::neverSaved()). 0233 The item will have assigned a new unique caption like e.g. "Table15", 0234 and unique name like "table15", but no specific identifier 0235 (because id will be assigned on creation at the backend side). 0236 0237 If \a suggestedCaption is not empty, it will be set as a caption 0238 (with number suffix, to avoid duplicated, e.g. "employees7" 0239 for "employees" sugested name). Name will be then built based 0240 on this caption using KDb::stringToIdentifier(). 0241 0242 This method is used before creating new object. 0243 \return newly created part item or NULL on any error. */ 0244 KexiPart::Item* createPartItem(KexiPart::Info *info, 0245 const QString& suggestedCaption = QString()); 0246 0247 //! Added for convenience. 0248 KexiPart::Item* createPartItem(KexiPart::Part *part, 0249 const QString& suggestedCaption = QString()); 0250 0251 /*! Adds item \a item after it is successfully stored as an instance of part 0252 pointed by \a info. Also clears 'neverSaved' flag if \a item. 0253 Used by KexiWindow::storeNewData(). 0254 @internal */ 0255 void addStoredItem(KexiPart::Info *info, KexiPart::Item *item); 0256 0257 /*! removes \a item from internal dictionaries. The item is destroyed 0258 after successful removal. 0259 Used to delete an unstored part item previously created with createPartItem(). */ 0260 void deleteUnstoredItem(KexiPart::Item *item); 0261 0262 /** 0263 * @returns parts metioned in the project meta tables but not available locally 0264 */ 0265 KexiPart::MissingPartsList missingParts() const; 0266 0267 KDbParser* sqlParser(); 0268 0269 /*! Shows dialog for creating new blank project, 0270 ans creates one. Dialog is not shown if option for automatic creation 0271 is checked or KexiStartupHandler::global()->projectData() was provided from command line. 0272 \a cancelled is set to true if creation has been cancelled (e.g. user answered 0273 no when asked for database overwriting, etc. 0274 \return true if database was created, false on error or when cancel was pressed */ 0275 static KexiProject* createBlankProject(bool *cancelled, const KexiProjectData& data, 0276 KDbMessageHandler* handler = 0); 0277 0278 /*! Drops project described by \a data. \return true on success. 0279 Use with care: Any KexiProject objects allocated for this project will become invalid! */ 0280 static tristate dropProject(const KexiProjectData& data, 0281 KDbMessageHandler* handler, bool dontAsk = false); 0282 0283 //! Helper method to ask user "Could not open file for reading and writing. Do you want to 0284 //! open the file as read only?". @return true if user agrees, false if user cancels opening. 0285 static bool askForOpeningNonWritableFileAsReadOnly(QWidget *parent, const QFileInfo &finfo); 0286 0287 /*! Generates ID for private "document" like Relations window. 0288 Private IDs are negative numbers (while ID regular part instance's IDs are >0) 0289 Private means that the object is not stored as-is in the project but is somewhat 0290 generated and in most cases there is at most one unique instance document of such type (part). 0291 To generate this ID, just app-wide internal counter is used. */ 0292 virtual int generatePrivateID(); 0293 0294 //! Closes connection. @return true on success. 0295 bool closeConnection(); 0296 0297 /*! Loads current user's data block, referenced by \a objectID and \a dataID 0298 and puts it to \a dataString. 0299 \return true on success, false on failure and cancelled when there is no such data block 0300 \sa storeUserDataBlock() removeUserDataBlock() copyUserDataBlock() KDbConnection::loadDataBlock(). */ 0301 tristate loadUserDataBlock(int objectID, const QString& dataID, QString *dataString); 0302 0303 /*! Stores current user's data block \a dataString, referenced by \a objectID and \a dataID. 0304 The block will be stored in "kexi__userdata" table 0305 If there is already such record in the table, it's simply overwritten. 0306 \return true on success 0307 \sa loadUserDataBlock() removeUserDataBlock() copyUserDataBlock() KDbConnection::storeDataBlock(). */ 0308 bool storeUserDataBlock(int objectID, const QString& dataID, const QString &dataString); 0309 0310 /*! Copies urrent user's data blocks referenced by \a sourceObjectID and pointed 0311 by optional \a dataID. 0312 \return true on success. Does not fail if blocks do not exist. 0313 Prior to copying, existing user data blocks are removed even if there is nothing to copy. 0314 Copied data blocks will have \a destObjectID object identifier assigned. 0315 Note that if \a dataID is not specified, all user data blocks found for the \a sourceObjectID 0316 will be copied. 0317 \sa loadUserDataBlock() storeUserDataBlock() removeUserDataBlock() KDbConnection::copyDataBlock(). */ 0318 bool copyUserDataBlock(int sourceObjectID, int destObjectID, const QString &dataID = QString()); 0319 0320 /*! Removes current user's data block referenced by \a objectID and \a dataID. 0321 \return true on success. Does not fail if the block does not exist. 0322 Note that if \a dataID is not specified, all data blocks for this user and object will be removed. 0323 \sa loadUserDataBlock() storeUserDataBlock() copyUserDataBlock() KDbConnection::removeDataBlock(). */ 0324 bool removeUserDataBlock(int objectID, const QString& dataID = QString()); 0325 0326 protected: 0327 /*! Creates connection using project data. 0328 The connection will be readonly if data()->isReadOnly(). 0329 \return true on success, otherwise false and appropriate error is set. */ 0330 bool createConnection(); 0331 0332 bool initProject(); 0333 0334 //! Used in open() and open(bool*). 0335 tristate openInternal(bool *incompatibleWithKexi); 0336 0337 /*! Kexi itself can define a number of internal database objects (mostly data structures), 0338 usually tables for it's own purposes. 0339 Even while at KDb library level, such "system" tables, like "kexi__objects", "kexi__objectdata" 0340 are created automatically on database project creation, this is not enough: there are objects 0341 needed specifically for Kexi but not for other applications utilizing the KDb library. 0342 Example table created here for now is "kexi__blobs". 0343 0344 This method is called on create() and open(): creates necessary objects 0345 if they are not yet existing. This especially allows to create to create these objects 0346 (on open) within a project made with previous Kexi version not supporting 0347 all currently defined structurtes. We're trying to be here as much backward compatible as possible. 0348 For this purpose, here's the complete list of currently created objects: 0349 - "kexi__blobs" - a table containing BLOBs data that can be accessed globally at Kexi projects 0350 from within any database-aware view (table views, forms, reports, etc.) 0351 0352 @param insideTransaction Embed entire creation process inside a transaction 0353 0354 \return true on successful object's creation. Objects are created only once, they are not overwritten. 0355 */ 0356 bool createInternalStructures(bool insideTransaction); 0357 0358 /*! \return Kexi part for \a item. */ 0359 KexiPart::Part *findPartFor(const KexiPart::Item& item); 0360 0361 //! Closes connection without altering the m_result if is actually set. @return true on success. 0362 //! Used on failed operations such as useDatabase(). 0363 bool closeConnectionInternal(); 0364 0365 Q_SIGNALS: 0366 /** signal emitted on error */ 0367 void error(const QString &title, KDbObject *obj); 0368 0369 /** signal emitted on error (not KDb-related) */ 0370 void error(const QString &msg, const QString &desc); 0371 0372 /** New \a item has been stored. */ 0373 void newItemStored(KexiPart::Item *item); 0374 0375 /** instance pointed by \a item is removed */ 0376 void itemRemoved(const KexiPart::Item &item); 0377 0378 /** instance pointed by \a item is renamed */ 0379 void itemRenamed(const KexiPart::Item &item, const QString& oldName); 0380 0381 /** caption for instance pointed by \a item is changed */ 0382 void itemCaptionChanged(const KexiPart::Item &item, const QString& oldCaption); 0383 0384 protected: 0385 bool createIdForPart(const KexiPart::Info& info); 0386 0387 private: 0388 /*! Checks whether the project's connection is read-only. 0389 If so, error message is set and false is returned. */ 0390 bool checkWritable(); 0391 0392 /*! Retrieves basic information (pluginId, typeId, name, caption) 0393 about all items of all types for this project. 0394 @return true on success. */ 0395 bool retrieveItems(); 0396 0397 /** 0398 * Checks project's kexi__part table. 0399 * @a singlePluginId can be provided to only check specified part. 0400 * Internal identifiers of part(s) are remembered. 0401 * 0402 * Use @ref missingParts() to get a list of missing parts. 0403 * @see typeIdForPluginId() 0404 */ 0405 bool checkProject(const QString& singlePluginId = QString()); 0406 0407 class Private; 0408 Private * const d; 0409 0410 friend class KexiMainWindow; 0411 friend class KexiWindow; 0412 friend class Private; 0413 }; 0414 0415 #endif