Russian Qt Forum

Qt => Model-View (MV) => Тема начата: RVZ от Март 02, 2011, 09:47



Название: Метод record (int row) для самописной модели
Отправлено: RVZ от Март 02, 2011, 09:47
Всем доброе время суток!
В общем, с ляпил модель по типу описанной тут - http://www.prog.org.ru/topic_12435_0.html (у меня не для дерева)  данные в структуре.
не могу сообразить как для этой модели сделать метод

QSqlRecord record (int row) const;

чтобы можно было перебрать все данные таким способом
Код
C
for(int i = 0; i < model.rowCount(); i++){
       int ID = model.record(i).value(1).toInt();
       QString name = model.record(i).value(3).toString();
}
 
Или что то подобно.
Заранее всем спасибо.


Название: Re: Метод record (int row) для самописной модели
Отправлено: GraninAS от Март 04, 2011, 06:01
Уточните, пожалуйста, что вы слепили. Вы сделали модель на основе какой модели? QAbstractItemModel или на основе чего-то другого?

Делается, я полагаю, так: в модель передается строка запроса или сам запрос через метод setQuery(). Запрос выполняется и сохраняется в классе вашей модели. Затем прописываете метод record(), который обращается к такому же методу сохраненного QSqlQuery. А вот с rowCount() все несколько сложнее.

Вообще, можете посмотреть мои модели для примера:
QstTreeQueryModel ([cpp] (http://qstsqltools.svn.sourceforge.net/viewvc/qstsqltools/trunk/0.5/src/qst/qsttreequerymodel.cpp?revision=19&view=markup), [h]) (http://qstsqltools.svn.sourceforge.net/viewvc/qstsqltools/trunk/0.5/src/qst/qsttreequerymodel.h?revision=19&view=markup)
QstPlainQueryModel ([cpp] (http://qstsqltools.svn.sourceforge.net/viewvc/qstsqltools/trunk/0.5/src/qst/qstplainquerymodel.cpp?revision=19&view=markup), [h] (http://qstsqltools.svn.sourceforge.net/viewvc/qstsqltools/trunk/0.5/src/qst/qstplainquerymodel.h?revision=19&view=markup))
AbstractTreeModel ([cpp] (http://qstsqltools.svn.sourceforge.net/viewvc/qstsqltools/trunk/0.5/src/qst/common/abstracttreemodel.cpp?view=log), [h] (http://qstsqltools.svn.sourceforge.net/viewvc/qstsqltools/trunk/0.5/src/qst/common/abstracttreemodel.h?view=log))


Название: Re: Метод record (int row) для самописной модели
Отправлено: RVZ от Март 05, 2011, 00:10
В общем  с чего все началось:
В программке потребовался список который бы представлял из себя выборку представления + еще несколько полей с галочками которые бы юзверь мог потыкать а потом на основе этих галок заполнялись поля в отчете.
Дальше признаюсь ступил причем осознал только сейчас :)
буквально заклинило что не существующие столбцы от запроса мне не получить принял решение организовать все на уровне модели (хотя ни кто не мешал сделать SELECT *, 0 As p1, 0 As p2, 1 As p3 FROM rec.view) или добавить поля к представлению и юзать QSqlTableModel (без отправки изменений в базу они там все равно не нужны)

ниже то что у меня получилось собрать из разных источников.
кстати опыта у меня совсем мало и половина кода вообще за гранью моего понимания
для хранения записей используется класс
Код
C++ (Qt)
//rectransfer.h
class RecTransfer
{
public:
   RecTransfer(int p_sid, int p_id, QString p_sfp, bool p_rec);
   ~RecTransfer() {qDeleteAll(children); }
   int getSID() const { return sid; }
   int getID() const { return id; }
   QString getSFP() const { return sfp; }
   bool getREC() const { return rec; }
   int getParentId() const { return parent ? parent->id : -1; }
   int row() const {return parent? parent->children.indexOf( const_cast<RecTransfer*>(this) ): 0;}
 
   RecTransfer *parent;
   QList<RecTransfer*> children;
 
   int sid, id;
   QString sfp;
   bool rec;
};
 

Код
C++ (Qt)
//rectransfer.cpp
#include "rectransfer.h"
 
RecTransfer::RecTransfer(int p_sid, int p_id, QString p_sfp, bool p_rec): sid(p_sid), id(p_id), sfp(p_sfp), rec(p_rec), parent(0){
}
 

далее сам класс модели
Код
C++ (Qt)
//rectransfermodel.h
#include "rectransfer.h"
#include <QSqlTableModel>
 
class RecTransferModel : public QSqlTableModel
{
   Q_OBJECT
public:
   explicit RecTransferModel(QObject *parent = 0);
   int rowCount(const QModelIndex &parent = QModelIndex()) const;
   int columnCount( const QModelIndex& parent ) const;
   QModelIndex index(int row, int col, const QModelIndex& parent ) const;
   RecTransfer* categoryFromIndex(const QModelIndex& index ) const;
   QVariant data ( const QModelIndex &index, int role = Qt::DisplayRole ) const;
   QSqlRecord record (int row) const;
   bool setData(const QModelIndex &index, const QVariant &value, int role);
   QVariant Alterdata( const QModelIndex &index, int column ) const;
   Qt::ItemFlags flags( const QModelIndex &index ) const;
   QVariant headerData(int section, Qt::Orientation orientation, int role = Qt::DisplayRole) const;
   void refreshModel();
   void setRoot( RecTransfer* node );
   void setFilt(QString &F);
 
private:
   void setupModel(RecTransfer* parent);
   RecTransfer* root;
 
   QSqlDatabase db;
   QString Filtr;
};
 

Код
C++ (Qt)
//rectransfermodel.cpp
RecTransferModel::RecTransferModel(QObject *parent):QSqlTableModel(parent){
   root = new RecTransfer(0, 0, tr("Types"),0);
   root->parent = 0;
   setupModel(root);
}
 
void RecTransferModel::setupModel(RecTransfer* parent){
   db = QSqlDatabase::database();
   QSqlQuery q;
   QString S;
 
    //формирование запроса к представлению с условием
Код
C++ (Qt)
   S = "SELECT EnID, (SE+' '+Na+' '+Pa)As SFP, 0 As rec FROM rec.view";
   if( this->Filtr!= "" ){
       S += " WHERE "+ this->Filtr;
   }
   if(q.prepare(S)){
       if(q.exec()){
           qDebug()<<"Query "<<S;
           QList<RecTransfer*> parents;
           QList<int> levels;
           parents<<parent;
           levels<<1;
           int i = 1;
           while(q.next()){
 
                //раскладывание данных запроса в класс RecTransfer для хранения и дальнейшего проставления галочек
                //юзверем
Код
C++ (Qt)
               RecTransfer* n = new RecTransfer(i, q.value(0).toInt(), q.value(1).toString(), q.value(2).toBool());
               i++;
               n->parent = parents.last();
               parents.last()->children.append(n);
           }
           q.clear();
           return;
       }
   }
}
 
int RecTransferModel::rowCount(const QModelIndex &parent) const{
   return categoryFromIndex(parent)->children.count();
}
 
int RecTransferModel::columnCount( const QModelIndex& parent ) const{
   return 4;
}
 
QModelIndex RecTransferModel::index(int row, int col, const QModelIndex& parent ) const{
   RecTransfer* parentNode = categoryFromIndex(parent);
   return createIndex(row, col, parentNode->children.value(row) );
}
 
RecTransfer* RecTransferModel::categoryFromIndex(const QModelIndex& index ) const{
   return index.isValid()? static_cast<RecTransfer*>(index.internalPointer()): root;
}
 
QVariant RecTransferModel::data ( const QModelIndex &index, int role) const{
   RecTransfer* node = categoryFromIndex(index);
   if( !node ) return QVariant();
   if( role == Qt::DisplayRole && index.column() == 0 )return QVariant(node->getSID());
   if( role == Qt::DisplayRole && index.column() == 1 )return QVariant(node->id);
   if( role == Qt::DisplayRole && index.column() == 2 )return QVariant(node->sfp);
   if( role == Qt::DisplayRole && index.column() == 3 )return QVariant(node->rec);
   return QVariant();
}
 
QSqlRecord RecTransferModel::record (int row) const{
 
    //не могу тут ничего придумать
    //record запрроса вернуть по моему нельзя потому что он не содержит изменений введенных пользователем
Код
C++ (Qt)
 
}
 
bool RecTransferModel::setData(const QModelIndex &index, const QVariant &value, int role){
    if (index.isValid() && role == Qt::EditRole){
        RecTransfer* node = categoryFromIndex(index);
        if(node){
            if(index.column() == 3) node->rec = value.toInt();
            qDebug()<<"В модель Value"<<value.toInt();
        }
        emit dataChanged(index, index);
        return true;
    }
    return false;
}
 
QVariant RecTransferModel::Alterdata( const QModelIndex& index, int column ) const{
   if (!index.isValid()) return QVariant();
   RecTransfer* node = categoryFromIndex(index);
   if(node){
       if(column == 0)return QVariant(node->sid);
       if(column == 1)return QVariant(node->id);
       if(column == 2)return QVariant(node->sfp);
       if(column == 3)return QVariant(node->rec);
   }else{
       if(!node)return QVariant();
       else return QVariant(node->sfp);
   }
   return QVariant();
}
 
Qt::ItemFlags RecTransferModel::flags( const QModelIndex& index ) const{
   if (!index.isValid() || index.column() != 3) return Qt::ItemIsEnabled;
   return QAbstractItemModel::flags(index) | Qt::ItemIsEditable;
}
 
QVariant RecTransferModel::headerData(int section, Qt::Orientation orientation, int role) const{
   if( orientation == Qt::Horizontal && role == Qt::DisplayRole && section == 0 ) return QString("SID");
   if( orientation == Qt::Horizontal && role == Qt::DisplayRole && section == 1 ) return QString("EnID");
   if( orientation == Qt::Horizontal && role == Qt::DisplayRole && section == 2 ) return QString("SFP");
   if( orientation == Qt::Horizontal && role == Qt::DisplayRole && section == 3 ) return QString("REC");
   return QVariant();
}
 
void RecTransferModel::refreshModel(){
   RecTransfer* newRoot = new RecTransfer(0, 0, tr("Types"),0);
   newRoot->parent = NULL;
   setupModel(newRoot);
   setRoot(newRoot);
}
 
void RecTransferModel::setRoot( RecTransfer* node ){
   delete root;
   root = node;
   reset();
}
 
void RecTransferModel::setFilt(QString &F){
   this->Filtr = F;
   this->refreshModel();
}