Lange SQL Tabelle editieren Ohne QSqlTableModel > QTableW

Code-Schnippsel, oder Tipps und Tricks, die einem beim Programmieren mit Qt helfen können.
Antworten
patrik08
Beiträge: 746
Registriert: 27. Februar 2006 10:48
Wohnort: DE Freiburg

Lange SQL Tabelle editieren Ohne QSqlTableModel > QTableW

Beitrag von patrik08 »

Kurz entschlossen musste ich eine Imb DB2 tabelle mit 45'000 zeilen editieren ... mit dem QSqlTableModel kenne ich kein Weg 30 zeilen zu blaetter.... Und Komplexe such query sind nicht editierbar mit QSqlTableModel doch mit dieser methode ist alles editierbar wichtig ist dass eine unique id dabei ist in kolonne 0.

das geht naturlich nur wenn die erste kolonne einen Unique ist als id den man nicht zum editieren frei gibt!

Also:
  • man nehme 1 QTableWidget
    2 buttons vor (>>) und retour (<<)
    eine qlineedit zum suchen...
    eine abgeleitete class von QTableWidgetItem
    eine class die query bauen und updaten kann
Die abgeleitete QTableWidgetItem die dass noetige abspeichert...
in eine ....

QList<DayItem *> items; um die 300 zelle aufs mal beim blaettern..

Code: Alles auswählen

/* ist alles drinnen im header source hat nur die construct function.. */
class DayItem : public QTableWidgetItem
{
public:
	DayItem();
    QString FieldName;
    inline void SetFieldName( const QString f ) { FieldName = f; }
    inline QString GetFieldName() const { return FieldName; }
    QString type;
    inline void SetType( const QString t ) { type = t; }
    inline QString GetType() const { return type; }
    QString where;
    inline void SetWhere( const QString w ) { where = w; }
    inline QString GetWhere() const { return where; }
    QString OrData;
    inline void SetDataOrig( QString d ) { OrData = d; setText(d); }
    inline QString GetDataOrig() { return OrData; }
    int colum;
    int mkrows;
    inline void SetListPos( const int ro , const int co ) { colum = co; mkrows = ro; }
    inline int GetCPos() const { return colum; }
    inline int GetRPos() const { return mkrows; }
protected:
private:
public slots:
};
Die db classe

Code: Alles auswählen


/* header mit  */
/* typedef QMap<int, QStringList> resultMap; */  
/* um jede zeile abzuspeichern */
/* einen namen der odbc verbidung pass ecc ist im odbc system */
bool Sql_Box::Connect(QString name)
{
    db.setDatabaseName( name );
    if (db.open()) {
    is_open = true;
    qDebug() << "db open";
    } else {
    is_open = false;
    qDebug() << "db close";
    }
return is_open;
}


/* return total nummer row query */
bool Sql_Box::MakeQueryBool( QString humanquery )
{
     if (is_open) {
        QSqlQuery query; 
        return query.exec(humanquery);
     } else {
       return false;  
     }
}


/* return total nummer row query */
int Sql_Box::TotAffectRow( QString humanquery )
{
int sumrow=0;
    
    if (is_open) {
       QSqlQuery query;
       query.exec(humanquery);
       return query.numRowsAffected();
    }
return sumrow;
}

/* return a list of fieldname of query */
QStringList Sql_Box::FieldName( QString humanquery )
{
QStringList fname;
fname.clear();
    if (is_open) {
       QSqlQuery query;
       query.exec(humanquery);
       QSqlRecord rec = query.record();  /* nummer col */
       int sumcol = rec.count();
       /*int sumrow = query.numRowsAffected();*/
       /* int recnum = 0 - 1;*/
             fname.clear();
                 for(int i=0;i<sumcol;i++){
                     QString cosas = rec.fieldName(i);
                     /*qDebug() << "### fieldname "  << cosas;*/
                     fname.append(cosas);
                 }
     return fname;
    }
return fname;
}

/* return a qmap of query */
resultMap Sql_Box::QMap_Query( QString humanquery )
{
resultMap resrow;
resrow.clear();
    if (is_open) {
       QSqlQuery query;
       query.exec(humanquery);
       QSqlRecord rec = query.record();  /* nummer col */
       int sumcol = rec.count();
       /*int sumrow = query.numRowsAffected();*/
       int recnum = 0 - 1;
            while (query.next()) { 
             recnum++;
             QStringList line;
                         line.clear();
                 for(int i=0;i<sumcol;i++){
                     QString cosas = query.value(i).toString();
                     line.append(cosas);
                 }  
            resrow.insert(recnum,line);
            }  
     return resrow;
    }
return resrow;
}

Sql_Box::Sql_Box()
{
  db = QSqlDatabase::addDatabase("QODBC");
}

Sql_Box::~Sql_Box()
{
  if (is_open) {
   db.close();
  }
}

Die vor next und prev funktionen....
mit der funktion UserModell(QTableWidgetItem *))); die jedes feld einzel updatet und einen lock um es nicht mehrmals zu updaten... im header abspeichern...

im Header QList<DayItem *> items; alle zelle attribute abspeichern

in den mann queryexec neu setzt zur class kann man immer die query neu setzen ... am anfang kommt nur eine default query mit der erste zeilen die im limit angegeben sind....

Code: Alles auswählen



Gui_Main::Gui_Main( QWidget* parent )
	: QMainWindow( parent )
{
    limit = 30;
    position = 0;
    steeps = 0;
    LockCell = 0;
	setupUi( this );
    wokupdate = false;
    
    if (Connect("nord")) {
     dbok = true;
     connect(db_next, SIGNAL(clicked()), this , SLOT(next_pos()));
     connect(db_prev, SIGNAL(clicked()), this , SLOT(prev_pos()));
     queryexec = "SELECT * FROM companies WHERE cpn_city!='' order by cpn_person_name";
     tablename="companies";
     sumlinetotal = TotAffectRow(queryexec);
     qDebug() << "### totalelinetrovate "  << sumlinetotal;
     MakeNow();  
     
    }
}

void Gui_Main::MakeNow()
{   
    if (position == 0) {
    db_prev->setDisabled (true);
    } else {
    db_prev->setDisabled (false);  
    }
    total_text_query =QString( "%1 LIMIT %2,%3" ).arg( queryexec ,  QString::number(position) , QString::number(limit) );
    FillTable();
}

void Gui_Main::UserModell(QTableWidgetItem * elempi)
{
    qDebug() << "### works ###";
    if (wokupdate) {
    QString titem = elempi->text();
    int cool = flotable->column(elempi);
    int xrows = flotable->row(elempi);
    int totalcell = items.size();
        if ( totalcell > 0) {
             for ( int x = 0; x < totalcell ; ++x ) {
                 if (items[x]->GetCPos() == cool and items[x]->GetRPos() == xrows) {
                       if (LockCell !=x) {  
                         QString MakeUpdate = QString("%1 SET %2='%3' %4").arg( items[x]->GetType() , items[x]->GetFieldName() , titem , items[x]->GetWhere() );
                         if (!MakeQueryBool(MakeUpdate)) {
                         qDebug() << "### Error Query " << MakeUpdate;
                         }
                         LockCell=x;  /* save on class & not update moore as 1 time go to next to update */
                       }
                 break;
                 }
             }
         }
    }
}

void Gui_Main::FillTable()
{   
    wokupdate = false;
    flotable->clear();
    items.clear();
    int posixe =  -1;
    int rowposx = -1;
    QStringList headers = FieldName(total_text_query);
    resultMap dataloop = QMap_Query(total_text_query);
    int cooltot = headers.size();
    flotable->setColumnCount(cooltot);
    connect(flotable, SIGNAL(itemChanged(QTableWidgetItem *)), this, SLOT(UserModell(QTableWidgetItem *)));  
                for(int i=0;i<cooltot;i++){
                  posixe++;
                  DayItem *hitem = new DayItem(); 
                  hitem->SetDataOrig( headers.at(i) );
                  hitem->setToolTip(QString("Field Name NR. %1").arg(QString::number(i)));
                  hitem->SetFieldName("NULL");
                  hitem->SetType( "header" );
                  hitem->SetWhere( "header" );
                  hitem->SetListPos(0,0);
                  flotable->setHorizontalHeaderItem(i,hitem);
                  items.append( hitem );
                 }

                 flotable->setRowCount(limit);

                 resultMap::Iterator en;
                 for ( en = dataloop.begin(); en != dataloop.end(); ++en ) {
                 posixe++;
                 rowposx++;
                 QStringList dataline = en.value(); 
                     for(int o=0;o<cooltot;o++){
                          DayItem *ditem = new DayItem(); 
                          ditem->SetDataOrig( dataline.at(o) );
                          if (o == 0) {
                          ditem->setFlags(Qt::ItemIsSelectable);  /* first index ID xx Unique not edit!  */
                          ditem->setToolTip(QString("Field %1 is not editable.").arg(headers.at(o)));
                          } else {
                          ditem->setToolTip(QString("Field Name - %1").arg(headers.at(o)));
                          }
                          ditem->SetFieldName(headers.at(o));
                          ditem->SetType(QString("UPDATE %1").arg(tablename));
                          ditem->SetWhere(QString("WHERE %1=%2 LIMIT 1").arg(headers.at(0),dataline.at(0)));
                          ditem->SetListPos(rowposx,o);
                          flotable->setItem(rowposx,o,ditem);   
                          items.append( ditem );      
                                                  
                     }
                
                 }   
    
qDebug() << "### Total Cell "  << items.size();
LockCell = 0;
wokupdate = true;
}


void Gui_Main::next_pos()
{   
    qDebug() << "### pos ++ ";
    position = position + limit;
    WakePosition();
    MakeNow();
}

void Gui_Main::prev_pos()
{   
    qDebug() << "### pos -- ";
     position = position - limit;
     WakePosition();
     MakeNow();
}

void Gui_Main::WakePosition()
{
     qDebug() << "### WakePosition " << position << sumlinetotal;
     if (position > sumlinetotal ) {
      position = 0;    
     }
     if (position < 0) {
      position = 0;   
     }
}



Performance mit der starke IMB db2 ein kinderspiel.... sicher auch mysql..
Wie mann die zelle editiert ... ist es bereit updatet...
Antworten