How to make a constant or variable accessible in entire program - c++

I would like to have access to constant/variable of desktop width and height in entire program.
This is how I do it - add this code to every .h file of my program and then use it normally.
#include <QDesktopWidget>
QDesktopWidget desktop;
int desktopHeight = desktop.geometry().height();
int desktopWidth = desktop.geometry().width();
I know it is not a good way how to do it. I tried to make one special desktopSize.h and then include to required parts of my program. But I was not successful.
What should be in header file like this one which I need?

You really do not want to use that particular approach and include that code in all translation units. If you did each one would include two variables named desktopWidth and desktopHeight causing duplicate symbol errors during link time. It will also make it difficult to manage updating them if the size of the desktop changes after the application starts. If you really want to provide global variables holding the size of the desktop you should place them in a single .cpp file and place extern declarations in a single header file that is included when needed.
Header file (GlobalDesktopInfo.h)
#ifndef GLOBALDESKTOPINFO_H
#define GLOBALDESKTOPINFO_H
extern int desktopHeight;
extern int desktopWidth;
#endif GLOBALDESKTOPINFO_H
Source file (GlobalDesktopInfo.cpp)
#include "GlobalDesktopInfo.h"
int desktopHeight = 0;
int desktopWidth = 0;
You will also need to initialize it at the earlier point reasonably possible. I suggest doing this in your main() function.
#include "GlobalDesktopInfo.h"
// other includes
int main()
{
QApplication app;
QDesktopWidget desktop;
desktopHeight = desktop.geometry().height();
desktopWidth = desktop.geometry().width();
// other code and initialization
}

I think it's better to have some slots in a class which return the desired values and use Qt's Signal/slot mechanism to access them from other classes.
Just make a signal in the target class, connect it to a slot in the class containing the slots and make a connection between two objects of the classes. This way you can access them in every class you like by connecting a signal to a slot returning that value and just emitting the signal and getting the returned value.
For example you can have a class like :
class DesktopInformation
{
Q_OBJECT
public:
DesktopInformation(QObject *parent = 0);
~DesktopInformation();
QDesktopWidget desktop;
public slots:
int getWidth()
{
return desktop.geometry().width();
}
int getHeight()
{
return desktop.geometry().height();
}
};
And access the desktop information from any other class like :
class SomeClass: public QObject
{
Q_OBJECT
public:
SomeClass(QObject *parent = 0);
~SomeClass();
signals:
int getWidth();
int getHeight();
private:
void someFunction()
{
int width = getWidth();
int heigth = getHeight();
...
}
};
And connect the signal from an object of SomeClass to the slot in an object of DesktopInformation :
connect(someClass, SIGNAL(getWidth()), desktopInformation, SLOT(getWidth()));
In class someClass you can access the value returned from getWidth slot in desktopInformation by just calling the signal and using the returned value.
Note that the two objects should be in the same thread for this to work. If they are in different threads then the connection type should be of type Qt::BlockingQueuedConnection :
connect(someClass, SIGNAL(getWidth()), desktopInformation, SLOT(getWidth()), Qt::BlockingQueuedConnection);
Another way is two use static member functions but it is not recommended unless you have a good reason to do it :
class desktopInformation {
public:
static QDesktopWidget desktop;
static int getWidth()
{
return desktop.geometry().width();
}
static int getHeight()
{
return desktop.geometry().height();
}
};
class someClass {
public:
void do_something();
};
You can access desktopInformation's static member function from someClass like this:
void someClass::do_something()
{
int width = A::getWidth();
...
};

Related

c++ Use a class variable in a non-class function

I'm facing this novice issue. Assume the class MainFrame (the following code isn't going to compile - I'm trying to give a basic idea of what I'm doing because I think my problem is easy to solve by someone more knowledgeable than me) which lives on file gui.cxx along with other functions. Note that this is part of a larger project so I'm skipping the main.cxx which I have included gui.h.
In the function start_gui_with_config() I'm trying to use an object from MainFrame. At the moment is declared as private so I'm expecting to have an text_data_path was not declared in this scope.
I also declared this variable as public and static in the class definition in gui.h but then I get the same error when using either text_data_path ->SetText(data_path);.
When I'm using MainFrame::text_data_path ->SetText(data_path); (still text_data_path is declared as private and static) I get the error undefined reference to MainFrame::text_data_path in any line I'm using text_data_path within the MainFrame::MainFrame constructor (file gui.cxx) and strangely I get this error twice for each line.
Finally I tried making all the functions (start_gui(), start_gui_with_config()) part of MainFrame and I declared them as either static void (in this case I got an error error: cannot declare member function static void MainFrame::start_gui_with_config() to have static linkage on the gui.cxx ) or void (in this case I got the error error: cannot call member function void MainFrame::start_gui_with_config() without object on the main.cxx).
Any idea on how to use text_data_path in a function (i.e. start_gui_with_config()) that doesn't belong to the class?
gui.cxx
#include "../include/gui.h"
MainFrame::MainFrame(const TGWindow *p, UInt_t width, UInt_t height):TGMainFrame(p, width, height, kMainFrame|kHorizontalFrame){
// Define widgets
text_data_path = new TGTextEntry("/data/2020");
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// This is a virtual constructor
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
MainFrame::~MainFrame() {
// Clean up used widgets: frames, buttons, layout hints
Cleanup();
}//_____MainFrame::~MainFrame()
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// This is to start the GUI with default settings
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
void start_gui(){
// Popup the gui
std::cout << "Starting the gui" << std::endl;
new MainFrame(gClient->GetRoot(), 1000, 800);
}//_____start_gui()
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// This is to start the GUI using the configuration file from previous session
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
void start_gui_with_config(){
TString data_path = gSystem->GetFromPipe("awk '{if(NR==1) print $NF}' Config/last_session.cfg.viewer");
start_gui();
MainFrame::text_data_path->SetText(data_path);
}//____MainFrame::start_gui_with_config()
gui.h
#ifndef ___GUI_H
#define ___GUI_H
//ROOT Includes
#include <TGTextEntry.h>
//C++ includes
using namespace std;
class MainFrame : public TGMainFrame {
private:
// Widgets
TGTextEntry *text_data_path;
public:
// Widgets
//static TGTextEntry *text_data_path;
MainFrame(const TGWindow *p, UInt_t width, UInt_t height);
virtual ~MainFrame();
//void start_gui_with_config();
//static void start_gui();
ClassDef (MainFrame,0);// Remove for ROOT6 and rootcling
};
void start_gui();
void start_gui_with_config();
#endif
I suggest you use a setter on the MainFrame class:
void setDatapathText(TString const& newDatapath) {
text_data_path->SetText(data_path);
}
You can then call it like so in your start_gui_with_config function :
auto frame = MainFrame(p, w, h);
frame.setDatapathText(data_path);
Be careful, your code clearly has memory management problems, and as a general rule you should never deal with raw new and delete outside of smart pointers. I suggest making sure you are comfortable with dynamic allocation, else I'm afraid you will be facing hard-to-debug errors earlier than expected
Your problem is you throw away the pointer to your MainFrame so you have no way to access it in start_gui_with_config() after you created the MainFrame.
One way to fix this is to change the signature of void start_gui(); to MainFrame* start_gui(); in your gui.h header.
In the gui.cxx change the implementation to
MainFrame* start_gui() {
return new MainFrame(gClient->GetRoot(), 1000, 800);
}
And then in your start_gui_with_config() use the pointer like this:
void start_gui_with_config(){
TString data_path = gSystem->GetFromPipe("awk '{if(NR==1) print $NF}' Config/last_session.cfg.viewer");
MainFrame* frame = start_gui();
frame->text_data_path->SetText(data_path);
}//____MainFrame::start_gui_with_config()
This code assumes the MainFrame object destroys itself otherwise the code will leak memory. I assume this destruction happens after the window closes. I have seen other GUI frameworks like Qt do this.

QT good global Variable / Object handling

I'm still new to QT and don't really know how to deal with global variables here.
I want to load a file in main() and store the data in Objects / Variables which I then need to access via functions like ::on_Button_clicked().
What are the best ways to have access to the Objects / Variables I set in the main function from the slots?
In your header file you can declare them like this:
class frmMain : public QMainWindow
{
Q_OBJECT
public:
explicit frmMain(QWidget *parent = 0);
~frmMain();
private slots:
void on_lineEdit_returnPressed();
private:
Ui::frmMain *ui; // <--
QComboBox *comboBox; // <--
QDialog *dialog; // <--
QString test; // <--
};
And then define them in your .cpp and use them within the class:
void frmMain::on_lineEdit_returnPressed()
{
comboBox = new QComboBox( );
test = "Hello";
comboBox->addItem( test );
}
On top of that declaring variables outside any scope still makes them global like you know it from basic c++.

Unique Identifier for sent messages in good programming practice

A system send xml warning messages. To put the xml file together, a class was created so the warning could be generated before translating it to xml. Each message has to have an unique ID.
How unique? The IDs go from 3400 until 3500. If maximum is reached, the ID is reset.
#ifndef WARNINGMESSAGE_H
#define WARNINGMESSAGE_H
#include <ctime>
static unsigned int control_ID = 3399;
//Effect Codes:
const unsigned int TRAFFIC_FREE = 2;
//(...)
class WarningMessage{
public:
//setters
void setActionID();
//getters
//(...)
private:
unsigned int actionID; //to be controlled by control_ID
};
#endif // WARNINGPARAMVEHICLE_H
And in the cpp file, when the id of a message needs to be setted, the following is executed:
#include "project/include/warningmessage.h"
//setters
void WarningParamVehicle::setActionID(){
if(control_ID == 3500){
control_ID = 3399;
}
control_ID++;
actionID = control_ID;
}
Another detail that is important, the space in memory for this class message is given just once. Every time another message has to be sent, the instance is deleted and re-created as such:
void WarningDetector::createWarning(){
delete currentWarningMessage; // delete previous warning instance
currentWarningMessage = new WarningMessage();
(...)
}
and lastly, currentWarningMessage was declared in warning detector as a pointer:
WarningMessage* currentWarningMessage;
I can notice the bad programming practice in declaring the variable control_ID in the header file and outside of the class scope, however, given scenario coding like this look optimized. Is there a better way to solve this unique identifier problem seen here? Thanks a lot in advance
Good programming practice could include single responsibilities. For instance, setting the action id for the current message could be decoupled from deciding on the action id for the next message. This could enable consistent behavior when exceptions happen during the construction of a WarningMessage (if you get a chance to fix the cause of the exception you might want to try again to create the WarningMessage and expect the same actionId).
To address that and the other comments above you could for instance:
make control_ID a private static member of WarningMessage (setActionID is currently a member of WarningMessage)
remove the public setter setActionID and initialize actionID in the initialization list instead
manage control_ID, last thing inside the constructor (in case there are exceptions)
In the header:
#ifndef WARNINGMESSAGE_H
#define WARNINGMESSAGE_H
#include <ctime>
//Effect Codes:
const unsigned int TRAFFIC_FREE = 2;
//(...)
class WarningMessage{
public:
WarningMessage();
//remove public setters if your use case doesn't require them
//getters
//(...)
private:
// deconstructing control_ID
static const unsigned ID_COUNT = 100;
static const unsigned ID_START = 3400;
static unsigned idOffset = 0;
const unsigned int actionID; //to be controlled by control_ID
};
#endif // WARNINGPARAMVEHICLE_H
And in the cpp file:
#include "project/include/warningmessage.h"
unsigned WarningMessage::idOffset = 0;
WarningMessage::WarningMessage()
: actionId(ID_START + idOffset) /* ... */
{
// increment idOffset only when you are sure that it is safe
++idOffset;
idOffset %= ID_COUNT;
}
Note that this is not going to work in a multi-threaded environment, but that doesn't seem to be your concern at the moment
I would create 2 constants IDMIN = 3499 and IDMAX = 3500 to avoid having magic numbers in an implementation file. Those constants should be static const members of class WarningMessage.
I would set control_ID as a static variable in the method WarningParamVehicle::setActionID (isn't it WarningMessage::setActionID ?). It would then give :
class WarningMessage{
public:
static const int IDMIN = 3499;
static const int IDMAX = 3500;
//setters
void setActionID();
...
and later in implementation :
void WarningParamVehicle::setActionID(){
static int control_ID = WarningMessage::IDMIN;
if(control_ID == IDMAX){
control_ID = IDMIN;
}
control_ID++;
actionID = control_ID;
}

access wxFrame(s) & wxDialog(s) globally

I'm new to C++ and new to codelite and also new to wxCrafter. I'm trying to build some GUI apps, but I'm messed up about object passthrough in C++. I spent a few hours and I just understand a little bit of that. First, to pass variables between wxFrame/wxDialog, I should create a instance of that class.
in frameA.cpp
void frameA::buttonAClicked() {
frameB * frameB1 = new frameB(NULL);
frameB1->connect(this);
}
in frameB.cpp
void frameB::connect(frameA *upper) {
//now I can access frameA via upper
}
But for a more complex case(e.g. 10 frames), values entered by user need to be shared between frames. I think it's better to make the frames/dialogs to be handle by a parent. Since all classes were triggered by main.cpp, so I think MainApp() will be good idea. So I tried to do this:
main.cpp:
class MainApp : public wxApp {
public:
frameA * frameA1;
frameB * frameB1
//frameC, frameD, frameE etc.
MainApp() {}
virtual ~MainApp() {}
virtual bool OnInit() {
frameA1 = new frameA(NULL);
frameB1 = new frameB(NULL);
frameA1->connect(this);
frameB1->connect(this);
SetTopWindow(frameA);
return GetTopWindow()->Show();
}
};
in both frameA.cpp and frameB.cpp:
frameA::connect(wxApp *par) {
this->parent = par;
}
Now I'm able to access MainApp via parent, but the two member objects(one is itself) was not found. Am I missed something? I'm really new to C++. Is that any better way (or a formal way) to do?
There is convenient way to make kind of global data in wxWidgets application. Create file ApplicationData.h:
#pragma once // replace with #ifndef ... if not supported by your compiler
class frameA;
// place here required forward declarations
// ...
struct ApplicationData
{
frameA* frameA1;
// any other data you need
};
Include this file to application class h-file:
#include "ApplicationData.h"
class MainApp: public wxApp
{
public:
ApplicationData applicationData; // or may it private with get/set functions
...
};
Finally, you can access applicationData from any place of wxWidgets application:
ApplicationData* pData = &wxGetApp().applicationData;
// Set/read global data members here:
// pData->...
See also: wxGetApp function definition in wxWidgets reference: http://docs.wxwidgets.org/2.6/wx_appinifunctions.html Note that you must add IMPLEMENT_APP and DECLARE_APP macros to make it working.

Setting espeak_SetSynthCallback to member function in C++

My application makes heavy use of text-to-speech (through libespeak). It is written in C++/Qt5 with a QML-based frontend.
I have no formal C++ training (I have a Java background though) and as such I'm not entirely sure how to properly implement some of the more esoteric features.
libespeak supports a callback feature, which is called every time speech is synthesized.
The callback function takes three arguments, which I would like to use to visualize the speech. The code below works in the sense that the callback function is called correctly, but not useful since I can't access other member functions or variables.
itemvoice.h
#include "espeak/speak_lib.h"
int callback(short *wav, int numsamples, espeak_EVENT *events);
class ItemVoice : public Item
{
public:
explicit ItemVoice(QQuickItem *parent = 0);
};
itemvoice.cpp
#include "itemvoice.h"
extern int callback(short *wav, int numsamples, espeak_EVENT *events)
{
// do stuff
}
ItemVoice::ItemVoice(QQuickItem *parent):Item(parent)
{
espeak_Initialize(AUDIO_OUTPUT_PLAYBACK,500,NULL,0);
espeak_SetSynthCallback(callback);
}
I would like to make the callback function a member of the ItemVoice class. However if I try (and set the callback function with espeak_SetSynthCallback(ItemVoice::callback), the code won't compile anymore because of arguments which cannot be converted.
UPDATE: The suggestion below works. However, I have now run into another problem.
This is what the class looks like now:
itemvoice.h
#include "espeak/speak_lib.h"
int staticCallback(short *wav, int numsamples, espeak_EVENT *events);
class ItemVoice : public Item
{
Q_OBJECT
public:
explicit ItemVoice(QQuickItem *parent = 0);
void startSpeaking();
void stopSpeaking();
signals:
void updateGUI();
}
itemvoice.cpp
#include "itemvoice.h"
ItemVoice::ItemVoice(QQuickItem *parent):Item(parent)
{
espeak_Initialize(AUDIO_OUTPUT_PLAYBACK,500,NULL,0);
espeak_SetSynthCallback(staticCallback);
}
int staticCallback(short *wav, int numsamples, espeak_EVENT *events)
{
espeak_EVENT_TYPE type=events->type;
if(type==2) // start sentence
(static_cast<ItemVoice*>(events[0].user_data))->startSpeaking();
else if(type==6) // stop sentence
(static_cast<ItemVoice*>(events[0].user_data))->stopSpeaking();
}
void ItemVoice::startSpeaking()
{
//do stuff
updateGUI();
}
void ItemVoice::stopSpeaking()
{
// do stuff
updateGUI();
}
This works correctly. startSpeaking() is called when synthesis begins, and stopSpeaking() when it stops. The problem is that I need to send a Qt signal to update the GUI (updateGUI), and about a second after it's sent, my application crashes with a segmentation fault, even if the signal is not connected anywhere. It works perfectly otherwise.
Any idea?
Thanks for reading!
There is no direct way to do what you want. In your case you are lucky because there is void* user_data field in espeak_EVENT. You can set it to this when you call espeak_Synth():
void ItemVoice::synthSpeech() {
espeak_Synth(...., this);
}
So in the callback (which is still a global function, or a static function in ItemVoice) you can do roughly this:
int staticCallback(short *wav, int numsamples, espeak_EVENT *events) {
if (numsamples > 0)
return (static_cast<ItemVoice*>(events[0].user_data))->nonStaticCallback(wav, numsamples, events);
}