ユーザーをログイン/ログアウトできるシンプルなアプリケーションがあります。ユーザーがログインすると、アプリケーションはメイン ウィンドウ (従業員/管理者/顧客) に適切なタブを表示します。私はそれを持ってQMainWindow
いQTabWidget
ます。私QMainWindow
はデータベースを作成します(このために特別なクラスを実装しました):
class DataBase
{
public:
DataBase();
void initDatabase();
void closeDatabase();
private:
QSqlDatabase db;
};
DataBase::DataBase()
{
}
void DataBase::initDatabase()
{
QString filename = "database.sql";
QFile file(filename);
db = QSqlDatabase::addDatabase("QSQLITE");
db.setHostName("localhost");
db.setDatabaseName(filename);
// create users table
if(this->db.open())
{
QSqlQuery usersTableQuery;
QString usersTableQueryStr = "CREATE TABLE IF NOT EXISTS USERS (ID INTEGER PRIMARY KEY NOT NULL, "
"LOGIN TEXT,"
"PASSWORD TEXT,"
"FIRSTNAME TEXT,"
"LASTNAME TEXT,"
"EMAIL TEXT,"
"ACCOUNT_TYPE INTEGER"
");";
if(usersTableQuery.exec(usersTableQueryStr))
{
qDebug() << "Create USERS table OK";
}
else
{
qDebug() << usersTableQuery.lastError().text();
}
}
else
{
qDebug() << "DB is not opened!\n";
}
// create service table
if(this->db.open())
{
QSqlQuery serviceTableQuery;
QString serviceTableQueryStr = "CREATE TABLE IF NOT EXISTS SERVICE (ID INTEGER PRIMARY KEY NOT NULL, "
"NAME TEXT,"
"PRICE REAL"
");";
if(serviceTableQuery.exec(serviceTableQueryStr))
{
qDebug() << "Create SERVICE table OK";
}
else
{
qDebug() << serviceTableQuery.lastError().text();
}
}
else
{
qDebug() << "DB is not opened!\n";
}
}
void DataBase::closeDatabase()
{
db.close();
}
従業員、管理者、クライアントのタブは次のようになります。
class AdminTab : public QWidget
{
Q_OBJECT
public:
explicit AdminTab(DataBase *db, QWidget *parent = 0);
//...
誰でも (従業員、クライアント、管理者) データベースに変更を加えることができます (たとえば、管理者はサービスを挿入でき、ユーザーは利用可能なサービスを確認できます)。ただし、管理者がサービスを追加し (開いているデータベースで挿入操作を行う)、ログアウトすると、クライアントがログインすると、管理者が行った変更が表示されません。アプリケーションを再起動してクライアントがログインすると、新しく追加されたサービスが表示されます。
サービスの追加は次のようになります。
bool DataBase::insertService(QString name, double price)
{
if(!db.isOpen())
{
qDebug() << query.lastError();
return false;
}
else
{
QSqlQuery query;
query.prepare("INSERT INTO SERVICE (NAME, PRICE) "
"VALUES (:NAME, :PRICE)");
query.bindValue(":NAME", name);
query.bindValue(":PRICE", price);
if(query.exec())
{
return true;
}
else
{
qDebug() << query.lastError();
}
}
return false;
}
データベースが常に開いていることが問題だと思いますが、データベースに何かを挿入/削除した直後に変更を利用できるようにするにはどうすればよいですか? 作成時にデータベースを開き、QMainWindow
デストラクタで閉じます。
データベースを使用する必要があるたびにデータベースを開閉することを考えましたが、それが良い解決策かどうかはわかりません。
追加しても:
if(query.exec())
{
query.clear();
db.commit();
return true;
}
助けにならない。
クライアントには:QVector<Service*> availableServices;
およびがありQComboBox *servicesComboBox;
、クライアントがログインしたときに利用可能なすべてのサービスをチェックします:
void ClientTab::updateAllServices()
{
availableServices.clear();
availableServices = db->selectAllServices();
servicesComboBox->clear();
for(int i=0; i<availableServices.size(); i++)
servicesComboBox->addItem(availableServices[i]->getServiceName(), QVariant::fromValue(availableServices[i]));
servicesComboBox->setCurrentIndex(-1);
}
Service
クラス:
#ifndef SERVICE_H
#define SERVICE_H
#include <QString>
#include <QMetaType>
#include <QVariant>
class Service : public QObject
{
Q_OBJECT
public:
Service(int id, QString name, double price);
Service(){ id = -1; name = ""; price = 0;}
QString getServiceName() const;
void setServiceName(const QString &value);
double getServicePrice() const;
void setServicePrice(double value);
int getId() const;
void setId(int value);
private:
QString name;
double price;
int id;
};
Q_DECLARE_METATYPE(Service*)
#endif // SERVICE_H
最後に、データベースからすべてのサービスを選択します (この方法を使用してコンボボックスをオンにしますClientTab
)。
QVector<Service*> DataBase::selectAllServices()
{
QVector<Service*> services;
if(!db.isOpen())
{
return services;
}
else
{
QSqlQuery query;
if(query.exec("SELECT * FROM SERVICE;"))
{
while( query.next() )
{
int id = query.value(0).toInt();
QString name = query.value(1).toString();
double price = query.value(2).toDouble();
Service *s = new Service(id, name, price);
services.push_back(s);
}
}
else
{
qDebug() << "DataBase::selectAllServices " << query.lastError();
}
}
return services;
}