Add SQLite profile repository and Qt SQL dependency
This commit is contained in:
1
.gitignore
vendored
Normal file
1
.gitignore
vendored
Normal file
@@ -0,0 +1 @@
|
|||||||
|
/build/
|
||||||
@@ -10,18 +10,20 @@ set(CMAKE_AUTOMOC ON)
|
|||||||
set(CMAKE_AUTOUIC ON)
|
set(CMAKE_AUTOUIC ON)
|
||||||
set(CMAKE_AUTORCC ON)
|
set(CMAKE_AUTORCC ON)
|
||||||
|
|
||||||
find_package(Qt6 6.2 REQUIRED COMPONENTS Widgets)
|
find_package(Qt6 6.2 REQUIRED COMPONENTS Widgets Sql)
|
||||||
|
|
||||||
qt_standard_project_setup()
|
qt_standard_project_setup()
|
||||||
|
|
||||||
add_executable(orbithub
|
add_executable(orbithub
|
||||||
src/main.cpp
|
src/main.cpp
|
||||||
|
src/profile_repository.cpp
|
||||||
|
src/profile_repository.h
|
||||||
src/profiles_window.cpp
|
src/profiles_window.cpp
|
||||||
src/profiles_window.h
|
src/profiles_window.h
|
||||||
src/session_window.cpp
|
src/session_window.cpp
|
||||||
src/session_window.h
|
src/session_window.h
|
||||||
)
|
)
|
||||||
|
|
||||||
target_link_libraries(orbithub PRIVATE Qt6::Widgets)
|
target_link_libraries(orbithub PRIVATE Qt6::Widgets Qt6::Sql)
|
||||||
|
|
||||||
install(TARGETS orbithub RUNTIME DESTINATION bin)
|
install(TARGETS orbithub RUNTIME DESTINATION bin)
|
||||||
|
|||||||
163
src/profile_repository.cpp
Normal file
163
src/profile_repository.cpp
Normal file
@@ -0,0 +1,163 @@
|
|||||||
|
#include "profile_repository.h"
|
||||||
|
|
||||||
|
#include <QDir>
|
||||||
|
#include <QSqlDatabase>
|
||||||
|
#include <QSqlError>
|
||||||
|
#include <QSqlQuery>
|
||||||
|
#include <QStandardPaths>
|
||||||
|
#include <QVariant>
|
||||||
|
|
||||||
|
namespace {
|
||||||
|
QString buildDatabasePath()
|
||||||
|
{
|
||||||
|
QString appDataPath = QStandardPaths::writableLocation(QStandardPaths::AppDataLocation);
|
||||||
|
if (appDataPath.isEmpty()) {
|
||||||
|
appDataPath = QDir::currentPath();
|
||||||
|
}
|
||||||
|
|
||||||
|
QDir dataDir(appDataPath);
|
||||||
|
dataDir.mkpath(QStringLiteral("."));
|
||||||
|
|
||||||
|
return dataDir.filePath(QStringLiteral("orbithub_profiles.sqlite"));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ProfileRepository::ProfileRepository() : m_connectionName(QStringLiteral("orbithub_main"))
|
||||||
|
{
|
||||||
|
if (!initializeDatabase()) {
|
||||||
|
QSqlDatabase::removeDatabase(m_connectionName);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ProfileRepository::~ProfileRepository()
|
||||||
|
{
|
||||||
|
if (QSqlDatabase::contains(m_connectionName)) {
|
||||||
|
QSqlDatabase db = QSqlDatabase::database(m_connectionName);
|
||||||
|
if (db.isOpen()) {
|
||||||
|
db.close();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
QSqlDatabase::removeDatabase(m_connectionName);
|
||||||
|
}
|
||||||
|
|
||||||
|
QString ProfileRepository::initError() const
|
||||||
|
{
|
||||||
|
return m_initError;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::vector<Profile> ProfileRepository::listProfiles(const QString& searchQuery) const
|
||||||
|
{
|
||||||
|
std::vector<Profile> result;
|
||||||
|
|
||||||
|
if (!QSqlDatabase::contains(m_connectionName)) {
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
QSqlQuery query(QSqlDatabase::database(m_connectionName));
|
||||||
|
if (searchQuery.trimmed().isEmpty()) {
|
||||||
|
query.prepare(QStringLiteral(
|
||||||
|
"SELECT id, name FROM profiles ORDER BY lower(name) ASC, id ASC"));
|
||||||
|
} else {
|
||||||
|
query.prepare(QStringLiteral(
|
||||||
|
"SELECT id, name FROM profiles "
|
||||||
|
"WHERE lower(name) LIKE lower(?) "
|
||||||
|
"ORDER BY lower(name) ASC, id ASC"));
|
||||||
|
query.addBindValue(QStringLiteral("%") + searchQuery.trimmed() + QStringLiteral("%"));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!query.exec()) {
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
while (query.next()) {
|
||||||
|
result.push_back(Profile{query.value(0).toLongLong(), query.value(1).toString()});
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::optional<Profile> ProfileRepository::createProfile(const QString& name) const
|
||||||
|
{
|
||||||
|
if (!QSqlDatabase::contains(m_connectionName)) {
|
||||||
|
return std::nullopt;
|
||||||
|
}
|
||||||
|
|
||||||
|
const QString trimmedName = name.trimmed();
|
||||||
|
if (trimmedName.isEmpty()) {
|
||||||
|
return std::nullopt;
|
||||||
|
}
|
||||||
|
|
||||||
|
QSqlQuery query(QSqlDatabase::database(m_connectionName));
|
||||||
|
query.prepare(QStringLiteral("INSERT INTO profiles(name) VALUES (?)"));
|
||||||
|
query.addBindValue(trimmedName);
|
||||||
|
|
||||||
|
if (!query.exec()) {
|
||||||
|
return std::nullopt;
|
||||||
|
}
|
||||||
|
|
||||||
|
return Profile{query.lastInsertId().toLongLong(), trimmedName};
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ProfileRepository::updateProfile(qint64 id, const QString& name) const
|
||||||
|
{
|
||||||
|
if (!QSqlDatabase::contains(m_connectionName)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
const QString trimmedName = name.trimmed();
|
||||||
|
if (trimmedName.isEmpty()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
QSqlQuery query(QSqlDatabase::database(m_connectionName));
|
||||||
|
query.prepare(QStringLiteral("UPDATE profiles SET name = ? WHERE id = ?"));
|
||||||
|
query.addBindValue(trimmedName);
|
||||||
|
query.addBindValue(id);
|
||||||
|
|
||||||
|
if (!query.exec()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return query.numRowsAffected() > 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ProfileRepository::deleteProfile(qint64 id) const
|
||||||
|
{
|
||||||
|
if (!QSqlDatabase::contains(m_connectionName)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
QSqlQuery query(QSqlDatabase::database(m_connectionName));
|
||||||
|
query.prepare(QStringLiteral("DELETE FROM profiles WHERE id = ?"));
|
||||||
|
query.addBindValue(id);
|
||||||
|
|
||||||
|
if (!query.exec()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return query.numRowsAffected() > 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ProfileRepository::initializeDatabase()
|
||||||
|
{
|
||||||
|
QSqlDatabase database = QSqlDatabase::addDatabase(QStringLiteral("QSQLITE"), m_connectionName);
|
||||||
|
database.setDatabaseName(buildDatabasePath());
|
||||||
|
|
||||||
|
if (!database.open()) {
|
||||||
|
m_initError = database.lastError().text();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
QSqlQuery query(database);
|
||||||
|
const bool created = query.exec(QStringLiteral(
|
||||||
|
"CREATE TABLE IF NOT EXISTS profiles ("
|
||||||
|
"id INTEGER PRIMARY KEY AUTOINCREMENT,"
|
||||||
|
"name TEXT NOT NULL UNIQUE"
|
||||||
|
")"));
|
||||||
|
|
||||||
|
if (!created) {
|
||||||
|
m_initError = query.lastError().text();
|
||||||
|
}
|
||||||
|
|
||||||
|
return created;
|
||||||
|
}
|
||||||
35
src/profile_repository.h
Normal file
35
src/profile_repository.h
Normal file
@@ -0,0 +1,35 @@
|
|||||||
|
#ifndef ORBITHUB_PROFILE_REPOSITORY_H
|
||||||
|
#define ORBITHUB_PROFILE_REPOSITORY_H
|
||||||
|
|
||||||
|
#include <QString>
|
||||||
|
|
||||||
|
#include <optional>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
struct Profile
|
||||||
|
{
|
||||||
|
qint64 id;
|
||||||
|
QString name;
|
||||||
|
};
|
||||||
|
|
||||||
|
class ProfileRepository
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
ProfileRepository();
|
||||||
|
~ProfileRepository();
|
||||||
|
|
||||||
|
QString initError() const;
|
||||||
|
|
||||||
|
std::vector<Profile> listProfiles(const QString& searchQuery = QString()) const;
|
||||||
|
std::optional<Profile> createProfile(const QString& name) const;
|
||||||
|
bool updateProfile(qint64 id, const QString& name) const;
|
||||||
|
bool deleteProfile(qint64 id) const;
|
||||||
|
|
||||||
|
private:
|
||||||
|
QString m_connectionName;
|
||||||
|
QString m_initError;
|
||||||
|
|
||||||
|
bool initializeDatabase();
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
||||||
Reference in New Issue
Block a user