I am writing a simple task planner and reminder using Qt which will play a sound file when the date and time of any given task matches with the the current date and time.
To implement this, I am running a QThread which checks the task in the list to see if any match the current time and if so, plays the sound file.
This id my original class:
class Task
{
public:
QString ta, desc;
QTime ti;
QDate da;
int pri, diff;
bool ala;
};
This is my Thread Class:
class AlarmCheck : public QThread
{
public:
void setTask(QList<Task>);
void run();
bool isRunning;
QString music;
QTime alarmOffset;
private:
QList<Task> list;
};
My Implementation:
void AlarmCheck::setTask(QList<Task> l)
{
list = l;
}
void AlarmCheck::run()
{
while(isRunning)
{
foreach(Task t, list)
{
if((t.da == QDate::currentDate()) && (t.ti == QTime::currentTime()) && t.ala)
{
Phonon::MediaObject *gaana =
Phonon::createPlayer(Phonon::MusicCategory,
Phonon::MediaSource(music));
gaana->play();
QMessageBox::information(NULL,
"Alarm!!!",
"The time has come for\n"
+ t.ta +
"\n Time to do it!");
gaana->stop();
}
qDebug("Curr = " + QTime::currentTime().toString().toAscii() + " Date = " + QDate::currentDate().toString().toAscii());
qDebug("Task = " + t.ti.toString().toAscii() + " Date = " + t.da.toString().toAscii());
}
sleep(1);
}
}
The thing is that the thread is running perfectly, but the if() condition inside the foreach() loop is never satisfied for some reason. I even checked the individual date/time/alarm setting (t.ala) using qDebugs (as you can see); they are all fine.
Your if statement requires that the date and time match exactly, down to the millisecond. It is unlikely that your loop will evaluate at this exact moment. If you want to maintain similar logic (processing tasks in a loop), you might try sorting them by "next task first" (or perhaps using a queue), then testing in your if statement if the current QDateTime is equal-to-or-greater than the task date/time of the first task.
Related
I am writing code for a school project that will be used for a Chromebook charging station with security. The problem I am having now is when I am detecting if a Chromebook is actually in the slot after the user has been assigned one, I am using a rocker switch to simulate this but when I am declaring the pin to the rocker, the arduino verfier comes up with that
"'slot1' does not name a type".
Code is below:
//class
class Chromebook_slot {
public:
String Name = "";
String RFID_tag = "";
int rocker = 0;
boolean chromebook_in = false;
//class function to check if chromebook is in.
//if not, redirect already to reassigning so chromebook slot is entered as open and free.
void set_if_in()
{
int momen_1_state = digitalRead(momen_1);
int momen_2_state = digitalRead(momen_2);
// the button has been pushed down and the previous process has been completed
// eg. servos would have been reset if there was a previous user
if (momen_1_state == HIGH || momen_2_state == HIGH)
{
chromebook_in = digitalRead(this->rocker);
if (chromebook_in == 0)
{
re_assigning();
}
else
{
return;
}
}
}
};
//this is now outside the class..
//class declarations
Chromebook_slot slot1;
Chromebook_slot slot2;
//variables for rocker switches which will act for detecting chromebooks.
// in my final version, this will replaced by a photoresistor and laser.
slot1.rocker = 3;
slot2.rocker = 2;
Where the function re_assigning() is a separate function declared further in the code and just resets the slot as open for future use.
slot1.rocker = 3;
slot2.rocker = 2;
These are statements that cannot be at the top level of a C++ (or .ino) file. They need to be inside of a function. What's happening is the compiler is looking looking at the slot1 identifier through the lens of potential valid constructions. It sees an identifier, and about the only thing that could legally exist at this point in the code that starts with an identifier like that is some declaration, e.g. int a = 7;, or more abstractly some_type some_more_stuff. So it expects slot1 to be a type, which it isn't, hence the message.
If you want an assignment like those to happen early on in an Arduino program, the simplest thing you could do is put them in setup():
void setup() {
slot1.rocker = 3;
slot2.rocker = 2;
// ...
}
Or, you'd make these part of the Chromebook_slot's constructor, such that they could be given in slot1 and slot2's declaration:
class Chromebook_slot {
public:
Chromebook_slot(int rocker_init_value) {
rocker = rocker_init_value;
}
// ...
Or in a maybe less familiar but more proper form, using the constructor's initialization list:
class Chromebook_slot {
public:
Chromebook_slot(int rocker_init_value)
: rocker(rocker_init_value) {}
// ...
Once you have a constructor for Chromebook_slot, your variables can become:
Chromebook_slot slot1(3);
Chromebook_slot slot2(2);
I am making a program in turbo C++ to create student records and modify/delete them in a binary file on user's command.
The main class that is needed to know is the student class:
class student
{
private:
int roll_no;
char name[50];
academic ac;
co_curricular cc;
void calculate();
public:
int get_data(int);
void show_data();
void show_tabular();
int ret_roll_no();
};
There is some problem with the get_data() function, specially in the part where the roll number is assigned. The logic to assign the roll number is:
student temp;
fstream fp;
roll_no = random(9000) + 1000;
//Checking if roll number is unique
fp.open("STUDENT.DAT", ios::in);
while(!fp.eof())
{
fp.read((char*)&temp, sizeof(temp));
if(roll_no == temp.ret_roll_no())
roll_no = random(9000) + 1000; //Set roll number to another random value
}
fp.close();
Binary file STUDENT.DAT already exists, but the code doesn't go after the loop. It is somehow stuck.
Please help
I'm quite new to c++ and am not very good at understanding about references and pointers.
I'm making a project in Qt to book appointments in a salon and am currently trying to assign a stylist object to the stylist data member in the chair object.
The function below is to assign stylist to a particular chair. At the end of this function, if you print out the stylist name of the stylist in the chair it has been assigned, however outside of this function the value is not assigned. All the getters are returning a reference but the Calender vector, a vector of Week objects, is just called as it is a data member of the class holders. I am wondering if this is the issue but I thought using the [] operator meant that the vector value at that index was returned by reference.
void Holders::BookStylistToChair(int week, int day, float timeslot, stylist temp)
{
for (int i = 0; i < Calender[week].getaweek()[day].getaday()[timeslot].GetNumberOfChairsInslot(); i++) {
bool check = Calender[week].getaweek()[day].getaday()[timeslot].GetChairVector()[i].getoccupied();
if (check == false) {
Calender[week].getaweek()[day].getaday()[timeslot].GetChairVector()[i].SetStylist(temp);
Calender[week].getaweek()[day].getaday()[timeslot].GetChairVector()[i].Setoccupied();
break;
}
}
}
The Week class is shown below:
class Week {
private:
//A week full of 7 days
QVector<Day> AWeek;
public:
//CREATE DAYS IN A WEEK
void Create7days(int, int, int);
//Getter
QVector<Day>& getaweek() ;
};
The week class contains a getter getaweek, which returns a vector of objects of class day. Day contains
class Day {
private:
QString DayName;
// A day full of timeslots
QVector<Timeslot> ADay;
public:
//Create Timeslots
void CreateTimeSlot(int, int, int);
void setdayname(QString);
//Getter
QString getdayname();
QVector<Timeslot>& getaday() ;
};
The getters are all returning references but I'm unsure if they are correct because I haven't used const even though I know I probably should but I keep getting errors when I do I'm not sure how to include const references.
I hope this is enough information I'm sorry if it isn't.
Thank you
I need to notify some objects to clear their cache at new day begins. So, I could create QTimer or something similar and check every ms that now midnight +-5ms or not, but it's not a good idea for me.
Is there(in QT) any standard mechanisms to get notified about this event without allocating any new object? Something static or living since application's initialization like qApp?
What would you do in situation like this where you need to do something at 00:00?
UPD:
I'm looking for fast enough solution. Fast means that I need to clear container in slot as quick as it possible, 'cause since midnight data in the container become invalid. So, there is some other timer which shots every 100ms for instance and it trying to get data from container. I need to clear container with invalid data right before any possible try of getting access.
The simplest solution does indeed utilize a timer. Polling for the passage of time in not only unnecessary, but would be horrible performance-wise. Simply start the actions when the midnight strikes:
static int msecsTo(const QTime & at) {
const int msecsPerDay = 24 * 60 * 60 * 1000;
int msecs = QTime::currentTime().msecsTo(at);
if (msecs < 0) msecs += msecsPerDay;
return msecs;
}
// C++11
void runAt(const std::function<void> & job, const QTime & at, Qt::TimerType type = Qt::VeryCoarseTimer) {
// Timer ownership prevents timer leak when the thread terminates.
auto timer = new QTimer(QAbstractEventDispatcher::instance());
timer->start(msecsTo(at), type);
QObject::connect(timer, &QTimer::timeout, [=job, &timer]{
job();
timer->deleteLater();
});
}
runAt([&]{ object->member(); }, QTime(...));
// C++98
void scheduleSlotAt(QObject * obj, const char * member, const QTime & at, Qt::TimerType type = Qt::VeryCoarseTimer) {
QTimer::singleShot(msecsTo(at), type, obj, member);
}
class MyObject : public QObject {
Q_OBJECT
void scheduleCleanup() {
scheduleSlotAt(this, SLOT(atMidnight()), QTime(0, 0));
}
Q_SLOT void atMidnight() {
// do some work here
...
scheduleCleanup();
}
public:
MyObject(QObject * parent = 0) : QObject(parent) {
...
scheduleCleanup();
}
};
there is some other timer which shots every 100ms for instance and it trying to get data from container.
Since both of these timers presumably run in the same thread, they execute serially and it doesn't matter how much "later" either one is. They won't both run at the same time.
I wrote a program to test my binary tree and when I run it, the program seems to crash (btree.exe has stopped working, Windows is checking for a solution ...).
When I ran it through my debugger and placed the breakpoint on the function I suspect is causing it, destroy_tree(), it seemed to run as expected and returned back to the main function. Main, in turn, returned from the program but then the cursor jumped back to destroy_tree() and looped recusively within itself.
The minimal code sample is below so it can be ran instantly. My compiler is MinGW and my debugger is gdb (I'm using Code::Blocks).
#include <iostream>
using namespace std;
struct node
{
int key_value;
node *left;
node *right;
};
class Btree
{
public:
Btree();
~Btree();
void insert(int key);
void destroy_tree();
private:
node *root;
void destroy_tree(node *leaf);
void insert(int key, node *leaf);
};
Btree::Btree()
{
root = NULL;
}
Btree::~Btree()
{
destroy_tree();
}
void Btree::destroy_tree()
{
destroy_tree(root);
cout<<"tree destroyed\n"<<endl;
}
void Btree::destroy_tree(node *leaf)
{
if(leaf!=NULL)
{
destroy_tree(leaf->left);
destroy_tree(leaf->right);
delete leaf;
}
}
void Btree::insert(int key, node *leaf)
{
if(key < leaf->key_value)
{
if(leaf->left!=NULL)
insert(key, leaf->left);
else
{
leaf->left = new node;
leaf->left->key_value = key;
leaf->left->left = NULL;
leaf->left->right = NULL;
}
}
else if (key >= leaf->key_value)
{
if(leaf->right!=NULL)
insert(key, leaf->right);
else
{
leaf->right = new node;
leaf->right->key_value = key;
leaf->right->left = NULL;
leaf->right->right = NULL;
}
}
}
void Btree::insert(int key)
{
if(root!=NULL)
{
insert(key, root);
}
else
{
root = new node;
root->key_value = key;
root->left = NULL;
root->right = NULL;
}
}
int main()
{
Btree tree;
int i;
tree.insert(1);
tree.destroy_tree();
return 0;
}
As an aside, I'm planning to switch from Code::Blocks built-in debugger to DDD for debugging these problems. I heard DDD can display visually pointers to objects instead of just displaying the pointer's address. Do you think making the switch will help with solving these types of problems (data structure and algorithm problems)?
Your destroy_tree() is called twice, you call it once and then it gets called after the execution leaves main() from the destructor.
You may think it should work anyway, because you check whether leaf!=NULL, but delete does not set the pointer to NULL. So your root is not NULL when destroy_tree() is called for the second time,
Not directly related (or maybe it is) to your problem, but it's good practice to give structs a constructor. For example:
struct node
{
int key_value;
node *left;
node *right;
node( int val ) : key_val( val ), left(NULL), right(NULL) {}
};
If you do this, your code becomes simpler, because you don't need worry about setting the pointers when you create a node, and it is not possible to forget to initialise them.
Regarding DDD, it;'s a fine debugger, but frankly the secret of debugging is to write correct code in the first place, so you don't have to do it. C++ gives you a lot of help in this direction (like the use of constructors), but you have to understand and use the facilities it provides.
Btree::destroy_tree doesn't set 'root' to 0 after successfully nuking the tree. As a result, the destructor class destroy_tree() again and you're trying to destroy already destroyed objects.
That'll be undefined behaviour then :).
Once you destroy the root.
Make sure it is NULL so it does not try to do it again (from the destructor)
void Btree::destroy_tree(node *leaf)
{
if(leaf!=NULL)
{
destroy_tree(leaf->left);
destroy_tree(leaf->right);
delete leaf;
leaf = NULL; // add this line
}
}