Skip to content
  • Categories
  • Recent
  • Tags
  • Popular
  • Users
  • Groups
  • Search
  • Get Qt Extensions
  • Unsolved
Collapse
Brand Logo
  1. Home
  2. Qt Development
  3. General and Desktop
  4. What Is a Best WAY popuplate QTreeWidget & Database?
Forum Updated to NodeBB v4.3 + New Features

What Is a Best WAY popuplate QTreeWidget & Database?

Scheduled Pinned Locked Moved Solved General and Desktop
9 Posts 3 Posters 3.0k Views
  • Oldest to Newest
  • Newest to Oldest
  • Most Votes
Reply
  • Reply as topic
Log in to reply
This topic has been deleted. Only users with topic management privileges can see it.
  • Taz742T Offline
    Taz742T Offline
    Taz742
    wrote on last edited by
    #1

    alt text
    alt text

    This is My ALgorithm:
    I have only ONE ROOT And ONE COLUMN.

    Wooden arrangement:

       QSqlQuery qry;
        qry.prepare("select * from tree");
        if(qry.exec()){
            while(qry.next()){
                QTreeWidgetItem *item = new QTreeWidgetItem(QStringList() << qry.value("name").toString());
                item->setWhatsThis(0, qry.value("parent").toString());
                mp[qry.value("UID").toInt()] = item;
    
                if(qry.value("parent").toInt() == 0){
                    top = item;
                }
    
                mpuid[item] = qry.value("uid").toInt();
            }
        }
    
        ui->treeWidget->addTopLevelItem(top);
    
        for(it = mp.begin(); it != mp.end(); it++){
            if(it.key() == mpuid[top]) continue;
            QTreeWidgetItem *item = mp[it.value()->whatsThis(0).toInt()];
            item->addChild(it.value());
        }
    

    Insert Child:
    void MainWindow::on_btnInsertChild_clicked()
    {
    QTreeWidgetItem *last = ui->treeWidget->currentItem();

    if(db.open()){
        QSqlQuery qry;
                  qry.prepare("insert into tree(name, parent) values (:nm, :pr)");
                  qry.bindValue(":nm", QString::number(++cnt));
                  qry.bindValue(":pr", mpuid[last]);
    
        QTreeWidgetItem * newitem = new QTreeWidgetItem(QStringList() << QString::number(cnt));
    
        if(qry.exec()){
            last->addChild(newitem);
        }
    
        //Get Last Item UID
        
        QSqlQuery sel;
                  sel.prepare("select seq from sqlite_sequence where name = 'Tree'");
                  sel.exec();
                  sel.next();
    
        mpuid[newitem] = sel.value(0).toInt();
    }
    

    }

    Remove Node:

    void MainWindow::DFS(QTreeWidgetItem *v, QTreeWidgetItem *pr)
    {
        used[v] = true;
    
        for(int i = 0; i < v->childCount(); i++){
            if(v == pr) continue;
            QTreeWidgetItem * go = v->child(i);
            if(!used[go]){
                DFS(go, v);
            }
        }
    
        if(v != top){
            removeitems.push_back({pr, v});
        }
    }
    void MainWindow::on_btnRemoveNode_clicked()
    {
        DFS(ui->treeWidget->currentItem(), ui->treeWidget->currentItem()->parent());
        
        for(unsigned int i = 0; i < removeitems.size(); i++){
            std::pair<QTreeWidgetItem*, QTreeWidgetItem*> now = removeitems[i];
                now.first->removeChild(now.second);
        }
    }
    

    H.file

    #ifndef MAINWINDOW_H
    #define MAINWINDOW_H
    
    #include <QMainWindow>
    #include "form.h"
    #include "QAction"
    #include "QTreeWidget"
    #include "QDebug"
    #include "QSqlDatabase"
    #include "QSqlQuery"
    #include "QSqlError"
    #include "queue"
    
    namespace Ui {
    class MainWindow;
    }
    
    class MainWindow : public QMainWindow
    {
        Q_OBJECT
    
    public:
        explicit MainWindow(QWidget *parent = 0);
        ~MainWindow();
    
        QTreeWidgetItem * top;
    
        std::vector<std::pair<QTreeWidgetItem*, QTreeWidgetItem*> > removeitems;
    
        QMap<int, QTreeWidgetItem*> mp;
        QMap<int, QTreeWidgetItem*> ::iterator it;
    
        QMap<QTreeWidgetItem*, int> mpuid;
        QMap<QTreeWidgetItem*, bool> used;
    
        void DFS(QTreeWidgetItem * v, QTreeWidgetItem * pr);
    
        int cnt;
    
        QSqlDatabase db;
    
    signals:
    
    public slots:
    
    private slots:
        void on_treeWidget_itemDoubleClicked(QTreeWidgetItem *item, int column);
    
        void on_btnRemoveNode_clicked();
    
        void on_treeWidget_doubleClicked(const QModelIndex &index);
    
        void on_btnInsertChild_clicked();
    
        void on_treeWidget_itemClicked(QTreeWidgetItem *item, int column);
    
    private:
        Ui::MainWindow *ui;
    };
    
    #endif // MAINWINDOW_H
    
    

    Do what you want.

    Taz742T 1 Reply Last reply
    0
    • Taz742T Taz742

      alt text
      alt text

      This is My ALgorithm:
      I have only ONE ROOT And ONE COLUMN.

      Wooden arrangement:

         QSqlQuery qry;
          qry.prepare("select * from tree");
          if(qry.exec()){
              while(qry.next()){
                  QTreeWidgetItem *item = new QTreeWidgetItem(QStringList() << qry.value("name").toString());
                  item->setWhatsThis(0, qry.value("parent").toString());
                  mp[qry.value("UID").toInt()] = item;
      
                  if(qry.value("parent").toInt() == 0){
                      top = item;
                  }
      
                  mpuid[item] = qry.value("uid").toInt();
              }
          }
      
          ui->treeWidget->addTopLevelItem(top);
      
          for(it = mp.begin(); it != mp.end(); it++){
              if(it.key() == mpuid[top]) continue;
              QTreeWidgetItem *item = mp[it.value()->whatsThis(0).toInt()];
              item->addChild(it.value());
          }
      

      Insert Child:
      void MainWindow::on_btnInsertChild_clicked()
      {
      QTreeWidgetItem *last = ui->treeWidget->currentItem();

      if(db.open()){
          QSqlQuery qry;
                    qry.prepare("insert into tree(name, parent) values (:nm, :pr)");
                    qry.bindValue(":nm", QString::number(++cnt));
                    qry.bindValue(":pr", mpuid[last]);
      
          QTreeWidgetItem * newitem = new QTreeWidgetItem(QStringList() << QString::number(cnt));
      
          if(qry.exec()){
              last->addChild(newitem);
          }
      
          //Get Last Item UID
          
          QSqlQuery sel;
                    sel.prepare("select seq from sqlite_sequence where name = 'Tree'");
                    sel.exec();
                    sel.next();
      
          mpuid[newitem] = sel.value(0).toInt();
      }
      

      }

      Remove Node:

      void MainWindow::DFS(QTreeWidgetItem *v, QTreeWidgetItem *pr)
      {
          used[v] = true;
      
          for(int i = 0; i < v->childCount(); i++){
              if(v == pr) continue;
              QTreeWidgetItem * go = v->child(i);
              if(!used[go]){
                  DFS(go, v);
              }
          }
      
          if(v != top){
              removeitems.push_back({pr, v});
          }
      }
      void MainWindow::on_btnRemoveNode_clicked()
      {
          DFS(ui->treeWidget->currentItem(), ui->treeWidget->currentItem()->parent());
          
          for(unsigned int i = 0; i < removeitems.size(); i++){
              std::pair<QTreeWidgetItem*, QTreeWidgetItem*> now = removeitems[i];
                  now.first->removeChild(now.second);
          }
      }
      

      H.file

      #ifndef MAINWINDOW_H
      #define MAINWINDOW_H
      
      #include <QMainWindow>
      #include "form.h"
      #include "QAction"
      #include "QTreeWidget"
      #include "QDebug"
      #include "QSqlDatabase"
      #include "QSqlQuery"
      #include "QSqlError"
      #include "queue"
      
      namespace Ui {
      class MainWindow;
      }
      
      class MainWindow : public QMainWindow
      {
          Q_OBJECT
      
      public:
          explicit MainWindow(QWidget *parent = 0);
          ~MainWindow();
      
          QTreeWidgetItem * top;
      
          std::vector<std::pair<QTreeWidgetItem*, QTreeWidgetItem*> > removeitems;
      
          QMap<int, QTreeWidgetItem*> mp;
          QMap<int, QTreeWidgetItem*> ::iterator it;
      
          QMap<QTreeWidgetItem*, int> mpuid;
          QMap<QTreeWidgetItem*, bool> used;
      
          void DFS(QTreeWidgetItem * v, QTreeWidgetItem * pr);
      
          int cnt;
      
          QSqlDatabase db;
      
      signals:
      
      public slots:
      
      private slots:
          void on_treeWidget_itemDoubleClicked(QTreeWidgetItem *item, int column);
      
          void on_btnRemoveNode_clicked();
      
          void on_treeWidget_doubleClicked(const QModelIndex &index);
      
          void on_btnInsertChild_clicked();
      
          void on_treeWidget_itemClicked(QTreeWidgetItem *item, int column);
      
      private:
          Ui::MainWindow *ui;
      };
      
      #endif // MAINWINDOW_H
      
      
      Taz742T Offline
      Taz742T Offline
      Taz742
      wrote on last edited by Taz742
      #2

      IM sorry. I forgot to remove it from the base. After deleting the Node.

          std::vector<int> del;
      
          for(unsigned int i = 0; i < removeitems.size(); i++){
              std::pair<QTreeWidgetItem*, QTreeWidgetItem*> now = removeitems[i];
                  now.first->removeChild(now.second);
                  del.push_back(mpuid[now.second]);
          }
      
          if (db.open()) {
              for(unsigned int i = 0; i < del.size(); i++){
                  QSqlQuery qry;
                            qry.prepare("delete from tree where uid = :id or parent = :id");
                            qry.bindValue(":id", del.at(i));
                            qry.exec();
              }
      
              db.close();
          }
      

      Do what you want.

      Taz742T m.sueM 2 Replies Last reply
      0
      • Taz742T Taz742

        IM sorry. I forgot to remove it from the base. After deleting the Node.

            std::vector<int> del;
        
            for(unsigned int i = 0; i < removeitems.size(); i++){
                std::pair<QTreeWidgetItem*, QTreeWidgetItem*> now = removeitems[i];
                    now.first->removeChild(now.second);
                    del.push_back(mpuid[now.second]);
            }
        
            if (db.open()) {
                for(unsigned int i = 0; i < del.size(); i++){
                    QSqlQuery qry;
                              qry.prepare("delete from tree where uid = :id or parent = :id");
                              qry.bindValue(":id", del.at(i));
                              qry.exec();
                }
        
                db.close();
            }
        
        Taz742T Offline
        Taz742T Offline
        Taz742
        wrote on last edited by
        #3

        It is My Second WAY

        void MainWindow::on_btnRemoveNode_Clicked()
        {
            QTableWidgetItem * item = ui->tablewidget->currentItem();
        
            std::vector<int> del;
            std::vector<QTreeWidgetItem*> delitems;
        
            std::queue<QTreeWidgetItem*> Q;
                                         Q.push(item);
        
            QTreeWidgetItem *last = item;
        
            while (!Q.empty()) {
                QTreeWidgetItem *now = Q.front(); Q.pop(); delitems.clear();
        
                for(int i = 0; i < now->childCount(); i++){
                    del.push_back(mpuid[now->child(i)]);
                    Q.push(now->child(i));
                    delitems.push_back(item->child(i));
                }
        
                for(unsigned int i = 0; i < delitems.size(); i++){
                    now->removeChild(delitems[i]);
                }
        
                if(now == last){
                    now->parent()->removeChild(now);
                    del.push_back(mpuid[now]);
                }
            }
        
            if (db.open()) {
                for(unsigned int i = 0; i < del.size(); i++){
                    QSqlQuery qry;
                              qry.prepare("delete from tree where uid = :id or parent = :id");
                              qry.bindValue(":id", del.at(i));
                              qry.exec();
                }
        
                db.close();
            }
        }```

        Do what you want.

        1 Reply Last reply
        0
        • Taz742T Taz742

          IM sorry. I forgot to remove it from the base. After deleting the Node.

              std::vector<int> del;
          
              for(unsigned int i = 0; i < removeitems.size(); i++){
                  std::pair<QTreeWidgetItem*, QTreeWidgetItem*> now = removeitems[i];
                      now.first->removeChild(now.second);
                      del.push_back(mpuid[now.second]);
              }
          
              if (db.open()) {
                  for(unsigned int i = 0; i < del.size(); i++){
                      QSqlQuery qry;
                                qry.prepare("delete from tree where uid = :id or parent = :id");
                                qry.bindValue(":id", del.at(i));
                                qry.exec();
                  }
          
                  db.close();
              }
          
          m.sueM Offline
          m.sueM Offline
          m.sue
          wrote on last edited by m.sue
          #4

          Hi @Taz742

          The usual way is to fill a model and let the model fill the view (visualization widget). You may think it's not worth the time as the sql query result is nothing permanent enough. But there is already a class that helps to build the model. You may want to take a look at QSqlQueryModel: http://doc.qt.io/qt-5/qsqlquerymodel.html#details

          -Michael.

          Taz742T 1 Reply Last reply
          0
          • m.sueM m.sue

            Hi @Taz742

            The usual way is to fill a model and let the model fill the view (visualization widget). You may think it's not worth the time as the sql query result is nothing permanent enough. But there is already a class that helps to build the model. You may want to take a look at QSqlQueryModel: http://doc.qt.io/qt-5/qsqlquerymodel.html#details

            -Michael.

            Taz742T Offline
            Taz742T Offline
            Taz742
            wrote on last edited by
            #5

            @m.sue
            Yes I know about QsqlQueryModel.
            But I can not understand how to use this particular case.
            That's why I started with my knowledge for this problem.
            Can you explain how to use this case QsqlQueryModel?

            Do what you want.

            1 Reply Last reply
            0
            • VRoninV Offline
              VRoninV Offline
              VRonin
              wrote on last edited by VRonin
              #6

              You can't use QSqlQueryModel here.

              enum { UidRole = Qt::UserRole + 123 };
              QModelIndex findParent(const QAbstractItemModel* model, const QVariant& val, int colIdx = 0, const QModelIndex& parent = QModelIndex())
              {
                  Q_ASSERT(model);
                  Q_ASSERT(colIdx >= 0 && colIdx < model->columnCount(parent));
                  const int rowCnt = model->rowCount(parent);
                  for (int i = 0; i < rowCnt; ++i) {
                      QModelIndex currIdx = model->index(i, colIdx, parent);
                      if (currIdx.data(UidRole) == val)
                          return currIdx;
                      currIdx = findParent(model, val, colIdx, currIdx);
                      if (currIdx.isValid())
                          return currIdx;
                  }
                  return QModelIndex();
              }
              
              void populateModel(QAbstractItemModel* model)
              {
                  Q_ASSERT(model);
                  model->removeRows(0, model->rowCount());
                  model->removeColumns(0, model->columnCount());
                  QSqlQuery qry;
                  qry.prepare(QStringLiteral("select * from tree"));
                  if (qry.exec()) {
                      while (qry.next()) {
                          const QSqlRecord recrd = qry.record();
                          const QModelIndex parentIdx = findParent(model, recrd.value(QStringLiteral("Parent")));
                          const int rowCnt = model->rowCount(parentIdx);
                          model->insertRow(rowCnt, parentIdx);
                          if (model->columnCount(parentIdx) <= 0) model->insertColumn(0, parentIdx);
                          const QModelIndex currIdx = model->index(rowCnt, 0, parentIdx);
                          model->setData(currIdx, recrd.value(QStringLiteral("Name")));
                          model->setData(currIdx, recrd.value(QStringLiteral("UID")), UidRole);
                      }
                  }
              }
              

              This assumes that in the query the parent will never come after the child in order. As a model you can use anything that supports trees, QStandardItemModel is more than fine but even passing treeWidget->model() should work

              The code is untested but should work


              To update the database with the changes you made just connect to the relevant signals of the model and split adding the row/updating the data functionality from the DB update itself

              "La mort n'est rien, mais vivre vaincu et sans gloire, c'est mourir tous les jours"
              ~Napoleon Bonaparte

              On a crusade to banish setIndexWidget() from the holy land of Qt

              Taz742T 1 Reply Last reply
              2
              • VRoninV VRonin

                You can't use QSqlQueryModel here.

                enum { UidRole = Qt::UserRole + 123 };
                QModelIndex findParent(const QAbstractItemModel* model, const QVariant& val, int colIdx = 0, const QModelIndex& parent = QModelIndex())
                {
                    Q_ASSERT(model);
                    Q_ASSERT(colIdx >= 0 && colIdx < model->columnCount(parent));
                    const int rowCnt = model->rowCount(parent);
                    for (int i = 0; i < rowCnt; ++i) {
                        QModelIndex currIdx = model->index(i, colIdx, parent);
                        if (currIdx.data(UidRole) == val)
                            return currIdx;
                        currIdx = findParent(model, val, colIdx, currIdx);
                        if (currIdx.isValid())
                            return currIdx;
                    }
                    return QModelIndex();
                }
                
                void populateModel(QAbstractItemModel* model)
                {
                    Q_ASSERT(model);
                    model->removeRows(0, model->rowCount());
                    model->removeColumns(0, model->columnCount());
                    QSqlQuery qry;
                    qry.prepare(QStringLiteral("select * from tree"));
                    if (qry.exec()) {
                        while (qry.next()) {
                            const QSqlRecord recrd = qry.record();
                            const QModelIndex parentIdx = findParent(model, recrd.value(QStringLiteral("Parent")));
                            const int rowCnt = model->rowCount(parentIdx);
                            model->insertRow(rowCnt, parentIdx);
                            if (model->columnCount(parentIdx) <= 0) model->insertColumn(0, parentIdx);
                            const QModelIndex currIdx = model->index(rowCnt, 0, parentIdx);
                            model->setData(currIdx, recrd.value(QStringLiteral("Name")));
                            model->setData(currIdx, recrd.value(QStringLiteral("UID")), UidRole);
                        }
                    }
                }
                

                This assumes that in the query the parent will never come after the child in order. As a model you can use anything that supports trees, QStandardItemModel is more than fine but even passing treeWidget->model() should work

                The code is untested but should work


                To update the database with the changes you made just connect to the relevant signals of the model and split adding the row/updating the data functionality from the DB update itself

                Taz742T Offline
                Taz742T Offline
                Taz742
                wrote on last edited by
                #7

                @VRonin
                Thank VRonin for answer.
                I only had one question. My algorithm is bad?

                Do what you want.

                VRoninV 1 Reply Last reply
                0
                • Taz742T Taz742

                  @VRonin
                  Thank VRonin for answer.
                  I only had one question. My algorithm is bad?

                  VRoninV Offline
                  VRoninV Offline
                  VRonin
                  wrote on last edited by VRonin
                  #8

                  @Taz742 said in What Is a Best WAY popuplate QTreeWidget & Database?:

                  My algorithm is bad?

                  Honestly I hate the QStandardItem interface so much I really can't judge an algorithm using it with a clear mind. the only "design flaw" is that you are doing too many things in the same function but, once again, it's not a break of functionality

                  "La mort n'est rien, mais vivre vaincu et sans gloire, c'est mourir tous les jours"
                  ~Napoleon Bonaparte

                  On a crusade to banish setIndexWidget() from the holy land of Qt

                  Taz742T 1 Reply Last reply
                  0
                  • VRoninV VRonin

                    @Taz742 said in What Is a Best WAY popuplate QTreeWidget & Database?:

                    My algorithm is bad?

                    Honestly I hate the QStandardItem interface so much I really can't judge an algorithm using it with a clear mind. the only "design flaw" is that you are doing too many things in the same function but, once again, it's not a break of functionality

                    Taz742T Offline
                    Taz742T Offline
                    Taz742
                    wrote on last edited by
                    #9

                    @VRonin
                    Thank!
                    I will choose your algorithm and I think I will make a good decision.

                    Do what you want.

                    1 Reply Last reply
                    0

                    • Login

                    • Login or register to search.
                    • First post
                      Last post
                    0
                    • Categories
                    • Recent
                    • Tags
                    • Popular
                    • Users
                    • Groups
                    • Search
                    • Get Qt Extensions
                    • Unsolved