Error in QSqlTableModel inherited table - c++

I have this class that inherits from QSqlTableModel and it brokes after calling the submitAll() slot, after calling insertPoint some times. Here is the code.
Thanks for the help.
Regards.
#ifndef VWLANDMARKTABLEMODEL_H
#define VWLANDMARKTABLEMODEL_H
#include <QSqlTableModel>
class GraphicsPointLandmarkItem;
class VWLandmarkTableModel : public QSqlTableModel
{
Q_OBJECT
public:
enum Column {
IdColumn=0,
IdImageColumn=1,
UsernameColumn=2,
NameColumn=3,
DefinitionColumn=4
};
VWLandmarkTableModel(QObject *parent=0);
int idImage() const { return m_idImage; }
QString username() const { return m_username; }
void setIdImage(int idImage);
void setUsername(const QString &username);
virtual bool select();
bool insertPoint(GraphicsPointLandmarkItem *item);
signals:
protected:
virtual void setFilter(const QString &filter)
{ QSqlTableModel::setFilter(filter); }
virtual bool insertRowIntoTable(const QSqlRecord &values);
protected slots:
void setDefaults(int row, QSqlRecord &r);
private:
QString m_username;
int m_idImage;
};
#endif // VWLANDMARKTABLEMODEL_H
#include "vwlandmarktablemodel.h"
#include <QtGui>
#include <QtSql>
#include <QtCore>
#include "graphicspointlandmarkitem.h"
VWLandmarkTableModel::VWLandmarkTableModel(QObject *parent)
: QSqlTableModel(parent)
{
setTable("vwLandmark");
setEditStrategy(OnManualSubmit);
connect(this, SIGNAL(primeInsert(int,QSqlRecord&)),
SLOT(setDefaults(int,QSqlRecord&)));
}
void VWLandmarkTableModel::setIdImage(int idImage)
{ m_idImage=idImage; }
void VWLandmarkTableModel::setUsername(const QString &username)
{ m_username=username; }
bool VWLandmarkTableModel::select()
{
Q_ASSERT(!username().isEmpty());
QString stmt="IdImage = %1 AND Username = '%2'";
setFilter(stmt.arg(idImage()).arg(username()));
return QSqlTableModel::select();
}
bool VWLandmarkTableModel::insertPoint(GraphicsPointLandmarkItem *item)
{
QString text;
QTextStream out(&text);
int row=rowCount();
bool ok;
ok=insertRow(row); Q_ASSERT(ok);
QModelIndex idx=index(row, DefinitionColumn);
out<<*item;
ok=setData(idx, text);
Q_ASSERT(ok);
idx=index(row, NameColumn);
ok=setData(idx, tr("New point landmark"));
Q_ASSERT(ok);
return ok;
}
bool VWLandmarkTableModel::insertRowIntoTable(const QSqlRecord &values)
{
QString sql="EXEC InsertLandmark :IdImage,:Definition";
QSqlQuery q;
bool ok;
ok=q.prepare(sql); Q_ASSERT(ok);
q.bindValue(":IdImage", values.value("IdImage"));
q.bindValue(":Definition", values.value("Definition"));
q.setForwardOnly(true);
if(!q.exec()) {
setLastError(q.lastError());
return false;
}
qDebug()<<"hola mundo";
return true;
}
void VWLandmarkTableModel::setDefaults(int row, QSqlRecord &r)
{
r.setValue("IdImage", idImage());
r.setValue("Name", "Unnamed landmark");
r.setValue("Username", username());
}

The problem was in my custom select. Calling setFilter() causes a infinite calling loop

Related

Qt Model-View custom delegate not working

I'm studying model-view programming in Qt. I'm trying to implement a custom list model with a custom delegate. It's a simple list widget with with in every row a widget with a few of label.
The widget show nothing. Debugging I noticed the delegates method are never called, so of course I'm missing something, but I can't figure out what it is.
userinfo.h
#ifndef USERINFO_H
#define USERINFO_H
#include <QString>
#include <QTime>
#include <QImage>
class UserInfo
{
public:
UserInfo();
UserInfo(const UserInfo&);
~UserInfo();
QString getTitle() const;
QString getSubtitle() const;
QTime getTime() const;
QImage getAvatar() const;
void setTitle(const QString& value);
void setSubtitle(const QString& value);
void setTime(const QTime& value);
void setAvatar(const QImage& value);
private:
UserInfo(const QString& title);
UserInfo(const QString& title, const QString& subtitle, const QTime& time, const QImage& icon);
QString title;
QString subtitle;
QTime time;
QImage avatar;
};
Q_DECLARE_METATYPE(UserInfo)
#endif // USERINFO_H
userinfo.cpp
#include "userinfo.h"
static const int _regUserInfo = qRegisterMetaType<UserInfo>("UserInfo");
UserInfo::UserInfo()
: UserInfo("User")
{
}
UserInfo::UserInfo(const QString& title)
: UserInfo(title, "Comment", QTime(0,0,0,0), QImage(":/resources/icon.png"))
{
}
UserInfo::UserInfo(const QString& title, const QString& subtitle, const QTime& time, const QImage& icon) :
title(title),
subtitle(subtitle),
time(time),
avatar(icon)
{
}
QImage UserInfo::getAvatar() const
{
return avatar;
}
void UserInfo::setAvatar(const QImage& value)
{
avatar = value;
}
QTime UserInfo::getTime() const
{
return time;
}
void UserInfo::setTime(const QTime& value)
{
time = value;
}
QString UserInfo::getSubtitle() const
{
return subtitle;
}
void UserInfo::setSubtitle(const QString& value)
{
subtitle = value;
}
QString UserInfo::getTitle() const
{
return title;
}
void UserInfo::setTitle(const QString& value)
{
title = value;
}
UserInfo::UserInfo(const UserInfo&) = default;
UserInfo::~UserInfo() = default;
userlistmodel.h
#ifndef USERMODEL_H
#define USERMODEL_H
#include <QAbstractListModel>
#include "userinfo.h"
class UserListModel : public QAbstractListModel
{
public:
UserListModel(QObject* parent = nullptr);
int rowCount(const QModelIndex& parent) const;
QVariant data(const QModelIndex& index, int role) const;
bool setData(const QModelIndex& index, const QVariant& value, int role);
QVariant headerData(int section, Qt::Orientation orientation,
int role = Qt::DisplayRole) const;
bool insertRows(int position, int row, const QModelIndex& parent=QModelIndex());
private:
QList<UserInfo> users;
};
#endif // USERMODEL_H
userlistmodel.cpp
#include "userlistmodel.h"
#include <QDebug>
UserListModel::UserListModel(QObject* parent) : QAbstractListModel(parent)
{
}
int UserListModel::rowCount(const QModelIndex& parent) const
{
Q_UNUSED(parent)
return users.size();
}
QVariant UserListModel::data(const QModelIndex& index, int role) const
{
if (!index.isValid())
return QVariant();
if (role != Qt::DisplayRole)
return QVariant();
if (index.row() >= users.size())
return QVariant();
return QVariant::fromValue<UserInfo>(users.at(index.row()));
}
bool UserListModel::setData(const QModelIndex& index, const QVariant& value, int role)
{
qDebug() << index.isValid();
qDebug() << (role == Qt::EditRole) ;
qDebug() <<value.canConvert<UserInfo>();
if (index.isValid() && role == Qt::EditRole && value.canConvert<UserInfo>()) {
users.replace(index.row(), value.value<UserInfo>());
emit dataChanged(index, index);
return true;
}
return false;
}
QVariant UserListModel::headerData(int section, Qt::Orientation orientation, int role) const
{
if (role != Qt::DisplayRole)
return QVariant();
if (orientation == Qt::Horizontal)
return QString("Column %1").arg(section);
else
return QString("Row %1").arg(section);
}
bool UserListModel::insertRows(int position, int rows, const QModelIndex &parent)
{
beginInsertRows(QModelIndex(), position, position+rows-1);
for (int row = 0; row < rows; ++row) {
users.insert(position, UserInfo());
}
endInsertRows();
return true;
}
userentrywidget.h
#ifndef USERENTRYWIDGET_H
#define USERENTRYWIDGET_H
#include <QWidget>
#include <QLabel>
#include "userinfo.h"
class UserEntryWidget : public QWidget
{
Q_OBJECT
public:
explicit UserEntryWidget(QWidget* parent = nullptr);
void setUserInfo(const UserInfo& user);
private:
QLabel *avatar, *title, *subtitle, *time;
};
#endif // USERENTRYWIDGET_H
userentrywidget.cpp
#include "userentrywidget.h"
#include <QHBoxLayout>
#include <QVBoxLayout>
#include <QLabel>
UserEntryWidget::UserEntryWidget(QWidget* parent) : QWidget(parent)
{
avatar = new QLabel();
title = new QLabel("title");
subtitle = new QLabel("subtitle");
time = new QLabel("00:00");
auto layout = new QHBoxLayout();
layout->addWidget(avatar);
auto centralColumn = new QVBoxLayout();
centralColumn->addWidget(title);
centralColumn->addWidget(subtitle);
layout->addItem(centralColumn);
layout->addWidget(time);
this->setLayout(layout);
}
void UserEntryWidget::setUserInfo(const UserInfo& user)
{
avatar->setPixmap(QPixmap::fromImage(user.getAvatar()));
title->setText(user.getTitle());
subtitle->setText(user.getSubtitle());
time->setText(user.getTime().toString("hh:mm"));
}
useritemdelegate.h
#ifndef USERITEMDELEGATE_H
#define USERITEMDELEGATE_H
#include <QStyledItemDelegate>
#include "userentrywidget.h"
class UserItemDelegate : public QStyledItemDelegate
{
public:
UserItemDelegate(QObject* parent = nullptr);
QWidget* createEditor(QWidget* parent, const QStyleOptionViewItem& option, const QModelIndex& index) const;
void setEditorData(QWidget* editor, const QModelIndex& index) const;
};
#endif // USERITEMDELEGATE_H
useritemdelegate.cpp
#include "useritemdelegate.h"
UserItemDelegate::UserItemDelegate(QObject* parent) : QStyledItemDelegate (parent)
{
}
QWidget* UserItemDelegate::createEditor(QWidget* parent, const QStyleOptionViewItem& option, const QModelIndex& index) const
{
if (index.data().canConvert<UserInfo>()) {
UserInfo user = qvariant_cast<UserInfo>(index.data());
auto editor = new UserEntryWidget(parent);
editor->setUserInfo(user);
return editor;
} else {
return QStyledItemDelegate::createEditor(parent, option, index);
}
}
void UserItemDelegate::setEditorData(QWidget* editor, const QModelIndex& index) const
{
if (index.data().canConvert<UserInfo>()) {
UserInfo user = qvariant_cast<UserInfo>(index.data());
UserEntryWidget* userEditor = qobject_cast<UserEntryWidget*>(editor);
userEditor->setUserInfo(user);
} else {
QStyledItemDelegate::setEditorData(editor, index);
}
}
main.cpp
#include <QApplication>
#include <QListView>
#include <QListWidget>
#include <QIcon>
#include <QLabel>
#include <QDebug>
#include "userentrywidget.h"
#include "useritemdelegate.h"
#include "userlistmodel.h"
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
qRegisterMetaType<UserInfo>("UserInfo");
qDebug() << QMetaType::type("UserInfo");
auto lm = new UserListModel();
lm->insertRows(0, 5);
auto widget = new QListView();
widget->setModel(lm);
widget->setItemDelegate(new UserItemDelegate());
widget->resize(500, 300);
widget->show();
return a.exec();
}

Qt QPropertyAnimation for widgets in layout - widgets shaking

I want to make widgets increase in height with QPropertyAnimation, when widgets are arranged with QVboxLayout.
The problem is that when I open more than one widget, they start to move/shake during animation.
I have prepared minimum working example, here tar gz project
The problem appears when you press "open" button for first, second, then third widget, you can see then that they are shaking, moving slightly up and down during "open" animation.
Has someone idea what to do to avoid this ?
I can set setSizeConstraint(QLayout::SetFixedSize) on main layout and they dont shake, but then resizing and other doesn't work.
Best Regards
Marek
Some time ago I've wrote a layout which animates widget position it contains.
You should build your layout in such way that each widget which should be animated should be inside this layout (one AnimLayout per widget which should be animated):
#include <QLayout>
QT_FORWARD_DECLARE_CLASS(QPropertyAnimation)
class AnimLayout : public QLayout
{
Q_OBJECT
Q_PROPERTY(QPoint delta
READ delta
WRITE setDelta
NOTIFY deltaChanged)
Q_PROPERTY(QRect widgetRect
READ widgetRect
WRITE setWidgetRect
NOTIFY widgetRectChanged)
Q_PROPERTY(bool active
READ isDeltaActive
WRITE setDeltaActive
NOTIFY deltaActiveChanged)
public:
explicit AnimLayout(QWidget *parent = 0);
~AnimLayout();
QPoint delta() const;
void setDelta(const QPoint &value);
QSize sizeHint() const;
void setGeometry(const QRect &);
QSize minimumSize() const;
int count() const;
QSize deltaSize() const;
QRect widgetRect() const;
void setWidgetRect(const QRect &value);
bool isDeltaActive() const;
void setDeltaActive(bool active = true);
void updateItemPosition();
private:
void addItem(QLayoutItem *item);
QLayoutItem *itemAt(int index) const;
QLayoutItem *takeAt(int index);
signals:
void deltaChanged(const QPoint &value);
void widgetRectChanged(const QRect &value);
void deltaActiveChanged(bool active);
public slots:
void testIt();
private:
QLayoutItem *item;
QPropertyAnimation *animation;
QPoint mDelta;
bool mDeltaActive;
};
///////////////////////////////////////////////////////////
#include "animlayout.h"
#include <QPropertyAnimation>
AnimLayout::AnimLayout(QWidget *parent) :
QLayout(parent) ,
item(0)
{
animation = new QPropertyAnimation(this);
animation->setPropertyName("widgetRect");
animation->setDuration(400);
animation->setTargetObject(this);
mDeltaActive = false;
}
AnimLayout::~AnimLayout()
{
delete item;
}
QPoint AnimLayout::delta() const
{
return mDelta;
}
void AnimLayout::setDelta(const QPoint &value)
{
if (mDelta != value) {
mDelta = value;
emit deltaChanged(mDelta);
invalidate();
}
}
void AnimLayout::addItem(QLayoutItem *newItem)
{
Q_ASSERT(!item);
animation->stop();
item =newItem;
emit widgetRectChanged(item->geometry());
invalidate();
}
QSize AnimLayout::sizeHint() const
{
if (!item)
return QSize();
QSize result(item->sizeHint());
result += deltaSize();
int m = 2*margin();
result += QSize(m,m);
return result;
}
void AnimLayout::updateItemPosition()
{
QRect dest = contentsRect();
QPoint d = delta();
if (isDeltaActive()) {
d = -d;
}
if (d.x()!=0) {
if (d.x()>0) {
dest.setLeft(dest.left()+d.x());
} else {
dest.setRight(dest.right()+d.x());
}
}
if (d.y()) {
if (d.y()>0) {
dest.setTop(dest.top()+d.y());
} else {
dest.setBottom(dest.bottom()+d.y());
}
}
animation->setEndValue(dest);
if (widgetRect()!=dest) {
animation->start();
}
}
void AnimLayout::setGeometry(const QRect &rect)
{
QLayout::setGeometry(rect);
updateItemPosition();
}
QLayoutItem *AnimLayout::itemAt(int i) const
{
return i==0?item:0;
}
QLayoutItem *AnimLayout::takeAt(int i)
{
Q_ASSERT(i==0);
QLayoutItem *r = item;
item = 0;
return r;
}
void AnimLayout::testIt()
{
setDeltaActive(!isDeltaActive());
}
QRect AnimLayout::widgetRect() const
{
if (item)
return item->geometry();
return QRect();
}
void AnimLayout::setWidgetRect(const QRect &value)
{
if (item && item->geometry()!=value) {
item->setGeometry(value);
emit widgetRectChanged(item->geometry());
}
}
bool AnimLayout::isDeltaActive() const
{
return mDeltaActive;
}
void AnimLayout::setDeltaActive(bool active)
{
if (active!=mDeltaActive) {
mDeltaActive = active;
animation->stop();
updateItemPosition();
emit deltaActiveChanged(active);
}
}
QSize AnimLayout::minimumSize() const
{
QSize result(deltaSize());
if (item) {
result += item->minimumSize();
}
int m = 2*margin();
result += QSize(m,m);
return result;
}
int AnimLayout::count() const
{
return item?1:0;
}
QSize AnimLayout::deltaSize() const
{
return QSize(qAbs(mDelta.x()), qAbs(mDelta.y()));
}
It has some extra functionality you don't need (mDelta).
Sorry it took me so long ;)
I have tested it and it works great.
However, when I was working with my previous code I have made it work without shaking. The change I made was to add QWidget into QScrollArea and then set QVBoxLayout on that widget.
Anyway many thanks for help.
Below there is example in one main.cpp and there is variable "animatedLayout" which turns on or off your AnimLayout.
#include
#include
class AnimLayout : public QLayout
{
Q_OBJECT
Q_PROPERTY(QRect widgetRect
READ widgetRect
WRITE setWidgetRect
NOTIFY widgetRectChanged)
public:
explicit AnimLayout(QWidget *parent = 0);
~AnimLayout();
QSize sizeHint() const;
void setGeometry(const QRect &);
QSize minimumSize() const;
int count() const;
QRect widgetRect() const;
void setWidgetRect(const QRect &value);
void updateItemPosition();
private:
void addItem(QLayoutItem *item);
QLayoutItem *itemAt(int index) const;
QLayoutItem *takeAt(int index);
signals:
void widgetRectChanged(const QRect &value);
public slots:
private:
QLayoutItem *item;
QPropertyAnimation *animation;
};
struct FrameDataStruct {
QFrame *mainFrame;
QFrame *upFrame;
QFrame *downFrame;
QPushButton *button;
QVBoxLayout *upFrameLayout;
QLabel *text;
QVBoxLayout *downFrameLayout;
QVBoxLayout *frameLayout;
QPropertyAnimation *animation;
int frame_id;
int basic_height;
bool expanded;
AnimLayout *animLayout;
};
class Proptest : public QMainWindow
{
Q_OBJECT
public:
explicit Proptest();
~Proptest();
private slots:
void setDataStruct();
void startAnimation(int frame_id);
void animFinished(int frame_id);
private:
QMap frameMap;
QSignalMapper *animStartMapper;
QSignalMapper *animFinishedMapper;
bool initialized;
QWidget *scrollWidget;
QVBoxLayout *main_layout;
QWidget *widget;
QScrollArea *scrollArea;
QVBoxLayout *central_layout;
bool layoutAnimated;
};
Proptest::Proptest()
: widget(new QWidget)
{
setCentralWidget(widget);
this->setGeometry(200,200,300,600);
central_layout=new QVBoxLayout(widget);
scrollArea=new QScrollArea(widget);
central_layout->addWidget(scrollArea);
animStartMapper=new QSignalMapper(this);
connect(animStartMapper,SIGNAL(mapped(int)),this,SLOT(startAnimation(int)));
animFinishedMapper=new QSignalMapper(this);
connect(animFinishedMapper,SIGNAL(mapped(int)),this,SLOT(animFinished(int)));
scrollWidget=new QWidget(widget);
scrollArea->setWidget(scrollWidget);
main_layout=new QVBoxLayout(scrollWidget);
main_layout->setSizeConstraint(QLayout::SetMinAndMaxSize);
scrollArea->setWidgetResizable(true);
scrollArea->setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOn);
layoutAnimated=true;
this->setDataStruct();
}
void Proptest::setDataStruct() {
for(int i=0;iexpanded=false;
r->frame_id=i;
r->mainFrame=new QFrame(scrollWidget);
r->upFrame=new QFrame(r->mainFrame);
r->upFrame->setMinimumHeight(40);
r->button=new QPushButton(QString("open"),r->upFrame);
r->upFrameLayout=new QVBoxLayout(r->upFrame);
r->upFrameLayout->addWidget(r->button);
r->downFrame=new QFrame(r->mainFrame);
r->text=new QLabel(QString("some text SOME TEXT some text"),r->downFrame);
r->downFrameLayout=new QVBoxLayout(r->downFrame);
r->downFrameLayout->addWidget(r->text);
r->frameLayout=new QVBoxLayout(r->mainFrame);
r->frameLayout->addWidget(r->upFrame);
r->frameLayout->addItem(new QSpacerItem(10,10));
r->frameLayout->addWidget(r->downFrame);
r->frameLayout->setStretch(0,0);
r->frameLayout->setStretch(1,1);
r->frameLayout->setStretch(2,0);
r->downFrame->setVisible(false);
r->animation=new QPropertyAnimation(r->mainFrame,"minimumHeight");
r->animation->setDuration(500);
connect(r->button,SIGNAL(clicked(bool)),animStartMapper,SLOT(map()));
animStartMapper->setMapping(r->button,r->frame_id);
connect(r->animation,SIGNAL(finished()),animFinishedMapper,SLOT(map()));
animFinishedMapper->setMapping(r->animation,r->frame_id);
if(layoutAnimated) {
r->animLayout=new AnimLayout();
r->animLayout->addWidget(r->mainFrame);
main_layout->addItem(r->animLayout);
}
else {
main_layout->addWidget(r->mainFrame);
}
frameMap.insert(r->frame_id,r);
}
main_layout->addItem(new QSpacerItem(10,10,QSizePolicy::Minimum,QSizePolicy::Expanding));
main_layout->setStretch(main_layout->count()-1,1);
}
void Proptest::startAnimation(int frame_id) {
FrameDataStruct *r=frameMap[frame_id];
if(r->expanded) {
r->expanded=false;
if(layoutAnimated) {
r->downFrame->hide();
}
else {
r->downFrame->setVisible(false);
r->animation->setStartValue(r->mainFrame->geometry().height());
r->animation->setEndValue(r->basic_height);
}
} else {
r->expanded=true;
if(layoutAnimated) {
r->downFrame->show();
}
else {
r->basic_height=r->mainFrame->geometry().height();
r->animation->setStartValue(r->basic_height);
r->animation->setEndValue(r->basic_height*2);
r->upFrame->setMinimumHeight(r->upFrame->height());
}
}
if(!layoutAnimated)
r->animation->start();
}
void Proptest::animFinished(int frame_id) {
FrameDataStruct *r=frameMap[frame_id];
if(r->expanded)
r->downFrame->setVisible(true);
}
Proptest::~Proptest() {
}
AnimLayout::AnimLayout(QWidget *parent) :
QLayout(parent) ,
item(0)
{
animation = new QPropertyAnimation(this);
animation->setPropertyName("widgetRect");
animation->setDuration(400);
animation->setTargetObject(this);
}
AnimLayout::~AnimLayout()
{
delete item;
}
void AnimLayout::addItem(QLayoutItem *newItem)
{
Q_ASSERT(!item);
animation->stop();
item =newItem;
emit widgetRectChanged(item->geometry());
invalidate();
}
QSize AnimLayout::sizeHint() const
{
if (!item)
return QSize();
QSize result(item->sizeHint());
int m = 2*margin();
result += QSize(m,m);
return result;
}
void AnimLayout::updateItemPosition()
{
QRect dest = contentsRect();
animation->setEndValue(dest);
if (widgetRect()!=dest) {
animation->start();
}
}
void AnimLayout::setGeometry(const QRect &rect)
{
QLayout::setGeometry(rect);
updateItemPosition();
}
QLayoutItem *AnimLayout::itemAt(int i) const
{
return i==0?item:0;
}
QLayoutItem *AnimLayout::takeAt(int i)
{
Q_ASSERT(i==0);
QLayoutItem *r = item;
item = 0;
return r;
}
QRect AnimLayout::widgetRect() const
{
if (item)
return item->geometry();
return QRect();
}
void AnimLayout::setWidgetRect(const QRect &value)
{
if (item && item->geometry()!=value) {
item->setGeometry(value);
emit widgetRectChanged(item->geometry());
}
}
QSize AnimLayout::minimumSize() const
{
QSize result(item->minimumSize());
int m = 2*margin();
result += QSize(m,m);
return result;
}
int AnimLayout::count() const
{
return item?1:0;
}
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
Proptest w;
w.show();
return a.exec();
}
#include "main.moc"
Best Regards
Marek
My answer again, dont know why but previosu was deleted.
I have used Your AnimLayout and it works great.
Below there is example in main.cpp with "layoutAnimated" variable to switch on and off AnimLayout.
#include <QApplication>
#include <QtWidgets>
class AnimLayout : public QLayout
{
Q_OBJECT
Q_PROPERTY(QRect widgetRect
READ widgetRect
WRITE setWidgetRect
NOTIFY widgetRectChanged)
public:
explicit AnimLayout(QWidget *parent = 0);
~AnimLayout();
QSize sizeHint() const;
void setGeometry(const QRect &);
QSize minimumSize() const;
int count() const;
QRect widgetRect() const;
void setWidgetRect(const QRect &value);
void updateItemPosition();
private:
void addItem(QLayoutItem *item);
QLayoutItem *itemAt(int index) const;
QLayoutItem *takeAt(int index);
signals:
void widgetRectChanged(const QRect &value);
public slots:
private:
QLayoutItem *item;
QPropertyAnimation *animation;
};
struct FrameDataStruct {
QFrame *mainFrame;
QFrame *upFrame;
QFrame *downFrame;
QPushButton *button;
QVBoxLayout *upFrameLayout;
QLabel *text;
QVBoxLayout *downFrameLayout;
QVBoxLayout *frameLayout;
QPropertyAnimation *animation;
int frame_id;
int basic_height;
bool expanded;
AnimLayout *animLayout;
};
class Proptest : public QMainWindow
{
Q_OBJECT
public:
explicit Proptest();
~Proptest();
private slots:
void setDataStruct();
void startAnimation(int frame_id);
void animFinished(int frame_id);
private:
QMap<int,FrameDataStruct*> frameMap;
QSignalMapper *animStartMapper;
QSignalMapper *animFinishedMapper;
bool initialized;
QWidget *scrollWidget;
QVBoxLayout *main_layout;
QWidget *widget;
QScrollArea *scrollArea;
QVBoxLayout *central_layout;
bool layoutAnimated;
};
Proptest::Proptest()
: widget(new QWidget)
{
setCentralWidget(widget);
this->setGeometry(200,200,300,600);
central_layout=new QVBoxLayout(widget);
scrollArea=new QScrollArea(widget);
central_layout->addWidget(scrollArea);
animStartMapper=new QSignalMapper(this);
connect(animStartMapper,SIGNAL(mapped(int)),this,SLOT(startAnimation(int)));
animFinishedMapper=new QSignalMapper(this);
connect(animFinishedMapper,SIGNAL(mapped(int)),this,SLOT(animFinished(int)));
scrollWidget=new QWidget(widget);
scrollArea->setWidget(scrollWidget);
main_layout=new QVBoxLayout(scrollWidget);
main_layout->setSizeConstraint(QLayout::SetMinAndMaxSize);
scrollArea->setWidgetResizable(true);
scrollArea->setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOn);
layoutAnimated=true;
this->setDataStruct();
}
void Proptest::setDataStruct() {
for(int i=0;i<5;i++) {
FrameDataStruct *r=new FrameDataStruct;
r->expanded=false;
r->frame_id=i;
r->mainFrame=new QFrame(scrollWidget);
r->upFrame=new QFrame(r->mainFrame);
r->upFrame->setMinimumHeight(40);
r->button=new QPushButton(QString("open"),r->upFrame);
r->upFrameLayout=new QVBoxLayout(r->upFrame);
r->upFrameLayout->addWidget(r->button);
r->downFrame=new QFrame(r->mainFrame);
r->text=new QLabel(QString("some text SOME TEXT some text"),r->downFrame);
r->downFrameLayout=new QVBoxLayout(r->downFrame);
r->downFrameLayout->addWidget(r->text);
r->frameLayout=new QVBoxLayout(r->mainFrame);
r->frameLayout->addWidget(r->upFrame);
r->frameLayout->addItem(new QSpacerItem(10,10));
r->frameLayout->addWidget(r->downFrame);
r->frameLayout->setStretch(0,0);
r->frameLayout->setStretch(1,1);
r->frameLayout->setStretch(2,0);
r->downFrame->setVisible(false);
r->animation=new QPropertyAnimation(r->mainFrame,"minimumHeight");
r->animation->setDuration(500);
connect(r->button,SIGNAL(clicked(bool)),animStartMapper,SLOT(map()));
animStartMapper->setMapping(r->button,r->frame_id);
connect(r->animation,SIGNAL(finished()),animFinishedMapper,SLOT(map()));
animFinishedMapper->setMapping(r->animation,r->frame_id);
if(layoutAnimated) {
r->animLayout=new AnimLayout();
r->animLayout->addWidget(r->mainFrame);
main_layout->addItem(r->animLayout);
}
else {
main_layout->addWidget(r->mainFrame);
}
frameMap.insert(r->frame_id,r);
}
main_layout->addItem(new QSpacerItem(10,10,QSizePolicy::Minimum,QSizePolicy::Expanding));
main_layout->setStretch(main_layout->count()-1,1);
}
void Proptest::startAnimation(int frame_id) {
FrameDataStruct *r=frameMap[frame_id];
if(r->expanded) {
r->expanded=false;
if(layoutAnimated) {
r->downFrame->hide();
}
else {
r->downFrame->setVisible(false);
r->animation->setStartValue(r->mainFrame->geometry().height());
r->animation->setEndValue(r->basic_height);
}
} else {
r->expanded=true;
if(layoutAnimated) {
r->downFrame->show();
}
else {
r->basic_height=r->mainFrame->geometry().height();
r->animation->setStartValue(r->basic_height);
r->animation->setEndValue(r->basic_height*2);
r->upFrame->setMinimumHeight(r->upFrame->height());
}
}
if(!layoutAnimated)
r->animation->start();
}
void Proptest::animFinished(int frame_id) {
FrameDataStruct *r=frameMap[frame_id];
if(r->expanded)
r->downFrame->setVisible(true);
}
Proptest::~Proptest() {
}
AnimLayout::AnimLayout(QWidget *parent) :
QLayout(parent) ,
item(0)
{
animation = new QPropertyAnimation(this);
animation->setPropertyName("widgetRect");
animation->setDuration(400);
animation->setTargetObject(this);
}
AnimLayout::~AnimLayout()
{
delete item;
}
void AnimLayout::addItem(QLayoutItem *newItem)
{
Q_ASSERT(!item);
animation->stop();
item =newItem;
emit widgetRectChanged(item->geometry());
invalidate();
}
QSize AnimLayout::sizeHint() const
{
if (!item)
return QSize();
QSize result(item->sizeHint());
int m = 2*margin();
result += QSize(m,m);
return result;
}
void AnimLayout::updateItemPosition()
{
QRect dest = contentsRect();
animation->setEndValue(dest);
if (widgetRect()!=dest) {
animation->start();
}
}
void AnimLayout::setGeometry(const QRect &rect)
{
QLayout::setGeometry(rect);
updateItemPosition();
}
QLayoutItem *AnimLayout::itemAt(int i) const
{
return i==0?item:0;
}
QLayoutItem *AnimLayout::takeAt(int i)
{
Q_ASSERT(i==0);
QLayoutItem *r = item;
item = 0;
return r;
}
QRect AnimLayout::widgetRect() const
{
if (item)
return item->geometry();
return QRect();
}
void AnimLayout::setWidgetRect(const QRect &value)
{
if (item && item->geometry()!=value) {
item->setGeometry(value);
emit widgetRectChanged(item->geometry());
}
}
QSize AnimLayout::minimumSize() const
{
QSize result(item->minimumSize());
int m = 2*margin();
result += QSize(m,m);
return result;
}
int AnimLayout::count() const
{
return item?1:0;
}
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
Proptest w;
w.show();
return a.exec();
}
#include "main.moc"
Best Regards
Marek

QSettings subclass does not have any keys

I am working on project as addition to existing Java app. This Java app has its configuration file, like this:
screen.600800=false
payment.commerceid=
machine.printer=printer\:(Default),receipt
paper.standard.mediasizename=A4
machine.printername=(Show dialog)
payments.textoverlay=false
paper.receipt.height=546
till.receiptsize=1
swing.defaultlaf=org.pushingpixels.substance.skinpack.StreetlightsSkin
paper.standard.y=72
paper.standard.x=72
table.tablecolour=black
till.SCRate=0
format.integer=\#,\#\#0
user.language=sl
paper.receipt.width=190
till.receiptprintoff=false
db.user=user
start.text=
machine.uniqueinstance=false
menu.autohide=false
till.pricewith00=false
table.waitercolour=red
format.double=\#,\#\#0.\#
user.country=
till.amountattop=false
till.pickupsize=1
till.autoLogoffrestaurant=false
machine.screenmode=window
screen.receipt.columns=42
machine.printer.6=Not defined
machine.printer.5=Not defined
db.engine=MySQL
machine.printer.4=Not defined
user.variant=
machine.printer.3=screen
machine.printer.2=printer\:(Show dialog),standard
payment.gateway=Not defined
till.SCOnOff=false
start.logo=logo.png
format.percent=\#,\#\#0.\#\#%
db.driver=com.mysql.jdbc.Driver
table.showwaiterdetails=true
format.date=
machine.ticketsbag=simple
db.driverlib=/opt/uBlagajna/./lib/mysql-connector-java-5.1.26-bin.jar
table.showcustomerdetails=true
db.password=test
till.receiptprefix=
paper.standard.height=698
table.customercolour=blue
till.taxincluded=false
paper.standard.width=451
till.autotimer=100
machine.display=screen
payment.testmode=true
format.datetime=
machine.scanner=Not defined
machine.hostname=work002
till.autoLogoff=false
paper.receipt.y=10
paper.receipt.x=10
payment.magcardreader=Not defined
payment.commercepassword=password
format.time=
format.currency='EUR' \#,\#\#0.00
db.URL=jdbc\:mysql\://127.0.0.1\:3306/testdb
till.hideinfo=false
machine.scale=Not defined
paper.receipt.mediasizename=A4
till.SCRestaurant=false
till.marineoption=false
Now, whatever I do on Qt C++ side, I cannot get values from keys. Therefore I've subclassed QSettings class as in here:
#ifndef UEPOSSESTTINGS_H
#define UEPOSSESTTINGS_H
#include <QtCore/qglobal.h>
#include <QSettings>
#include <QDirIterator>
#include <QStringList>
#include <QString>
#include <QFile>
#include <QDebug>
#include <QFile>
#include "settings/uedefaults.h"
class UePOSSesttings : public QSettings
{
Q_OBJECT
private:
QString m_strSettingsFilePath;
QString m_strParsedData;
QString m_strDbUrl;
inline void ueSetConfigurationFilePath(const QString& path)
{ this->m_strSettingsFilePath=path; }
inline QString ueParsedData() const
{ return this->m_strParsedData; }
inline void ueSetParsedData(const QString& data)
{ this->m_strParsedData=data; }
inline QString ueDbUrl() const
{ return this->m_strDbUrl; }
inline void ueSetDbUrl(const QString& dbUrl)
{ this->m_strDbUrl=dbUrl; }
void ueParseData(const QString& filename);
public:
UePOSSesttings(const QString& organization,
const QString & application=QString(),
QObject* parent = 0);
UePOSSesttings(const QString& fileName,
Format format,
QObject* parent = 0);
~UePOSSesttings();
static QString ueSearchConfigurationFile();
inline QString ueConfigurationFilePath() const
{ return this->m_strSettingsFilePath; }
QString ueReadDbDriver() const;
QString ueReadDbPassword() const;
QString ueReadDbUrl() const;
QString ueReadDbDriverLib() const;
QString ueReadDbEngine() const;
QString ueReadDbUser() const;
QString ueReadDbHostname() const;
QString ueReadDbName() const;
int ueReadDbPort() const;
};
#endif // UEPOSSESTTINGS_H
and implementation:
#include "uepossesttings.h"
UePOSSesttings::UePOSSesttings(const QString& organization,
const QString& application,
QObject* parent)
: QSettings(organization,
application,
parent)
{
this->setDefaultFormat(QSettings::NativeFormat);
this->ueSetConfigurationFilePath(UePOSSesttings::ueSearchConfigurationFile());
this->ueParseData(this->ueConfigurationFilePath());
}
UePOSSesttings::UePOSSesttings(const QString& fileName,
Format format,
QObject* parent)
: QSettings(fileName,
format,
parent)
{
this->ueSetConfigurationFilePath(fileName);
this->ueParseData(this->ueConfigurationFilePath());
}
UePOSSesttings::~UePOSSesttings()
{
}
QString UePOSSesttings::ueSearchConfigurationFile()
{
QDirIterator dirIterator("/home",
QStringList() << UeDefaults::UeApplication::APPLICATION_SETTINGS_FILE,
QDir::Files,
QDirIterator::Subdirectories);
while(dirIterator.hasNext())
{
dirIterator.next();
if(dirIterator.fileName()==UeDefaults::UeApplication::APPLICATION_SETTINGS_FILE)
{
return dirIterator.filePath();
} // if
} // while
return dirIterator.filePath();
}
QString UePOSSesttings::ueReadDbDriver() const
{
return this->value(UeDefaults::UeDbKeys::KEY_DB_DRIVER).toString();
}
QString UePOSSesttings::ueReadDbPassword() const
{
return this->value(UeDefaults::UeDbKeys::KEY_DB_PASSWORD).toString();
}
QString UePOSSesttings::ueReadDbUrl() const
{
return this->value(UeDefaults::UeDbKeys::KEY_DB_URL).toString();
}
QString UePOSSesttings::ueReadDbDriverLib() const
{
return this->value(UeDefaults::UeDbKeys::KEY_DB_DRIVER_LIB).toString();
}
QString UePOSSesttings::ueReadDbEngine() const
{
return this->value(UeDefaults::UeDbKeys::KEY_DB_ENGINE).toString();
}
QString UePOSSesttings::ueReadDbUser() const
{
return this->value(UeDefaults::UeDbKeys::KEY_DB_USER).toString();
}
QString UePOSSesttings::ueReadDbHostname() const
{
int iDbHostnameIndexStart=this->ueDbUrl().indexOf("//")+2;
int iDbHostnameIndexStop=this->ueDbUrl().lastIndexOf(":");
QString strHostname=this->ueDbUrl().mid(iDbHostnameIndexStart,
(iDbHostnameIndexStop-iDbHostnameIndexStart));
return strHostname;
}
QString UePOSSesttings::ueReadDbName() const
{
int iDbNameIndexStart=this->ueDbUrl().lastIndexOf("/")+1;
int iDbNameIndexStop=this->ueDbUrl().size();
QString strDbName=this->ueDbUrl().mid(iDbNameIndexStart,
(iDbNameIndexStop-iDbNameIndexStart));
return strDbName;
}
int UePOSSesttings::ueReadDbPort() const
{
int iDbPortIndexStart=this->ueDbUrl().lastIndexOf(":")+1;
int iDbPortIndexStop=this->ueDbUrl().lastIndexOf("/");
QString strPort=this->ueDbUrl().mid(iDbPortIndexStart,
(iDbPortIndexStop-iDbPortIndexStart));
return strPort.toInt();
}
void UePOSSesttings::ueParseData(const QString& filename)
{
QFile settingsFile(filename);
QString data;
settingsFile.open(QIODevice::ReadOnly);
data=QString::fromLatin1(settingsFile.readAll().constData());
data.replace("\\:",
":");
this->ueSetParsedData(data);
int iDbUrlIndexStart=data.indexOf(UeDefaults::UeDbKeys::KEY_DB_URL);
int iDbUrlIndexStop=data.indexOf("\n",
iDbUrlIndexStart);
QString strDbUrl=data.mid(iDbUrlIndexStart,
(iDbUrlIndexStop-iDbUrlIndexStart));
this->ueSetDbUrl(strDbUrl);
settingsFile.close();
}
Now, whatever I do, I the that short method via ueRead...., for instance, ueReadUser() returns empty string. Does anyone has some idea what am I doing wrong?
I've dumped the QSettings and here is working code. Header:
#ifndef UEPOSSETTINGS_H
#define UEPOSSETTINGS_H
#include <QtCore/qglobal.h>
#include <QDirIterator>
#include <QStringList>
#include <QString>
#include <QFile>
#include <QDebug>
#include <QFile>
#include "uedefaults.h"
class UePOSSettings : public QObject
{
Q_OBJECT
private:
QString m_strSettingsFilePath;
QString m_strParsedData;
QString m_strDbUrl;
QString m_strUser;
QString m_strPassword;
QString m_strHostname;
QString m_strDbName;
int m_iDbPort;
inline void ueSetConfigurationFilePath(const QString& path)
{ this->m_strSettingsFilePath=path; }
inline QString ueParsedData() const
{ return this->m_strParsedData; }
inline void ueSetParsedData(const QString& data)
{ this->m_strParsedData=data; }
inline QString ueDbUrl() const
{ return this->m_strDbUrl; }
inline void ueSetDbUrl(const QString& dbUrl)
{ this->m_strDbUrl=dbUrl; }
inline void ueSetDbUser(const QString& dbUser)
{ this->m_strUser=dbUser; }
inline void ueSetDbPassword(const QString& dbPassword)
{ this->m_strPassword=dbPassword; }
inline void ueSetDbHostname(const QString& dbHostname)
{ this->m_strHostname=dbHostname; }
inline void ueSetDbName(const QString& dbName)
{ this->m_strDbName=dbName; }
inline void ueSetDbPort(const int& dbPort)
{ this->m_iDbPort=dbPort; }
void ueParseData(const QString& filename);
public:
explicit UePOSSettings(QObject *parent = 0);
~UePOSSettings();
Q_INVOKABLE static QString ueSearchConfigurationFile();
inline QString ueConfigurationFilePath() const
{ return this->m_strSettingsFilePath; }
Q_INVOKABLE inline QString ueDbUser() const
{ return this->m_strUser; }
Q_INVOKABLE inline QString ueDbPassword() const
{ return this->m_strPassword; }
Q_INVOKABLE inline QString ueDbHostname() const
{ return this->m_strHostname; }
Q_INVOKABLE inline QString ueDbName() const
{ return this->m_strDbName; }
Q_INVOKABLE inline int ueDbPort() const
{ return this->m_iDbPort; }
};
#endif // UEPOSSETTINGS_H
Implementation:
#include "uepossettings.h"
UePOSSettings::UePOSSettings(QObject *parent)
: QObject(parent)
{
this->ueSetConfigurationFilePath(UePOSSettings::ueSearchConfigurationFile());
this->ueParseData(this->ueConfigurationFilePath());
} // default constructor
UePOSSettings::~UePOSSettings()
{
} // destructor
QString UePOSSettings::ueSearchConfigurationFile()
{
QDirIterator dirIterator("/home",
QStringList() << UeDefaults::UeApplication::APPLICATION_SETTINGS_FILE,
QDir::Files,
QDirIterator::Subdirectories);
while(dirIterator.hasNext())
{
dirIterator.next();
if(dirIterator.fileName()==UeDefaults::UeApplication::APPLICATION_SETTINGS_FILE)
{
return dirIterator.filePath();
} // if
} // while
return dirIterator.filePath();
} // ueSearchConfigurationFile
void UePOSSettings::ueParseData(const QString& filename)
{
QFile settingsFile(filename);
QString data;
settingsFile.open(QIODevice::ReadOnly);
data=QString::fromLatin1(settingsFile.readAll().constData());
data.replace("\\:",
":");
this->ueSetParsedData(data);
int iDbUrlIndexStart=data.indexOf(UeDefaults::UeDbKeys::KEY_DB_URL);
int iDbUrlIndexStop=data.indexOf("\n",
iDbUrlIndexStart);
QString strDbUrl=data.mid(iDbUrlIndexStart,
(iDbUrlIndexStop-iDbUrlIndexStart));
this->ueSetDbUrl(strDbUrl);
int iDbHostnameIndexStart=this->ueDbUrl().indexOf("//")+2;
int iDbHostnameIndexStop=this->ueDbUrl().lastIndexOf(":");
this->ueSetDbHostname(this->ueDbUrl().mid(iDbHostnameIndexStart,
(iDbHostnameIndexStop-iDbHostnameIndexStart)));
int iDbNameIndexStart=this->ueDbUrl().lastIndexOf("/")+1;
int iDbNameIndexStop=this->ueDbUrl().size();
this->ueSetDbName(this->ueDbUrl().mid(iDbNameIndexStart,
(iDbNameIndexStop-iDbNameIndexStart)));
int iDbPortIndexStart=this->ueDbUrl().lastIndexOf(":")+1;
int iDbPortIndexStop=this->ueDbUrl().lastIndexOf("/");
QString strPort=this->ueDbUrl().mid(iDbPortIndexStart,
(iDbPortIndexStop-iDbPortIndexStart));
this->ueSetDbPort(strPort.toInt());
int iDbUserIndexStart=data.indexOf(UeDefaults::UeDbKeys::KEY_DB_USER)+UeDefaults::UeDbKeys::KEY_DB_USER.length()+1;
int iDbUserIndexStop=data.indexOf("\n",
iDbUserIndexStart);
this->ueSetDbUser(data.mid(iDbUserIndexStart,
(iDbUserIndexStop-iDbUserIndexStart)));
int iDbPasswordIndexStart=data.indexOf(UeDefaults::UeDbKeys::KEY_DB_PASSWORD)+UeDefaults::UeDbKeys::KEY_DB_PASSWORD.length()+1;
int iDbPasswordIndexStop=data.indexOf("\n",
iDbPasswordIndexStart);
QString test=data.mid(iDbPasswordIndexStart,
iDbPasswordIndexStop);
this->ueSetDbPassword(data.mid(iDbPasswordIndexStart,
(iDbPasswordIndexStop-iDbPasswordIndexStart)));
settingsFile.close();
} // ueParseData

QThreadPool : Qt::QueuedConnection fails

I have a C++ Qt program that uses QThreadPool to process files in no more than MAX_THREAD_COUNT threads. And I'm having troubles with Qt::QueuedConnection. It looks like signals got lost. But with Qt::DirectConnection it works pretty perfect.
I'd be thankful if someone will explain what's going on.
UPDATE: This code works well in Qt, but not in Visual Studio 2005. In VS it stops after the first thread finished (but works with Qt::DirectConnection)
That's how it looks:
Manager.h:
#ifndef MANAGER_H
#define MANAGER_H
#include <QObject>
#include <QThreadPool>
#include <QDebug>
#include "threadbody.h"
class Manager : public QObject
{
Q_OBJECT
private:
QList<QString> processedfiles;
QList<QString> resultfiles;
bool ok;
QString lasterror;
public slots:
void addToProcessedFiles(const QString& filename);
void addToResultFiles(const QString& filename);
void setErrorMessage(const QString& message);
void startNewThread();
public:
bool startManager(const QString& firstfile);
explicit Manager(QObject *parent = 0);
~Manager();
};
#endif // MANAGER_H
ThreadBody.h:
#ifndef THREADBODY_H
#define THREADBODY_H
#include <QTemporaryFile>
#include <QRunnable>
#include <QTextStream>
#define MAX_THREAD_COUNT 4
class ThreadBody : public QObject, public QRunnable
{
Q_OBJECT
private:
QString filename;
public:
ThreadBody(const QString& filename);
~ThreadBody();
void run();
signals:
void sendResult(const QString& filename);
void sendFileName(const QString& filename);
void taskDone();
void threadError(const QString& message);
};
#endif // THREADBODY_H
Manager.cpp:
Manager::Manager(QObject *parent) :
QObject(parent)
{
ok=true;
QThreadPool::globalInstance()->setMaxThreadCount(MAX_THREAD_COUNT);
}
void Manager::addToProcessedFiles(const QString& filename)
{
processedfiles.push_back(filename);
if(QThreadPool::globalInstance()->activeThreadCount()<MAX_THREAD_COUNT)
startNewThread();
}
void Manager::addToResultFiles(const QString& filename)
{
resultfiles.push_back(filename);
}
void Manager::setErrorMessage(const QString& message)
{
ok=false;
lasterror=message;
}
void Manager::startNewThread()
{
if(processedfiles.isEmpty())
return;
if(!ok)
return;
QString filename=processedfiles.takeFirst();
ThreadBody* task=new ThreadBody(filename);
connect(task,SIGNAL(taskDone()),this,SLOT(startNewThread()),Qt::QueuedConnection);
connect(task,SIGNAL(sendResult(const QString&)),this,SLOT(addToResultFiles(const QString&)),Qt::QueuedConnection);
connect(task,SIGNAL(sendFileName(const QString&)),this,SLOT(addToProcessedFiles(const QString&)),Qt::QueuedConnection);
connect(task,SIGNAL(threadError(const QString&)),this,SLOT(setErrorMessage(const QString&)),Qt::QueuedConnection);
qDebug()<<"thread starts";
QThreadPool::globalInstance()->start(task);
}
bool Manager::startManager(const QString& firstfile)
{
processedfiles.push_back(firstfile);
startNewThread();
QThreadPool::globalInstance()->waitForDone();
return ok;
}
Manager::~Manager(){}
ThreadBody.cpp:
#include "threadbody.h"
#include <QThreadPool>
ThreadBody::ThreadBody(const QString& filename)
{
this->filename=filename;
}
ThreadBody::~ThreadBody(){}
void ThreadBody::run()
{
QFile file(filename);
if(!file.open(QIODevice::ReadOnly))
{
QString message=QString("Thread can't open file=%1: %2").arg(filename).arg(file.errorString());
emit threadError(message);
emit taskDone();
return;
}
QTextStream in(&file);
QTemporaryFile newProcessedFile;
newProcessedFile.setAutoRemove(false);
if(!newProcessedFile.open())
{
QString message="Thread can't open temporary file";
emit threadError(message);
emit taskDone();
return;
}
QTextStream out(&newProcessedFile);
QTemporaryFile resultFile;
resultFile.setAutoRemove(false);
if(!resultFile.open())
{
QString message="Thread can't open temporary file";
emit threadError(message);
emit taskDone();
return;
}
QTextStream resultOut(&resultFile);
while(!in.atEnd())
{
//!---time consuming task---!//
//example//
QString currentLine=in.readLine();
out<<currentLine;
resultOut<<currentLine;
}
resultFile.close();
newProcessedFile.close();
file.remove();
emit sendResult(resultFile.fileName());
emit sendFileName(newProcessedFile.fileName());
emit taskDone();
}
main.cpp:
#include <QCoreApplication>
#include "manager.h"
int main(int argc, char *argv[])
{
QCoreApplication a(argc, argv);
Manager manager;
QString filename="C:/airtest/ask.cpp";
manager.startManager(filename);
return a.exec();
}

Failure to build multi-widget QtDesigner plugin

I am attempting to create a single DLL "CustomPlugins" that contains two QtDesigner plugins. By replicating the WorldClockPlugin example I am able to get each of the plugins to work individually. However when I attempt to include both of them in a single DLL, I get the following build error:
LNK2005: _qt_plugin_instance already defined in moc_qledplugin.obj
It appears to me that by causing my plugin wrapper widgets to both inherit QDesignerCustomWidgetInterface it is resulting a multiple definition of the _qt_plugin_instance function. I've looked through the moc files and the customwidget header file (included by QDesignerCustomWidgetInterface) but cannot find any reference to this function.
QDesignerExportWidget is included in both of the plugin headers and QDESIGNER_WIDGET_EXPORT is included in both widget declarations.
Is it simply not possible to wrap two plugins in the same DLL? Or am I missing something?
Thank you.
Following is the code. qdragabletoolboxplugin.* files (not shown) are nearly identical to the qledplugin* files. Furthermore, qdragabletoolbox (also not shown) is declared in the same way as qled but obviously does something very different. For the sake of saving space I've left off those files and replaced some of the function definitions with ellipses.
.pro file:
QT += widgets designer
QMAKE_LFLAGS += /INCREMENTAL:NO
TARGET = $$qtLibraryTarget($$TARGET)
CONFIG += plugin
TEMPLATE = lib
target.path = $$[QT_INSTALL_PLUGINS]/designer
INSTALLS += target
HEADERS = qled.h \
qledplugin.h \
qdragabletoolbox.h \
qdragabletoolboxplugin.h
SOURCES = qled.cpp \
qledplugin.cpp \
qdragabletoolbox.cpp \
qdragabletoolboxplugin.cpp
RESOURCES += CustomDesignerPlugins.qrc
qled.h:
#ifndef QLED_H
#define QLED_H
#include <QWidget>
#include <QPaintEvent>
#include <QPainter>
#include <QList>
#include <QColor>
#include <QGradient>
#include <QtDesigner/QDesignerExportWidget>
class QDESIGNER_WIDGET_EXPORT QLED : public QWidget
{
Q_OBJECT
Q_ENUMS(ledColor)
Q_ENUMS(ledShape)
Q_PROPERTY(ledColor offColor READ offColor WRITE setOffColor)
Q_PROPERTY(ledColor onColor READ onColor WRITE setOnColor)
Q_PROPERTY(bool shadow READ shadow WRITE setShadow)
Q_PROPERTY(ledShape shape READ shape WRITE setShape)
Q_PROPERTY(bool value READ value WRITE setValue)
public:
enum ledColor { Red = 0, Orange, Yellow, Green, Blue, Indigo, Violet, Black, Gray, DarkGray };
enum ledShape { Ellipse = 0, Rectangle, Circle, Square };
explicit QLED(QWidget *parent = NULL);
virtual ~QLED() { /*empty*/ }
bool value() const { return mValue; }
ledColor onColor() const { return mOnColor; }
ledColor offColor() const { return mOffColor; }
ledShape shape() const { return mShape; }
bool shadow() const { return mShadow; }
signals:
public slots:
void setValue(bool value) { mValue = value; update(); }
void setShape(ledShape shape) { mShape = shape; update(); }
void setOnColor(ledColor color) { mOnColor = color; update(); }
void setOffColor(ledColor color) { mOffColor = color; update(); }
void setShadow(bool b) { mShadow = b; update(); }
void toggle() { mValue = !mValue; update(); }
protected:
void paintEvent(QPaintEvent *event);
private:
void drawBezel(QPainter *painter);
void drawFace(QPainter *painter);
void drawShadow(QPainter *painter);
private:
bool mValue;
ledColor mOnColor;
ledColor mOffColor;
bool mBezel;
float mBezelWidth;
ledColor mBezelColor;
bool mShadow;
ledShape mShape;
QList<QColor> colors;
};
#endif
qled.cpp
#include "qled.h"
QLED::QLED(QWidget *parent)
: QWidget(parent)
{
...
}
void QLED::paintEvent(QPaintEvent *event)
{
...
}
void QLED::drawBezel(QPainter *painter)
{
...
}
void QLED::drawFace(QPainter *painter)
{
...
}
void QLED::drawShadow(QPainter *painter)
{
...
}
qledplugin.h
#ifndef QLEDPLUGIN_H
#define QLEDPLUGIN_H
#include <QDesignerCustomWidgetInterface>
class QLEDPlugin : public QObject, public QDesignerCustomWidgetInterface
{
Q_OBJECT
Q_PLUGIN_METADATA(IID "org.qt-project.Qt.QDesignerCustomWidgetInterface" FILE "qled.json")
Q_INTERFACES(QDesignerCustomWidgetInterface)
public:
QLEDPlugin(QObject *parent = 0);
bool isContainer() const;
bool isInitialized() const;
QIcon icon() const;
QString domXml() const;
QString group() const;
QString includeFile() const;
QString name() const;
QString toolTip() const;
QString whatsThis() const;
QWidget *createWidget(QWidget *parent);
void initialize(QDesignerFormEditorInterface *core);
private:
bool initialized;
};
#endif
qledplugin.cpp
#include "qled.h"
#include "qledplugin.h"
#include <QtPlugin>
QLEDPlugin::QLEDPlugin(QObject *parent)
: QObject(parent)
{
initialized = false;
}
void QLEDPlugin::initialize(QDesignerFormEditorInterface *core)
{
Q_UNUSED(core);
if (initialized)
return;
else
initialized = true;
}
bool QLEDPlugin::isInitialized() const
{
return initialized;
}
QWidget *QLEDPlugin::createWidget(QWidget *parent)
{
return new QLED(parent);
}
QString QLEDPlugin::name() const
{
return QLatin1String("QLED");
}
QString QLEDPlugin::group() const
{
return QLatin1String("Display Widgets");
}
QIcon QLEDPlugin::icon() const
{
return QIcon(QLatin1String(":/QLED/LEDIcon.png"));
}
QString QLEDPlugin::toolTip() const
{
return "Binary status indicator";
}
QString QLEDPlugin::whatsThis() const
{
return "";
}
bool QLEDPlugin::isContainer() const
{
return false;
}
QString QLEDPlugin::domXml() const
{
return "<ui language=\"c++\">\n"
" <widget class=\"QLED\" name=\"qLed\">\n"
" <property name=\"geometry\">\n"
" <rect>\n"
" <x>0</x>\n"
" <y>0</y>\n"
" <width>25</width>\n"
" <height>25</height>\n"
" </rect>\n"
" </property>\n"
" </widget>\n"
"</ui>";;
}
QString QLEDPlugin::includeFile() const
{
return QLatin1String("QtWidgets/QLED.h");
}
The compiler error message gives you all the information you need: you have two widgets, but you need just one plugin.
Instead of implementing QDesignerCustomWidgetInterface, implement QDesignerCustomWidgetCollectionInterface.