Setting a QTextStream declared in header to stdout - c++

I am going crazy here and I promise that I have looked at the documentation.
I declare a QTextStream as a member variable in my header file, but in my constructor, I want to set it to go to stdout in my constructor.....but I can't get the syntax right to let me do it!
All I want to do is this:
QTextStream m_text_out;
m_text_out = QTextStream(stdout)........
Any help would be great!

Use an initializer list.
class MyClass {
public:
MyClass();
private:
QTextStream m_text_out;
}
MyClass::MyClass() : m_text_out(stdout) {
}

Related

How to initialize QXmlStreamWriter with QString as member variable?

I have implemented my own xml writer to generate xml as QString.
i have create a class "MyXmlWriter" with private member variable as QXmlStreamWriter and try to initialize it in the public method writeToString()
in declaration header file:
class MyXmlWriter {
public:
MyXmlWriter();
~MyXmlWriter();
QString writeToString();
private:
QXmlStreamWriter writer;
void writePart();
}
in cpp file:
void MyXmlWriter::writePart() {
// i want to use the QXmlStreamWriter instance hier
}
QString MyXmlWriter::writeToString(){
QString result;
writer(&result); // at this became the error: no match for call to '(QXmlStreamWriter) (QString*)'
xmlWriter.setAutoFormatting(true);
// private method called
writePart();
return result;
}
this error appear on build:
error: no match for call to (QXmlStreamWriter) (QString) writer(&result); *
If the QXmlStreamWriter write is declared in the local method writeToString() then i cant access this writer in private method writePart()
i want to use the member variable "writer" in other methods that's why a local declaration isn't an option for me.
You have to assign a new object to your variable writer, like this:
QString MyXmlWriter::writeToString() {
QString result;
writer = QXmlStreamWriter(&result); // will not compile
return result;
}
This code is dangerous. result is destroyed at the end of writeToString(), so writer then contains invalid data and you cannot use it anymore.
Additionally, QXmlStreamWriter cannot be copied, so this would probably not compile at all. It's better to just pass the QXmlStreamWriter to your methods, like this:
class MyXmlWriter {
public:
MyXmlWriter();
~MyXmlWriter();
QString writeToString();
private:
void writePart(QXmlStreamWriter &writer);
}
and
QString MyXmlWriter::writeToString() {
QString result;
QXmlStreamWriter writer(&result);
writePart(writer);
writePart(writer);
return result;
}

Using Q_Property to display properties

I have a GUI displaying a tree architecture as shown here.
Each of those nodes are separate classes that are derived from the node above them. All of them inherit QObject for their implementation.
Now I need to add a few properties to be displayed when the user selects Properties under the Right-Click menu of Implicit. Selecting this opens a window with the properties.
I added these properties in the header file of Implicit like so :
#ifndef FCIMPLICIT_H
#define FCIMPLICIT_H
#include <QObject>
#include "Interface.h"
#include "ResourceItem.h"
#include "MonWindow.h"
#include "FCTab.h"
#include "ResourceItem.h"
#include "FCAbstract.h"
#include "FCInterface.h"
#include "FCConnections.h"
class CFCImplicit: public CResourceItem
{
Q_OBJECT
Q_PROPERTY(int FCPortID READ getPortID )
Q_PROPERTY(QString Type READ getType )
Q_PROPERTY(QString Status READ getStat )
Q_PROPERTY(int WWNodeNumber READ getNodeNo )
Q_PROPERTY(int WWPortNumber READ getPortNo )
Q_PROPERTY(bool AutoActive READ getAuto )
public:
CFCImplicit(QObject*);
~CFCImplicit();
QString getType();
QString getStat();
int getPortID();
int getPortNo();
int getNodeNo();
bool getAuto();
};
FCinterface.h is the header of the FCASM node.
The issue is that only the first property is displayed, as seen in the second picture. Is there a reason why this is happening? Am I supposed to add something to the constructor or a new function?
The constructor for the Implicit class is
CFCImplicit::CFCImplicit(QObject* parent) : CResourceItem(parent)
{
fnSetProperty("objectName", QString("Implicit"));
((CResourceItem*)parent)->fnAddResources(this);
}
EDIT:
This is the code for all the READ functions
QString CFCImplicit::getType()
{
QString a;
a="Implicit";
return a;
}
QString CFCImplicit::getStat()
{QString a;
a="Idle";
return a;}
int CFCImplicit::getPortID()
{int a;
a=1;
return a;}
int CFCImplicit::getPortNo()
{int a;
a=2;
return a;}
int CFCImplicit::getNodeNo()
{int a;
a=2;
return a;}
bool CFCImplicit::getAuto()
{bool a;
a=true;
return a;}
I found out what I was doing wrong. I assumed that since the properties were read only, I only needed a READ accessor function. By adding the WRITE accessor and adding the required WRITE functions, the properties were displayed. I don't exactly understand why this condition is required (maybe having just READ just makes the properties available for introspection), but it worked! So there you go.
Happy coding everyone!
No need to add the READ and the function, you can use the MEMBER to have direct access to the variable.

QFile init/assignment op issue when objects are class members

So i have a QFile and QTextStream member as part of my class... trying to init. them together in my constructor:
Class.h:
QFile _file;
QTextStream _textstrm;
Class.cpp:
_file = QFile (/*file name*/);
_file.open(/*set stuff*/);
_textstrm = QTextTream ( &_file );
And the comp error i get, C2248, says the objects to have access to the operators in their own class..
The problem is that you are creating a new object and you are adding an attribute that has no access, you must use the functions provided by the object.
_file.setFileName(/*file name*/);
_file.open(/*set stuff*/);
_textstrm.setDevice( &_file );

C++ Calling a getter method when it is not ready

I'm working on a project and it works but it is really messy so I am trying to clean it up by moving things around.
Here is a short version of the class containing the getter method
Link::Link
{
jsonUrl = QUrl("www.example.json");
QNetworkAccessManager *nam = new QNetworkAccessManager(this);
connect(nam,SIGNAL(finished(QNetworkReply*)),this,SLOT(downloadFinished(QNetworkReply*)));
QNetworkRequest request(jsonUrl);
nam->get(request)
}
void Link::downloadFinished(QNetworkReply *reply)
{
jsonArray = reply->readAll();
jsonStuff();
}
void Link::jsonStuff()
{
//does a bunch of json stuff then gets a string
string = map["url"].toString();
}
QString Link::getString()
{
return string;
}
Here is a short version of the class that calls the getter in the constructor
Header
class Commands
{
private:
Link link;
}
Source inside the constructor
Commands::Commands()
{
addCommand("!test", link.getString());
}
The problem is when I try to do it like this, I think the Commands constructor runs first and the string from the Link class is not ready yet so the string that comes out of link.getString() is empty. Is there a way to wait until the Link class finishes doing it's stuff and fills up the string before calling link.getString() inside the constructor of Commands? Not sure if this matters but most of my code is written in Qt
I hope you guys can understand what I'm trying to ask. My terminology is really poor.
Edit: Added more to my Link class
When the constructor of Commands (in this case Commands()) is called firstly it creates all variables(they are unintialized) in Commands class. That being said link is created via Link(). What you might want to do is to use jsonStuff() in the Link() constructor (it creates all member variables as well as), NOTE THAT it creates variables in this case it creates string with base costructor - it creates empty string.) Try following to fill the string:
Link() {
jsonStuff(); // string will be set
}
Or you can initialize it via initialization section:
Link() : string("Text") { }
Also you might want to return reference to string from getString() function. Reference means it doesn't create additional copy and it returns string which is stored in Link, so you can change string in a function where getString() is called. Also if it is read only you should use const reference.
Is there a way to wait until the Link class finishes doing it's stuff and fills up the string before calling link.getString() inside the constructor of Commands?
Certainly. The Link class must be a QObject that emits a signal when it has changed its properties - presumably based on the replies it got to its network request.
class Link : public QObject {
Q_OBJECT
Q_PROPERTY(QString string READ string WRITE setString NOTIFY stringChanged)
QString m_string;
public:
void jsonStuff() {
...
connect(reply, &QNetworkReply::finished, this, [this]{
...
setString(map["url"].toString());
});
}
void setString(const QString &s) {
if (m_string == s) return;
m_string = s;
emit stringChanged(m_string);
}
QString string() const { return m_string; }
Q_SIGNAL void stringChanged(const QString &);
};
You can then add the command when the link is ready:
Commands::Commands()
{
connect(&link, &Link::stringChanged, this, [this](const QString &string){
if (!string.isEmpty()) addCommand("!test", string);
});
}

Qt: Pass variables from ClassA to ClassB via Class C

I have the following layout:
MainWindow <--------- Settings
\
\
V
PerformOps
MainWindow takes in variables passed from Settings, and passes them on to PerformOps.
If the Settings class is not used, MainWindow passed on defaults to PerformOps.
Currently I do:
class Settings{
public:
Settings(*parent);
var1, var2, var3
.
.
void exec();
}
class PerformOps{
public:
PerformOps();
var1, var2, var3;
.
.
void start();
}
class MainWindow{
private:
Settings *set; //share pointers over all methods
PerformOps *op;
bool settings_not_clicked = false;
void saveChanges()
{
QSettings settings("my","app");
settings.setValue("value1", op->var1);
settings.setValue("value2", op->var2);
settings.setValue("value3", op->var3);
}
void loadChanges()
{
QSettings settings("my","app");
op->var1 = settings.value("value1");
op->var2 = settings.value("value2");
op->var3 = settings.value("value3");
}
void closeEvent(QCloseEvent *event)
{
event->ignore();
saveChanges();
event->accept();
}
void takeDataAndDoStuff() //This is always called
{
op = new PerformOps;
if(settings_not_clicked) {
loadChanges()
}
else {
op->var1 = 33;
op->var2 = "Geronimo!";
op->var3 = true;
}
op->start();
}
void getStuff_maybe_if_clicked() //This might not be always called
{
Settings *set = new Settings(this);
set->exec() //Pause parent, run Settings
settings_not_clicked = false;
}
Question: Is there a cleaner way to share data across classes without resorting to the dirty method of : op->var1 = set->var1;, taking into account that the set pointer might not always be initialised?
Well, the approach itself is not that bad, however there are some things you can improve.
First of all, if I understood you correctly, you want to pass the settings if they exist, and pass the default values if they don't. In this case you can utilize the constructor:
class PerformOps
{
public:
PerformOps( int v1 = 33, string v2 = "Geronimo!", bool v3 = true ): var1(v1), var2(v2), var3(v3)
{
}
<...>
}
Now, if you call the constructor as PerformOps(), the default values will be set. If you call it and feed it some of the values, it will use them:
<...>
PerformOps *op;
if(settings_not_clicked) {
op = new PerformOps( set->var1, set->var2, set->var3 );
}
else {
op = new PerformOps();
}
<...>
of course, if you don't want to do it via the cunstructor, you could just make a function and call it like "setData()" and use the same technique with default function parameters.
Now, as for the pointers. It is a good idea to always initialize pointers with NULL, or nullptr if you have c++0x. Also, when you delete the memory, assign the pointer to NULL or nullptr again. This way you will be able to always see if the pointer is valid by a simple check.
someClass * ptr = nullptr;
<...>
ptr = new someClass();
<...>
delete ptr;
ptr = nullptr;
UPD
I would suggest you to get rid of your Settings class, and just use QSettings directly. You will not need to mess with the pointers, and reading/writing to QSettings is very fast.
Now, also don't forget that you can use QSettings from the heap:
QSettings * settings = new QSettings();
If you want each settings set to have a "parent", you could just derive your Settings class from QSettings, and just add one parent field into it. This will keep all the functionality of QSettings, which is very convenient.
Actually, your approach is fine too, all you need to do is just to check if the pointers are valid.
Ok, so the problem is "I'm setting a pointer to a pointer that may or may not exist". In such a case Null Object pattern should help. This way you should be able getting rid of if-clause
Oh hang on.
I just realized that I can use QSettings between classes (which is what SingerOfTheFall was clearly hinting at)
So from my Settings.cpp class I can do:
QSettings sett("my");
sett.begingroup("my_groupname");
sett.setValue("value1", var1);
sett.setValue("value2", var2);
sett.setValue("value3", var3);
sett.endGroup();
and I can retrieve this same information from ANY CLASS (duh!) by doing:
someRandomClass.cpp:
QSettings settings("my");
settings.beginGroup("my_groupname");
myvar1 = settings.value("value1");
myvar2 = settings.value("value2");
myvar3 = settings.value("value3");
settings.endGroup();