File indexing completed on 2024-04-21 15:30:06

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-2017 Jarosław Staniek <staniek@kde.org>
0005 
0006    This program is free software; you can redistribute it and/or
0007    modify it under the terms of the GNU Library General Public
0008    License as published by the Free Software Foundation; either
0009    version 2 of the License, or (at your option) any later version.
0010 
0011    This program is distributed in the hope that it will be useful,
0012    but WITHOUT ANY WARRANTY; without even the implied warranty of
0013    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
0014    Library General Public License for more details.
0015 
0016    You should have received a copy of the GNU Library General Public License
0017    along with this program; see the file COPYING.  If not, write to
0018    the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
0019  * Boston, MA 02110-1301, USA.
0020 
0021    Original Author:  Till Busch <till@bux.at>
0022    Original Project: buX (www.bux.at)
0023 */
0024 
0025 #include "KDbTableViewColumn.h"
0026 
0027 #include "KDbConnection.h"
0028 #include "KDbConnectionOptions.h"
0029 #include "KDbCursor.h"
0030 #include "KDb.h"
0031 #include "KDbQuerySchema.h"
0032 #include "KDbRecordEditBuffer.h"
0033 #include "KDbTableViewData.h"
0034 #include "KDbValidator.h"
0035 
0036 #include <QIcon>
0037 
0038 class Q_DECL_HIDDEN KDbTableViewColumn::Private
0039 {
0040 public:
0041   Private()
0042       : data(nullptr)
0043       , validator(nullptr)
0044       , relatedData(nullptr)
0045       , field(nullptr)
0046       , columnInfo(nullptr)
0047       , visibleLookupColumnInfo(nullptr)
0048       , width(0)
0049       , readOnly(false)
0050       , visible(true)
0051       , relatedDataEditable(false)
0052       , headerTextVisible(true)
0053     {
0054     }
0055 
0056     //! Data that this column is assigned to. Set by KDbTableViewColumn::setData()
0057     KDbTableViewData* data;
0058 
0059     QString captionAliasOrName;
0060 
0061     QIcon icon;
0062 
0063     KDbValidator* validator;
0064 
0065     KDbTableViewData* relatedData;
0066     int relatedDataPKeyID;
0067 
0068     KDbField* field;
0069 
0070     //! @see columnInfo()
0071     KDbQueryColumnInfo* columnInfo;
0072 
0073     //! @see visibleLookupColumnInfo()
0074     KDbQueryColumnInfo* visibleLookupColumnInfo;
0075 
0076     int width;
0077     bool isDBAware; //!< true if data is stored in DB, not only in memeory
0078     bool readOnly;
0079     bool fieldOwned;
0080     bool visible;
0081     bool relatedDataEditable;
0082     bool headerTextVisible;
0083 };
0084 
0085 //------------------------
0086 
0087 KDbTableViewColumn::KDbTableViewColumn(KDbField *f, FieldIsOwned isOwned)
0088         : d(new Private)
0089 {
0090     d->field = f;
0091     d->isDBAware = false;
0092     d->fieldOwned = isOwned == FieldIsOwned::Yes;
0093     d->captionAliasOrName = d->field->captionOrName();
0094 }
0095 
0096 KDbTableViewColumn::KDbTableViewColumn(const QString &name, KDbField::Type ctype,
0097         KDbField::Constraints cconst,
0098         KDbField::Options options,
0099         int maxLength, int precision,
0100         QVariant defaultValue,
0101         const QString &caption, const QString &description)
0102         : d(new Private)
0103 {
0104     d->field = new KDbField(
0105         name, ctype, cconst, options, maxLength, precision, defaultValue, caption, description);
0106 
0107     d->isDBAware = false;
0108     d->fieldOwned = true;
0109     d->captionAliasOrName = d->field->captionOrName();
0110 }
0111 
0112 KDbTableViewColumn::KDbTableViewColumn(const QString &name, KDbField::Type ctype,
0113         const QString &caption, const QString &description)
0114         : d(new Private)
0115 {
0116     d->field = new KDbField(
0117         name, ctype,
0118         KDbField::NoConstraints,
0119         KDbField::NoOptions,
0120         0, 0,
0121         QVariant(),
0122         caption, description);
0123 
0124     d->isDBAware = false;
0125     d->fieldOwned = true;
0126     d->captionAliasOrName = d->field->captionOrName();
0127 }
0128 
0129 // db-aware
0130 KDbTableViewColumn::KDbTableViewColumn(
0131     const KDbQuerySchema &query, KDbQueryColumnInfo *aColumnInfo,
0132     KDbQueryColumnInfo *aVisibleLookupColumnInfo)
0133         : d(new Private)
0134 {
0135     Q_ASSERT(aColumnInfo);
0136     d->field = aColumnInfo->field();
0137     d->columnInfo = aColumnInfo;
0138     d->visibleLookupColumnInfo = aVisibleLookupColumnInfo;
0139     d->isDBAware = true;
0140     d->fieldOwned = false;
0141 
0142     //setup column's caption:
0143     if (!d->columnInfo->field()->caption().isEmpty()) {
0144         d->captionAliasOrName = d->columnInfo->field()->caption();
0145     } else {
0146         //reuse alias if available:
0147         d->captionAliasOrName = d->columnInfo->alias();
0148         //last hance: use field name
0149         if (d->captionAliasOrName.isEmpty())
0150             d->captionAliasOrName = d->columnInfo->field()->name();
0151         //! @todo compute other auto-name?
0152     }
0153     //setup column's readonly flag: true, if
0154     // - it's not from parent table's field, or
0155     // - if the query itself is coming from read-only connection, or
0156     // - if the query itself is stored (i.e. has connection) and lookup column is defined
0157     const bool columnFromMasterTable = query.masterTable() == d->columnInfo->field()->table();
0158     d->readOnly = !columnFromMasterTable;
0159 //! @todo remove this when queries become editable            ^^^^^^^^^^^^^^
0160 // kdbDebug() << "KDbTableViewColumn: query.masterTable()=="
0161 //  << (query.masterTable() ? query.masterTable()->name() : "notable") << ", columnInfo->field->table()=="
0162 //  << (columnInfo->field->table() ? columnInfo->field->table()->name()  : "notable");
0163 }
0164 
0165 KDbTableViewColumn::KDbTableViewColumn(bool)
0166         : d(new Private)
0167 {
0168     d->isDBAware = false;
0169 }
0170 
0171 KDbTableViewColumn::~KDbTableViewColumn()
0172 {
0173     if (d->fieldOwned)
0174         delete d->field;
0175     setValidator(nullptr);
0176     delete d->relatedData;
0177     delete d;
0178 }
0179 
0180 void KDbTableViewColumn::setValidator(KDbValidator *v)
0181 {
0182     if (d->validator) {//remove old one
0183         if (!d->validator->parent()) //destroy if has no parent
0184             delete d->validator;
0185     }
0186     d->validator = v;
0187 }
0188 
0189 void KDbTableViewColumn::setData(KDbTableViewData *data)
0190 {
0191     d->data = data;
0192 }
0193 
0194 void KDbTableViewColumn::setRelatedData(KDbTableViewData *data)
0195 {
0196     if (d->isDBAware)
0197         return;
0198     if (d->relatedData)
0199         delete d->relatedData;
0200     d->relatedData = nullptr;
0201     if (!data)
0202         return;
0203     //find a primary key
0204     const QList<KDbTableViewColumn*> *columns = data->columns();
0205     int id = -1;
0206     foreach(KDbTableViewColumn* col, *columns) {
0207         id++;
0208         if (col->field()->isPrimaryKey()) {
0209             //found, remember
0210             d->relatedDataPKeyID = id;
0211             d->relatedData = data;
0212             return;
0213         }
0214     }
0215 }
0216 
0217 bool KDbTableViewColumn::isReadOnly() const
0218 {
0219     return d->readOnly || (d->data && d->data->isReadOnly());
0220 }
0221 
0222 void KDbTableViewColumn::setReadOnly(bool ro)
0223 {
0224     d->readOnly = ro;
0225 }
0226 
0227 bool KDbTableViewColumn::isVisible() const
0228 {
0229     return d->columnInfo ? d->columnInfo->isVisible() : d->visible;
0230 }
0231 
0232 void KDbTableViewColumn::setVisible(bool v)
0233 {
0234     bool changed = d->visible != v;
0235     if (d->columnInfo && d->columnInfo->isVisible() != v) {
0236         d->columnInfo->setVisible(v);
0237         changed = true;
0238     }
0239     d->visible = v;
0240     if (changed && d->data) {
0241         d->data->columnVisibilityChanged(*this);
0242     }
0243 }
0244 
0245 void KDbTableViewColumn::setIcon(const QIcon& icon)
0246 {
0247     d->icon = icon;
0248 }
0249 
0250 QIcon KDbTableViewColumn::icon() const
0251 {
0252     return d->icon;
0253 }
0254 
0255 void KDbTableViewColumn::setHeaderTextVisible(bool visible)
0256 {
0257     d->headerTextVisible = visible;
0258 }
0259 
0260 bool KDbTableViewColumn::isHeaderTextVisible() const
0261 {
0262     return d->headerTextVisible;
0263 }
0264 
0265 QString KDbTableViewColumn::captionAliasOrName() const
0266 {
0267     return d->captionAliasOrName;
0268 }
0269 
0270 KDbValidator* KDbTableViewColumn::validator() const
0271 {
0272     return d->validator;
0273 }
0274 
0275 KDbTableViewData *KDbTableViewColumn::relatedData()
0276 {
0277     return d->relatedData;
0278 }
0279 
0280 const KDbTableViewData *KDbTableViewColumn::relatedData() const
0281 {
0282     return d->relatedData;
0283 }
0284 
0285 KDbField* KDbTableViewColumn::field()
0286 {
0287     return d->field;
0288 }
0289 
0290 const KDbField* KDbTableViewColumn::field() const
0291 {
0292     return d->field;
0293 }
0294 
0295 void KDbTableViewColumn::setRelatedDataEditable(bool set)
0296 {
0297     d->relatedDataEditable = set;
0298 }
0299 
0300 bool KDbTableViewColumn::isRelatedDataEditable() const
0301 {
0302     return d->relatedDataEditable;
0303 }
0304 
0305 KDbQueryColumnInfo* KDbTableViewColumn::columnInfo()
0306 {
0307     return d->columnInfo;
0308 }
0309 
0310 const KDbQueryColumnInfo* KDbTableViewColumn::columnInfo() const
0311 {
0312     return d->columnInfo;
0313 }
0314 
0315 KDbQueryColumnInfo* KDbTableViewColumn::visibleLookupColumnInfo()
0316 {
0317     return d->visibleLookupColumnInfo;
0318 }
0319 
0320 const KDbQueryColumnInfo* KDbTableViewColumn::visibleLookupColumnInfo() const
0321 {
0322     return d->visibleLookupColumnInfo;
0323 }
0324 
0325 bool KDbTableViewColumn::isDBAware() const
0326 {
0327     return d->isDBAware;
0328 }
0329 
0330 
0331 bool KDbTableViewColumn::acceptsFirstChar(const QChar &ch) const
0332 {
0333     // the field we're looking at can be related to "visible lookup column"
0334     // if lookup column is present
0335     KDbField *visibleField = d->visibleLookupColumnInfo
0336                                   ? d->visibleLookupColumnInfo->field() : d->field;
0337     const KDbField::Type type = visibleField->type(); // cache: evaluating type of expressions can be expensive
0338     if (KDbField::isNumericType(type)) {
0339         if (ch == QLatin1Char('.') || ch == QLatin1Char(','))
0340             return KDbField::isFPNumericType(type);
0341         if (ch == QLatin1Char('-'))
0342             return !visibleField->isUnsigned();
0343         if (ch == QLatin1Char('+') || (ch >= QLatin1Char('0') && ch <= QLatin1Char('9')))
0344             return true;
0345         return false;
0346     }
0347 
0348     switch (type) {
0349     case KDbField::Boolean:
0350         return false;
0351     case KDbField::Date:
0352     case KDbField::DateTime:
0353     case KDbField::Time:
0354         return ch >= QLatin1Char('0') && ch <= QLatin1Char('9');
0355     default:;
0356     }
0357     return true;
0358 }
0359 
0360 void KDbTableViewColumn::setWidth(int w)
0361 {
0362     d->width = w;
0363 }
0364 
0365 int KDbTableViewColumn::width() const
0366 {
0367     return d->width;
0368 }
0369 
0370 QDebug operator<<(QDebug dbg, const KDbTableViewColumn &column)
0371 {
0372     dbg.nospace() << "TableViewColumn(";
0373     dbg.space() << "columnInfo:";
0374     if (column.columnInfo()) {
0375         dbg.space() << *column.columnInfo();
0376     } else {
0377         dbg.space() << "<NONE>";
0378     }
0379     dbg.space() << "captionAliasOrName:" << column.captionAliasOrName();
0380     dbg.space() << "visibleLookupColumnInfo:";
0381     if (column.visibleLookupColumnInfo()) {
0382         dbg.space() << *column.visibleLookupColumnInfo();
0383     } else {
0384         dbg.space() << "<NONE>";
0385     }
0386     dbg.space() << "data: KDbTableViewData(";
0387     const KDbTableViewData *data = column.d->data;
0388     if (data) {
0389         dbg.space() << "count:" << data->count() << ")";
0390     } else {
0391         dbg.space() << "<NONE>)";
0392     }
0393     dbg.space() << "relatedData: KDbTableViewData(";
0394     const KDbTableViewData *relatedData = column.d->relatedData;
0395     if (relatedData) {
0396         dbg.space() << "count:" << relatedData->count() << ")";
0397     } else {
0398         dbg.space() << "<NONE>)";
0399     }
0400     const KDbField *field = column.d->field;
0401     if (data) {
0402         dbg.space() << "field:" << *field;
0403     } else {
0404         dbg.space() << "<NONE>";
0405     }
0406     dbg.space() << "fieldOwned:" << column.d->fieldOwned;
0407     dbg.space() << "validator:";
0408     if (column.validator()) {
0409         dbg.space() << "<YES>";
0410     } else {
0411         dbg.space() << "<NO>";
0412     }
0413     dbg.space() << "icon:" << column.icon().name();
0414     dbg.space() << "fieldOwned:" << column.d->fieldOwned;
0415     dbg.space() << "width:" << column.width();
0416     dbg.space() << "isDBAware:" << column.isDBAware();
0417     dbg.space() << "readOnly:" << column.isReadOnly();
0418     dbg.space() << "visible:" << column.isVisible();
0419     dbg.space() << "relatedDataEditable:" << column.isRelatedDataEditable();
0420     dbg.space() << "headerTextVisible:" << column.isHeaderTextVisible();
0421     return dbg.space();
0422 }