Beispiel #1
1
	QVariant RelationalProxyModel::getRelationData(QModelIndex index) const {
		int column = index.column();
		if (not m_relations.contains(column))
			return QVariant();

		const QSqlRelation relation = m_relations[column];

		QVariant related_id = sourceModel()->data(mapToSource(index));

		QSqlDriver *driver = QSqlDatabase::database().driver();

		QSqlRecord search_record;
		search_record.append(QSqlField(relation.indexColumn(), QVariant::Int));
		search_record.setValue(relation.indexColumn(), QVariant(related_id.toInt()));

		QString where_statement = driver->sqlStatement(QSqlDriver::WhereStatement, relation.tableName(), search_record, false);
		QString select_statement = driver->sqlStatement(QSqlDriver::SelectStatement, relation.tableName(), QSqlDatabase::database().record(relation.tableName()), false);
		QSqlQuery query(QString("%1 %2").arg(select_statement, where_statement));

		query.next();
		if (not query.isValid())
			return QVariant();

		return query.record().value(relation.displayColumn());
	}
void QRelation::populateDictionary()
{
    if (!isValid())
        return;

    if (model ==  NULL)
        populateModel();

    QSqlRecord record;
    QString indexColumn;
    QString displayColumn;
    for (int i=0; i < model->rowCount(); ++i) {
        record = model->record(i);

        indexColumn = rel.indexColumn();
        if (m_parent->database().driver()->isIdentifierEscaped(indexColumn, QSqlDriver::FieldName))
            indexColumn = m_parent->database().driver()->stripDelimiters(indexColumn, QSqlDriver::FieldName);

        displayColumn = rel.displayColumn();
        if (m_parent->database().driver()->isIdentifierEscaped(displayColumn, QSqlDriver::FieldName))
            displayColumn = m_parent->database().driver()->stripDelimiters(displayColumn, QSqlDriver::FieldName);

        dictionary[record.field(indexColumn).value().toString()] =
            record.field(displayColumn).value();
    }
    m_dictInitialized = true;
}
void ComboBoxFileldDelegate::paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const
{

	QString pole = index.model()->data(index.sibling(index.row(),0)).toString();
	int j;
	for(int i=0;i<fieldName.count();i++){
		QString s = model->headerData( fieldName.at(i) , Qt::Horizontal).toString();
		s.replace("\n"," ");
		if (s==pole){
			j=fieldName.at(i);
			break;
		}
	}

	QSqlRelation rel =  model->relation(j);
	if (index.column()>2){
		if (rel.indexColumn()!=QString("")){
			QSqlQuery query;
			query.exec(QString("SELECT * FROM %1 WHERE %2='%3'").arg(rel.tableName()).arg(rel.indexColumn()).arg(index.model()->data(index).toString()));
			while (query.next())
				drawDisplay(painter, option, option.rect,query.record().value(rel.displayColumn()).toString());
			return;
		}

		if (model->data(model->index(0,j), Qt::EditRole).type() == QVariant::Date){
			drawDisplay(painter, option, option.rect, index.model()->data(index, Qt::EditRole).toDate().toString("dd.MM.yyyy"));
			return;
		}

		if (this->model->data(this->model->index(0,j), Qt::EditRole).type() == QVariant::Bool){
			if (index.model()->data(index, Qt::DisplayRole).toInt()>0)
				drawDisplay(painter, option, option.rect, tr("Да"));
			else
				drawDisplay(painter, option, option.rect, tr("Нет"));
			drawFocus(painter, option, option.rect);
			return;
		}


	}


	QItemDelegate::paint(painter, option, index);
}
void QRelation::populateDictionary()
{
    if (!isValid())
        return;

    if (model ==  NULL)
        populateModel();

    QSqlRecord record;
    for (int i=0; i < model->rowCount(); ++i) {
        record = model->record(i);
        dictionary[record.field(rel.indexColumn()).value().toString()] =
            record.field(rel.displayColumn()).value();
    }
    m_dictInitialized = true;
}
/*!
    \reimp
*/
QString QSqlRelationalTableModel::selectStatement() const
{
    Q_D(const QSqlRelationalTableModel);
    QString query;

    if (tableName().isEmpty())
        return query;
    if (d->relations.isEmpty())
        return QSqlTableModel::selectStatement();

    QString tList;
    QString fList;
    QString where;

    QSqlRecord rec = d->baseRec;
    QStringList tables;
    const QRelation nullRelation;

    // Count how many times each field name occurs in the record
    QHash<QString, int> fieldNames;
    QStringList fieldList;
    for (int i = 0; i < rec.count(); ++i) {
        QSqlRelation relation = d->relations.value(i, nullRelation).rel;
        QString name;
        if (relation.isValid())
        {
            // Count the display column name, not the original foreign key
            name = relation.displayColumn();
            if (d->db.driver()->isIdentifierEscaped(name, QSqlDriver::FieldName))
                name = d->db.driver()->stripDelimiters(name, QSqlDriver::FieldName);

            QSqlRecord rec = database().record(relation.tableName());
            for (int i = 0; i < rec.count(); ++i) {
                if (name.compare(rec.fieldName(i), Qt::CaseInsensitive) == 0) {
                    name = rec.fieldName(i);
                    break;
                }
            }
        }
        else
            name = rec.fieldName(i);
        fieldNames.insert(name, fieldNames.value(name, 0) + 1);
        fieldList.append(name);
    }

    for (int i = 0; i < rec.count(); ++i) {
        QSqlRelation relation = d->relations.value(i, nullRelation).rel;
        if (relation.isValid()) {
            QString relTableAlias = QString::fromLatin1("relTblAl_%1").arg(i);
            if (!fList.isEmpty())
                fList.append(QLatin1String(", "));
            fList.append(d->relationField(relTableAlias,relation.displayColumn()));

            // If there are duplicate field names they must be aliased
            if (fieldNames.value(fieldList[i]) > 1) {
                QString relTableName = relation.tableName().section(QChar::fromLatin1('.'), -1, -1);
                if (d->db.driver()->isIdentifierEscaped(relTableName, QSqlDriver::TableName))
                    relTableName = d->db.driver()->stripDelimiters(relTableName, QSqlDriver::TableName);
                QString displayColumn = relation.displayColumn();
                if (d->db.driver()->isIdentifierEscaped(displayColumn, QSqlDriver::FieldName))
                    displayColumn = d->db.driver()->stripDelimiters(displayColumn, QSqlDriver::FieldName);
                fList.append(QString::fromLatin1(" AS %1_%2_%3").arg(relTableName).arg(displayColumn).arg(fieldNames.value(fieldList[i])));
                fieldNames.insert(fieldList[i], fieldNames.value(fieldList[i])-1);
            }

            // this needs fixing!! the below if is borken.
            tables.append(relation.tableName().append(QLatin1Char(' ')).append(relTableAlias));
            if(!where.isEmpty())
                where.append(QLatin1String(" AND "));
            where.append(d->relationField(tableName(), d->db.driver()->escapeIdentifier(rec.fieldName(i), QSqlDriver::FieldName)));
            where.append(QLatin1String(" = "));
            where.append(d->relationField(relTableAlias, relation.indexColumn()));
        } else {
            if (!fList.isEmpty())
                fList.append(QLatin1String(", "));
            fList.append(d->relationField(tableName(), d->db.driver()->escapeIdentifier(rec.fieldName(i), QSqlDriver::FieldName)));
        }
    }
    if (!tables.isEmpty())
        tList.append(tables.join(QLatin1String(", ")));
    if (fList.isEmpty())
        return query;
    if(!tList.isEmpty())
        tList.prepend(QLatin1String(", "));
    tList.prepend(tableName());
    query.append(QLatin1String("SELECT "));
    query.append(fList).append(QLatin1String(" FROM ")).append(tList);
    qAppendWhereClause(query, where, filter());

    QString orderBy = orderByClause();
    if (!orderBy.isEmpty())
        query.append(QLatin1Char(' ')).append(orderBy);

    return query;
}
/*!
    \reimp
*/
QString QSqlRelationalTableModel::selectStatement() const
{
    Q_D(const QSqlRelationalTableModel);

    if (tableName().isEmpty())
        return QString();
    if (d->relations.isEmpty())
        return QSqlTableModel::selectStatement();

    // Count how many times each field name occurs in the record
    QHash<QString, int> fieldNames;
    QStringList fieldList;
    for (int i = 0; i < d->baseRec.count(); ++i) {
        QSqlRelation relation = d->relations.value(i).rel;
        QString name;
        if (relation.isValid()) {
            // Count the display column name, not the original foreign key
            name = relation.displayColumn();
            if (d->db.driver()->isIdentifierEscaped(name, QSqlDriver::FieldName))
                name = d->db.driver()->stripDelimiters(name, QSqlDriver::FieldName);

            const QSqlRecord rec = database().record(relation.tableName());
            for (int i = 0; i < rec.count(); ++i) {
                if (name.compare(rec.fieldName(i), Qt::CaseInsensitive) == 0) {
                    name = rec.fieldName(i);
                    break;
                }
            }
        }
        else {
            name = d->baseRec.fieldName(i);
        }
        fieldNames[name] = fieldNames.value(name, 0) + 1;
        fieldList.append(name);
    }

    QString fList;
    QString conditions;
    QString from = Sql::from(tableName());
    for (int i = 0; i < d->baseRec.count(); ++i) {
        QSqlRelation relation = d->relations.value(i).rel;
        const QString tableField = d->fullyQualifiedFieldName(tableName(), d->db.driver()->escapeIdentifier(d->baseRec.fieldName(i), QSqlDriver::FieldName));
        if (relation.isValid()) {
            const QString relTableAlias = Sql::relTablePrefix(i);
            QString displayTableField = d->fullyQualifiedFieldName(relTableAlias, relation.displayColumn());

            // Duplicate field names must be aliased
            if (fieldNames.value(fieldList[i]) > 1) {
                QString relTableName = relation.tableName().section(QChar::fromLatin1('.'), -1, -1);
                if (d->db.driver()->isIdentifierEscaped(relTableName, QSqlDriver::TableName))
                    relTableName = d->db.driver()->stripDelimiters(relTableName, QSqlDriver::TableName);
                QString displayColumn = relation.displayColumn();
                if (d->db.driver()->isIdentifierEscaped(displayColumn, QSqlDriver::FieldName))
                    displayColumn = d->db.driver()->stripDelimiters(displayColumn, QSqlDriver::FieldName);
                const QString alias = QString::fromLatin1("%1_%2_%3").arg(relTableName).arg(displayColumn).arg(fieldNames.value(fieldList[i]));
                displayTableField = Sql::as(displayTableField, alias);
                --fieldNames[fieldList[i]];
            }

            fList = Sql::comma(fList, displayTableField);

            // Join related table
            const QString tblexpr = Sql::concat(relation.tableName(), relTableAlias);
            const QString relTableField = d->fullyQualifiedFieldName(relTableAlias, relation.indexColumn());
            const QString cond = Sql::eq(tableField, relTableField);
            if (d->joinMode == QSqlRelationalTableModel::InnerJoin) {
                // FIXME: InnerJoin code is known to be broken.
                // Use LeftJoin mode if you want correct behavior.
                from = Sql::comma(from, tblexpr);
                conditions = Sql::et(conditions, cond);
            } else {
                from = Sql::concat(from, Sql::leftJoin(tblexpr));
                from = Sql::concat(from, Sql::on(cond));
            }
        } else {
            fList = Sql::comma(fList, tableField);
        }
    }

    if (fList.isEmpty())
        return QString();

    const QString stmt = Sql::concat(Sql::select(fList), from);
    const QString where = Sql::where(Sql::et(Sql::paren(conditions), Sql::paren(filter())));
    return Sql::concat(Sql::concat(stmt, where), orderByClause());
}
/*!
    \reimp
*/
QString QSqlRelationalTableModel::selectStatement() const
{
    Q_D(const QSqlRelationalTableModel);
    QString query;

    if (tableName().isEmpty())
        return query;
    if (d->relations.isEmpty())
        return QSqlTableModel::selectStatement();

    QString tList;
    QString fList;
    QString where;

    QSqlRecord rec = d->baseRec;
    QStringList tables;
    const QRelation nullRelation;

    // Count how many times each field name occurs in the record
    QHash<QString, int> fieldNames;
    for (int i = 0; i < rec.count(); ++i) {
        QSqlRelation relation = d->relations.value(i, nullRelation).rel;
        QString name;
        if (relation.isValid())
            // Count the display column name, not the original foreign key
            name = relation.displayColumn();
        else
            name = rec.fieldName(i);
        fieldNames.insert(name, fieldNames.value(name, 0) + 1);
    }

    for (int i = 0; i < rec.count(); ++i) {
        QSqlRelation relation = d->relations.value(i, nullRelation).rel;
        if (relation.isValid()) {
            QString relTableAlias = QString::fromLatin1("relTblAl_%1").arg(i);
            fList.append(d->escapedRelationField(relTableAlias, relation.displayColumn()));
            
            // If there are duplicate field names they must be aliased
            if (fieldNames.value(relation.displayColumn()) > 1)
                fList.append(QString::fromLatin1(" AS %1_%2").arg(relation.tableName()).arg(relation.displayColumn()));

            fList.append(QLatin1Char(','));
            if (!tables.contains(relation.tableName()))
                tables.append(d->db.driver()->escapeIdentifier(relation.tableName(),
                       QSqlDriver::TableName).append(QLatin1String(" ")).append(
                       d->db.driver()->escapeIdentifier(relTableAlias, QSqlDriver::TableName)));
            where.append(d->escapedRelationField(tableName(), rec.fieldName(i)));
            where.append(QLatin1Char('='));
            where.append(d->escapedRelationField(relTableAlias, relation.indexColumn()));
            where.append(QLatin1String(" AND "));
        } else {
            fList.append(d->escapedRelationField(tableName(), rec.fieldName(i)));
            fList.append(QLatin1Char(','));
        }
    }
    if (!tables.isEmpty())
        tList.append(tables.join(QLatin1String(","))).append(QLatin1String(","));
    if (fList.isEmpty())
        return query;
    tList.prepend(QLatin1Char(',')).prepend(d->db.driver()->escapeIdentifier(tableName(),
                QSqlDriver::TableName));
    // truncate tailing comma
    tList.chop(1);
    fList.chop(1);
    query.append(QLatin1String("SELECT "));
    query.append(fList).append(QLatin1String(" FROM ")).append(tList);
    if (!where.isEmpty())
        where.chop(5);
    qAppendWhereClause(query, where, filter());

    QString orderBy = orderByClause();
    if (!orderBy.isEmpty())
        query.append(QLatin1Char(' ')).append(orderBy);

    return query;
}
// Предоставление редактора
QWidget*  ComboBoxFileldDelegate::createEditor ( QWidget * parent, const QStyleOptionViewItem & option,
												 const QModelIndex & index ) const
{
	if (index.column()>2){

		// QMessageBox::critical(0,"",index.model()->data(index.sibling(index.row(),0)).toString());
		QString pole = index.model()->data(index.sibling(index.row(),0)).toString();
		int j;
		for(int i=0;i<fieldName.count();i++){
				QString s = model->headerData( fieldName.at(i) , Qt::Horizontal).toString();
				s.replace("\n"," ");
				if (s==pole){
					j=fieldName.at(i);
					break;
				}
		}

		//QMessageBox::critical(0,"",QString("%1").arg(j));
		QSqlRelation rel =  model->relation(j);
		if (rel.indexColumn()!=QString("")){
			//QMessageBox::critical(0,"",rel.indexColumn()+" "+rel.displayColumn()+" "+rel.tableName());
			QComboBox * pRes = new QComboBox(parent);
			QSqlTableModel* relModel = new QSqlTableModel;

			relModel->setTable(rel.tableName());
			relModel->select();

			pRes->setModel(relModel);
			pRes->setModelColumn(relModel->fieldIndex(rel.displayColumn()));

			return pRes;

		}

		if (model->data(model->index(0,j), Qt::EditRole).type() == QVariant::Date){
			QDateEdit* pRes = new  QDateEdit(parent);
			pRes->setCalendarPopup(true);
			pRes->setDisplayFormat("dd.MM.yyyy");
			return pRes;
		}

		if (model->data(model->index(0,j), Qt::EditRole).type() == QVariant::Bool){
			QComboBox * pRes = new QComboBox(parent);

			pRes->addItem(tr("Нет"));
			pRes->addItem(tr("Да"));
			return pRes;
		}


		return QItemDelegate::createEditor(parent,option,index);
	}

	QComboBox * pRes = new QComboBox(parent);

	switch (index.column()) {
		case 0: {

			QStringList field;
			for(int i=0;i<fieldName.count();i++){
				QString s = model->headerData( fieldName.at(i) , Qt::Horizontal).toString();
				s.replace("\n"," ");
				field<<s;
			}
			pRes->addItems(field);
			break;
		}
		case 1: {
			pRes->addItem(tr(" "));
			pRes->addItem(tr("не"));
			break;
		}
		case 2: {
			pRes->addItem(tr("равно"));
			pRes->addItem(tr("похоже на"));
			pRes->addItem(tr("больше"));
			pRes->addItem(tr("меньше"));
			break;
		}

	}

	// это строка нужна для того чтобы по enter и esc завершалось редактирование итд
	pRes->installEventFilter(const_cast<ComboBoxFileldDelegate*>(this));

	return pRes;

};
// Предоставление редактора
QWidget*  ComboBoxMailDelegate::createEditor(QWidget* parent, const QStyleOptionViewItem& option,
        const QModelIndex& index) const
{

    if (index.column() == 1) {

        // QMessageBox::critical(0,"",index.model()->data(index.sibling(index.row(),0)).toString());
        QString pole = index.model()->data(index.sibling(index.row(), 0)).toString();
        int j;
        for (int i = 0; i < fieldName.count(); i++) {
            QString s = model->headerData(fieldName.at(i) , Qt::Horizontal).toString();
            s.replace("\n", " ");

            if (s == pole) {
                j = fieldName.at(i);
                break;
            }
        }

        //QMessageBox::critical(0,"",QString("%1").arg(j));
        QSqlRelation rel =  model->relation(j);
        if (rel.indexColumn() != QString("")) {
            //QMessageBox::critical(0,"",rel.indexColumn()+" "+rel.displayColumn()+" "+rel.tableName());
            QComboBox* pRes = new QComboBox(parent);
            QSqlTableModel* relModel = new QSqlTableModel;
            relModel->setTable(rel.tableName());

            /* Удаление выбранных значений в кому */
            if (pole == tr("Кому")) {
                QString relFilter = QString("user_id != '00000000-0000-0000-0000-000000000000'");
                for (int i = 0; i < index.model()->rowCount(); i++) {

                    QString pole = index.model()->data(index.sibling(i, 0)).toString();

                    if (pole == tr("Кому") && index.row() != i) {
                        QString val = index.model()->data(index.sibling(i, 1)).toString();
                        if ( val != QString(""))
                            relFilter = QString("%1 and not user_id = '%2'").arg(relFilter).arg(val);
                    }
                    //QMessageBox::critical(0,"",index.model()->data(index.sibling(i,1)).toString());
                }
                //QMessageBox::critical(0,"","-"+relFilter+"-");
                relModel->setFilter(relFilter);
            }

            relModel->select();

            pRes->setModel(relModel);
            pRes->setModelColumn(relModel->fieldIndex(rel.displayColumn()));

            return pRes;

        }

        if (model->data(model->index(0, j)).type() == QVariant::Date) {
            QDateEdit* pRes = new  QDateEdit(parent);
            pRes->setCalendarPopup(true);
            pRes->setDisplayFormat("dd.MM.yyyy");
            return pRes;
        }

        if (model->data(model->index(0, j)).type() == QVariant::Bool) {
            QComboBox* pRes = new QComboBox(parent);

            pRes->addItem(tr("Нет"));
            pRes->addItem(tr("Да"));
            return pRes;
        }


        return QItemDelegate::createEditor(parent, option, index);
    }

    if (index.column() == 0) {
        QComboBox* pRes = new QComboBox(parent);

        bool typeflag       = true;
        bool priorflag      = true;
        bool recipientflag  = true;
        bool beginflag  = true;
        bool endflag  = true;

        for (int i = 0; i < index.model()->rowCount(); i++) {

            QString pole = index.model()->data(index.sibling(i, 0)).toString();

            if (pole == tr("Тип") && index.row() != i)
                typeflag = false;
            if (pole == tr("Приоритет") && index.row() != i)
                priorflag = false;
            if (pole == tr("Начало") && index.row() != i)
                beginflag = false;
            if (pole == tr("Конец") && index.row() != i)
                endflag = false;
        }

        //if (recipientflag)
        pRes->addItem(tr("Кому"));

        if (typeflag)
            pRes->addItem(tr("Тип"));
        if (priorflag)
            pRes->addItem(tr("Приоритет"));
        if (beginflag)
            pRes->addItem(tr("Начало"));
        if (endflag)
            pRes->addItem(tr("Конец"));

        //pRes->addItem(tr("Копия"));

        // это строка нужна для того чтобы по enter и esc завершалось редактирование итд
        pRes->installEventFilter(const_cast<ComboBoxMailDelegate*>(this));

        return pRes;
    }


    return QItemDelegate::createEditor(parent, option, index);

};