I have the following bit of code:
QTimer *timer = new QTimer(this);
connect(timer, SIGNAL(timeout()), this, SLOT(updatecommstatus()));
timer -> start();
void MainWindow::updatecommstatus()
{
const auto infos = QSerialPortInfo::availablePorts();
for (const QSerialPortInfo &info : infos) {
QString s = QObject::tr("Port: ") + info.portName() + "\n"
+ QObject::tr("Location: ") + info.systemLocation() + "\n"
+ QObject::tr("Description: ") + info.description() + "\n"
+ QObject::tr("Manufacturer: ") + info.manufacturer() + "\n"
+ QObject::tr("Serial number: ") + info.serialNumber() + "\n"
+ QObject::tr("Vendor Identifier: ") + (info.hasVendorIdentifier() ? QString::number(info.vendorIdentifier(), 16) : QString()) + "\n"
+ QObject::tr("Product Identifier: ") + (info.hasProductIdentifier() ? QString::number(info.productIdentifier(), 16) : QString()) + "\n"
+ QObject::tr("Busy: ") + (info.isBusy() ? QObject::tr("Yes") : QObject::tr("No")) + "\n";
if (QString::number(info.vendorIdentifier(), 16) == "16d0" && QString::number(info.productIdentifier(), 16) == "650")
{
ui->label_commport->setText(info.portName());
}
else
{
ui->label_commport->setText("COM Error");
}
}
}
It is utilising QSerial to display all the available COM ports info. I want to display the portName in a label when certain vendorIdentifierand and productIdentifier match some number.
The above code works well when the device is plugged in (my label displays the right information). But I want to have it when I unplug it that the label displays COM Error. This part does not work. The above code is being targetted by a QTimer and updated, but the Qlist infos is not clearing. Basically, how can I clear this Qlist ? infos.clear(); does not work.
As #lucaAngiolini alluded to in his comment, the scope of you label update seems wrong. I think your trying to do actually compile all available ports into a string, and then set the label thereafter.
void MainWindow::updatecommstatus()
{
const auto infos = QSerialPortInfo::availablePorts();
QStringList comport_labels;
if (infos.empty())
comprt_labels << "COM Error";
for (const QSerialPortInfo &info : infos) {
QString s = QObject::tr("Port: ") + info.portName() + "\n"
+ QObject::tr("Location: ") + info.systemLocation() + "\n"
+ QObject::tr("Description: ") + info.description() + "\n"
+ QObject::tr("Manufacturer: ") + info.manufacturer() + "\n"
+ QObject::tr("Serial number: ") + info.serialNumber() + "\n"
+ QObject::tr("Vendor Identifier: ") + (info.hasVendorIdentifier() ? QString::number(info.vendorIdentifier(), 16) : QString()) + "\n"
+ QObject::tr("Product Identifier: ") + (info.hasProductIdentifier() ? QString::number(info.productIdentifier(), 16) : QString()) + "\n"
+ QObject::tr("Busy: ") + (info.isBusy() ? QObject::tr("Yes") : QObject::tr("No")) + "\n";
if (QString::number(info.vendorIdentifier(), 16) == "16d0" && QString::number(info.productIdentifier(), 16) == "650")
{
comport_labels << info.portName();
}
else
{
comport_labels << "COM Error";
}
}
ui->label_commport->setText(comport_labels.join(","));
}
Related
How may I correct the following code in C++11:
const char *what() const noexcept override {
return "Mtm matrix error: Dimension mismatch: (" + std::to_string(mat1_height) + "," +
std::to_string(mat1_width)
+ ") (" + std::to_string(mat2_height) + "," + std::to_string(mat2_width) + ")";
}
As you can see I'm returning string instead of const char* but won't that be converrted automatically? and how to fix that?
Note: I want something to look like c++ code and not c using sprintf for example
but won't that be converrted automatically?
No.
and how to fix that?
Store the string as a member, and call c_str() in what. Example:
struct descriptive_name : std::exception {
std::string msg;
descriptive_name(
int mat1_width,
int mat1_height,
int mat2_width,
int mat2_height)
: msg(
"Mtm matrix error: Dimension mismatch: ("
+ std::to_string(mat1_height)
+ ","
+ std::to_string(mat1_width)
+ ") ("
+ std::to_string(mat2_height)
+ ","
+ std::to_string(mat2_width)
+ ")"
)
{}
const char *what() const noexcept override {
return msg.c_str();
}
};
Even better: Inherit from std::runtime_error, don't override what, and initialise the base class with the message string. Example:
struct descriptive_name : std::runtime_error {
descriptive_name(
int mat1_width,
int mat1_height,
int mat2_width,
int mat2_height)
: std::runtime_error(
"Mtm matrix error: Dimension mismatch: ("
+ std::to_string(mat1_height)
+ ","
+ std::to_string(mat1_width)
+ ") ("
+ std::to_string(mat2_height)
+ ","
+ std::to_string(mat2_width)
+ ")"
)
{}
};
It's not as simple because you are returning a temporary object which you are trying to convert into a pointer. You CAN do that by using
const char *what() const noexcept override {
return ("Mtm matrix error: Dimension mismatch: (" + std::to_string(mat1_height) + "," +
std::to_string(mat1_width)
+ ") (" + std::to_string(mat2_height) + "," + std::to_string(mat2_width) + ")").c_str();
}
but after converting the object will be destroyed and this will result in the actual data being deleted. Instead you can just copy the data.
const char* what()
{
std::string temp = "Mtm matrix error: Dimension mismatch: (" + std::to_string(mat1_height) + "," +
std::to_string(mat1_width)
+ ") (" + std::to_string(mat2_height) + "," + std::to_string(mat2_width) + ")";
char * p = new char[temp.size()+1]{};
strcpy(p,temp.data());
return p;
}
Just note that this is inefficient since you are creating and destroying and object and there is an extra copy which might be slow. Also you must remember to delete the char* after using this function.
I have a smart contract in which I simulate an event through a set that manually inputs certain data like this: (I use Remix)
[ "From", "to", "object", [ "rules1", "rules2"]], [[1, "data1"], [2, "data2"], [3, "data3"]]
This is my code:
pragma experimental "v0.5.0";
pragma experimental ABIEncoderV2;
contract StructContract {
struct Certificate{
uint id;
string data;
}
struct StructEvent {
string _from;
string _to;
string _object;
string[] _rules;
}
StructEvent structEvent;
Certificate[] certificate;
function setEvent(StructEvent eventS,Certificate[] eventC) public{
certificate.length=0;
structEvent = eventS;
for(uint i=0;i<(eventC.length);i++){
certificate.push(Certificate(eventC[i].id,eventC[i].data));
}
}
function getStruct() view public returns(StructEvent){
return(structEvent);
}
function getCertificate() view public returns(Certificate[]){
return(certificate);
}
function returnAllData() view public returns(StructEvent,Certificate[]){
return(structEvent,certificate);
}
}
once this is done, what I expect is that these data are put into a transaction that is then uploaded to blockchain. Then I have to take the data in these transactions to perform checks on them.
So I need to have data that are put on blockchain, as a solution to this problem I created this code: (I use web3 1.0.0-beta.36)
function printTransaction(txHash) {
web3.eth.getTransaction(txHash, function (error, tx) {
if (tx != null) {
var inputData = tx.input;
try {
var myContract = new web3.eth.Contract(abi, tx.to);
var result = web3.eth.abi.decodeParameters(['tuple(string,string,string,string[])',
'tuple(uint,string)[]'], inputData.slice(10));
var data1 = result[0];
var data2 = result[1];
console.log("\n\n");
console.log("--- transactions ---");
console.log(" tx hash : " + tx.hash + "\n"
+ " nonce : " + tx.nonce + "\n"
+ " blockHash : " + tx.blockHash + "\n"
+ " blockNumber : " + tx.blockNumber + "\n"
+ " transactionIndex: " + tx.transactionIndex + "\n"
+ " from : " + tx.from + "\n"
+ " to : " + tx.to + "\n"
+ " value : " + tx.value + "\n"
+ " gasPrice : " + tx.gasPrice + "\n"
+ " gas : " + tx.gas + "\n"
+ " input : " + tx.input + "\n"
+ " decodeinput : " + "\n"
+ " Struct : " + data1 + "\n"
+ " Certificates : " + data2);
web3.eth.getAccounts(function (err, account) {
myContract.methods.setEvent(data1, data2).send({ from: account[0], gas: 3000000 }, function (err, resul) {
if (err) {
console.log("err");
} else {
console.log("\n\n");
console.log("--- data ---");
myContract.methods.returnAllData().call().then(console.log);
}
});
});
} catch (Error) { }
}
});
}
What I decided to do is create, in a js file, a method that was able to take the transactions, decode the input related to the data contained in it and pass this data, through the send, to my smart contract in which it will be used.
these methods that I created represent the right solution? or I have to use another kind of approach, another method to do this?
Thanks in advance.
I'd like to write something to my path.
My code is following
QString Log::logPacketsPath = QDir::currentPath() + "/logs/Packets/";
int userID = 1;
QString text = "test 1 2 3";
QFile logPacketFile(logPacketsPath + "UserID: " + userID + " - " + QDateTime::currentDateTime().toString("dd.MM.yy") + ".log");
if (logPacketFile.open(QFile::WriteOnly | QFile::Text | QFile::Append))
{
QTextStream out(&logPacketFile);
out << "[" << QDateTime::currentDateTime().toString("dd.MM.yy, hh:mm:ss") << "]: " << text << "\n";
logPacketFile.close();
}
But it only creates the file named "UserID" with nothing in it.
Do you know where the mistake is?
I'm not sure which OS you're using, but ':' is invalid in a Windows filename.
Next, you should flush the QTextStream before closing the file:
out.flush();
logPacketFile.close();
or create additional scope:
{
QTextStream out(&logPacketFile);
out << "[" << QDateTime::currentDateTime().toString("dd.MM.yy, hh:mm:ss") << "]: " << text << "\n";
}
logPacketFile.close();
Also, as Chemobyl has pointed out, you can get into trouble by concatinating the int userID to your filepath. I'd suggest using string formatting to create the filename:
QString logPacketFile("%1UserID%2 - %3.log")
.arg(logPacketsPath)
.arg(userID)
.arg(QDateTime::currentDateTime().toString("dd.MM.yy"));
Convert int to QString:
Use QString::number().
Output with your current code:
"C:/.../logs/Packets/UserID [bad symbols here] - 17.11.14.log"
Output with
QFile logPacketFile(logPacketsPath + "UserID " + QString::number(userID) + " - " + QDateTime::currentDateTime().toString("dd.MM.yy") + ".log");//removed colon
is:
"C:/.../logs/Packets/UserID 1 - 17.11.14.log"
It is source of big troubles. See next:
int userID = 70;
QString text = "test 1 2 3";
QFile logPacketFile(logPacketsPath + "UserID " + userID + " - " + QDateTime::currentDateTime().toString("dd.MM.yy") + ".log");
Output:
.../UserID F - 17.11.14.log"
Note F, not a 70 because operator+ thought that you use simple char and 70 in char is F:
http://www.asciitable.com/
So I strongly suggest you to use QString::number to prevent errors.
I am trying to use an array to keep track of the totals of different types of items (up to 50 types). When I want to print the totals out, I get an error saying "'+' cannot add two pointers." I'm thinking the problem is with my totals array somehow, but I can't figure it out. Below is a sample of my code:
string printSolution()
{
int totals[50];
string printableSolution = "";
for (int k = 0; k < itemTypeCount; k++)
{
totals[k] = 0;
}
for (int i = 0; i < itemCount; i++)
{
totals[items[i].typeCode]++;
}
for (int a = 0; a < itemTypeCount; a++)
{
printableSolution.append("There are " + totals[a] + " of Item type " + (a + 1) + ". \n");
}
}
The string literals "Foo" are of const char*, i.e. pointer type.
To understand what happens with:
"There are " + totals[a] + " of Item type " + (a + 1) + ". \n"
Let's look at an expression:
"0123456789" + 5
This actually just offsets 5 bytes from the start, so becomes:
"56789"
So an expression:
"0123456789" + 5 + "foo"
becomes:
"56789" + "foo"
as pointers, and this is not defined.
What you really want is string concatenation; this can be achieved using std::string.
We can write:
std::string("56789") + "foo"
and this generates a std::string with value: "56789foo" as you desire.
But:
std::string("0123456789") + 5
is also not defined. You need to use:
std::string("0123456789") + std::to_string(5)
So, finally you want:
std::string("There are ") + std::to_string(totals[a]) + " of Item type " + std::to_string(a + 1) + ". \n"
Note now you do not need to explitly convert all the "" to std:string, as once you have one implicit type conversion will take care of the other operand in operator+. However, adding them would do no harm:
std::string("There are ") + std::to_string(totals[a]) + std::string(" of Item type ") + std::to_string(a + 1) + std::string(". \n")
The problem is here:
"There are " + totals[a] + " of Item type " + (a + 1) + ". \n"
It means char* + int + char* + int + char*. You need to print them out separately or change the int to a std::string.
Use C++-style formatting instead:
std::ostringstream oss;
oss << "There are " << totals[a] << " of Item type " << (a + 1) << ". \n";
printableSolution += oss.str();
I'm trying to create a search engine that gets information from my SQL database. Right now I'm struggling to make the combobox and textfield work. So far I can only make the first part of the code work, it allows the user to search for a name in the database. The rest however doesn't work at all, resulting in just an empty window where the info should pop up.
Here are some translations of the Swedish words present in the code:
Namn - Name
sokt - Searched
ANSTALLD - Employee
Aid - Employee id
telefon - phone
try
{
if(jComboBoxSokAID.getSelectedItem().equals("Namn"))
{
String namn = jTextFieldSokText.getText();
String namnQuery = "select * from ANSTALLD where namn = '" + namn + "'";
try
{
HashMap <String, String> soktNamn = idb.fetchRow(namnQuery);
jTextAreaSpecialistInfo.setText("Namn: " + soktNamn.get("namn") + "\n" + "Aid: " + soktNamn.get ("aid") + "\n" + "Telefon: " + soktNamn.get ("telefon") + "\n" + "Mail: " + soktNamn.get ("mail"));
if(jComboBoxSokAID.getSelectedItem().equals("Mail"))
{
String mail = jTextFieldSokText.getText();
String mailQuery = "select * from ANSTALLD where mail = '" + mail + "'";
try
{
HashMap <String, String> soktMail = idb.fetchRow(mailQuery);
jTextAreaSpecialistInfo.setText("Namn: " + soktMail.get("namn") + "\n" + "Aid: " + soktMail.get ("aid") + "\n" + "Telefon: " + soktMail.get ("telefon") + "\n" + "Mail: " + soktMail.get ("mail"));
if(jComboBoxSokAID.getSelectedItem().equals("Telefon"))
{
String telefon = jTextFieldSokText.getText();
String telefonQuery = "select * from ANSTALLD where telefon = '" + telefon + "'";
try
{
HashMap <String, String> soktTelefon = idb.fetchRow(telefonQuery);
jTextAreaSpecialistInfo.setText("Namn: " + soktTelefon.get("namn") + "\n" + "Aid: " + soktTelefon.get ("aid") + "\n" + "Telefon: " + soktTelefon.get ("telefon") + "\n" + "Mail: " + soktTelefon.get ("mail"));
if(jComboBoxSokAID.getSelectedItem().equals("AID"))
{
String AID = jTextFieldSokText.getText();
String AIDQuery = "select * from ANSTALLD where aid = '" + AID + "'";
try
{
HashMap <String, String> soktAID = idb.fetchRow(AIDQuery);
jTextAreaSpecialistInfo.setText("Namn: " + soktAID.get("namn") + "\n" + "Aid: " + soktAID.get ("aid") + "\n" + "Telefon: " + soktAID.get ("telefon") + "\n" + "Mail: " + soktAID.get ("mail"));
}
catch (InformatikException e)
{
if(jComboBoxSokAID == null)
jTextAreaSpecialistInfo.setText("Sökningen gav inga resultat");
}
}
}
catch (InformatikException e)
{
}
}
}
catch (InformatikException e)
{
}
}
}
catch (InformatikException e)
{
}
Don't write code this way.
Never have empty catch blocks.
I prefer to have a single try/catch in a method. Nesting them this way is an indication that you ought to refactor a method that's doing too much.
You've mingled persistence and UI code together in the worst way possible. Tease them apart so you can test and use them separately.
You don't close any database resources. This will come to grief.