File indexing completed on 2024-10-06 04:17:54
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 }