Qt Forum

    • Login
    • Search
    • Categories
    • Recent
    • Tags
    • Popular
    • Users
    • Groups
    • Search
    • Unsolved

    Unsolved Compile problem

    C++ Gurus
    2
    3
    270
    Loading More Posts
    • 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.
    • Q
      Q139 last edited by

      Hello guys,

      Im getting this error when attempting to compile: U:\proj\dfw\mainwindow.cpp:-1: error: undefined reference to `void ui_sync_and_save::addUiItem<int>(QObject*, int&, uiItemMath, double)'

      mainWin .h

      #ifndef MAINWINDOW_H
      #define MAINWINDOW_H
      #include <QMainWindow>
      #include "../usual/ui_sync_and_save.h"
      
      namespace Ui {
      class MainWindow;
      }
      
      class MainWindow : public QMainWindow
      {
          Q_OBJECT
      
      public:
      
      
          explicit MainWindow(QWidget *parent = nullptr);
          ~MainWindow();
         ui_sync_and_save test;
         int val=0;
      private slots:
      
      private:
          Ui::MainWindow *ui;
      };
      
      #endif // MAINWINDOW_H
      
      
      }
      
      MainWindow::~MainWindow()
      {
          delete ui;
      }
      
      

      mainWin .cpp

      #include "mainwindow.h"
      #include "ui_mainwindow.h"
      
      MainWindow::MainWindow(QWidget *parent) :
          QMainWindow(parent),
          ui(new Ui::MainWindow)
      {
          ui->setupUi(this);
          test.addUiItem(ui->checkBox,val);//compile problem occurs here<<<<<
      
      }
      
      MainWindow::~MainWindow()
      {
          delete ui;
      }
      
      

      include .h

      #ifndef UI_SYNC_AND_SAVE_H
      #define UI_SYNC_AND_SAVE_H
      
      #include <QObject>
      #include "QSettings"
      
      using namespace std;
      
      enum uiOp{
          valToUi,
          valFromUi,
          fileFromUi,
          fileToUiAndPtr
      };
      
      enum uiItemMath{
         noCorrection,add,rem,multip,divide
      };
      
      class ui_sync_and_save : public QObject
      {
         // Q_OBJECT
      public:
      
          ui_sync_and_save();
      
      
      
          enum uiItems{
              spinBox,doubleSpinBox,checkBox,radioButton,dateTimeEdit
          };
      
          struct uiItem{
              QObject*ptr;
              void*valPtr;
              bool writeLock=0;
              uiItems type;
              uiItemMath mathOp;
              double mathVal;
          };
          vector<uiItem>uiItems;
      
          template <typename S>
          void addUiItem(QObject*uiItem,S&setVariable,uiItemMath correctionOp=noCorrection,double correctionVal=0);
          void syncUiVals(QObject *target=NULL, uiOp op=uiOp::valFromUi);
      
          QSettings uiSet;
          void saveUiValsToFile(QString path);
          void loadUiValsFromFile(QString path);
      
          bool setWriteLock(QObject*uiItem, bool lock);
      
          template <typename Val>
          QString n(Val num,char decimals=2){
             if(typeid(num)==typeid(double)){
                 return QString::number(num,'f',decimals);
             }else{
                 return QString::number(num);
             }
          }
      
      private:
          template <typename V>
          V valCorrection(V val,uiItem&itm,uiOp op=valFromUi);
      
      public slots:
          void syncSingleVal();
      
      signals:
          QString errorMsg(QString error){
              return error;
          }
      };
      
      #endif // UI_SYNC_AND_SAVE_H
      
      
      

      include .cpp

      #include "ui_sync_and_save.h"
      #include "QDoubleSpinBox"
      #include "QSpinBox"
      #include "QCheckBox"
      #include "QRadioButton"
      #include "QDateTimeEdit"
      
      ui_sync_and_save::ui_sync_and_save()
      {
      
      }
      
      template<typename S>//possibly template related mistake here<<<<<<<<
      void ui_sync_and_save::addUiItem(QObject *uiItem, S &setVar, uiItemMath mathOp, double mathVal)
      {
          ui_sync_and_save::uiItem item;
           item.ptr=uiItem;
           item.valPtr=&setVar;
           item.mathOp=mathOp;
           item.mathVal=mathVal;
      
               QDoubleSpinBox*dsBox=qobject_cast<QDoubleSpinBox*>(item.ptr);
               if (dsBox != NULL){
                   item.type=doubleSpinBox;
                   connect(dsBox, SIGNAL(valueChanged(double)), this, SLOT(syncSingleVal()));
                   uiItems.emplace_back(item);
                   return;
               }
      
               QSpinBox*sBox=qobject_cast<QSpinBox*>(item.ptr);
               if (sBox != NULL){
                   item.type=spinBox;
                   connect(sBox, SIGNAL(valueChanged(int)), this, SLOT(syncSingleVal()));
                   uiItems.emplace_back(item);
                   return;
               }
      
               QCheckBox*cBox=qobject_cast<QCheckBox*>(item.ptr);
               if (cBox != NULL){
                   item.type=checkBox;
                   connect(cBox, SIGNAL(stateChanged(int)), this, SLOT(syncSingleVal()));
                   uiItems.emplace_back(item);
                   return;
               }
               QRadioButton*rBut=qobject_cast<QRadioButton*>(item.ptr);
               if (rBut != NULL){
                   item.type=radioButton;
                   connect(rBut, SIGNAL(pressed()), this, SLOT(syncSingleVal()));
                   uiItems.emplace_back(item);
                   return;
               }
      
      
               QDateTimeEdit*dtEdit=qobject_cast<QDateTimeEdit*>(item.ptr);
               if (dtEdit != NULL){
                   item.type=dateTimeEdit;
                   connect(dtEdit, SIGNAL(dateTimeChanged(QDateTime)), this, SLOT(uuendaSet()));
                   uiItems.emplace_back(item);
                   return;
               }
      
             emit errorMsg("UiItemCastsFailed");
      
      }
      
      
      #ifdef QT_DEBUG
          int nullCounter=0;
      #endif
          void ui_sync_and_save::syncUiVals(QObject *target,uiOp op)
          {
      
          #ifdef QT_DEBUG
              if(op==uiOp::valFromUi && target==NULL){
                  nullCounter++;
                  if(nullCounter>1)
                      emit errorMsg("loopTroughUiItems NULL passed "+n(nullCounter)+" times.. Could use only once for initialization and set loading");
              }
          #endif
      
      
              bool found=0;
      
              for(auto &item:uiItems){
      
                  if((target!=NULL && item.ptr!=target)||(item.writeLock&&op==uiOp::valFromUi)){
                      continue;
                  }else{
                      found=1;
                  }
      
                  switch (item.type) {
      
                  case spinBox:{
                      QSpinBox*sBox=qobject_cast<QSpinBox*>(item.ptr);
                      if (sBox != NULL){
                          int*p=(int*)item.valPtr;
                          switch (op){
                           case uiOp::valToUi:
                              sBox->setValue(valCorrection(*p,item,uiOp::valToUi));
                              continue;
                           case uiOp::valFromUi:
                              *p=valCorrection(sBox->value(),item);  ;
                              continue;
                           case uiOp::fileFromUi:
                               uiSet.setValue(sBox->objectName(), sBox->value());
                              continue;
                           case uiOp::fileToUiAndPtr:
                              sBox->setValue(uiSet.value(sBox->objectName()).toInt());
                              continue;
                          }
                      }}
                  case doubleSpinBox:{
                      QDoubleSpinBox*dsBox=qobject_cast<QDoubleSpinBox*>(item.ptr);
                      if (dsBox != NULL){
                          double*p=(double*)item.valPtr;
                          switch (op){
                           case uiOp::valToUi:
                              dsBox->setValue(valCorrection(*p,item,uiOp::valToUi));
                              continue;
                           case uiOp::valFromUi:
                              *p=valCorrection(dsBox->value(),item);
                              continue;
                           case uiOp::fileFromUi:
                               uiSet.setValue(dsBox->objectName(), dsBox->value());
                              continue;
                           case uiOp::fileToUiAndPtr:
                              dsBox->setValue(uiSet.value(dsBox->objectName()).toDouble());
                              continue;
                          }
                      }}
                  case checkBox:{
                      QCheckBox*cBox=qobject_cast<QCheckBox*>(item.ptr);
                      if (cBox != NULL){
                          bool*p=(bool*)item.valPtr;
                          switch (op){
                           case uiOp::valToUi:
                              cBox->setChecked(*p);
                              continue;
                           case uiOp::valFromUi:
                              *p=cBox->isChecked();
                              continue;
                           case uiOp::fileFromUi:
                               uiSet.setValue(cBox->objectName(), cBox->isChecked());
                              continue;
                           case uiOp::fileToUiAndPtr:
                              cBox->setChecked(uiSet.value(cBox->objectName()).toBool());
                              continue;
                          }
                      }}
      
                  case radioButton:{
      
                      QRadioButton*rBut=qobject_cast<QRadioButton*>(item.ptr);
                      if (rBut != NULL){
                          bool*p=(bool*)item.valPtr;
                          switch (op){
                           case uiOp::valToUi:
                              rBut->setChecked(*p);
                              continue;
                           case uiOp::valFromUi:
                              *p=rBut->isChecked();
                              continue;
                           case uiOp::fileFromUi:
                               uiSet.setValue(rBut->objectName(), rBut->isChecked());
                              continue;
                           case uiOp::fileToUiAndPtr:
                              rBut->setChecked(uiSet.value(rBut->objectName()).toBool());
                              continue;
                          }
                      }
                  }
                  case dateTimeEdit:{
      
                      QDateTimeEdit*dtEdit=qobject_cast<QDateTimeEdit*>(item.ptr);
                      if (dtEdit != NULL){
                          QDateTime*p=(QDateTime*)item.valPtr;
                          switch (op){
                           case uiOp::valToUi:
                              dtEdit->setDateTime(*p);
                              continue;
                           case uiOp::valFromUi:
                              *p=dtEdit->dateTime();
                              continue;
                           case uiOp::fileFromUi:
                              uiSet.setValue(dtEdit->objectName(), dtEdit->dateTime());
                              continue;
                           case uiOp::fileToUiAndPtr:
                              dtEdit->setDateTime(uiSet.value(dtEdit->objectName()).toDateTime());
                              continue;
                          }
                      }}
                  default:{
                      emit errorMsg("ui CaseNotDefined or type and passed ptr mismatch, nam: "+item.ptr->objectName());
                      continue;
                  }
                  }
      
                  if(!found)
                     emit errorMsg("ui ptr not found , nam:"+item.ptr->objectName());
      
      
              }
      
               if(op==uiOp::fileToUiAndPtr){
                   syncUiVals(NULL,uiOp::valFromUi);
                   #ifdef QT_DEBUG
                        nullCounter--;
                   #endif
               }
      
          }
      
          void ui_sync_and_save::syncSingleVal(){
               syncUiVals(sender());//should return ptr of signal caller widget
          }
      
          void ui_sync_and_save::saveUiValsToFile(QString path)
          {
              uiSet.setPath(QSettings::IniFormat,QSettings::UserScope, path);
              syncUiVals(NULL,uiOp::fileFromUi);
          }
      
          void ui_sync_and_save::loadUiValsFromFile(QString path)
          {
              uiSet.setPath(QSettings::IniFormat,QSettings::UserScope, path);
              syncUiVals(NULL,uiOp::fileToUiAndPtr);
          }
      
          bool ui_sync_and_save::setWriteLock(QObject *uiItem,bool lock)
          {
              for(auto &item:uiItems){
                  if(item.ptr==uiItem){
                    item.writeLock=lock;
                    return 1;
                  }
              }
              return 0;
          }
      
      
      
          template<typename V>
          V ui_sync_and_save::valCorrection(V val, uiItem &itm,uiOp op)
          {
                  switch (itm.mathOp) {
                  noCorrection:
                  return val;
                  add:
                  if(op=valFromUi){
                      return val-itm.mathVal;
                  }else{
                      return val+itm.mathVal;
                  }
                  rem:
                  if(op=valFromUi){
                      return val+itm.mathVal;
                  }else{
                      return val-itm.mathVal;
                  }
                  multip:
                  if(op=valFromUi){
                      return val/itm.mathVal;
                  }else{
                      return val*itm.mathVal;
                  }
                  div:
                  if(op=valFromUi){
                      return val*itm.mathVal;
                  }else{
                      return val/itm.mathVal;
                  }
      
                  }
      
          }
      
      
      

      All help is welcome.

      1 Reply Last reply Reply Quote 0
      • Chris Kawa
        Chris Kawa Moderators last edited by

        Templates are instantiated at the call site, so their body needs to be available at that point. The error says it's not.
        To fix this and as a general rule of thumb - move your template implementation to the header file.

        1 Reply Last reply Reply Quote 4
        • Q
          Q139 last edited by

          Wonderful , also had some problems with using signals improperly.

          1 Reply Last reply Reply Quote 0
          • First post
            Last post