PDA

View Full Version : Log-in information available through whole app



omci
19th November 2011, 06:22
Hi!

This one is probably dead simple by all of you, but I can't figure out what will be the best way to do it.
I have an app that require log-in. What is the best and the safest way to make user name, user group and app state available through while application (main window and dialogs)?
I figure out several ways, but do not know which one to choose and I need your help:
- use global variables (obviously this would be my first choice, but I have found several posts that advise against globals),
- use signal-slot to transfer information to a hidden field (good one, but I have to invoke signal-slot every time I do something),
- use temporary file with that info (easily broken into).
Is there any other way to do it? Please advise and/or comment on those three options.

Regards; Luka

mvuori
19th November 2011, 08:18
As the current user can be seen as a property of the application, just subclass QApplication and store the user info as its member variable.
(Preferably make a class for the user related info.)

thefatladysingsopera
19th November 2011, 17:06
If your application is not that complicated,you could insert the details of a user who successfully logged in a table and then use lastinsertedid function to know who is currently logged in and the rights that user has.

grin
19th November 2011, 17:52
I'll describe our experience.
We have a single-tone security object - which contains info about user and his permissions.
Any action (login,logout, permission-request) perform through this object.
As result of any action, which influence (or can) to permissions of current user (login, logout, permission changed)
signal evCheckPermission() will be emitted. Appropriate recepient can check needed info (user login, name, permission and so on) through security object's interface.
Interface of this object defined in header-file, which include anywhere, where it's needed.
As result, we avoid duplication of data (and all available errors related with duplication of data).

P.S. In our case this object is a wrapper over ldap =).

omci
19th November 2011, 19:08
@mvuori: thanks, your reply about sub classing suits my case the most. Now I only have to figure out why my QApplication subclass doesn't work.
@thefatladysingsopera: Unfortunately it is possible to use my app by several users at the same time. Your comment reminded me that I should create a way to log users and their actions.
@grin: not really useful for my app, but interesting insight about more complex application for permissions. I have no need to push permission to all running instances at the moment. Will remember this for later use.

Thanks to all!

omci
20th November 2011, 09:59
@mvuori: Subclassing QApplication works perfectly. I would like to know, if there is a signal emitted when a variable changes? I can't find it in documents.
This is my appl.h file with declaration of appl class as subclass of QApplication. If any of the variable (u_name, permission, state) changes, I would like to trigger a specific action, let say change the greeting message on main window. However, a user can log out and another log in at several dialogue windows as well as main window. I can't find a signal that would trigger that action. Do I have to manually create one or does it exists already in Qt?

// // // appl.h // // //
#ifndef APPL_H
#define APPL_H

#include <QApplication>
#define cApp ((appl *) qApp)

class appl : public QApplication {

public:
appl(int &argc, char **argv);
~appl();

QString u_name; // user name
QString permission; //user permission
QString state; // state of the application
void change_state(); // function that changes state from public to private

};

#endif // APPL_H

Oleg
20th November 2011, 15:20
Actually you should to use get/set functions (i.e. for user name userName()/setUserName()) and then emit needed signals inside setters. Having public vars isn't a good idea, as it can be accessed everywhere in code through qApp (QApplication::instance()).

omci
20th November 2011, 18:20
@Oleg: I am an amateur programmer and everything I know I learned only from beginners books and on-line tutorials. I am lacking knowledge how to make a variable available through all application. Global vars are not good solution, they say, public vars are not good solution, they say. Private vars are available only to the private parts of code and frankly I have no idea at how get/set functions work. At PHP this is usually solved with $_SESSION[] variables. Can you please explain or give simple example for get/set functions to work across application. Thank you.

grin
20th November 2011, 18:32
Standart practic:


// // // appl.h // // //
#ifndef APPL_H
#define APPL_H

#include <QApplication>
#define cApp ((appl *) qApp)

class appl : public QApplication {

public:
appl(int &argc, char **argv);
~appl();
void change_state(); // function that changes state from public to private

//get functions
QString userName() const {return m_u_name;}
QString permission() const {return m_permission;}
QString state() const {return m_state;}

//set functions
void setUserName(QString uname) {m_u_name = uname;}
void setPermission(QString permission) {m_permission = permission;}
void setState(QString state) {m_state = state;}


private:
QString m_u_name; // user name
QString m_permission; //user permission
QString m_state; // state of the application

};
#endif // APPL_H


all get functions returns a COPY of you data - and through this get-functions nobody can change private data.
So you avoid case, when your private data is changed unexpected.

Oleg
20th November 2011, 20:36
@omci: Here's an sample code with signals emitted on property change.

application.h


#ifndef APPLICATION_H
#define APPLICATION_H

#include <QApplication>

class Application : public QApplication, public Settings
{
Q_OBJECT
public:
explicit Application(int &argc, char *argv[]);
~Application();

// Getters
QString userName() const;
QString permission() const;

// Setters
void setUserName(const QString & userName);
void setPermission(const QString & permission);

signals:
void userNameChanged();
void permissionChanged();

private:
QString m_userName;
QString m_permission;

private:
}

#endif // APPLICATION_H


application.cpp


#include "application.h"

Application::Application(int &argc, char *argv[]) :
QApplication(argc, argv)
{
}

Application::~Application()
{
}


QString Application::userName() const
{
return m_userName;
}

QString permission() const
{
return m_permission;
}

void Application::setUserName(const QString & userName)
{
m_userName = userName;
emit userNameChanged();
}

void Application::setPermission(const QString & permission)
{
m_permission = permission;
emit permissionChanged();
}

omci
23rd November 2011, 09:20
How do I catch the emit signal?
the signal is emitted in application.cpp as seen in post #10, while the setUserName() is called from login.cpp? I have tried
// login.cpp //
QObject::connect(Application, SIGNAL(userNameChanged()), this, SLOT(on_userNameChanged()));
The error I get is:
error: expected primary-expression before ‘,’ token

If I try
// login.cpp //
Application appl;
QObject::connect(appl, SIGNAL(userNameChanged()), this, SLOT(on_userNameChanged()));
the error is:
No matching function for call to 'Application::Application()'
What am I doing wrong?

Oleg
26th November 2011, 23:54
Application appl(argc, argv);

Lykurg
27th November 2011, 08:10
Just as a small improvement: Signals should only be emitted when the data really changes. E.g.:

void Application::setUserName(const QString & userName)
{
if (userName == m_userName)
return;

m_userName = userName;
Q_EMIT userNameChanged();
}

omci
27th November 2011, 10:44
Just a couple more questions. Where do I put QObject::connect call? In main.cpp (where I start the application), application.cpp (the definition of the class), login.cpp (where the setUserName is changed, the signal is emitted and one of the places that are affected by the emitted signal)? Do I need to define QObject::connect at all or is it possible to just use something like on_UserName_changed() that would automatically listen to the change in username?

Regards; Luka

Lykurg
27th November 2011, 14:13
You can't use "on_UserName_changed()" because its syntax is on_<object name>_<signal name>()!