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
Related
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();
}
I'm using the Qt settings and it saves the object into a file. it saves to a file called sessionrc.
Now I'm trying to load the object from the settings and save it back.
The problem is I can not identify the object from the settings, so that I can load all the profiles that are saved.
I'm using the following load and save functionality
void ProfileManager::loadFrom(Settings &set, bool ownGroup)
{
qDebug()<<"LOAD";
foreach (const QString &group, set.childGroups()) {
if(group == "Profile")
{
Profile *profile = new Profile();
profile->setObjectName(group);
profile->loadFrom(set);
m_Profiles << profile;
}
}
EraObject::staticLoadFrom(set, this);
}
void ProfileManager::saveTo(Settings &set, bool ownGroup, bool force)
{
EraObject::staticSaveTo(set, this, ownGroup, force);
foreach(Profile * profile, m_Profiles) {
profile->saveTo(set);
}
}
The current setting file is
[www]
Ta=20
Te=48
Texp=38
lim1=0
lim2=0
offset=0
profilename=www
[www] is the profile that is saved. but I have many of it. How would I load it back and save it correctly
// main.cpp
#include <QCoreApplication>
#include <QSettings>
#include <QVector>
#include <QDebug>
#include <QMetaProperty>
class Profile : public QObject
{
Q_OBJECT
Q_PROPERTY(QString name READ name WRITE setName )
Q_PROPERTY(QString title READ title WRITE setTitle )
public:
explicit Profile(QObject *parent = 0) : QObject(parent) {
}
QString name() const {
return name_;
}
void setName(QString name) {
name_ = name;
}
QString title() const {
return title_;
}
void setTitle(QString title) {
title_ = title;
}
void save(QSettings& settings) const {
for(int i=0; i<metaObject()->propertyCount(); ++i) {
const auto& p = metaObject()->property(i);
if(p.isStored(this)) {
settings.setValue(p.name(), property(p.name()));
}
}
}
void load(QSettings& settings) {
for(int i=0; i<metaObject()->propertyCount(); ++i) {
const auto& p = metaObject()->property(i);
if(p.isStored(this)) {
setProperty(p.name(), settings.value(p.name()));
}
}
}
private:
QString name_;
QString title_;
};
#include "main.moc"
int main(int argc, char *argv[])
{
QCoreApplication a(argc, argv);
QObject garbageCollector;
QVector<Profile*> profiles;
{
Profile* p1 = new Profile(&garbageCollector);
p1->setName("profilename1");
p1->setTitle("Profile 1");
Profile* p2 = new Profile(&garbageCollector);
p2->setName("profilename2");
p2->setTitle("Profile 2");
profiles.append(p1);
profiles.append(p2);
}
QSettings s("profiles.ini", QSettings::IniFormat);
// write profiles
{
s.beginGroup("profiles");
foreach(const Profile*p, profiles) {
s.beginGroup(p->name());
p->save(s);
s.endGroup();
}
s.endGroup();
s.sync(); // force write
}
// read profiles
{
s.beginGroup("profiles");
foreach(const QString& g, s.childGroups()) {
Profile p;
s.beginGroup(g);
p.load(s);
s.endGroup();
qDebug() << p.name();
qDebug() << p.title();
}
s.endGroup();
}
return 0;
}
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();
}
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.
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