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.
Related
The project im trying to build is a media player with c++ and qt inclusion. However im failing to do this due to error , which i am not sure why or how it occurs. Please excuse me since this is my first ever project with c ++ or QT .
The Error is multiple defintions of frames for the media player which i am not sure because in header file only definitions are written and source (cpp) the code is written . I would really appreciate the help , thank you everyone for taking time of your day to help means a lot.
Code:
playeframe.h
#include <QAbstractVideoSurface>
#include <QImage>
#include <QVideoFrame>
#include <QLabel>
class PlayerFrame : public QAbstractVideoSurface
{
Q_OBJECT
public:
PlayerFrame(QObject *parent = nullptr);
void stopVideo();
Q_SIGNALS:
void fnSurfaceStopped(QPixmap pix);
private slots:
void fnClearPixmap();
private:
QPixmap CapImage;
QImage::Format imgFormat;
QVideoFrame curFrame;
bool Videostart(const QVideoSurfaceFormat &format);
QList<QVideoFrame::PixelFormat> supportedPixelFormats(QAbstractVideoBuffer::HandleType handleType) const;
bool isFormatSupported(const QVideoSurfaceFormat &format) const;
bool present(const QVideoFrame &frame);
};
#endif
playerframe.cpp
#include "playerframe.h"
#include <QtWidgets>
#include <qvideosurfaceformat.h>
#include "playerwindow.h"
PlayerFrame::PlayerFrame(QObject *parent)
: QAbstractVideoSurface(parent)
, imgFormat(QImage::Format_Invalid)
{
}
bool PlayerFrame::Videostart(const QVideoSurfaceFormat &format)
{
QImage::Format imageFormat = QVideoFrame::imageFormatFromPixelFormat(format.pixelFormat());
QSize size = format.frameSize();
if (imageFormat != QImage::Format_Invalid && !size.isEmpty())
{
this->imgFormat = imageFormat;
QAbstractVideoSurface::start(format);
return true;
}
else return false;
}
void PlayerFrame::fnClearPixmap()
{
CapImage = QPixmap();
}
void PlayerFrame::stopVideo()
{
QAbstractVideoSurface::stop();
}
QList<QVideoFrame::PixelFormat> PlayerFrame::supportedPixelFormats(QAbstractVideoBuffer::HandleType handleType) const
{
if (handleType == QAbstractVideoBuffer::NoHandle) {
return QList<QVideoFrame::PixelFormat>()
<< QVideoFrame::Format_RGB32
<< QVideoFrame::Format_ARGB32
<< QVideoFrame::Format_ARGB32_Premultiplied
<< QVideoFrame::Format_RGB565
<< QVideoFrame::Format_RGB555;
}
else
{
return QList<QVideoFrame::PixelFormat>();
}
}
bool PlayerFrame::isFormatSupported(const QVideoSurfaceFormat &format) const
{
QImage::Format imageFormat = QVideoFrame::imageFormatFromPixelFormat(format.pixelFormat());
QSize size = format.frameSize();
return imageFormat != QImage::Format_Invalid && !size.isEmpty() && format.handleType() == QAbstractVideoBuffer::NoHandle;
}
bool PlayerFrame::present(const QVideoFrame &frame)
{
if (surfaceFormat().pixelFormat() != frame.pixelFormat() || surfaceFormat().frameSize() != frame.size())
{
setError(IncorrectFormatError);
stop();
return false;
}
else
{
if (!CapImage.isNull())
{
fnSurfaceStopped(CapImage);
}
curFrame = frame;
if (curFrame.map(QAbstractVideoBuffer::ReadOnly))
{
QImage image(
curFrame.bits(),
curFrame.width(),
curFrame.height(),
curFrame.bytesPerLine(),
imgFormat);
if (CapImage.isNull())
{
CapImage = QPixmap::fromImage(image.copy(image.rect()));
}
curFrame.unmap();
}
return true;
}
}
The problem I'm having has been discussed multiple times, but I still don't understand how to fix the issue I'm having. I used to program in C++ a lot but switched over to Java for a while due to work. I'm getting back into C++ and I'm now having a lot of issues with memory management/pointers/references etc. This problem stems from that.
For context, these are files for a Qt 5.14 project that I'm working on.
The problem is that I have a private class variable named loggerLevel and the method that creates the segmentation fault error is getLevel which just returns the value of the loggerLevel. The that is supposed to be stored in the variable is an enum named Level that is defined in the header of the class.
I don't know if the problem stems from my lack of knowledge or if I am misunderstanding something about how classes work in C++, or if its something completely different. In any case, if anyone can help me out that would be great :)
--- Source code below ---
logger.cpp
#include "logger.h"
QString debugHTML = "<font color=\"gray\">";
QString infoHTML = "<font color=\"black\">";
QString warningHTML = "<font color=\"yellow\">";
QString errorHTML = "<font color=\"orange\">";
QString criticalHTML = "<font color=\"red\">";
QString endHTML = "</font><br>";
Logger::Logger(QObject *parent,
QString fileName,
QTextEdit *editor) : QObject(parent)
{
m_editor = editor;
m_showDate = true;
loggerLevel = Level::INFO;
if (!fileName.isEmpty()) {
file = new QFile;
file->setFileName(fileName);
file->open(QIODevice::Append | QIODevice::Text);
}
}
void Logger::write(const QString &value) {
QString text = value;
if (m_showDate) {
text = QDateTime::currentDateTime()
/*.toString("dd.MM.yyyy hh:mm:ss ") + text;*/
.toString("hh:mm:ss: ") + text;
}
QTextStream out(file);
out.setCodec("UTF-8");
if (file != 0) {
out << text;
} else {
//TODO: add QMessageBox here with error
}
//Adds HTML color/formatting
switch(loggerLevel)
{
case DEBUG: text = debugHTML + text; break;
case INFO: text = infoHTML + text; break;
case WARNING: text = warningHTML + text; break;
case ERROR: text = errorHTML + text; break;
case CRITICAL: text = criticalHTML + text; break;
default: text = infoHTML + text; break;
}
text = text + endHTML;
if (m_editor != 0) {
m_editor->insertHtml(text);
} else {
//TODO: add QMessageBox here with error
}
}
void Logger::write(const Level &level, const QString &value) {
Level prevLoggerLevel = Logger::getLevel();
Logger::setLevel(level);
write(value);
Logger::setLevel(prevLoggerLevel);
}
//--------Setters--------
void Logger::setLevel(const Level &level) {
loggerLevel = level;
}
void Logger::setShowDateTime(bool value) {
m_showDate = value;
}
//--------Getters--------
Logger::Level Logger::getLevel() {
return loggerLevel;
}
Logger::~Logger() {
if (file != 0) {
file->close();
}
}
logger.h
#ifndef LOGGER_H
#define LOGGER_H
#include <QObject>
#include <QPlainTextEdit>
#include <QFile>
#include <QTextStream>
#include <QDateTime>
class Logger : public QObject
{
Q_OBJECT
public:
explicit Logger(QObject *parent,
QString fileName = 0,
QTextEdit *editor = 0);
~Logger();
void setShowDateTime(bool value);
enum Level
{
DEBUG,
INFO,
WARNING,
ERROR,
CRITICAL
};
private:
QFile *file;
QTextEdit *m_editor;
bool m_showDate;
Level loggerLevel;
signals:
public slots:
void write(const QString &value);
void write(const Level &level, const QString &value);
void setLevel(const Level &level);
Level getLevel();
};
#endif // LOGGER_H
MainWindow.cpp
#include <string>
#include "mainwindow.h"
#include "ui_mainwindow.h"
#include "settingsdialog.h"
#include "logger.h"
Logger *logger;
MainWindow::MainWindow(QWidget *parent)
: QMainWindow(parent)
, ui(new Ui::MainWindow)
{
ui->setupUi(this);
QString logFileName = "log.txt";
Logger *logger = new Logger(this, logFileName, ui->loggerOutput);
logger->write(Logger::Level::INFO, "Logger Initilized!");
}
MainWindow::~MainWindow()
{
delete ui;
}
void MainWindow::on_toolButton_clicked()
{
SettingsDialog settingsDialog;
settingsDialog.setModal(true);
settingsDialog.exec();
}
//Left Side of controller
void MainWindow::on_s_leftJoystickX_Throttle_sliderMoved(int position)
{ ui->l_leftJoystickX->setText(QStringLiteral("X-Axis: %1%").arg(position)); }
void MainWindow::on_s_leftJoystickY_Throttle_sliderMoved(int position)
{ ui->l_leftJoystickY->setText(QStringLiteral("Y-Axis: %1%").arg(position)); }
void MainWindow::on_s_leftTrigger_Throttle_sliderMoved(int position)
{ ui->l_leftTrigger->setText(QStringLiteral("Trigger: %1%").arg(position)); }
void MainWindow::on_s_joystickThrottle_sliderMoved(int position)
{ ui->l_joystickThrottle->setText(QStringLiteral("Throttle: %1%").arg(position)); }
//Right Side of controller
void MainWindow::on_s_rightJoystickX_Throttle_sliderMoved(int position)
{ ui->l_rightJoystickX->setText(QStringLiteral("X-Axis: %1%").arg(position)); }
void MainWindow::on_s_rightJoystickY_Throttle_sliderMoved(int position)
{ ui->l_rightJoystickY->setText(QStringLiteral("Y-Axis: %1%").arg(position)); }
void MainWindow::on_s_rightTrigger_Throttle_sliderMoved(int position)
{ ui->l_rightTrigger->setText(QStringLiteral("Trigger: %1%").arg(position)); }
void MainWindow::on_s_keyboardThrottle_sliderMoved(int position)
{ ui->l_keyboardThrottle->setText(QStringLiteral("Throttle: %1%").arg(position)); }
void MainWindow::on_b_keyboardAction_1_clicked()
{
logger->write(Logger::Level::CRITICAL, "test");
}
There are more files, but I believe they are not relevant to the problem, if needed I can post the other files aswell.
-----Solution!-----
#churill Solution explains what needs to be done to fix this problem but I also will detail it below to complete this question.
Since I had already made a forward declaration of logger
Logger *logger
at the top of MainWindow.cpp, creating a new Logger object
Logger *logger = new Logger(this, logFileName, ui->loggerOutput);
is unnecessary so calling the forward declarations variable name instead of creating a new Logger object
logger = new Logger(this, logFileName, ui->loggerOutput);
fixes the problem!
From first glance:
Logger *logger = new Logger(this, logFileName, ui->loggerOutput);
creates an object that has nothing to do with the global variable logger which is never initialized. Maybe you meant to write only
logger = new Logger(this, logFileName, ui->loggerOutput);
to initialize this global variable.
To somewhat address the title of your question: Yes you actually can call functions on invalid pointers, but then the this-pointer is not valid, thus accessing a member variable causes the seg-fault.
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
I'm using QGraphicView to show game map that consist QGraphicsPixmapItems. I need to show tooltip on mouse hover at QGraphicsPixmapItem.
For saving QGraphicsPixmapItem position I using MazeItem:
#ifndef MAZEITEM_H
#define MAZEITEM_H
#include <QPoint>
#include <QGraphicsItem>
class MazeItem
{
private:
QPoint myPosition;
QString myToolTip;
public:
MazeItem();
QPoint position() const;
QString toolTip() const;
void setToolTip(const QString &toolTip);
void setPosition(const QPoint &position);
QPoint getPosition();
QGraphicsPixmapItem * pixmap;
};
#endif // MAZEITEM_H
I have widget class to display game map:
#include <QWidget>
#include <QtGui>
#include <QGraphicsView>
#include <QToolTip>
#include "mazeitem.h"
class MazeGUI : public QWidget
{
Q_OBJECT
private:
QGraphicsView * graphicsView;
QGraphicsScene * graphicsScene;
QString sceneString;
int imageSize;
QList<MazeItem> mazeItems;
void addItem(int x, int y, QPixmap picture);
bool event(QEvent *event);
int itemAt(const QPoint &pos);
public:
explicit MazeGUI(QWidget *parent = 0);
void setScene(QString sceneString);
signals:
public slots:
void redraw();
};
#endif // MAZEGUI_H
In constructor I set mouse tracking.
MazeGUI::MazeGUI(QWidget *parent) :
QWidget(parent)
{
setMouseTracking(true);
...
}
This is how I add new maze item.
void MazeGUI::addItem(int x, int y, QPixmap picture)
{
MazeItem mazeItem;
mazeItem.setPosition(QPoint(x, y));
mazeItem.setToolTip("text");
mazeItem.pixmap = this->graphicsScene->addPixmap(picture);
mazeItem.pixmap->setPos(y, x);
mazeItems.append(mazeItem);
}
And this I have from Qt tutorials,
bool MazeGUI::event(QEvent *event)
{
if (event->type() == QEvent::ToolTip) {
// HERE - it never goes here!!
QHelpEvent *helpEvent = static_cast<QHelpEvent *>(event);
int index = itemAt(helpEvent->pos());
if (index != -1) {
QToolTip::showText(helpEvent->globalPos(), mazeItems[index].toolTip());
} else {
QToolTip::hideText();
event->ignore();
}
return true;
}
return QWidget::event(event);
}
int MazeGUI::itemAt(const QPoint &pos)
{
for (int i=0; i < mazeItems.size(); ++i)
{
if (mazeItems[i].getPosition() == pos)
return i;
}
return -1;
}
Was adding the tooltip on wrong object:
Instead of:
mazeItem.setToolTip("text");
It should be:
mazeItem.pixmap->setToolTip("text");
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