ListView undefined reference to vtable for Custom Delegate (QStyledItemDelegate)
-
Good day
I required a QListView to display information in a readable fashion to a user. After much searching, I came across this post made in 2010.
What I tried:
Following the code provided had me creating a custom delegate, a QStyledItemDelegate.A delegate is required to allow a developer to 'customize' how they want data to be displayed. e.g. Display 2 icons on a ListView item/entry with text inbetween.
Using this understanding which I derived from the
paint()
andsizeHint()
methods, I proceeded to edit it for my own use. See below for code example.The Problem:
The issue I have is simple.
Undefined reference to 'vtable for ServerDelegate'
.serverdelegate.o: In function `ServerDelegate::ServerDelegate()': /../../../serverdelegate.cpp:3: undefined reference to `vtable for ServerDelegate' collect2: error: ld returned 1 exit status make: *** [Makefile:291: VPNSumo] Error 1 09:32:22: The process "/usr/bin/make" exited with code 2. Error while building/deploying project VPNSumo (kit: Desktop Qt 5.9.3 GCC 64bit) When executing step "Make"
Out of experience (and lots of Google'ing), I have found that this is very often a case where the
Q_OBJECT
macro is not defined/declared in the header file, since methods defined in theQ_OBJECT
macro are used within this class.See for reference:
What I tried v2
I then proceeded to append the
Q_OBJECT
macro to theServerDelegate
class, also adding a constructor argument to theServerDelegate
constructor:ServerDelegate(QStyledItemDelegate* parent = 0);
and implemented by:
ServerDelegate::ServerDelegate(QStyledItemDelegate *parent) : QStyledItemDelegate(parent) { //... }
but the error persisted. I added a default constructor as a last resort taking no arguments, and as expected, it also did not work.
Error after adding parent argument and default constructor:
serverdelegate.o: In function `ServerDelegate::ServerDelegate()': /../../../serverdelegate.cpp:3: undefined reference to `vtable for ServerDelegate' serverdelegate.o: In function `ServerDelegate::ServerDelegate(QStyledItemDelegate*)': /../../../serverdelegate.cpp:15: undefined reference to `vtable for ServerDelegate' collect2: error: ld returned 1 exit status make: *** [Makefile:291: VPNSumo] Error 1 09:40:52: The process "/usr/bin/make" exited with code 2. Error while building/deploying project VPNSumo (kit: Desktop Qt 5.9.3 GCC 64bit) When executing step "Make"
I am out of ideas, and at Google Results page 5
Help would be very much appreciated
Code for
class ServerDelegate
ServerDelegate.h
#ifndef SERVERDELEGATE_H #define SERVERDELEGATE_H #include <QApplication> #include <QtGui> #include <QStyledItemDelegate> #include <QtWidgets> class ServerDelegate : public QStyledItemDelegate { public: ServerDelegate(); virtual ~ServerDelegate(); enum DataRole{ CountryText = Qt::UserRole + 100, CityText = Qt::UserRole+101, CountryFlag = Qt::UserRole+102, PremiumFlag = Qt::UserRole+103, ListIndex = Qt::UserRole+104 }; void paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const; QSize sizeHint(const QStyleOptionViewItem &option, const QModelIndex &index) const; private: QFont fontCountry, fontCity; }; #endif // SERVERDELEGATE_H
and the implementation serverdelegate.cpp
**Please note: the implementation is untested due to the error below
#include "serverdelegate.h" ServerDelegate::ServerDelegate() { fontCountry = QApplication::font(); fontCountry.setBold(true); fontCountry.setPointSize(QApplication::font().pointSize() + 3); fontCity = QApplication::font(); fontCity.setItalic(true); fontCity.setPointSize(QApplication::font().pointSize() - 1); } QSize ServerDelegate::sizeHint(const QStyleOptionViewItem &option, const QModelIndex &index) const{ QIcon countryFlag = qvariant_cast<QIcon>(index.data(CountryFlag)); QIcon premiumFlag = qvariant_cast<QIcon>(index.data(PremiumFlag)); QSize totalCountrySize = countryFlag.actualSize(option.decorationSize); QSize totalPremiumSize = premiumFlag.actualSize(option.decorationSize); QFontMetrics fmCountry(fontCountry); QFontMetrics fmCity(fontCity); int fontHeight = 4 + fmCountry.height() + 2 + fmCity.height() + 4; int iconHeight = 4 + (totalCountrySize.height() > totalPremiumSize.height() ? totalCountrySize.height() : totalPremiumSize.height()) + 4; return QSize(totalCountrySize.width() + totalPremiumSize.width(), (fontHeight > iconHeight ? fontHeight : iconHeight)); } void ServerDelegate::paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const{ QStyledItemDelegate::paint(painter, option, index); painter->save(); QString countryText = index.data(DataRole::CountryText).toString(); QString cityText = index.data(DataRole::CityText).toString(); QFontMetrics fmCountry(fontCountry); QFontMetrics fmCity(fontCity); QPixmap cF, pF; cF.loadFromData(index.data(DataRole::CountryFlag).toByteArray(), "PNG"); pF.loadFromData(index.data(DataRole::PremiumFlag).toByteArray(), "PNG"); QIcon countryFlag = QIcon(cF); QIcon premiumFlag = QIcon(pF); QSize totalCountrySize = countryFlag.actualSize(option.decorationSize); QSize totalPremiumSize = premiumFlag.actualSize(option.decorationSize); QRect rectSeperator = option.rect; QRect rectCountryText = option.rect; QRect rectCityText = option.rect; QRect rectCountryFlag = option.rect; QRect rectPremiumFlag = option.rect; rectSeperator.setTop(0); rectSeperator.setLeft(0); rectSeperator.setBottom(2); rectSeperator.setRight(option.rect.width()); rectCountryFlag.setRight(totalCountrySize.width()+20); rectCountryFlag.setTop(totalCountrySize.height()+4); rectCountryText.setLeft(rectCountryFlag.right()); rectCountryText.setTop(fmCountry.height()+4); rectCityText.setLeft(rectCountryFlag.right()); rectCityText.setTop(fmCity.height()+2); rectPremiumFlag.setLeft(rectCountryFlag.right()); rectCountryFlag.setTop(totalCountrySize.height()); painter->drawRect(rectSeperator); painter->drawPixmap(QPoint(rectCountryFlag.left()+totalCountrySize.width()/2+2,rectCountryFlag.top()+totalCountrySize.height()/2+3),countryFlag.pixmap(totalCountrySize.width(),totalCountrySize.height())); painter->setFont(fontCountry); painter->drawText(rectCountryText, countryText); painter->setFont(fontCity); painter->drawText(rectCityText, cityText); painter->drawPixmap(QPoint(rectPremiumFlag.left()+totalPremiumSize.width()/2+2,rectPremiumFlag.top()+totalPremiumSize.height()/2+3),premiumFlag.pixmap(totalPremiumSize.width(),totalPremiumSize.height())); painter->restore(); }
Update v1
According to a suggestion on StackOverflow, it was mentioned that I did not
Run qMake
after adding the macro. I did so, resulting in further errors. I took the following steps when I built the application:- clean
- run qmake
- rebuild
The resulting error indicates and issue with the moc* output. To my knowledge, this results from an old build with classes not all including the required macros.
However, this error points to the
virtual
destructor of theServerDelegate
class.In the tutorial I followed, it required one to create the
virtual
destructor to allow the parent to handle deleting the object.and here is the error output:
moc_serverdelegate.o:(.data.rel.ro._ZTV14ServerDelegate[_ZTV14ServerDelegate]+0x28): undefined reference to `ServerDelegate::~ServerDelegate()' moc_serverdelegate.o:(.data.rel.ro._ZTV14ServerDelegate[_ZTV14ServerDelegate]+0x30): undefined reference to `ServerDelegate::~ServerDelegate()' collect2: error: ld returned 1 exit status make: *** [Makefile:293: VPNSumo] Error 1 10:09:41: The process "/usr/bin/make" exited with code 2. Error while building/deploying project VPNSumo (kit: Desktop Qt 5.9.3 GCC 64bit) When executing step "Make"