I have MySQL database, QSqlTableModel and QTableView with few checkbox columns. It works, but the last click on checkbox does not cause changes in database. It means that if I launch a program, click on some checkbox once and close program, no changes in database will be made. If I'll change the state of several checkboxes, the last change will not be shown in database. Maybe there's something wrong in my setData method?
bool PartyModel::setData(const QModelIndex &index, const QVariant &value, int role)
{
QString h=headerData(index.column(),Qt::Horizontal).toString();
QVariant v=value;
switch(role)
{
case Qt::CheckStateRole:
if(h=="One" || h=="Two" || h=="Three" || h=="Four")
{
if(value.toInt()==Qt::Unchecked) v=0;
else v=1;
bool ret = QSqlTableModel::setData(index,v,Qt::EditRole);
if(ret) emit dataChanged(index,index);
return ret;
}
break;
case Qt::DisplayRole:
case Qt::EditRole:
.......
break;
default:
break;
}
return QSqlTableModel::setData(index,v,role);
}
QVariant PartyModel::data(const QModelIndex &idx, int role) const
{
QString h=headerData(idx.column(),Qt::Horizontal).toString();
QVariant v=QSqlTableModel::data(idx,role);
switch(role)
{
case Qt::CheckStateRole:
if(h=="One" || h=="Two" || h=="Three" || h=="Four")
v = (QSqlTableModel::data(idx,Qt::DisplayRole).toInt()==0 ? Qt::Unchecked : Qt::Checked);
break;
case Qt::DisplayRole:
if(h=="One" || h=="Two" || h=="Three" || h=="Four")
v="";
break;
default:
break;
}
return v;
}
Qt::ItemFlags PartyModel::flags(const QModelIndex &index) const
{
QString h=headerData(index.column(),Qt::Horizontal).toString();
Qt::ItemFlags f=QSqlQueryModel::flags(index);
if(h=="One" || h=="Two" || h=="Three" || h=="Four")
{
f |= Qt::ItemIsUserCheckable;
f &= ~Qt::ItemIsEditable;
}
return f;
}
The default "edit strategy" of QSqlTabelModel is OnRowChange, which means that changes are only submitted, as the name suggests, when the selected row changes. To submit changes to the database at other times, you need to either change the edit strategy to OnFieldChange, or manually call submit() or submitAll() at appropriate times.
Related
I am trying to send 2 int variables from client to server using ESP-NOW.
The full code of the client is:
/**
ESPNOW - Basic communication - Master
Date: 26th September 2017
Author: Arvind Ravulavaru <https://github.com/arvindr21>
Purpose: ESPNow Communication between a Master ESP32 and a Slave ESP32
Description: This sketch consists of the code for the Master module.
Resources: (A bit outdated)
a. https://espressif.com/sites/default/files/documentation/esp-now_user_guide_en.pdf
b. http://www.esploradores.com/practica-6-conexion-esp-now/
<< This Device Master >>
Flow: Master
Step 1 : ESPNow Init on Master and set it in STA mode
Step 2 : Start scanning for Slave ESP32 (we have added a prefix of `slave` to the SSID of slave for an easy setup)
Step 3 : Once found, add Slave as peer
Step 4 : Register for send callback
Step 5 : Start Transmitting data from Master to Slave
Flow: Slave
Step 1 : ESPNow Init on Slave
Step 2 : Update the SSID of Slave with a prefix of `slave`
Step 3 : Set Slave in AP mode
Step 4 : Register for receive callback and wait for data
Step 5 : Once data arrives, print it in the serial monitor
Note: Master and Slave have been defined to easily understand the setup.
Based on the ESPNOW API, there is no concept of Master and Slave.
Any devices can act as master or salve.
*/
#include <esp_now.h>
#include <WiFi.h>
// Global copy of slave
esp_now_peer_info_t slave;
#define CHANNEL 1
#define PRINTSCANRESULTS 0
#define DELETEBEFOREPAIR 0
// Init ESP Now with fallback
void InitESPNow() {
WiFi.disconnect();
if (esp_now_init() == ESP_OK) {
Serial.println("ESPNow Init Success");
}
else {
Serial.println("ESPNow Init Failed");
// Retry InitESPNow, add a counte and then restart?
// InitESPNow();
// or Simply Restart
ESP.restart();
}
}
// Scan for slaves in AP mode
void ScanForSlave() {
int8_t scanResults = WiFi.scanNetworks();
// reset on each scan
bool slaveFound = 0;
memset(&slave, 0, sizeof(slave));
Serial.println("");
if (scanResults == 0) {
Serial.println("No WiFi devices in AP Mode found");
} else {
Serial.print("Found "); Serial.print(scanResults); Serial.println(" devices ");
for (int i = 0; i < scanResults; ++i) {
// Print SSID and RSSI for each device found
String SSID = WiFi.SSID(i);
int32_t RSSI = WiFi.RSSI(i);
String BSSIDstr = WiFi.BSSIDstr(i);
if (PRINTSCANRESULTS) {
Serial.print(i + 1);
Serial.print(": ");
Serial.print(SSID);
Serial.print(" (");
Serial.print(RSSI);
Serial.print(")");
Serial.println("");
}
delay(10);
// Check if the current device starts with `Slave`
if (SSID.indexOf("Slave") == 0) {
// SSID of interest
Serial.println("Found a Slave.");
Serial.print(i + 1); Serial.print(": "); Serial.print(SSID); Serial.print(" ["); Serial.print(BSSIDstr); Serial.print("]"); Serial.print(" ("); Serial.print(RSSI); Serial.print(")"); Serial.println("");
// Get BSSID => Mac Address of the Slave
int mac[6];
if ( 6 == sscanf(BSSIDstr.c_str(), "%x:%x:%x:%x:%x:%x", &mac[0], &mac[1], &mac[2], &mac[3], &mac[4], &mac[5] ) ) {
for (int ii = 0; ii < 6; ++ii ) {
slave.peer_addr[ii] = (uint8_t) mac[ii];
}
}
slave.channel = CHANNEL; // pick a channel
slave.encrypt = 0; // no encryption
slaveFound = 1;
// we are planning to have only one slave in this example;
// Hence, break after we find one, to be a bit efficient
break;
}
}
}
if (slaveFound) {
Serial.println("Slave Found, processing..");
} else {
Serial.println("Slave Not Found, trying again.");
}
// clean up ram
WiFi.scanDelete();
}
// Check if the slave is already paired with the master.
// If not, pair the slave with master
bool manageSlave() {
if (slave.channel == CHANNEL) {
if (DELETEBEFOREPAIR) {
deletePeer();
}
Serial.print("Slave Status: ");
// check if the peer exists
bool exists = esp_now_is_peer_exist(slave.peer_addr);
if ( exists) {
// Slave already paired.
Serial.println("Already Paired");
return true;
} else {
// Slave not paired, attempt pair
esp_err_t addStatus = esp_now_add_peer(&slave);
if (addStatus == ESP_OK) {
// Pair success
Serial.println("Pair success");
return true;
} else if (addStatus == ESP_ERR_ESPNOW_NOT_INIT) {
// How did we get so far!!
Serial.println("ESPNOW Not Init");
return false;
} else if (addStatus == ESP_ERR_ESPNOW_ARG) {
Serial.println("Invalid Argument");
return false;
} else if (addStatus == ESP_ERR_ESPNOW_FULL) {
Serial.println("Peer list full");
return false;
} else if (addStatus == ESP_ERR_ESPNOW_NO_MEM) {
Serial.println("Out of memory");
return false;
} else if (addStatus == ESP_ERR_ESPNOW_EXIST) {
Serial.println("Peer Exists");
return true;
} else {
Serial.println("Not sure what happened");
return false;
}
}
} else {
// No slave found to process
Serial.println("No Slave found to process");
return false;
}
}
void deletePeer() {
esp_err_t delStatus = esp_now_del_peer(slave.peer_addr);
Serial.print("Slave Delete Status: ");
if (delStatus == ESP_OK) {
// Delete success
Serial.println("Success");
} else if (delStatus == ESP_ERR_ESPNOW_NOT_INIT) {
// How did we get so far!!
Serial.println("ESPNOW Not Init");
} else if (delStatus == ESP_ERR_ESPNOW_ARG) {
Serial.println("Invalid Argument");
} else if (delStatus == ESP_ERR_ESPNOW_NOT_FOUND) {
Serial.println("Peer not found.");
} else {
Serial.println("Not sure what happened");
}
}
//=================DATA======================
typedef struct test_struct {
int x;
int y;
} test_struct;
test_struct test;
test.x = 10;
test.y = 20;
//uint8_t data = 0;
// send data
void sendData() {
//data++;
const uint8_t *peer_addr = slave.peer_addr;
Serial.print("Sending: "); Serial.println(test);
esp_err_t result = esp_now_send(peer_addr, (uint8_t *) &test,
sizeof(test_struct));
Serial.print("Send Status: ");
if (result == ESP_OK) {
Serial.println("Success");
} else if (result == ESP_ERR_ESPNOW_NOT_INIT) {
// How did we get so far!!
Serial.println("ESPNOW not Init.");
} else if (result == ESP_ERR_ESPNOW_ARG) {
Serial.println("Invalid Argument");
} else if (result == ESP_ERR_ESPNOW_INTERNAL) {
Serial.println("Internal Error");
} else if (result == ESP_ERR_ESPNOW_NO_MEM) {
Serial.println("ESP_ERR_ESPNOW_NO_MEM");
} else if (result == ESP_ERR_ESPNOW_NOT_FOUND) {
Serial.println("Peer not found.");
} else {
Serial.println("Not sure what happened");
}
}
// callback when data is sent from Master to Slave
void OnDataSent(const uint8_t *mac_addr, esp_now_send_status_t status) {
char macStr[18];
snprintf(macStr, sizeof(macStr), "%02x:%02x:%02x:%02x:%02x:%02x",
mac_addr[0], mac_addr[1], mac_addr[2], mac_addr[3], mac_addr[4], mac_addr[5]);
Serial.print("Last Packet Sent to: "); Serial.println(macStr);
Serial.print("Last Packet Send Status: "); Serial.println(status == ESP_NOW_SEND_SUCCESS ? "Delivery Success" : "Delivery Fail");
}
void setup() {
Serial.begin(115200);
//Set device in STA mode to begin with
WiFi.mode(WIFI_STA);
Serial.println("ESPNow/Basic/Master Example");
// This is the mac address of the Master in Station Mode
Serial.print("STA MAC: "); Serial.println(WiFi.macAddress());
// Init ESPNow with a fallback logic
InitESPNow();
// Once ESPNow is successfully Init, we will register for Send CB to
// get the status of Trasnmitted packet
esp_now_register_send_cb(OnDataSent);
}
void loop() {
// In the loop we scan for slave
ScanForSlave();
// If Slave is found, it would be populate in `slave` variable
// We will check if `slave` is defined and then we proceed further
if (slave.channel == CHANNEL) { // check if slave channel is defined
// `slave` is defined
// Add slave as peer if it has not been added already
bool isPaired = manageSlave();
if (isPaired) {
// pair success or already paired
// Send data to device
sendData();
} else {
// slave pair failed
Serial.println("Slave pair failed!");
}
}
else {
// No slave found to process
}
// wait for 3seconds to run the logic again
delay(3000);
}
everything worked when the data sent was just 0, when I substituted this struct ( it's just past the =========DATA======== line in the main code)
typedef struct test_struct {
int x;
int y;
} test_struct;
test_struct test;
test.x = 10;
test.y = 20;
I get an error message 'test' does not name a type.
any ideas?
I figured it out, the struct definition has to be inside a function, be it setup or any other. Thank you all for looking at this
Ok I thought I figured it out, but I just wrote another sketch and placed the struct ahead of all functions and it's working , so honestly I have no idea of what is going on, anybody else know the answer, or is this question so stupid that no one wants to comment? Which is fine with me, I am still a great neophyte at this, so if you can help, great, if not , thank you anyway, this is still a great resource for a newbie😅
You're trying to assign a value to test outside of any executable code. The definition is fine, the assignment test.x=10 is code that needs to be executed inside a new or existing function like setup() or loop(). Try assigning the value during initialization as shown below. That way the compiler puts the value in when it assigns memory to that variable.
typedef struct{
int x;
int y;
} test_struct;
test_struct t={10,20};
int input;
int choices;
void setup() {
Serial.begin(9600);
Serial.println("BIN, DEC, HEX, OCT Converter\n");
retry:
Serial.println("Kindly choose a number system to convert (1, 2, 3, 4)");
Serial.println("1. BIN\n2. DEC\n3. HEX\n4. OCT\n");
while (Serial.available() == 0) {}
choices = Serial.parseInt();
if (choices == 1) {
Serial.println("You have chosen BIN, please enter a valid input");
}
else if (choices == 2) {
Serial.println("You have chosen DEC, please enter a valid input");
}
else if (choices == 3) {
Serial.println("You have choses HEX, please enter a valid input");
}
else if (choices == 4) {
Serial.println("You have chosen OCT, please enter a valid input");
}
else {
Serial.println("Invalid choice."); \
goto retry;
}
switch (choices) {
case 1: while (Serial.available() == 0) {}
input = Serial.parseInt();
Serial.print("You have input ");
Serial.print(input);
break;
case 2: while (Serial.available() == 0) {}
input = Serial.parseInt();
Serial.print("You have input ");
Serial.print(input);
break;
}
}
void loop() {
}
In the part switch, when I run the code, it shows only 0 and it doesn't give me the option to enter at the serial monitor again.
I can't seem to figure this out, I'm a beginner who's trying to improve in the semantics of Arduino IDE. Thank you
I am getting a warning on the following function
function currencySubmenuTitle(ctx) {
let id = Object.keys(currencies).find(element => {
if (currencies[element].id === ctx.match[1]) {
return element
}
})
if (typeof id === 'undefined' || id === null) {
return "No match found"
} else {
return `💰 ${toTitleCase(id)} : ${currencies[id].current}`
}
}
Note: My id and element are different, so I can't just take the element and use that as the string return.
The warning is:
2:51 warning Expected to return a value at the end of arrow function array-callback-return
2:51 warning Expected to return a value at the end of arrow function consistent-return
How do I return my value in this function in a compliant way (aka not how I am doing it)
Can I thenify this? Run the if statement based on the return of the array-evaluation?
The evaluation of the statement can happen in the return line, so no specific if-statement is needed here. Simply do:
function currencySubmenuTitle(ctx) {
let id = Object.keys(currencies).find(element => {
return currencies[element].id === ctx.match[1]
})
if (typeof id === 'undefined' || id === null) {
return "No match found"
} else {
return `💰 ${toTitleCase(id)} : ${currencies[id].current}`
}
}
I have a set of get functions in JS such as:
get UserName() {
return this.userModel.Name;
}
I want the ability to check if the function exist before I call it.
I tried:
if (this.UserName == 'function')...
but it's always false, since userModel.name is a string, typeof UserName returns 'string' type and not a 'function'.
any idea how I can accomplish this ?
One simple way to check that UserName exists (without calling the getter) is to use in:
if ('UserName' in this) {
// this.UserName is defined
}
If you need a stronger check where you directly access the getter function, use Object.getOwnPropertyDescriptor:
var userNameDesc = Object.getOwnPropertyDescriptor(this, 'UserName');
if (userNameDesc && userNameDesc.get) {
// this.UserName is definitely a getter and is defined
}
You can use Object.getOwnPropertyDescriptor() which returns basically the same data structure that is fed to Object.defineProperty() like this:
let descriptor = Object.getOwnPropertyDescriptor(this, "UserName");
if (descriptor && typeof descriptor.get === "function") {
// this.UserName is a getter function
}
Or, if you want more granular info, you can do this:
let descriptor = Object.getOwnPropertyDescriptor(this, "UserName");
if (!descriptor) {
// property doesn't exist
} else if (typeof descriptor.get === "function") {
// this.UserName is a getter function
} else if (typeof descriptor.value === "function") {
// property directly contains a function (that is just a regular function)
} else {
// property exists, but it does not have a getter function and
// is not a regular function
}
You can also test many other properties of the descriptor such as value, set, writable, configurable, enumerable as described here on MDN.
I want a function to be able to take in various types. AS3 doesn't support overloading directly... so I can't do the following:
//THIS ISN'T SUPPORTED BY AS3
function someFunction(xx:int, yy:int, someBoolean:Boolean = true){
//blah blah blah
}
function someFunction(arr:Array, someBoolean:Boolean = true){
someFunction(arr[0], arr[1], someBoolean);
}
How can I work around it and still have a function that is able to take arguments of various types?
If you just want to be able to accept any type, you can use * to allow any type:
function someFunction( xx:*, yy:*, flag:Boolean = true )
{
if (xx is Number) {
...do stuff...
} else if (xx is String) {
...do stuff...
} else {
...do stuff...
}
}
If you have a large number of various parameters where order is unimportant, use an options object:
function someFunction( options:Object )
{
if (options.foo) doFoo();
if (options.bar) doBar();
baz = options.baz || 15;
...etc...
}
If you have a variable number of parameters, you can use the ... (rest) parameter:
function someFunction( ... args)
{
switch (args.length)
{
case 2:
arr = args[0];
someBool = args[1];
xx = arr[0];
yy = arr[1];
break;
case 3:
xx = args[0];
yy = args[1];
someBool = args[2];
break;
default:
throw ...whatever...
}
...do more stuff...
}
For cases where you need to call a common function to a number of classes, you should specify the interface common to each class:
function foo( bar:IBazable, flag:Boolean )
{
...do stuff...
baz = bar.baz()
...do more stuff...
}
Could just have:
function something(...args):void
{
trace(args[0], args[1]);
}
This way you can easily loop through your arguments and such too (and even check the argument type):
function something(...args):void
{
for each(var i:Object in args)
{
trace(typeof(i) + ": " + i);
}
}
something("hello", 4, new Sprite()); // string: hello
// number: 4
// object: [object Sprite]