File indexing completed on 2024-04-14 14:53:22

0001 /* This file is part of the KDE project
0002    Copyright (C) 2002 Lucijan Busch <lucijan@gmx.at>
0003    Copyright (C) 2003 Daniel Molkentin <molkentin@kde.org>
0004    Copyright (C) 2003-2016 Jarosław Staniek <staniek@kde.org>
0005    Copyright (C) 2014 Michał Poteralski <michalpoteralskikde@gmail.com>
0006 
0007    This program is free software; you can redistribute it and/or
0008    modify it under the terms of the GNU Library General Public
0009    License as published by the Free Software Foundation; either
0010    version 2 of the License, or (at your option) any later version.
0011 
0012    This program is distributed in the hope that it will be useful,
0013    but WITHOUT ANY WARRANTY; without even the implied warranty of
0014    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
0015    Library General Public License for more details.
0016 
0017    You should have received a copy of the GNU Library General Public License
0018    along with this program; see the file COPYING.  If not, write to
0019    the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
0020  * Boston, MA 02110-1301, USA.
0021 
0022    Original Author:  Till Busch <till@bux.at>
0023    Original Project: buX (www.bux.at)
0024 */
0025 
0026 #ifndef KDB_TABLEVIEWDATA_H
0027 #define KDB_TABLEVIEWDATA_H
0028 
0029 #include "KDbField.h"
0030 #include "KDbUtils.h"
0031 #include "KDbRecordData.h"
0032 #include "KDbOrderByColumn.h"
0033 
0034 class KDbCursor;
0035 class KDbRecordEditBuffer;
0036 class KDbResultInfo;
0037 class KDbTableViewColumn;
0038 
0039 typedef KDbUtils::AutodeletedList<KDbRecordData*> KDbTableViewDataBase;
0040 typedef KDbTableViewDataBase::ConstIterator KDbTableViewDataConstIterator;
0041 typedef KDbTableViewDataBase::Iterator KDbTableViewDataIterator;
0042 
0043 //! A list of records to allow configurable sorting and more.
0044 /*! @todo improve API */
0045 class KDB_EXPORT KDbTableViewData : public QObject, protected KDbTableViewDataBase
0046 {
0047     Q_OBJECT
0048 public:
0049     //! Non-db-aware version
0050     KDbTableViewData();
0051 
0052     //! Db-aware version. The cursor is not owned by the data.
0053     explicit KDbTableViewData(KDbCursor *c);
0054 
0055     /*! Defines two-column table usually used with comboboxes.
0056      First column is invisible and contains key values.
0057      Second column and contains user-visible value.
0058      @param keys a list of keys
0059      @param values a list of text values (must be of the same length as keys list)
0060      @param keyType a type for keys
0061      @param valueType a type for values
0062 
0063      @todo make this more generic: allow to add more columns! */
0064     KDbTableViewData(
0065         const QList<QVariant> &keys, const QList<QVariant> &values,
0066         KDbField::Type keyType = KDbField::Text, KDbField::Type valueType = KDbField::Text);
0067 
0068     /*! Like above constructor, but keys and values are not provided.
0069      You can do this later by calling append(KDbRecordData*) method.
0070      (KDbRecordData object must have exactly two columns) */
0071     KDbTableViewData(KDbField::Type keyType, KDbField::Type valueType);
0072 
0073     ~KDbTableViewData() override;
0074 
0075     /*! Preloads all records provided by cursor (only for db-aware version). */
0076     bool preloadAllRecords();
0077 
0078     /*! Sets sorting for @a column. If @a column is -1, sorting is disabled. */
0079     void setSorting(int column, KDbOrderByColumn::SortOrder order = KDbOrderByColumn::SortOrder::Ascending);
0080 
0081     /*! @return the column number by which the data is sorted,
0082      or -1 if sorting is disabled.
0083      Initial sorted column number for data after instantiating object is -1. */
0084     int sortColumn() const;
0085 
0086     /*! @return sorting order. This is independent of whether the data is actually sorted.
0087      sortColumn() should be checked first to see if sorting for any column is enabled
0088      (by default it is not). */
0089     KDbOrderByColumn::SortOrder sortOrder() const;
0090 
0091     //! Sorts this data using previously set order.
0092     void sort();
0093 
0094     /*! Adds column @a col.
0095      Warning: @a col will be owned by this object, and deleted on its destruction. */
0096     void addColumn(KDbTableViewColumn* col);
0097 
0098     //! @return Index of visible column @a visibleIndex on global list.
0099     int globalIndexOfVisibleColumn(int visibleIndex) const;
0100 
0101     //! @return Index on list of visible columns for column @a globalIndex
0102     //!         or -1 if column at @a globalIndex is not visible.
0103     int visibleColumnIndex(int globalIndex) const;
0104 
0105     /*! @return true if this db-aware data set. */
0106     /*! @todo virtual? */
0107     bool isDBAware() const;
0108 
0109     /*! For db-aware data set only: table name is returned;
0110      equivalent to cursor()->query()->parentTable()->name(). */
0111     QString dbTableName() const;
0112 
0113     KDbCursor* cursor() const;
0114 
0115     int columnCount() const;
0116 
0117     //! @return number of visible columns
0118     int visibleColumnCount() const;
0119 
0120     //! @return column at index @a index (visible or not)
0121     KDbTableViewColumn* column(int c);
0122 
0123     //! @return visible column at index @a index
0124     KDbTableViewColumn* visibleColumn(int index);
0125 
0126     //! @return list of all columns
0127     QList<KDbTableViewColumn*>* columns();
0128 
0129     //! @return list of visible columns
0130     QList<KDbTableViewColumn*>* visibleColumns();
0131 
0132     /*! @return true if data is not editable. Can be set using setReadOnly()
0133      but it's still true if database cursor returned by cursor()
0134      is not 0 and has read-only connection. */
0135     virtual bool isReadOnly() const;
0136 
0137     /*! Sets readOnly flag for this data.
0138      If @a set is true, insertingEnabled flag will be cleared automatically.
0139      @see isInsertingEnabled() */
0140     virtual void setReadOnly(bool set);
0141 
0142     /*! @return true if data inserting is enabled (the default). */
0143     virtual bool isInsertingEnabled() const;
0144 
0145     /*! Sets insertingEnabled flag. If true, empty record is available
0146      If @a set is true, read-only flag will be cleared automatically.
0147      @see setReadOnly() */
0148     virtual void setInsertingEnabled(bool set);
0149 
0150     /*! Clears and initializes internal record edit buffer for incoming editing.
0151      Creates buffer using recordEditBuffer(false) (false means not db-aware type)
0152      if our data is not db-aware,
0153      or db-aware buffer if data is db-aware (isDBAware()==true).
0154      @see KDbRecordEditBuffer */
0155     void clearRecordEditBuffer();
0156 
0157     /*! Updates internal record edit buffer: currently edited column @a col (number @a colnum)
0158      has now assigned new value of @a newval.
0159      Uses column's caption to address the column in buffer
0160      if the buffer is of simple type, or db-aware buffer if (isDBAware()==true).
0161      (then fields are addressed with KDbField, instead of caption strings).
0162      If @a allowSignals is true (the default), aboutToChangeCell() signal is emitted.
0163      @a visibleValueForLookupField allows to pass visible value (usually a text)
0164      for a lookup field (only reasonable if col->visibleLookupColumnInfo != 0).
0165      Note that @a newval may be changed in aboutToChangeCell() signal handler.
0166      If either @a record or @a col or @a newval is @c nullptr, @c false is returned.
0167      @see KDbRecordEditBuffer */
0168     bool updateRecordEditBufferRef(KDbRecordData *record,
0169                                    int colnum, KDbTableViewColumn* col, QVariant* newval,
0170                                    bool allowSignals = true,
0171                                    QVariant *visibleValueForLookupField = nullptr);
0172 
0173     /*! Added for convenience. Like above but @a newval is passed by value. */
0174     bool updateRecordEditBuffer(KDbRecordData *record, int colnum, KDbTableViewColumn* col,
0175                                 const QVariant &newval, bool allowSignals = true);
0176 
0177     /*! Added for convenience. Like above but it's assumed that @a record record's columns
0178      are ordered like in table view, not like in form view. Don't use this with form views. */
0179     bool updateRecordEditBuffer(KDbRecordData *record, int colnum,
0180                                 const QVariant &newval, bool allowSignals = true);
0181 
0182     //! @return record edit buffer for currently edited record. Can be 0 or empty.
0183     KDbRecordEditBuffer* recordEditBuffer() const;
0184 
0185     /*! @return last operation's result information (always not null). */
0186     const KDbResultInfo& result() const;
0187 
0188     bool saveRecordChanges(KDbRecordData *record, bool repaint = false);
0189 
0190     bool saveNewRecord(KDbRecordData *record, bool repaint = false);
0191 
0192     bool deleteRecord(KDbRecordData *record, bool repaint = false);
0193 
0194     /*! Deletes records (by number) passed with @a recordsToDelete.
0195      Currently, this method is only for non data-aware tables. */
0196     void deleteRecords(const QList<int> &recordsToDelete, bool repaint = false);
0197 
0198     /*! Deletes all records. Works either for db-aware and non db-aware tables.
0199      Column's definition is not changed.
0200      For db-aware version, all records are removed from a database.
0201      Record-edit buffer is cleared.
0202 
0203      If @a repaint is true, reloadRequested() signal
0204      is emitted after deleting (if at least one record was deleted),
0205      so presenters can repaint their contents.
0206 
0207      @return true on success. */
0208     virtual bool deleteAllRecords(bool repaint = false);
0209 
0210     /*! @internal method, used mostly by specialized classes like KexiTableView.
0211      Clears internal record structures. Record-edit buffer is cleared.
0212      Does not touch data @ database backend.
0213      Use deleteAllRecords() to safely delete all records. */
0214     virtual void clearInternal(bool processEvents = true);
0215 
0216     /*! Inserts new @a record at index @a index.
0217      @a record will be owned by this data object.
0218      Note: Reasonable only for not not-db-aware version. */
0219     void insertRecord(KDbRecordData *record, int index, bool repaint = false);
0220 
0221     //! @todo add this as well? void insertRecord(KDbRecordData *record, KDbRecordData *aboveRecord)
0222 
0223     //! @return index of autoincremented column. The result is cached.
0224     //! @todo what about multiple autoinc columns?
0225     //! @todo what about changing column order?
0226     int autoIncrementedColumn() const;
0227 
0228     //! Emits reloadRequested() signal to reload presenters.
0229     void reload() {
0230         emit reloadRequested();
0231     }
0232 
0233     inline KDbRecordData* at(int index) {
0234         return KDbTableViewDataBase::at(index);
0235     }
0236     inline virtual int count() const {
0237         return KDbTableViewDataBase::count();
0238     }
0239     inline bool isEmpty() const {
0240         return KDbTableViewDataBase::isEmpty();
0241     }
0242     inline KDbRecordData* first() {
0243         return KDbTableViewDataBase::first();
0244     }
0245     inline KDbRecordData* last() {
0246         return KDbTableViewDataBase::last();
0247     }
0248     inline int indexOf(const KDbRecordData* record, int from = 0) const {
0249         return KDbTableViewDataBase::indexOf(const_cast<KDbRecordData*>(record), from);
0250     }
0251     inline void removeFirst() {
0252         KDbTableViewDataBase::removeFirst();
0253     }
0254     inline void removeLast() {
0255         KDbTableViewDataBase::removeLast();
0256     }
0257     inline void append(KDbRecordData* record) {
0258         KDbTableViewDataBase::append(record);
0259     }
0260     inline void prepend(KDbRecordData* record) {
0261         KDbTableViewDataBase::prepend(record);
0262     }
0263     inline KDbTableViewDataConstIterator constBegin() const {
0264         return KDbTableViewDataBase::constBegin();
0265     }
0266     inline KDbTableViewDataConstIterator constEnd() const {
0267         return KDbTableViewDataBase::constEnd();
0268     }
0269     inline KDbTableViewDataIterator begin() {
0270         return KDbTableViewDataBase::begin();
0271     }
0272     inline KDbTableViewDataIterator end() {
0273         return KDbTableViewDataBase::end();
0274     }
0275 
0276     /*! @return true if ROWID information is stored within every record.
0277      Only reasonable for db-aware version. ROWID information is available
0278      if KDbDriverBehavior::ROW_ID_FIELD_RETURNS_LAST_AUTOINCREMENTED_VALUE == false
0279      for a KDb database driver and a table has no primary key defined.
0280      Phisically, ROWID information is stored after last KDbRecordData's element,
0281      so every KDbRecordData's length is expanded by one. */
0282     bool containsRecordIdInfo() const;
0283 
0284     //! Creates a single record data with proper number of columns.
0285     KDbRecordData* createItem() const;
0286 
0287     //! @return reusable i18n'd message
0288     //!         "Please correct data in this record or use the \"Cancel record changes\" function."
0289     static QString messageYouCanImproveData();
0290 
0291 public Q_SLOTS:
0292     //! @internal Clean up.
0293     void deleteLater();
0294 
0295 Q_SIGNALS:
0296     void destroying();
0297 
0298     /*! Emitted before change of the single, currently edited cell.
0299      Connect this signal to your slot and set @a result->success to false
0300      to disallow this change. You can also change @a newValue to other value,
0301      or change other columns in @a record. */
0302     void aboutToChangeCell(KDbRecordData *record, int colnum, QVariant* newValue,
0303                            KDbResultInfo* result);
0304 
0305     /*! Emitted before inserting of a new, current record.
0306      Connect this signal to your slot and set @a result->success to false
0307      to disallow this inserting. You can also change columns in @a record. */
0308     void aboutToInsertRecord(KDbRecordData *record, KDbResultInfo* result, bool repaint);
0309 
0310     /*! Emitted before changing of an edited, current record.
0311      Connect this signal to your slot and set @a result->success to false
0312      to disallow this change. You can also change columns in @a record. */
0313     void aboutToUpdateRecord(KDbRecordData *record, KDbRecordEditBuffer* buffer,
0314                              KDbResultInfo* result);
0315 
0316     void recordUpdated(KDbRecordData*); //!< Current record has been updated
0317 
0318     void recordInserted(KDbRecordData*, bool repaint); //!< A record has been inserted
0319 
0320     //! A record has been inserted at @a index position (not db-aware data only)
0321     void recordInserted(KDbRecordData*, int index, bool repaint);
0322 
0323     /*! Emitted before deleting of a current record.
0324      Connect this signal to your slot and set @a result->success to false
0325      to disallow this deleting. */
0326     void aboutToDeleteRecord(KDbRecordData *record, KDbResultInfo* result, bool repaint);
0327 
0328     //! Current record has been deleted
0329     void recordDeleted();
0330 
0331     //! Records have been deleted
0332     void recordsDeleted(const QList<int> &recordsToDelete);
0333 
0334     //! Displayed data needs to be reloaded in all presenters.
0335     void reloadRequested();
0336 
0337     void recordRepaintRequested(KDbRecordData*);
0338 
0339 protected:
0340     //! Used by KDbTableViewColumn::setVisible()
0341     void columnVisibilityChanged(const KDbTableViewColumn &column);
0342 
0343 private:
0344     //! @internal for saveRecordChanges() and saveNewRecord()
0345     bool saveRecord(KDbRecordData *record, bool insert, bool repaint);
0346 
0347     friend class KDbTableViewColumn;
0348 
0349     Q_DISABLE_COPY(KDbTableViewData)
0350     class Private;
0351     Private * const d;
0352 };
0353 
0354 //! Sends information about data @a data to debug output @a dbg.
0355 //! @since 3.1
0356 KDB_EXPORT QDebug operator<<(QDebug dbg, const KDbTableViewData &data);
0357 
0358 #endif