I have the QMap with QVector inside:
QMap<QString, QMap<QGraphicsView*, QVector<float>>> graphs;
I'm trying to execute this code:
QVector<float>* graphValues = &(graphs.values()[i - values.count()].values()[0]);
graphValues->push_back(1234);
qDebug() << "=== Debug messages ===\r\n";
qDebug() << "i - values.count() = " << i - values.count();
qDebug() << "graphValues = " << graphValues;
qDebug() << "*graphValues = " << *graphValues;
qDebug() << "graphs = " << graphs;
qDebug() << "graphs.values()[i - values.count()].values()[0] = " << graphs.values()[i - values.count()].values()[0];
It gives me output:
i - values.count() = 0
graphValues = 0x2000e90
*graphValues = QVector(1234)
graphs = QMap(("tempgraph", QMap((QGraphicsView(0x1fb1920) , QVector() ) ) ))
graphs.values()[i - values.count()].values()[0] = QVector()
So, where is my value? Using pointer i wait for my value in graphs, but it disappears.
QMap::values() method returns temporary object. You cannot change original data, by changing it. You should use iterators, or QMap::operator[] somehow.
Related
I want to insert the value of double spin box on 14th line and 19th column of my large text file. I have created loop to insert the value on 14th line, but it is just placed on first column of the line. Can anyone help me to move the value after text, parameter PW_x = ?
This is the portion of my text file.
parameter PW_x = "i want to insert value here this is 14th line and 19th column"
parameter PW_y =
parameter PD =
parameter PC =
This is my code
void MainWindow::on_doubleSpinBox_6_editingFinished()
{
QString file("D:\\my text file name");
QFile outputFile(file);
if (outputFile.open(QIODevice::ReadWrite | QIODevice::Text))
{
for (int i=0;i<13;i++) {
outputFile.readLine();
}
QTextStream stream(&outputFile);
stream << QString::number(ui->doubleSpinBox_6->value());
}
}
As I advised in my comment, you should parse->edit->save
you can for sure use other ways to insert the value in the file, like trying to match and replace the string in each line of the file (be aware that this is very inefficient..) but here an example:
in the for loop, try to replace the string "PW_x = " with the value PW_x = 'your spinbox double', the replace action will leave intact all the lines that dont match the string you are looking for...
here an example
QString l1{"parameter PW_x = " };
QString l2{"parameter PW_y = " };
QString l3{"parameter PD = " };
QString l4{"parameter PC = " };
QString doubleAsString{"3.1415"};
l1.replace("PW_x = ", "PW_x = " + doubleAsString);
l2.replace("PW_x = ", "PW_x = " + doubleAsString);
l3.replace("PW_x = ", "PW_x = " + doubleAsString);
l4.replace("PW_x = ", "PW_x = " + doubleAsString);
qDebug() << "v1: " << l1;
qDebug() << "v2: " << l2;
qDebug() << "v3: " << l3;
qDebug() << "v4: " << l4;
Consider this scenario.
I'm creating a struct(flatbuffers::Table) using CreateXXX generated code. This creates the struct on the FlatBuffer buffer and gives me the offset.
Then I can get the memory block with GetBufferPointer() and transfer it.
Reversely, if I get a memory block, I can use GetXXX to get my struct(flatbuffers::Table) from that.
But after I get this struct, if I need to serialize it again, how can I do it? After the serialization, I should be able to transfer that data and do GetXXX on that data like before.
flatbuffers::Parser parser;
parser.Parse(schema.c_str());
parser.SetRootType("license");
parser.Parse(j.c_str());
auto* buf = parser.builder_.GetBufferPointer();
auto li = flatbuffers::GetRoot<license>(buf);
std::cout << "ID: " << li->id()->c_str() << " Rand: " << li->rand()->c_str() << " Secret: " << li->secret()->c_str() << std::endl;
uint8_t* buf2 = ????????????
auto li2 = flatbuffers::GetRoot<license>(buf2);
std::cout << "ID: " << li2->id()->c_str() << " Rand: " << li2->rand()->c_str() << " Secret: " << li2->secret()->c_str() << std::endl;
The obvious answer is that you keep the original buffer pointer (and size) around. Then you can "re-serialize" it by just writing out the existing buffer.
There is a function GetBufferStartFromRootPointer if you really must use just the root (li in your example).
I have the following document in my MongoDB test database:
> db.a.find().pretty()
{
"_id" : ObjectId("5113d680732fb764c4464fdf"),
"x" : [
{
"a" : 1,
"b" : 2
},
{
"a" : 3,
"b" : 4
}
]
}
I'm trying to access and process the elements in the "x" array. However, it seems that the Mongo driver is identifying it not as an array of JSON document, but as Date type, as shown in the following code:
auto_ptr<DBClientCursor> cursor = c.query("test.a", BSONObj());
while (cursor->more()) {
BSONObj r = cursor->next();
cout << r.toString() << std::endl;
}
which output is:
{ _id: ObjectId('51138456732fb764c4464fde'), x: new Date(1360233558334) }
I'm trying to follow the documentation in http://api.mongodb.org/cplusplus and http://docs.mongodb.org/ecosystem/drivers/cpp-bson-array-examples/, but it is quite poor. I have found other examples of processing arrays, but always with simple types (e.g. array of integer), but not when the elements in the array are BSON documents themselves.
Do you have some code example of procesing arrays which elements are generic BSON elements, please?
you could use the .Array() method or the getFieldDotted() method: as in the following:
Query query = Query();
auto_ptr<DBClientCursor> cursor = myConn.query("test.a", query);
while( cursor->more() ) {
BSONObj nextObject = cursor->next();
cout << nextObject["x"].Array()[0]["a"] << endl;
cout << nextObject.getFieldDotted("x.0.a") << endl;
}
At the end, it seems that embeddedObject() method was the key:
auto_ptr<DBClientCursor> cursor = c.query("test.a", BSONObj());
while (cursor->more()) {
BSONObj r = cursor->next();
cout << "Processing JSON document: " << r.toString() << std::endl;
std::vector<BSONElement> be = r.getField("x").Array();
for (unsigned int i = 0; i<be.size(); i++) {
cout << "Processing array element: " << be[i].toString() << std::endl;
cout << " of type: " << be[i].type() << std::endl;
BSONObj bo = be[i].embeddedObject();
cout << "Processing a field: " << bo.getField("a").toString() << std::endl;
cout << "Processing b field: " << bo.getField("b").toString() << std::endl;
}
}
I was wrongly retrieving a different ObjectID and a different type (Date instead of array) becuase I was looking to a different collection :$
Sorry for the noise. I hope that the fragment above helps others to figure out how to manipulate arrays using the MongoDB C++ driver.
I have a subclass of QTableWidget with the following code:
connect(this, SIGNAL(cellChanged(int, int)), this, SLOT(pushCellChange(int, int)), Qt::QueuedConnection);
...
void MyTableView::pushCellChange(int row, int column)
{
QString text(item(row, column)->text());
QByteArray data = text.toAscii();
cout << data.length() << endl;
const char* cellData = text.toAscii().constData();
cout << "Cell ("<<row<<", "<<column<<") changed to: " << cellData << endl;
}
When I change the upper-right cell to anything this outputs:
2
Cell (0, 0) changed to: ▌▌▌▌▌▌▌▌▌▌▌▌▌▌▌▌░▬∟C▌▌
However, while this corrupt data is spewed out on the console, the table widget itself seems to behave normally and shows the correct string. Does anyone know what is going on here?
The call toAscii() is storing the QString's data to a QByteArray. In your code, you do this twice:
QByteArray data = text.toAscii();
const char* cellData = text.toAscii().constData();
_____________^ <-- temporary QByteArray
The const char* is actually pointing to the data within a temporary variable, which goes out of scope at the semicolon, at which point the pointer becomes invalid. If instead you were to make use of the local variable data, you'd be OK:
const char* cellData = data.constData();
___^ <-- still-in-scope QByteArray
Alternatively, you can do this all in-line with the cout and the data will still be valid when it is copied to the output stream:
cout << "Cell ("<<row<<","<<column<<") changed to: " << text.toAscii().constData() << endl;
std::string cellData = text.ToStdString();
cout << "Cell ("<<row<<", "<<column<<") changed to: " << cellData << endl;
That should work fine. As for why toAscii doesn't work, I have no clue.
If it's just about the console output, you could also use qDebug() (available after #include <QDebug>) and pass the QString directly:
void MyTableView::pushCellChange(int row, int column)
{
qDebug() << item(row, column)->text().length();
qDebug() << "Cell (" << row << ", " << column << ") changed to: "
<< item(row, column)->text();
}
This way, you don't have to mess with data conversion …
I have a somewhat unique situation that I can't quite get working.
I've followed a lot of examples of using maps of maps but the vector of shared pointers seems to throw me off a bit.
Suppose I have the following:
typedef boost::shared_ptr<RecCounts> RecCountsPtr;
typedef std::vector<RecCountsPtr> RecCountsPtrVec;
typedef std::map<std::string, RecCountsPtrVec> InnerActivityMap;
typedef std::map< std::string, InnerActivityMap > ActivityMap;
Where RecCounts is a simple structure.
Now, I think I've figured out how to populate my ActivityMap properly.
RecCountsPtr recCountsPtr(new RecCounts());
config.actType = "M";
config.mapDate = "2010/07";
recCountsPtr->iHousehold = "50";
recCountsPtr->iZero = "150";
config.actMap[config.actType][config.mapDate].push_back(recCountsPtr);
Yes? I don't get any compile/runtime errors for this...but since I haven't figured out how to access all the different elements of the map I can't confirm this!
This is the config structure:
struct Config
{
std::string actType;
std::string mapDate;
// Map
ActivityMap actMap;
InnerActivityMap innerActMap;
//Iterator
ActivityMap::iterator actMapIter;
InnerActivityMap::iterator innerActMapIter;
};
Now, suppose I want to access each element of the ActivityMap. How would I get the following elements?
The outer map Key?
for (config.actMapIter= config.actMap.begin();
config.actMapIter != config.actMap.end();
++config.actMapIter)
{
std::cout << "Outer Key = "
<< (*config.actMapIter).first << std::endl;
}
This seemed to do the trick.
The inner map Key?
I can't figure this out.
The inner map vector elements?
I can do it like this if I know the two keys:
config.actMap[config.actType][config.mapDate][0]->iHouehold
config.actMap[config.actType][config.mapDate][0]->iZero
...but can't seem to figure out how to iterate through them. :(
This is what I've done to try and iterate through all elements.
for (config.actMapIter= config.actMap.begin();
config.actMapIter != config.actMap.end();
++config.actMapIter)
{
std::cout << "Outer Key = " << (*config.actMapIter).first << std::endl;
for (config.innerActMapIter = config.innerActMap.begin();
config.innerActMapIter != config.innerActMap.end();
++config.innerActMapIter)
{
std::cout << "Inner Key = "
<< (*config.innerActMapIter).first << std::endl;
for (size_t i = 0;
i < config.actMap[(*config.actMapIter).first]
[(*config.innerActMapIter).first].size();
++i)
{
std::cout << "iHousehold = "
<< config.actMap[(*config.actMapIter).first]
[(*config.innerActMapIter).first]
[i]->iHousehold << std::endl;
std::cout << "iZero = "
<< config.actMap[(*config.actMapIter).first]
[(*config.innerActMapIter).first]
[i]->iZero << std::endl;
}
}
}
I don't get any errors but I only get the outer key print to the screen:
Outer Key = M
I suspect something is amiss with my inner iterator...in that it's not associated the ActivityMap. Even if I am correct I don't know how to make such an association.
Any suggestions?
ANSWER (thanks to crashmstr):
Here is a verbose version of the answer suggested by crashmstr.
for (config.actMapIter= config.actMap.begin();
config.actMapIter != config.actMap.end();
++config.actMapIter)
{
std::cout << "Outer Key = " << (*config.actMapIter).first << std::endl;
InnerActivityMap innerActMap = (*config.actMapIter).second;
InnerActivityMap::iterator innerActMapIter;
for (innerActMapIter = innerActMap.begin();
innerActMapIter != innerActMap.end();
++innerActMapIter)
{
std::cout << "Inner Key = " << (*innerActMapIter).first << std::endl;
for (size_t i = 0;
i < config.actMap[(*config.actMapIter).first][(*innerActMapIter).first].size();
++i)
{
std::cout << "iHousehold = "
<< config.actMap[(*config.actMapIter).first]
[(*innerActMapIter).first]
[i]->iHousehold << std::endl;
std::cout << "iZero = "
<< config.actMap[(*config.actMapIter).first]
[(*innerActMapIter).first]
[i]->iZero << std::endl;
}
}
}
I get the following printed to the screen:
Outer Key = M
Inner Key = 2010/07
iHousehold = 50
iZero = 150
When iterating over a map, .first is the "key", and .second is the data that belongs to that key.
So in your case:
for (config.actMapIter= config.actMap.begin();
config.actMapIter != config.actMap.end();
++config.actMapIter)
{
std::cout << "Outer Key = " << (*config.actMapIter).first << std::endl;
//(*config.actMapIter).second is a std::map<std::string, RecCountsPtrVec>
//create a new for loop to iterate over .second
}