Compare commits
11 Commits
28b18aa67b
...
2d2d5032c0
| Author | SHA1 | Date | |
|---|---|---|---|
| 2d2d5032c0 | |||
| 9d054d4119 | |||
| 4814d9002d | |||
| 5dd32e92b8 | |||
| dc4e547c62 | |||
| f11ac5cbfc | |||
| 786f423394 | |||
| 7c4f64e32d | |||
| 4590aeaee8 | |||
| 856d7ff67f | |||
| 394fa90d0d |
2
.gitignore
vendored
2
.gitignore
vendored
@ -1,2 +1,4 @@
|
|||||||
.idea/
|
.idea/
|
||||||
|
.vscode/
|
||||||
cmake-build-*
|
cmake-build-*
|
||||||
|
build/
|
||||||
|
|||||||
10
App.cpp
Normal file
10
App.cpp
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
//
|
||||||
|
// Created by selim on 01.10.22.
|
||||||
|
//
|
||||||
|
|
||||||
|
#include "App.h"
|
||||||
|
|
||||||
|
App &App::instance() {
|
||||||
|
static App app("pro.aliencat.autocat");
|
||||||
|
return app;
|
||||||
|
}
|
||||||
17
App.h
Normal file
17
App.h
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
//
|
||||||
|
// Created by selim on 01.10.22.
|
||||||
|
//
|
||||||
|
|
||||||
|
#ifndef AUTOCAT_GNOME_APP_H
|
||||||
|
#define AUTOCAT_GNOME_APP_H
|
||||||
|
|
||||||
|
#include "gtkpp/Application.h"
|
||||||
|
|
||||||
|
class App: public gtkpp::Application {
|
||||||
|
public:
|
||||||
|
using gtkpp::Application::Application;
|
||||||
|
static App& instance();
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
#endif //AUTOCAT_GNOME_APP_H
|
||||||
@ -1,17 +1,28 @@
|
|||||||
cmake_minimum_required(VERSION 3.0)
|
cmake_minimum_required(VERSION 3.16)
|
||||||
project(autocat_gnome)
|
project(autocat_gnome)
|
||||||
|
include(ExternalProject)
|
||||||
|
|
||||||
set(CMAKE_CXX_STANDARD 20)
|
set(CMAKE_CXX_STANDARD 20)
|
||||||
#set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fcoroutines")
|
set(CMAKE_CXX_STANDARD_REQUIRED ON)
|
||||||
|
|
||||||
|
#if(APPLE)
|
||||||
|
# set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fno-coroutines-ts")
|
||||||
|
#endif()
|
||||||
|
|
||||||
#set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fsanitize=undefined -g -Og")
|
#set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fsanitize=undefined -g -Og")
|
||||||
|
|
||||||
if(APPLE)
|
if(APPLE)
|
||||||
set(ENV{PKG_CONFIG_PATH} "$ENV{PKG_CONFIG_PATH}:/usr/local/opt/libsoup@2/lib/pkgconfig:/usr/local/opt/icu4c/lib/pkgconfig")
|
set(ENV{PKG_CONFIG_PATH} "$ENV{PKG_CONFIG_PATH}:/usr/local/opt/libsoup@2/lib/pkgconfig:/usr/local/opt/icu4c/lib/pkgconfig")
|
||||||
|
set(OPENSSL_ROOT_DIR /usr/local/opt/openssl)
|
||||||
|
set(OPENSSL_LIBRARIES /usr/local/opt/openssl/lib)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
find_package(PkgConfig REQUIRED)
|
find_package(PkgConfig REQUIRED)
|
||||||
find_package(nlohmann_json REQUIRED)
|
find_package(nlohmann_json REQUIRED)
|
||||||
find_package(folly REQUIRED)
|
find_package(concurrencpp REQUIRED)
|
||||||
|
find_package(Threads REQUIRED)
|
||||||
|
find_package(SQLite3 REQUIRED)
|
||||||
|
find_package(fmt REQUIRED)
|
||||||
|
|
||||||
pkg_check_modules(GTK REQUIRED gtk4)
|
pkg_check_modules(GTK REQUIRED gtk4)
|
||||||
pkg_check_modules(GLIB REQUIRED glib-2.0)
|
pkg_check_modules(GLIB REQUIRED glib-2.0)
|
||||||
@ -64,7 +75,17 @@ add_executable(autocat_gnome main.cpp
|
|||||||
gtkpp/MessageDialog.cpp
|
gtkpp/MessageDialog.cpp
|
||||||
gtkpp/MessageDialog.h
|
gtkpp/MessageDialog.h
|
||||||
gtkpp/Leaflet.cpp
|
gtkpp/Leaflet.cpp
|
||||||
gtkpp/Leaflet.h)
|
gtkpp/Leaflet.h
|
||||||
|
gtkpp/Dialog.cpp
|
||||||
|
gtkpp/Dialog.h
|
||||||
|
gui/AddNumberDialog.cpp
|
||||||
|
gui/AddNumberDialog.h
|
||||||
|
gui/custom/PlateView.h
|
||||||
|
gui/custom/PlateView.c
|
||||||
|
App.cpp
|
||||||
|
App.h
|
||||||
|
models/Vehicle.cpp
|
||||||
|
models/Vehicle.h services/Storage.cpp services/Storage.h models/Engine.cpp models/Engine.h services/IDBEntity.h models/JsonOptional.h services/IDBEntity.cpp gtkpp/ScrolledWindow.cpp gtkpp/ScrolledWindow.h gtkpp/ListView.cpp gtkpp/ListView.h gtkpp/SelectionModel.cpp gtkpp/SelectionModel.h gtkpp/ListItemFactory.cpp gtkpp/ListItemFactory.h models/VehiclesListFactory.cpp models/VehiclesListFactory.h gtkpp/Separator.cpp gtkpp/Separator.h gtkpp/Label.cpp gtkpp/Label.h)
|
||||||
|
|
||||||
target_link_libraries(autocat_gnome ${GTK_LIBRARIES}
|
target_link_libraries(autocat_gnome ${GTK_LIBRARIES}
|
||||||
${GLIB_LIBRARIES}
|
${GLIB_LIBRARIES}
|
||||||
@ -72,7 +93,10 @@ target_link_libraries(autocat_gnome ${GTK_LIBRARIES}
|
|||||||
${LIBADWAITA_LIBRARIES}
|
${LIBADWAITA_LIBRARIES}
|
||||||
${LIBSIGCPP_LIBRARIES}
|
${LIBSIGCPP_LIBRARIES}
|
||||||
nlohmann_json::nlohmann_json
|
nlohmann_json::nlohmann_json
|
||||||
Folly::folly)
|
concurrencpp::concurrencpp
|
||||||
|
Threads::Threads
|
||||||
|
SQLite::SQLite3
|
||||||
|
fmt::fmt)
|
||||||
|
|
||||||
set(XML gui/MainWindow.xml)
|
set(XML gui/MainWindow.xml)
|
||||||
|
|
||||||
|
|||||||
15
coro/Coro.h
15
coro/Coro.h
@ -5,19 +5,26 @@
|
|||||||
#ifndef AUTOCAT_GNOME_CORO_H
|
#ifndef AUTOCAT_GNOME_CORO_H
|
||||||
#define AUTOCAT_GNOME_CORO_H
|
#define AUTOCAT_GNOME_CORO_H
|
||||||
|
|
||||||
#include <coroutine>
|
|
||||||
#include <exception>
|
#include <exception>
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
|
|
||||||
|
#if __cpp_lib_coroutine
|
||||||
|
#include <coroutine>
|
||||||
|
namespace corons = std;
|
||||||
|
#else
|
||||||
|
#include <experimental/coroutine>
|
||||||
|
namespace corons = std::experimental;
|
||||||
|
#endif
|
||||||
|
|
||||||
template<typename... Args>
|
template<typename... Args>
|
||||||
struct std::coroutine_traits<void, Args...> {
|
struct corons::coroutine_traits<void, Args...> {
|
||||||
struct promise_type {
|
struct promise_type {
|
||||||
void get_return_object() noexcept {}
|
void get_return_object() noexcept {}
|
||||||
|
|
||||||
std::suspend_never initial_suspend() const noexcept {
|
corons::suspend_never initial_suspend() const noexcept {
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
std::suspend_never final_suspend() const noexcept {
|
corons::suspend_never final_suspend() const noexcept {
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -5,6 +5,8 @@
|
|||||||
#include "GLibMainContextExecutor.h"
|
#include "GLibMainContextExecutor.h"
|
||||||
#include <glib.h>
|
#include <glib.h>
|
||||||
|
|
||||||
|
/*
|
||||||
|
|
||||||
int callback(void* data) {
|
int callback(void* data) {
|
||||||
auto executor = reinterpret_cast<GLibMainContextExecutor*>(data);
|
auto executor = reinterpret_cast<GLibMainContextExecutor*>(data);
|
||||||
executor->runFront();
|
executor->runFront();
|
||||||
@ -30,3 +32,4 @@ folly::Executor::KeepAlive<GLibMainContextExecutor> GLibMainContextExecutor::ins
|
|||||||
static GLibMainContextExecutor instance;
|
static GLibMainContextExecutor instance;
|
||||||
return folly::getKeepAliveToken(instance);
|
return folly::getKeepAliveToken(instance);
|
||||||
}
|
}
|
||||||
|
*/
|
||||||
|
|||||||
@ -5,20 +5,16 @@
|
|||||||
#ifndef AUTOCAT_GNOME_GLIBMAINCONTEXTEXECUTOR_H
|
#ifndef AUTOCAT_GNOME_GLIBMAINCONTEXTEXECUTOR_H
|
||||||
#define AUTOCAT_GNOME_GLIBMAINCONTEXTEXECUTOR_H
|
#define AUTOCAT_GNOME_GLIBMAINCONTEXTEXECUTOR_H
|
||||||
|
|
||||||
#include <folly/Executor.h>
|
|
||||||
#include <queue>
|
#include <queue>
|
||||||
#include <mutex>
|
#include <mutex>
|
||||||
|
|
||||||
class GLibMainContextExecutor: public folly::Executor {
|
class GLibMainContextExecutor {
|
||||||
private:
|
private:
|
||||||
std::queue<folly::Func> _tasks;
|
//std::queue<folly::Func> _tasks;
|
||||||
std::mutex _mutex;
|
std::mutex _mutex;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
static folly::Executor::KeepAlive<GLibMainContextExecutor> instance();
|
//~GLibMainContextExecutor() override = default;
|
||||||
~GLibMainContextExecutor() override = default;
|
|
||||||
void add(folly::Func func) override;
|
|
||||||
void runFront();
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@ -13,7 +13,7 @@ namespace gtkpp {
|
|||||||
}
|
}
|
||||||
|
|
||||||
Application::Application(const std::string &id) {
|
Application::Application(const std::string &id) {
|
||||||
_app = adw_application_new(id.c_str(), G_APPLICATION_FLAGS_NONE);
|
_app = adw_application_new(id.c_str(), G_APPLICATION_DEFAULT_FLAGS);
|
||||||
g_signal_connect(_app, "activate", G_CALLBACK(activateCallback), this);
|
g_signal_connect(_app, "activate", G_CALLBACK(activateCallback), this);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -4,14 +4,22 @@
|
|||||||
|
|
||||||
#include "Box.h"
|
#include "Box.h"
|
||||||
|
|
||||||
gtkpp::Box::Box(GtkOrientation orientation, int spacing) : Widget() {
|
namespace gtkpp {
|
||||||
_widget = gtk_box_new(orientation, spacing);
|
|
||||||
}
|
|
||||||
|
|
||||||
void gtkpp::Box::append(const gtkpp::Widget& widget) {
|
Box::Box(GtkWidget *widget): Widget() {
|
||||||
gtk_box_append(GTK_BOX(_widget), widget.gobj());
|
_widget = widget;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Box::Box(GtkOrientation orientation, int spacing) : Widget() {
|
||||||
|
_widget = gtk_box_new(orientation, spacing);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Box::append(const gtkpp::Widget& widget) {
|
||||||
|
gtk_box_append(GTK_BOX(_widget), widget.gobj());
|
||||||
|
}
|
||||||
|
|
||||||
|
void Box::append(GtkWidget *widget) {
|
||||||
|
gtk_box_append(GTK_BOX(_widget), widget);
|
||||||
|
}
|
||||||
|
|
||||||
void gtkpp::Box::append(GtkWidget *widget) {
|
|
||||||
gtk_box_append(GTK_BOX(_widget), widget);
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -11,8 +11,9 @@
|
|||||||
|
|
||||||
namespace gtkpp {
|
namespace gtkpp {
|
||||||
|
|
||||||
class Box: public Widget{
|
class Box: public Widget {
|
||||||
public:
|
public:
|
||||||
|
Box(GtkWidget* widget);
|
||||||
Box(GtkOrientation orientation, int spacing);
|
Box(GtkOrientation orientation, int spacing);
|
||||||
void append(const Widget& widget);
|
void append(const Widget& widget);
|
||||||
void append(GtkWidget* widget);
|
void append(GtkWidget* widget);
|
||||||
|
|||||||
@ -6,22 +6,17 @@
|
|||||||
|
|
||||||
namespace gtkpp {
|
namespace gtkpp {
|
||||||
|
|
||||||
void clickedCallback(GtkButton*, void* data) {
|
|
||||||
auto button = reinterpret_cast<Button*>(data);
|
|
||||||
button->_signalClicked.emit();
|
|
||||||
}
|
|
||||||
|
|
||||||
Button::Button() : Widget() {
|
Button::Button() : Widget() {
|
||||||
_widget = gtk_button_new();
|
_widget = gtk_button_new();
|
||||||
g_signal_connect(_widget, "clicked", G_CALLBACK(clickedCallback), this);
|
setupSignals();
|
||||||
}
|
}
|
||||||
|
|
||||||
void Button::setTitle(const std::string &title) {
|
void Button::setTitle(const std::string &title) {
|
||||||
gtk_button_set_label(GTK_BUTTON(_widget), title.c_str());
|
gtk_button_set_label(GTK_BUTTON(_widget), title.c_str());
|
||||||
}
|
}
|
||||||
|
|
||||||
void Button::onClick(const std::function<void()> &callback) {
|
void Button::setIconName(const std::string &name) {
|
||||||
_signalClicked.connect(callback);
|
gtk_button_set_icon_name(GTK_BUTTON(_widget), name.c_str());
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -7,21 +7,15 @@
|
|||||||
|
|
||||||
#include "Widget.h"
|
#include "Widget.h"
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <sigc++/sigc++.h>
|
|
||||||
|
|
||||||
namespace gtkpp {
|
namespace gtkpp {
|
||||||
|
|
||||||
class Button: public Widget {
|
class Button: public Widget {
|
||||||
private:
|
|
||||||
sigc::signal<void()> _signalClicked;
|
|
||||||
|
|
||||||
private:
|
|
||||||
friend void clickedCallback(GtkButton*, void* data);
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
using Widget::Widget;
|
||||||
Button();
|
Button();
|
||||||
void setTitle(const std::string& title);
|
void setTitle(const std::string& title);
|
||||||
void onClick(const std::function<void()>& callback);
|
void setIconName(const std::string& name);
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
60
gtkpp/Dialog.cpp
Normal file
60
gtkpp/Dialog.cpp
Normal file
@ -0,0 +1,60 @@
|
|||||||
|
//
|
||||||
|
// Created by selim on 17.05.2022.
|
||||||
|
//
|
||||||
|
|
||||||
|
#include "Dialog.h"
|
||||||
|
|
||||||
|
namespace gtkpp {
|
||||||
|
|
||||||
|
void responseCallback(GtkDialog*, GtkResponseType responseId, void* data) {
|
||||||
|
auto dialog = reinterpret_cast<Dialog*>(data);
|
||||||
|
dialog->_response = responseId;
|
||||||
|
dialog->_signalResponse.emit(responseId);
|
||||||
|
}
|
||||||
|
|
||||||
|
Dialog::Dialog(Window* parent) {
|
||||||
|
|
||||||
|
auto flags = static_cast<GtkDialogFlags>(GTK_DIALOG_DESTROY_WITH_PARENT
|
||||||
|
| GTK_DIALOG_MODAL
|
||||||
|
| GTK_DIALOG_USE_HEADER_BAR);
|
||||||
|
|
||||||
|
auto dialog = gtk_dialog_new_with_buttons("Add plate number",
|
||||||
|
parent->gobj(),
|
||||||
|
flags,
|
||||||
|
"OK", GTK_RESPONSE_OK,
|
||||||
|
"Cancel", GTK_RESPONSE_CANCEL,
|
||||||
|
nullptr);
|
||||||
|
_window = GTK_WINDOW(dialog);
|
||||||
|
gtk_dialog_set_default_response (GTK_DIALOG (dialog), GTK_RESPONSE_OK);
|
||||||
|
_responseHandlerId = g_signal_connect (dialog, "response", G_CALLBACK(responseCallback), this);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Dialog::onResponse(const std::function<void(GtkResponseType)> &callback) {
|
||||||
|
_signalResponse.connect(callback);
|
||||||
|
}
|
||||||
|
|
||||||
|
cc::result<GtkResponseType> Dialog::responseAsync() {
|
||||||
|
auto promise = std::make_shared<cc::result_promise<GtkResponseType>>();
|
||||||
|
auto result = promise->get_result();
|
||||||
|
|
||||||
|
_signalResponse.connect([promise](GtkResponseType response){
|
||||||
|
promise->set_result(response);
|
||||||
|
});
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
Dialog::~Dialog() {
|
||||||
|
g_signal_handler_disconnect(_window, _responseHandlerId);
|
||||||
|
}
|
||||||
|
|
||||||
|
GtkResponseType Dialog::currentResponse() const {
|
||||||
|
return _response;
|
||||||
|
}
|
||||||
|
|
||||||
|
Box Dialog::contentWidget() const {
|
||||||
|
auto contentArea = gtk_dialog_get_content_area (GTK_DIALOG(_window));
|
||||||
|
return {contentArea};
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
37
gtkpp/Dialog.h
Normal file
37
gtkpp/Dialog.h
Normal file
@ -0,0 +1,37 @@
|
|||||||
|
//
|
||||||
|
// Created by selim on 17.05.2022.
|
||||||
|
//
|
||||||
|
|
||||||
|
#ifndef AUTOCAT_GNOME_DIALOG_H
|
||||||
|
#define AUTOCAT_GNOME_DIALOG_H
|
||||||
|
|
||||||
|
#include "Window.h"
|
||||||
|
#include "Box.h"
|
||||||
|
#include <sigc++/sigc++.h>
|
||||||
|
#include <concurrencpp/concurrencpp.h>
|
||||||
|
|
||||||
|
namespace cc = concurrencpp;
|
||||||
|
|
||||||
|
namespace gtkpp {
|
||||||
|
|
||||||
|
class Dialog: public Window {
|
||||||
|
private:
|
||||||
|
GtkResponseType _response = GTK_RESPONSE_NONE;
|
||||||
|
gulong _responseHandlerId;
|
||||||
|
sigc::signal<void(GtkResponseType)> _signalResponse;
|
||||||
|
friend void responseCallback(GtkDialog*, GtkResponseType responseId, void* data);
|
||||||
|
|
||||||
|
public:
|
||||||
|
void onResponse(const std::function<void(GtkResponseType)>& callback);
|
||||||
|
|
||||||
|
public:
|
||||||
|
explicit Dialog(Window* parent);
|
||||||
|
~Dialog();
|
||||||
|
cc::result<GtkResponseType> responseAsync();
|
||||||
|
GtkResponseType currentResponse() const;
|
||||||
|
Box contentWidget() const;
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif //AUTOCAT_GNOME_DIALOG_H
|
||||||
@ -13,7 +13,11 @@ namespace gtkpp {
|
|||||||
|
|
||||||
Entry::Entry() : Widget() {
|
Entry::Entry() : Widget() {
|
||||||
_widget = gtk_entry_new();
|
_widget = gtk_entry_new();
|
||||||
g_signal_connect(_widget, "changed", G_CALLBACK(changedCallback), this);
|
_changedHandlerId = g_signal_connect(_widget, "changed", G_CALLBACK(changedCallback), this);
|
||||||
|
}
|
||||||
|
|
||||||
|
Entry::~Entry() {
|
||||||
|
g_signal_handler_disconnect(_widget, _changedHandlerId);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Entry::setPlaceholder(const std::string &placeholder) {
|
void Entry::setPlaceholder(const std::string &placeholder) {
|
||||||
|
|||||||
@ -13,6 +13,7 @@ namespace gtkpp {
|
|||||||
|
|
||||||
class Entry: public Widget {
|
class Entry: public Widget {
|
||||||
private:
|
private:
|
||||||
|
gulong _changedHandlerId;
|
||||||
sigc::signal<void()> _signalChanged;
|
sigc::signal<void()> _signalChanged;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
@ -20,6 +21,7 @@ namespace gtkpp {
|
|||||||
|
|
||||||
public:
|
public:
|
||||||
Entry();
|
Entry();
|
||||||
|
~Entry();
|
||||||
void setPlaceholder(const std::string& placeholder);
|
void setPlaceholder(const std::string& placeholder);
|
||||||
void setPurpose(GtkInputPurpose purpose);
|
void setPurpose(GtkInputPurpose purpose);
|
||||||
void setVisibility(bool visibility);
|
void setVisibility(bool visibility);
|
||||||
|
|||||||
@ -18,4 +18,12 @@ namespace gtkpp {
|
|||||||
void HeaderBar::setTitle(const std::string& title) {
|
void HeaderBar::setTitle(const std::string& title) {
|
||||||
adw_header_bar_set_title_widget(ADW_HEADER_BAR(_widget), gtk_label_new(title.c_str()));
|
adw_header_bar_set_title_widget(ADW_HEADER_BAR(_widget), gtk_label_new(title.c_str()));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void HeaderBar::showEndButtons(bool show) {
|
||||||
|
adw_header_bar_set_show_end_title_buttons(ADW_HEADER_BAR(_widget), show);
|
||||||
|
}
|
||||||
|
|
||||||
|
void HeaderBar::packStart(const Widget &widget) {
|
||||||
|
adw_header_bar_pack_start(ADW_HEADER_BAR(_widget), widget.gobj());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
@ -15,6 +15,8 @@ namespace gtkpp {
|
|||||||
HeaderBar();
|
HeaderBar();
|
||||||
explicit HeaderBar(const std::string& title);
|
explicit HeaderBar(const std::string& title);
|
||||||
void setTitle(const std::string& title);
|
void setTitle(const std::string& title);
|
||||||
|
void showEndButtons(bool show);
|
||||||
|
void packStart(const Widget& widget);
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
17
gtkpp/Label.cpp
Normal file
17
gtkpp/Label.cpp
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
//
|
||||||
|
// Created by selim on 18.12.22.
|
||||||
|
//
|
||||||
|
|
||||||
|
#include "Label.h"
|
||||||
|
|
||||||
|
namespace gtkpp {
|
||||||
|
|
||||||
|
Label::Label(): Widget() {
|
||||||
|
_widget = gtk_label_new("");
|
||||||
|
}
|
||||||
|
|
||||||
|
void Label::setText(const std::string& text) {
|
||||||
|
gtk_label_set_text(GTK_LABEL(_widget), text.c_str());
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
23
gtkpp/Label.h
Normal file
23
gtkpp/Label.h
Normal file
@ -0,0 +1,23 @@
|
|||||||
|
//
|
||||||
|
// Created by selim on 18.12.22.
|
||||||
|
//
|
||||||
|
|
||||||
|
#ifndef AUTOCAT_GNOME_LABEL_H
|
||||||
|
#define AUTOCAT_GNOME_LABEL_H
|
||||||
|
|
||||||
|
#include "Widget.h"
|
||||||
|
|
||||||
|
namespace gtkpp {
|
||||||
|
|
||||||
|
class Label: public Widget {
|
||||||
|
public:
|
||||||
|
Label();
|
||||||
|
using Widget::Widget;
|
||||||
|
|
||||||
|
public:
|
||||||
|
void setText(const std::string& text);
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif //AUTOCAT_GNOME_LABEL_H
|
||||||
@ -11,8 +11,8 @@ namespace gtkpp {
|
|||||||
_widget = adw_leaflet_new();
|
_widget = adw_leaflet_new();
|
||||||
}
|
}
|
||||||
|
|
||||||
void Leaflet::append(Widget *widget) {
|
void Leaflet::append(const Widget& widget) {
|
||||||
adw_leaflet_append(ADW_LEAFLET(_widget), widget->gobj());
|
adw_leaflet_append(ADW_LEAFLET(_widget), widget.gobj());
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -12,7 +12,7 @@ namespace gtkpp {
|
|||||||
class Leaflet: public Widget {
|
class Leaflet: public Widget {
|
||||||
public:
|
public:
|
||||||
Leaflet();
|
Leaflet();
|
||||||
void append(Widget* widget);
|
void append(const Widget& widget);
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
32
gtkpp/ListItemFactory.cpp
Normal file
32
gtkpp/ListItemFactory.cpp
Normal file
@ -0,0 +1,32 @@
|
|||||||
|
//
|
||||||
|
// Created by selim on 13.11.22.
|
||||||
|
//
|
||||||
|
|
||||||
|
#include "ListItemFactory.h"
|
||||||
|
|
||||||
|
namespace gtkpp {
|
||||||
|
|
||||||
|
void setupListItemCallback(GtkListItemFactory* factory, GtkListItem* list_item, void* data) {
|
||||||
|
auto self = reinterpret_cast<ListItemFactory*>(data);
|
||||||
|
auto widget = self->setup();
|
||||||
|
gtk_list_item_set_child(list_item, widget);
|
||||||
|
}
|
||||||
|
|
||||||
|
void bindListItemCallback(GtkListItemFactory* factory, GtkListItem* list_item, void* data) {
|
||||||
|
auto self = reinterpret_cast<ListItemFactory*>(data);
|
||||||
|
auto widget = gtk_list_item_get_child(list_item);
|
||||||
|
auto item = gtk_list_item_get_item (list_item);
|
||||||
|
self->bind(widget);
|
||||||
|
}
|
||||||
|
|
||||||
|
ListItemFactory::ListItemFactory() {
|
||||||
|
_factory = gtk_signal_list_item_factory_new();
|
||||||
|
g_signal_connect(_factory, "setup", G_CALLBACK(setupListItemCallback), this);
|
||||||
|
g_signal_connect(_factory, "bind", G_CALLBACK(bindListItemCallback), this);
|
||||||
|
}
|
||||||
|
|
||||||
|
GtkListItemFactory *ListItemFactory::gobj() const {
|
||||||
|
return _factory;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
28
gtkpp/ListItemFactory.h
Normal file
28
gtkpp/ListItemFactory.h
Normal file
@ -0,0 +1,28 @@
|
|||||||
|
//
|
||||||
|
// Created by selim on 13.11.22.
|
||||||
|
//
|
||||||
|
|
||||||
|
#ifndef AUTOCAT_GNOME_LISTITEMFACTORY_H
|
||||||
|
#define AUTOCAT_GNOME_LISTITEMFACTORY_H
|
||||||
|
|
||||||
|
#include "Widget.h"
|
||||||
|
#include <gtk/gtk.h>
|
||||||
|
|
||||||
|
namespace gtkpp {
|
||||||
|
|
||||||
|
class ListItemFactory {
|
||||||
|
private:
|
||||||
|
GtkListItemFactory* _factory;
|
||||||
|
|
||||||
|
public:
|
||||||
|
ListItemFactory();
|
||||||
|
[[nodiscard]] GtkListItemFactory* gobj() const;
|
||||||
|
|
||||||
|
public:
|
||||||
|
virtual GtkWidget* setup() = 0;
|
||||||
|
virtual void bind(GtkWidget* widget) = 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif //AUTOCAT_GNOME_LISTITEMFACTORY_H
|
||||||
13
gtkpp/ListView.cpp
Normal file
13
gtkpp/ListView.cpp
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
//
|
||||||
|
// Created by selim on 13.11.22.
|
||||||
|
//
|
||||||
|
|
||||||
|
#include "ListView.h"
|
||||||
|
|
||||||
|
namespace gtkpp {
|
||||||
|
|
||||||
|
ListView::ListView(SelectionModel selectionModel, ListItemFactory* factory) {
|
||||||
|
_widget = gtk_list_view_new(selectionModel.gobj(), factory->gobj());
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
21
gtkpp/ListView.h
Normal file
21
gtkpp/ListView.h
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
//
|
||||||
|
// Created by selim on 13.11.22.
|
||||||
|
//
|
||||||
|
|
||||||
|
#ifndef AUTOCAT_GNOME_LISTVIEW_H
|
||||||
|
#define AUTOCAT_GNOME_LISTVIEW_H
|
||||||
|
|
||||||
|
#include "Widget.h"
|
||||||
|
#include "SelectionModel.h"
|
||||||
|
#include "ListItemFactory.h"
|
||||||
|
|
||||||
|
namespace gtkpp {
|
||||||
|
|
||||||
|
class ListView: public Widget {
|
||||||
|
public:
|
||||||
|
ListView(SelectionModel selectionModel, ListItemFactory* factory);
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif //AUTOCAT_GNOME_LISTVIEW_H
|
||||||
15
gtkpp/ScrolledWindow.cpp
Normal file
15
gtkpp/ScrolledWindow.cpp
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
//
|
||||||
|
// Created by selim on 13.11.22.
|
||||||
|
//
|
||||||
|
|
||||||
|
#include "ScrolledWindow.h"
|
||||||
|
|
||||||
|
#include <gtk/gtkscrolledwindow.h>
|
||||||
|
|
||||||
|
namespace gtkpp {
|
||||||
|
|
||||||
|
ScrolledWindow::ScrolledWindow() {
|
||||||
|
_widget = gtk_scrolled_window_new();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
19
gtkpp/ScrolledWindow.h
Normal file
19
gtkpp/ScrolledWindow.h
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
//
|
||||||
|
// Created by selim on 13.11.22.
|
||||||
|
//
|
||||||
|
|
||||||
|
#ifndef AUTOCAT_GNOME_SCROLLEDWINDOW_H
|
||||||
|
#define AUTOCAT_GNOME_SCROLLEDWINDOW_H
|
||||||
|
|
||||||
|
#include "Widget.h"
|
||||||
|
|
||||||
|
namespace gtkpp {
|
||||||
|
|
||||||
|
class ScrolledWindow: public Widget {
|
||||||
|
public:
|
||||||
|
ScrolledWindow();
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif //AUTOCAT_GNOME_SCROLLEDWINDOW_H
|
||||||
26
gtkpp/SelectionModel.cpp
Normal file
26
gtkpp/SelectionModel.cpp
Normal file
@ -0,0 +1,26 @@
|
|||||||
|
//
|
||||||
|
// Created by selim on 13.11.22.
|
||||||
|
//
|
||||||
|
|
||||||
|
#include "SelectionModel.h"
|
||||||
|
|
||||||
|
namespace gtkpp {
|
||||||
|
|
||||||
|
SelectionModel::SelectionModel(gtkpp::Selection selection) {
|
||||||
|
|
||||||
|
const char *array[] = { "one", "two", "three", "four", nullptr };
|
||||||
|
GtkStringList *sl = gtk_string_list_new ((const char * const *) array);
|
||||||
|
|
||||||
|
switch (selection) {
|
||||||
|
case None:
|
||||||
|
_model = GTK_SELECTION_MODEL(gtk_no_selection_new(G_LIST_MODEL(sl)));
|
||||||
|
case Single:
|
||||||
|
_model = GTK_SELECTION_MODEL(gtk_single_selection_new(G_LIST_MODEL(sl)));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
GtkSelectionModel *SelectionModel::gobj() const {
|
||||||
|
return _model;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
29
gtkpp/SelectionModel.h
Normal file
29
gtkpp/SelectionModel.h
Normal file
@ -0,0 +1,29 @@
|
|||||||
|
//
|
||||||
|
// Created by selim on 13.11.22.
|
||||||
|
//
|
||||||
|
|
||||||
|
#ifndef AUTOCAT_GNOME_SELECTIONMODEL_H
|
||||||
|
#define AUTOCAT_GNOME_SELECTIONMODEL_H
|
||||||
|
|
||||||
|
#include <gtk/gtk.h>
|
||||||
|
#include <gio/glistmodel.h>
|
||||||
|
|
||||||
|
namespace gtkpp {
|
||||||
|
|
||||||
|
enum Selection {
|
||||||
|
None,
|
||||||
|
Single
|
||||||
|
};
|
||||||
|
|
||||||
|
class SelectionModel {
|
||||||
|
private:
|
||||||
|
GtkSelectionModel* _model;
|
||||||
|
|
||||||
|
public:
|
||||||
|
explicit SelectionModel(Selection selection);
|
||||||
|
[[nodiscard]] GtkSelectionModel* gobj() const;
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif //AUTOCAT_GNOME_SELECTIONMODEL_H
|
||||||
9
gtkpp/Separator.cpp
Normal file
9
gtkpp/Separator.cpp
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
//
|
||||||
|
// Created by selim on 15.11.22.
|
||||||
|
//
|
||||||
|
|
||||||
|
#include "Separator.h"
|
||||||
|
|
||||||
|
gtkpp::Separator::Separator(GtkOrientation orientation) {
|
||||||
|
_widget = gtk_separator_new(orientation);
|
||||||
|
}
|
||||||
19
gtkpp/Separator.h
Normal file
19
gtkpp/Separator.h
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
//
|
||||||
|
// Created by selim on 15.11.22.
|
||||||
|
//
|
||||||
|
|
||||||
|
#ifndef AUTOCAT_GNOME_SEPARATOR_H
|
||||||
|
#define AUTOCAT_GNOME_SEPARATOR_H
|
||||||
|
|
||||||
|
#include "Widget.h"
|
||||||
|
|
||||||
|
namespace gtkpp {
|
||||||
|
|
||||||
|
class Separator: public Widget {
|
||||||
|
public:
|
||||||
|
explicit Separator(GtkOrientation orientation);
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif //AUTOCAT_GNOME_SEPARATOR_H
|
||||||
@ -4,35 +4,78 @@
|
|||||||
|
|
||||||
#include "Widget.h"
|
#include "Widget.h"
|
||||||
|
|
||||||
GtkWidget *gtkpp::Widget::gobj() const {
|
namespace gtkpp {
|
||||||
return _widget;
|
|
||||||
}
|
|
||||||
|
|
||||||
void gtkpp::Widget::setMargins(int margin) {
|
void clickedCallback(GtkButton*, void* data) {
|
||||||
gtk_widget_set_margin_top(_widget, margin);
|
auto widget = reinterpret_cast<Widget*>(data);
|
||||||
gtk_widget_set_margin_bottom(_widget, margin);
|
widget->_signalClicked.emit();
|
||||||
gtk_widget_set_margin_start(_widget, margin);
|
}
|
||||||
gtk_widget_set_margin_end(_widget, margin);
|
|
||||||
}
|
|
||||||
|
|
||||||
void gtkpp::Widget::setVAlign(GtkAlign align) {
|
void Widget::onClick(const std::function<void()> &callback) {
|
||||||
gtk_widget_set_valign(_widget, align);
|
_signalClicked.connect(callback);
|
||||||
}
|
}
|
||||||
|
|
||||||
void gtkpp::Widget::setVExpand(bool expand) {
|
Widget::Widget() {
|
||||||
gtk_widget_set_vexpand(_widget, expand);
|
_widget = nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
void gtkpp::Widget::setHorizontalMargins(int margin) {
|
Widget::Widget(GtkWidget *widget) {
|
||||||
gtk_widget_set_margin_start(_widget, margin);
|
_widget = widget;
|
||||||
gtk_widget_set_margin_end(_widget, margin);
|
//g_signal_connect(_widget, "clicked", G_CALLBACK(clickedCallback), this);
|
||||||
}
|
}
|
||||||
|
|
||||||
void gtkpp::Widget::setVerticalMargins(int margin) {
|
Widget::Widget(GtkBuilder *builder, const char *id) {
|
||||||
gtk_widget_set_margin_top(_widget, margin);
|
_widget = GTK_WIDGET(gtk_builder_get_object(builder, id));
|
||||||
gtk_widget_set_margin_bottom(_widget, margin);
|
g_signal_connect(_widget, "clicked", G_CALLBACK(clickedCallback), this);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
GtkWidget *Widget::gobj() const {
|
||||||
|
return _widget;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Widget::setMargins(int margin) {
|
||||||
|
gtk_widget_set_margin_top(_widget, margin);
|
||||||
|
gtk_widget_set_margin_bottom(_widget, margin);
|
||||||
|
gtk_widget_set_margin_start(_widget, margin);
|
||||||
|
gtk_widget_set_margin_end(_widget, margin);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Widget::setVAlign(GtkAlign align) {
|
||||||
|
gtk_widget_set_valign(_widget, align);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Widget::setVExpand(bool expand) {
|
||||||
|
gtk_widget_set_vexpand(_widget, expand);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Widget::setHExpand(bool expand) {
|
||||||
|
gtk_widget_set_hexpand(_widget, expand);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Widget::setHorizontalMargins(int margin) {
|
||||||
|
gtk_widget_set_margin_start(_widget, margin);
|
||||||
|
gtk_widget_set_margin_end(_widget, margin);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Widget::setVerticalMargins(int margin) {
|
||||||
|
gtk_widget_set_margin_top(_widget, margin);
|
||||||
|
gtk_widget_set_margin_bottom(_widget, margin);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Widget::setEnabled(bool enabled) {
|
||||||
|
gtk_widget_set_sensitive(_widget, enabled);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Widget::setupSignals() {
|
||||||
|
g_signal_connect(_widget, "clicked", G_CALLBACK(clickedCallback), this);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Widget::show() {
|
||||||
|
gtk_widget_show(_widget);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Widget::hide() {
|
||||||
|
gtk_widget_hide(_widget);
|
||||||
|
}
|
||||||
|
|
||||||
void gtkpp::Widget::setEnabled(bool enabled) {
|
|
||||||
gtk_widget_set_sensitive(_widget, enabled);
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -6,6 +6,7 @@
|
|||||||
#define AUTOCAT_GNOME_WIDGET_H
|
#define AUTOCAT_GNOME_WIDGET_H
|
||||||
|
|
||||||
#include <gtk/gtk.h>
|
#include <gtk/gtk.h>
|
||||||
|
#include <sigc++/sigc++.h>
|
||||||
|
|
||||||
namespace gtkpp {
|
namespace gtkpp {
|
||||||
|
|
||||||
@ -13,14 +14,32 @@ namespace gtkpp {
|
|||||||
protected:
|
protected:
|
||||||
GtkWidget* _widget;
|
GtkWidget* _widget;
|
||||||
|
|
||||||
|
private:
|
||||||
|
sigc::signal<void()> _signalClicked;
|
||||||
|
|
||||||
|
private:
|
||||||
|
friend void clickedCallback(GtkButton*, void* data);
|
||||||
|
|
||||||
|
protected:
|
||||||
|
void setupSignals();
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
void onClick(const std::function<void()>& callback);
|
||||||
|
|
||||||
|
public:
|
||||||
|
Widget();
|
||||||
|
explicit Widget(GtkWidget* widget);
|
||||||
|
Widget(GtkBuilder* builder, const char* id);
|
||||||
[[nodiscard]] GtkWidget* gobj() const;
|
[[nodiscard]] GtkWidget* gobj() const;
|
||||||
void setMargins(int margin);
|
void setMargins(int margin);
|
||||||
void setVerticalMargins(int margin);
|
void setVerticalMargins(int margin);
|
||||||
void setHorizontalMargins(int margin);
|
void setHorizontalMargins(int margin);
|
||||||
void setVAlign(GtkAlign align);
|
void setVAlign(GtkAlign align);
|
||||||
void setVExpand(bool expand);
|
void setVExpand(bool expand);
|
||||||
|
void setHExpand(bool expand);
|
||||||
void setEnabled(bool enabled);
|
void setEnabled(bool enabled);
|
||||||
|
void show();
|
||||||
|
void hide();
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -3,6 +3,7 @@
|
|||||||
//
|
//
|
||||||
|
|
||||||
#include "Window.h"
|
#include "Window.h"
|
||||||
|
#include "../App.h"
|
||||||
|
|
||||||
namespace gtkpp {
|
namespace gtkpp {
|
||||||
|
|
||||||
@ -10,29 +11,31 @@ namespace gtkpp {
|
|||||||
return wnd1._window == wnd2._window;
|
return wnd1._window == wnd2._window;
|
||||||
}
|
}
|
||||||
|
|
||||||
Window::Window(std::shared_ptr<Application> app, bool isAppWindow) {
|
Window::Window() {
|
||||||
|
_window = nullptr;
|
||||||
|
_builder = nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
Window::Window(bool isAppWindow): _isAppWindow(isAppWindow) {
|
||||||
if(isAppWindow) {
|
if(isAppWindow) {
|
||||||
_window = GTK_WINDOW(adw_application_window_new(GTK_APPLICATION(app->gobj())));
|
auto app = GTK_APPLICATION(App::instance().gobj());
|
||||||
|
_window = GTK_WINDOW(adw_application_window_new(app));
|
||||||
} else {
|
} else {
|
||||||
_window = GTK_WINDOW(adw_window_new());
|
_window = GTK_WINDOW(adw_window_new());
|
||||||
}
|
}
|
||||||
|
|
||||||
_app = app;
|
|
||||||
_builder = nullptr;
|
_builder = nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
Window::Window(std::shared_ptr<Application> app, const char* resourceName) {
|
Window::Window(const char* resourceName, const char* id) {
|
||||||
_app = app;
|
|
||||||
// _builder = gtk_builder_new();
|
|
||||||
//
|
|
||||||
// GError* error = nullptr;
|
|
||||||
// gtk_builder_add_from_resource(_builder, resourceName, &error);
|
|
||||||
// if(error) {
|
|
||||||
// throw std::runtime_error(error->message);
|
|
||||||
// }
|
|
||||||
|
|
||||||
_builder = gtk_builder_new_from_resource(resourceName);
|
_builder = gtk_builder_new_from_resource(resourceName);
|
||||||
_window = GTK_WINDOW(gtk_builder_get_object(_builder, "adw_main_window"));
|
_window = GTK_WINDOW(gtk_builder_get_object(_builder, id));
|
||||||
|
}
|
||||||
|
|
||||||
|
Window::~Window() {
|
||||||
|
if(_window) {
|
||||||
|
destroy();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Window::show() {
|
void Window::show() {
|
||||||
@ -51,12 +54,32 @@ namespace gtkpp {
|
|||||||
gtk_window_set_default_size(GTK_WINDOW(_window), width, height);
|
gtk_window_set_default_size(GTK_WINDOW(_window), width, height);
|
||||||
}
|
}
|
||||||
|
|
||||||
std::shared_ptr<Application> Window::application() const {
|
|
||||||
return _app.lock();
|
|
||||||
}
|
|
||||||
|
|
||||||
void Window::hide() {
|
void Window::hide() {
|
||||||
gtk_window_close(GTK_WINDOW(_window));
|
gtk_window_close(GTK_WINDOW(_window));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Window::destroy() {
|
||||||
|
gtk_window_destroy(GTK_WINDOW(_window));
|
||||||
|
}
|
||||||
|
|
||||||
|
void Window::setTransientFor(const Window* window) {
|
||||||
|
gtk_window_set_transient_for(_window, window->gobj());
|
||||||
|
}
|
||||||
|
|
||||||
|
void Window::setModal() {
|
||||||
|
gtk_window_set_modal(_window, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Window::setContent(const Widget& widget) {
|
||||||
|
if(_isAppWindow) {
|
||||||
|
adw_application_window_set_content(ADW_APPLICATION_WINDOW(_window), widget.gobj());
|
||||||
|
} else {
|
||||||
|
adw_window_set_content(ADW_WINDOW(_window), widget.gobj());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void Window::setResizable(bool resizable) {
|
||||||
|
gtk_window_set_resizable(_window, resizable);
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -6,6 +6,8 @@
|
|||||||
#define AUTOCAT_GNOME_WINDOW_H
|
#define AUTOCAT_GNOME_WINDOW_H
|
||||||
|
|
||||||
#include "Application.h"
|
#include "Application.h"
|
||||||
|
#include "Widget.h"
|
||||||
|
|
||||||
#include <adwaita.h>
|
#include <adwaita.h>
|
||||||
#include <memory>
|
#include <memory>
|
||||||
|
|
||||||
@ -15,22 +17,29 @@ namespace gtkpp {
|
|||||||
protected:
|
protected:
|
||||||
GtkBuilder* _builder;
|
GtkBuilder* _builder;
|
||||||
GtkWindow* _window;
|
GtkWindow* _window;
|
||||||
std::weak_ptr<Application> _app;
|
bool _isAppWindow;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
friend bool operator==(const Window& wnd1, const Window& wnd2);
|
friend bool operator==(const Window& wnd1, const Window& wnd2);
|
||||||
|
|
||||||
public:
|
public:
|
||||||
Window(std::shared_ptr<Application> app, bool isAppWindow);
|
Window();
|
||||||
Window(std::shared_ptr<Application> app, const char* resourceName);
|
explicit Window(bool isAppWindow);
|
||||||
|
Window(const char* resourceName, const char* id);
|
||||||
|
virtual ~Window();
|
||||||
void show();
|
void show();
|
||||||
void hide();
|
void hide();
|
||||||
|
void destroy();
|
||||||
void setTitle(const std::string& title);
|
void setTitle(const std::string& title);
|
||||||
void setDefaultSize(int width, int height);
|
void setDefaultSize(int width, int height);
|
||||||
|
void setTransientFor(const Window* window);
|
||||||
|
void setModal();
|
||||||
[[nodiscard]] GtkWindow* gobj() const;
|
[[nodiscard]] GtkWindow* gobj() const;
|
||||||
[[nodiscard]] std::shared_ptr<Application> application() const;
|
void setContent(const Widget& widget);
|
||||||
|
void setResizable(bool resizable);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
using WindowPtr = std::shared_ptr<Window>;
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif //AUTOCAT_GNOME_WINDOW_H
|
#endif //AUTOCAT_GNOME_WINDOW_H
|
||||||
|
|||||||
35
gui/AddNumberDialog.cpp
Normal file
35
gui/AddNumberDialog.cpp
Normal file
@ -0,0 +1,35 @@
|
|||||||
|
//
|
||||||
|
// Created by selim on 17.05.2022.
|
||||||
|
//
|
||||||
|
|
||||||
|
#include "AddNumberDialog.h"
|
||||||
|
#include "../services/Api.h"
|
||||||
|
#include "../services/Storage.h"
|
||||||
|
|
||||||
|
#include <iostream>
|
||||||
|
#include <algorithm>
|
||||||
|
#include <cctype>
|
||||||
|
|
||||||
|
AddNumberDialog::AddNumberDialog(gtkpp::Window* parent): gtkpp::Dialog(parent) {
|
||||||
|
auto content = contentWidget();
|
||||||
|
_entry.setMargins(16);
|
||||||
|
_entry.setPlaceholder("Plate number");
|
||||||
|
content.append(_entry);
|
||||||
|
content.append(_spinner);
|
||||||
|
_spinner.setMargins(16);
|
||||||
|
_spinner.hide();
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string AddNumberDialog::text() const {
|
||||||
|
return _entry.text();
|
||||||
|
}
|
||||||
|
|
||||||
|
cc::result<void> AddNumberDialog::checkNumber() {
|
||||||
|
_spinner.show();
|
||||||
|
_spinner.start();
|
||||||
|
std::string text = _entry.text();
|
||||||
|
std::transform(text.begin(), text.end(), text.begin(), [](unsigned char c){ return std::toupper(c); });
|
||||||
|
auto vehicle = co_await Api::check(text);
|
||||||
|
Storage::instance().insert(&vehicle);
|
||||||
|
}
|
||||||
|
|
||||||
29
gui/AddNumberDialog.h
Normal file
29
gui/AddNumberDialog.h
Normal file
@ -0,0 +1,29 @@
|
|||||||
|
//
|
||||||
|
// Created by selim on 17.05.2022.
|
||||||
|
//
|
||||||
|
|
||||||
|
#ifndef AUTOCAT_GNOME_ADDNUMBERDIALOG_H
|
||||||
|
#define AUTOCAT_GNOME_ADDNUMBERDIALOG_H
|
||||||
|
|
||||||
|
#include "../gtkpp/Dialog.h"
|
||||||
|
#include "../gtkpp/Entry.h"
|
||||||
|
#include "../gtkpp/Spinner.h"
|
||||||
|
|
||||||
|
#include <concurrencpp/concurrencpp.h>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
namespace cc = concurrencpp;
|
||||||
|
|
||||||
|
class AddNumberDialog: public gtkpp::Dialog {
|
||||||
|
private:
|
||||||
|
gtkpp::Entry _entry;
|
||||||
|
gtkpp::Spinner _spinner;
|
||||||
|
|
||||||
|
public:
|
||||||
|
explicit AddNumberDialog(gtkpp::Window* parent);
|
||||||
|
std::string text() const;
|
||||||
|
cc::result<void> checkNumber();
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
#endif //AUTOCAT_GNOME_ADDNUMBERDIALOG_H
|
||||||
@ -5,17 +5,14 @@
|
|||||||
#include "LoginWindow.h"
|
#include "LoginWindow.h"
|
||||||
#include "MainWindow.h"
|
#include "MainWindow.h"
|
||||||
#include "../services/Api.h"
|
#include "../services/Api.h"
|
||||||
#include "../coro/GLibMainContextExecutor.h"
|
|
||||||
|
|
||||||
#include "../gtkpp/HeaderBar.h"
|
#include "../gtkpp/HeaderBar.h"
|
||||||
#include "../gtkpp/MessageDialog.h"
|
#include "../gtkpp/MessageDialog.h"
|
||||||
|
#include "../App.h"
|
||||||
|
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
#include <utility>
|
#include <utility>
|
||||||
#include <folly/experimental/coro/Task.h>
|
|
||||||
#include <folly/executors/IOThreadPoolExecutor.h>
|
|
||||||
|
|
||||||
LoginWindow::LoginWindow(std::shared_ptr<gtkpp::Application> app): gtkpp::Window(std::move(app), false) {
|
LoginWindow::LoginWindow(): gtkpp::Window(false) {
|
||||||
|
|
||||||
setDefaultSize(640, 480);
|
setDefaultSize(640, 480);
|
||||||
|
|
||||||
@ -46,7 +43,7 @@ LoginWindow::LoginWindow(std::shared_ptr<gtkpp::Application> app): gtkpp::Window
|
|||||||
rootBox.append(gtkpp::HeaderBar("Login"));
|
rootBox.append(gtkpp::HeaderBar("Login"));
|
||||||
rootBox.append(contentBox);
|
rootBox.append(contentBox);
|
||||||
|
|
||||||
adw_window_set_content(ADW_WINDOW(_window), rootBox.gobj());
|
setContent(rootBox);
|
||||||
}
|
}
|
||||||
|
|
||||||
void LoginWindow::loginClicked() {
|
void LoginWindow::loginClicked() {
|
||||||
@ -57,14 +54,12 @@ void LoginWindow::loginClicked() {
|
|||||||
_spinner.start();
|
_spinner.start();
|
||||||
|
|
||||||
try {
|
try {
|
||||||
User user = co_await Api::login(email, password).scheduleOn(GLibMainContextExecutor::instance());
|
User user = co_await Api::login(email, password);
|
||||||
if(auto app = this->application()) {
|
auto mainWindow = std::make_shared<MainWindow>();
|
||||||
auto mainWindow = std::make_shared<MainWindow>(app);
|
mainWindow->show();
|
||||||
mainWindow->show();
|
App::instance().addWindow(mainWindow);
|
||||||
app->addWindow(mainWindow);
|
App::instance().removeWindow(this);
|
||||||
app->removeWindow(this);
|
hide();
|
||||||
hide();
|
|
||||||
}
|
|
||||||
} catch (std::exception& ex) {
|
} catch (std::exception& ex) {
|
||||||
enableControls(true);
|
enableControls(true);
|
||||||
_spinner.stop();
|
_spinner.stop();
|
||||||
|
|||||||
@ -11,7 +11,6 @@
|
|||||||
#include "../gtkpp/Entry.h"
|
#include "../gtkpp/Entry.h"
|
||||||
#include "../gtkpp/Button.h"
|
#include "../gtkpp/Button.h"
|
||||||
#include "../gtkpp/Spinner.h"
|
#include "../gtkpp/Spinner.h"
|
||||||
#include "../gtkpp/Application.h"
|
|
||||||
|
|
||||||
class LoginWindow: public gtkpp::Window {
|
class LoginWindow: public gtkpp::Window {
|
||||||
private:
|
private:
|
||||||
@ -21,7 +20,7 @@ private:
|
|||||||
gtkpp::Spinner _spinner;
|
gtkpp::Spinner _spinner;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
explicit LoginWindow(std::shared_ptr<gtkpp::Application> app);
|
LoginWindow();
|
||||||
|
|
||||||
void loginClicked();
|
void loginClicked();
|
||||||
void validateFields();
|
void validateFields();
|
||||||
|
|||||||
@ -3,15 +3,62 @@
|
|||||||
//
|
//
|
||||||
|
|
||||||
#include "MainWindow.h"
|
#include "MainWindow.h"
|
||||||
#include "../gtkpp/Box.h"
|
#include "AddNumberDialog.h"
|
||||||
|
#include "../gtkpp/MessageDialog.h"
|
||||||
|
#include "../coro/Coro.h"
|
||||||
|
#include "../services/Storage.h"
|
||||||
#include "../gtkpp/HeaderBar.h"
|
#include "../gtkpp/HeaderBar.h"
|
||||||
|
#include "../gtkpp/Separator.h"
|
||||||
|
#include "../gtkpp/SelectionModel.h"
|
||||||
|
|
||||||
MainWindow::MainWindow(std::shared_ptr<gtkpp::Application> app): gtkpp::Window(std::move(app), "/gui/MainWindow.xml") {
|
#include <iostream>
|
||||||
|
|
||||||
// gtkpp::Box rootBox(GTK_ORIENTATION_VERTICAL, 0);
|
MainWindow::MainWindow(): gtkpp::Window(true),
|
||||||
// rootBox.append(gtkpp::HeaderBar("Main"));
|
_vehiclesListView(gtkpp::SelectionModel(gtkpp::Selection::Single),
|
||||||
//
|
&_vehiclesListFactory) {
|
||||||
// _leaflet.append(&rootBox);
|
|
||||||
//
|
setDefaultSize(640, 480);
|
||||||
// adw_application_window_set_content(ADW_APPLICATION_WINDOW(_window), _leaflet.gobj());
|
setResizable(true);
|
||||||
|
|
||||||
|
_addNumberButton.setIconName("list-add-symbolic");
|
||||||
|
_addNumberButton.onClick([this] {
|
||||||
|
showCheckDialog();
|
||||||
|
});
|
||||||
|
|
||||||
|
gtkpp::HeaderBar leftHeader("Vehicles");
|
||||||
|
leftHeader.showEndButtons(false);
|
||||||
|
leftHeader.packStart(_addNumberButton);
|
||||||
|
|
||||||
|
gtkpp::Box leftPanel(GTK_ORIENTATION_VERTICAL, 0);
|
||||||
|
leftPanel.append(leftHeader);
|
||||||
|
leftPanel.append(_vehiclesListView);
|
||||||
|
|
||||||
|
gtkpp::HeaderBar rightHeader;
|
||||||
|
gtkpp::Box rightPanel(GTK_ORIENTATION_VERTICAL, 0);
|
||||||
|
rightPanel.append(rightHeader);
|
||||||
|
rightPanel.setHExpand(true);
|
||||||
|
|
||||||
|
_leaflet.append(leftPanel);
|
||||||
|
_leaflet.append(gtkpp::Separator(GTK_ORIENTATION_VERTICAL));
|
||||||
|
_leaflet.append(rightPanel);
|
||||||
|
_leaflet.setVExpand(true);
|
||||||
|
|
||||||
|
setContent(_leaflet);
|
||||||
|
|
||||||
|
auto vehicles = Storage::instance().select<Vehicle>();
|
||||||
|
std::cout << "" << std::endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
void MainWindow::showCheckDialog() {
|
||||||
|
AddNumberDialog dialog(this);
|
||||||
|
dialog.show();
|
||||||
|
GtkResponseType response = co_await dialog.responseAsync();
|
||||||
|
|
||||||
|
if(response == GTK_RESPONSE_OK) {
|
||||||
|
try {
|
||||||
|
co_await dialog.checkNumber();
|
||||||
|
} catch(std::exception& ex) {
|
||||||
|
gtkpp::MessageDialog::showError(this, ex.what());
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -7,13 +7,21 @@
|
|||||||
|
|
||||||
#include "../gtkpp/Window.h"
|
#include "../gtkpp/Window.h"
|
||||||
#include "../gtkpp/Leaflet.h"
|
#include "../gtkpp/Leaflet.h"
|
||||||
|
#include "../gtkpp/Button.h"
|
||||||
|
#include "../gtkpp/ListView.h"
|
||||||
|
#include "../models/VehiclesListFactory.h"
|
||||||
|
|
||||||
class MainWindow: public gtkpp::Window {
|
class MainWindow: public gtkpp::Window {
|
||||||
private:
|
private:
|
||||||
gtkpp::Leaflet _leaflet;
|
gtkpp::Leaflet _leaflet;
|
||||||
|
gtkpp::Button _addNumberButton;
|
||||||
|
|
||||||
|
VehiclesListFactory _vehiclesListFactory;
|
||||||
|
gtkpp::ListView _vehiclesListView;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
explicit MainWindow(std::shared_ptr<gtkpp::Application> app);
|
explicit MainWindow();
|
||||||
|
void showCheckDialog();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@ -31,6 +31,12 @@
|
|||||||
</object>
|
</object>
|
||||||
</property>
|
</property>
|
||||||
|
|
||||||
|
<child type="start">
|
||||||
|
<object class="GtkButton" id="add_number_button">
|
||||||
|
<property name="icon-name">list-add</property>
|
||||||
|
</object>
|
||||||
|
</child>
|
||||||
|
|
||||||
<child type="end">
|
<child type="end">
|
||||||
<object class="GtkMenuButton" id="gtk_btnHeaderHelp">
|
<object class="GtkMenuButton" id="gtk_btnHeaderHelp">
|
||||||
<property name="direction">none</property>
|
<property name="direction">none</property>
|
||||||
|
|||||||
5
gui/custom/PlateView.c
Normal file
5
gui/custom/PlateView.c
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
//
|
||||||
|
// Created by selim on 01.06.2022.
|
||||||
|
//
|
||||||
|
|
||||||
|
#include "PlateView.h"
|
||||||
25
gui/custom/PlateView.h
Normal file
25
gui/custom/PlateView.h
Normal file
@ -0,0 +1,25 @@
|
|||||||
|
//
|
||||||
|
// Created by selim on 01.06.2022.
|
||||||
|
//
|
||||||
|
|
||||||
|
#ifndef AUTOCAT_GNOME_PLATEVIEW_H
|
||||||
|
#define AUTOCAT_GNOME_PLATEVIEW_H
|
||||||
|
|
||||||
|
#include <gtk/gtk.h>
|
||||||
|
|
||||||
|
#define PLATEVIEW(obj) GTK_CHECK_CAST(obj, plateview_get_type(), PlateView)
|
||||||
|
#define PLATEVIEW_CLASS(klass) GTK_CHECK_CLASS_CAST(klass, plateview_get_type(), PlateViewClass)
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
|
||||||
|
} PlateView;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
GtkWidgetClass parent_class;
|
||||||
|
} PlateViewClass;
|
||||||
|
|
||||||
|
guint plateview_get_type (void);
|
||||||
|
GtkWidget* plateview_new (void);
|
||||||
|
void plateview_clear (PlateView* view);
|
||||||
|
|
||||||
|
#endif //AUTOCAT_GNOME_PLATEVIEW_H
|
||||||
19
main.cpp
19
main.cpp
@ -3,32 +3,31 @@
|
|||||||
#include "services/Settings.h"
|
#include "services/Settings.h"
|
||||||
#include "gtkpp/Application.h"
|
#include "gtkpp/Application.h"
|
||||||
#include "gtkpp/Window.h"
|
#include "gtkpp/Window.h"
|
||||||
|
#include "App.h"
|
||||||
|
|
||||||
#include <memory>
|
#include <memory>
|
||||||
#include <folly/init/Init.h>
|
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
|
|
||||||
std::shared_ptr<gtkpp::Window> createMainWindow(std::shared_ptr<gtkpp::Application> app) {
|
std::shared_ptr<gtkpp::Window> createMainWindow() {
|
||||||
auto settings = Settings::instance();
|
auto settings = Settings::instance();
|
||||||
if(settings.user().token.empty()) {
|
if(settings.user().token.empty()) {
|
||||||
return std::make_shared<LoginWindow>(app);
|
return std::make_shared<LoginWindow>();
|
||||||
} else {
|
} else {
|
||||||
return std::make_shared<MainWindow>(app);
|
return std::make_shared<MainWindow>();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
int main(int argc, char* argv[]) {
|
int main(int argc, char* argv[]) {
|
||||||
|
|
||||||
folly::init(&argc, &argv);
|
|
||||||
g_resources_register(g_resource_load("resources.gresource", nullptr));
|
g_resources_register(g_resource_load("resources.gresource", nullptr));
|
||||||
|
|
||||||
auto app = std::make_shared<gtkpp::Application>("pro.aliencat.autocat");
|
auto app = App::instance(); //std::make_shared<gtkpp::Application>("pro.aliencat.autocat");
|
||||||
|
|
||||||
app->onActivate([&](){
|
app.onActivate([&](){
|
||||||
auto window = createMainWindow(app);
|
auto window = createMainWindow();
|
||||||
app->addWindow(window);
|
app.addWindow(window);
|
||||||
window->show();
|
window->show();
|
||||||
});
|
});
|
||||||
|
|
||||||
return app->run(argc, argv);
|
return app.run(argc, argv);
|
||||||
}
|
}
|
||||||
|
|||||||
5
models/Engine.cpp
Normal file
5
models/Engine.cpp
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
//
|
||||||
|
// Created by selim on 06.11.22.
|
||||||
|
//
|
||||||
|
|
||||||
|
#include "Engine.h"
|
||||||
21
models/Engine.h
Normal file
21
models/Engine.h
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
//
|
||||||
|
// Created by selim on 06.11.22.
|
||||||
|
//
|
||||||
|
|
||||||
|
#ifndef AUTOCAT_GNOME_ENGINE_H
|
||||||
|
#define AUTOCAT_GNOME_ENGINE_H
|
||||||
|
|
||||||
|
#include <nlohmann/json.hpp>
|
||||||
|
|
||||||
|
class Engine {
|
||||||
|
public:
|
||||||
|
std::string number;
|
||||||
|
int volume;
|
||||||
|
float powerHp;
|
||||||
|
float powerKw;
|
||||||
|
std::string fuelType;
|
||||||
|
|
||||||
|
NLOHMANN_DEFINE_TYPE_INTRUSIVE(Engine, number, volume, powerHp, powerKw, fuelType)
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif //AUTOCAT_GNOME_ENGINE_H
|
||||||
75
models/JsonOptional.h
Normal file
75
models/JsonOptional.h
Normal file
@ -0,0 +1,75 @@
|
|||||||
|
//
|
||||||
|
// Created by selim on 06.11.22.
|
||||||
|
//
|
||||||
|
|
||||||
|
#ifndef AUTOCAT_GNOME_JSONOPTIONAL_H
|
||||||
|
#define AUTOCAT_GNOME_JSONOPTIONAL_H
|
||||||
|
|
||||||
|
#include <nlohmann/json.hpp>
|
||||||
|
#include <iostream>
|
||||||
|
|
||||||
|
namespace nlohmann {
|
||||||
|
|
||||||
|
template<class J, class T>
|
||||||
|
void optional_to_json(J& j, const char* name, const std::optional<T>& value)
|
||||||
|
{
|
||||||
|
if (value)
|
||||||
|
{
|
||||||
|
j[name] = *value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
template<class J, class T>
|
||||||
|
void optional_from_json(const J& j, const char* name, std::optional<T>& value)
|
||||||
|
{
|
||||||
|
const auto it = j.find(name);
|
||||||
|
if (it != j.end())
|
||||||
|
{
|
||||||
|
if(j.at(name).is_null()) {
|
||||||
|
value = std::nullopt;
|
||||||
|
} else {
|
||||||
|
value = it->template get<T>();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
value = std::nullopt;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename>
|
||||||
|
constexpr bool is_optional = false;
|
||||||
|
template <typename T>
|
||||||
|
constexpr bool is_optional<std::optional<T>> = true;
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
void extended_to_json(const char *key, nlohmann::json &j, const T &value) {
|
||||||
|
if constexpr (is_optional<T>)
|
||||||
|
optional_to_json(j, key, value);
|
||||||
|
else
|
||||||
|
j[key] = value;
|
||||||
|
}
|
||||||
|
template <typename T>
|
||||||
|
void extended_from_json(const char *key, const nlohmann::json &j, T &value) {
|
||||||
|
//std::cout << "parsing key " << key << std::endl;
|
||||||
|
if constexpr (is_optional<T>) {
|
||||||
|
optional_from_json(j, key, value);
|
||||||
|
} else {
|
||||||
|
j.at(key).get_to(value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#define EXTEND_JSON_TO(v1) extended_to_json(#v1, nlohmann_json_j, nlohmann_json_t.v1);
|
||||||
|
#define EXTEND_JSON_FROM(v1) extended_from_json(#v1, nlohmann_json_j, nlohmann_json_t.v1);
|
||||||
|
|
||||||
|
#define NLOHMANN_JSONIFY_ALL_THINGS(Type, ...) \
|
||||||
|
friend void to_json(nlohmann::json &nlohmann_json_j, const Type &nlohmann_json_t) { \
|
||||||
|
NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE(EXTEND_JSON_TO, __VA_ARGS__)) \
|
||||||
|
} \
|
||||||
|
friend void from_json(const nlohmann::json &nlohmann_json_j, Type &nlohmann_json_t) { \
|
||||||
|
NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE(EXTEND_JSON_FROM, __VA_ARGS__)) \
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif //AUTOCAT_GNOME_JSONOPTIONAL_H
|
||||||
@ -19,6 +19,7 @@ public:
|
|||||||
public:
|
public:
|
||||||
User() = default;
|
User() = default;
|
||||||
User(const User& user) = default;
|
User(const User& user) = default;
|
||||||
|
User(User&&) = default;
|
||||||
User(std::string_view email, std::string_view token);
|
User(std::string_view email, std::string_view token);
|
||||||
|
|
||||||
NLOHMANN_DEFINE_TYPE_INTRUSIVE(User, email, token)
|
NLOHMANN_DEFINE_TYPE_INTRUSIVE(User, email, token)
|
||||||
|
|||||||
91
models/Vehicle.cpp
Normal file
91
models/Vehicle.cpp
Normal file
@ -0,0 +1,91 @@
|
|||||||
|
//
|
||||||
|
// Created by selim on 03.10.22.
|
||||||
|
//
|
||||||
|
|
||||||
|
#include <fmt/core.h>
|
||||||
|
#include "Vehicle.h"
|
||||||
|
|
||||||
|
std::string Vehicle::createTableQuery() {
|
||||||
|
return R"(
|
||||||
|
CREATE TABLE IF NOT EXISTS vehicles(
|
||||||
|
number TEXT NOT NULL PRIMARY KEY,
|
||||||
|
currentNumber TEXT,
|
||||||
|
color TEXT,
|
||||||
|
category TEXT,
|
||||||
|
year INT,
|
||||||
|
addedDate REAL,
|
||||||
|
updatedDate REAL,
|
||||||
|
vin1 TEXT,
|
||||||
|
vin2 TEXT,
|
||||||
|
sts TEXT,
|
||||||
|
pts TEXT,
|
||||||
|
addedBy TEXT,
|
||||||
|
engineNumber TEXT,
|
||||||
|
engineVolume INT,
|
||||||
|
enginePowerHp REAL,
|
||||||
|
enginePowerKw REAL,
|
||||||
|
engineFuelType TEXT
|
||||||
|
);
|
||||||
|
)";
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string Vehicle::insertQuery() {
|
||||||
|
return fmt::format(R"(
|
||||||
|
INSERT INTO vehicles(number,
|
||||||
|
currentNumber,
|
||||||
|
color,
|
||||||
|
category,
|
||||||
|
year,
|
||||||
|
addedDate,
|
||||||
|
updatedDate,
|
||||||
|
vin1, vin2,
|
||||||
|
sts, pts,
|
||||||
|
addedBy,
|
||||||
|
engineNumber,
|
||||||
|
engineVolume,
|
||||||
|
enginePowerHp,
|
||||||
|
enginePowerKw,
|
||||||
|
engineFuelType)
|
||||||
|
VALUES('{}', '{}', '{}', '{}', '{}', '{}', '{}', '{}', '{}', '{}', '{}', '{}', '{}', '{}', '{}', '{}', '{}')
|
||||||
|
)",
|
||||||
|
number,
|
||||||
|
currentNumber,
|
||||||
|
color.value_or("NULL"),
|
||||||
|
category,
|
||||||
|
year,
|
||||||
|
addedDate,
|
||||||
|
updatedDate,
|
||||||
|
vin1,
|
||||||
|
vin2.value_or("NULL"),
|
||||||
|
sts, pts,
|
||||||
|
addedBy,
|
||||||
|
engine.number,
|
||||||
|
engine.volume,
|
||||||
|
engine.powerHp,
|
||||||
|
engine.powerKw,
|
||||||
|
engine.fuelType);
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string Vehicle::selectQuery() {
|
||||||
|
return "SELECT * FROM vehicles";
|
||||||
|
}
|
||||||
|
|
||||||
|
Vehicle::Vehicle(sqlite3_stmt *stmt) {
|
||||||
|
number = readString(stmt, 0);
|
||||||
|
currentNumber = readString(stmt, 1);
|
||||||
|
color = readStringOptional(stmt, 2);
|
||||||
|
category = readString(stmt, 3);
|
||||||
|
year = readInt(stmt, 4);
|
||||||
|
addedDate = readDouble(stmt, 5);
|
||||||
|
updatedDate = readDouble(stmt, 6);
|
||||||
|
vin1 = readString(stmt, 7);
|
||||||
|
vin2 = readStringOptional(stmt, 8);
|
||||||
|
sts = readString(stmt, 9);
|
||||||
|
pts = readString(stmt, 10);
|
||||||
|
addedBy = readString(stmt, 11);
|
||||||
|
engine.number = readString(stmt, 12);
|
||||||
|
engine.volume = readInt(stmt, 13);
|
||||||
|
engine.powerHp = readDouble(stmt, 14);
|
||||||
|
engine.powerKw = readDouble(stmt, 15);
|
||||||
|
engine.fuelType = readString(stmt, 16);
|
||||||
|
}
|
||||||
42
models/Vehicle.h
Normal file
42
models/Vehicle.h
Normal file
@ -0,0 +1,42 @@
|
|||||||
|
//
|
||||||
|
// Created by selim on 03.10.22.
|
||||||
|
//
|
||||||
|
|
||||||
|
#ifndef AUTOCAT_GNOME_VEHICLE_H
|
||||||
|
#define AUTOCAT_GNOME_VEHICLE_H
|
||||||
|
|
||||||
|
#include "../services/IDBEntity.h"
|
||||||
|
#include "Engine.h"
|
||||||
|
#include "JsonOptional.h"
|
||||||
|
|
||||||
|
#include <optional>
|
||||||
|
#include <sqlite3.h>
|
||||||
|
|
||||||
|
class Vehicle: public IDBEntity {
|
||||||
|
public:
|
||||||
|
std::string number;
|
||||||
|
std::string currentNumber;
|
||||||
|
std::optional<std::string> color;
|
||||||
|
std::string category;
|
||||||
|
int year;
|
||||||
|
double addedDate;
|
||||||
|
double updatedDate;
|
||||||
|
std::string vin1;
|
||||||
|
std::optional<std::string> vin2;
|
||||||
|
std::string sts;
|
||||||
|
std::string pts;
|
||||||
|
std::string addedBy;
|
||||||
|
Engine engine;
|
||||||
|
|
||||||
|
public:
|
||||||
|
Vehicle() = default;
|
||||||
|
explicit Vehicle(sqlite3_stmt* stmt);
|
||||||
|
static std::string createTableQuery();
|
||||||
|
static std::string selectQuery();
|
||||||
|
std::string insertQuery() override;
|
||||||
|
|
||||||
|
NLOHMANN_JSONIFY_ALL_THINGS(Vehicle, number, currentNumber, color, category, year, addedDate, updatedDate, vin1, vin2, sts, pts, addedBy, engine)
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
#endif //AUTOCAT_GNOME_VEHICLE_H
|
||||||
21
models/VehiclesListFactory.cpp
Normal file
21
models/VehiclesListFactory.cpp
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
//
|
||||||
|
// Created by selim on 13.11.22.
|
||||||
|
//
|
||||||
|
|
||||||
|
#include "VehiclesListFactory.h"
|
||||||
|
#include "../gtkpp/Label.h"
|
||||||
|
|
||||||
|
#include <iostream>
|
||||||
|
|
||||||
|
VehiclesListFactory::VehiclesListFactory() {
|
||||||
|
}
|
||||||
|
|
||||||
|
GtkWidget* VehiclesListFactory::setup() {
|
||||||
|
gtkpp::Label label;
|
||||||
|
return label.gobj();
|
||||||
|
}
|
||||||
|
|
||||||
|
void VehiclesListFactory::bind(GtkWidget *widget) {
|
||||||
|
gtkpp::Label label(widget);
|
||||||
|
label.setText("qwe");
|
||||||
|
}
|
||||||
20
models/VehiclesListFactory.h
Normal file
20
models/VehiclesListFactory.h
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
//
|
||||||
|
// Created by selim on 13.11.22.
|
||||||
|
//
|
||||||
|
|
||||||
|
#ifndef AUTOCAT_GNOME_VEHICLESLISTFACTORY_H
|
||||||
|
#define AUTOCAT_GNOME_VEHICLESLISTFACTORY_H
|
||||||
|
|
||||||
|
#include "../gtkpp/ListItemFactory.h"
|
||||||
|
|
||||||
|
class VehiclesListFactory: public gtkpp::ListItemFactory {
|
||||||
|
public:
|
||||||
|
VehiclesListFactory();
|
||||||
|
|
||||||
|
public:
|
||||||
|
GtkWidget* setup() override;
|
||||||
|
void bind(GtkWidget* widget) override;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
#endif //AUTOCAT_GNOME_VEHICLESLISTFACTORY_H
|
||||||
@ -5,53 +5,45 @@
|
|||||||
#include "Api.h"
|
#include "Api.h"
|
||||||
#include "Settings.h"
|
#include "Settings.h"
|
||||||
#include <memory>
|
#include <memory>
|
||||||
#include <folly/futures/Promise.h>
|
|
||||||
|
|
||||||
template<class...Args>
|
const std::string Api::_baseUrl = "http://127.0.0.1:3000/"; //"https://vps.aliencat.pro:8443/";
|
||||||
struct Callback {
|
|
||||||
void(*function)(Args..., void*) = nullptr;
|
|
||||||
void* state = nullptr;
|
|
||||||
};
|
|
||||||
|
|
||||||
template<typename... Args, typename Lambda>
|
|
||||||
Callback<Args...> voidify(Lambda&& l) {
|
|
||||||
using Func = typename std::decay<Lambda>::type;
|
|
||||||
auto data = new Func(std::forward<Lambda>(l));
|
|
||||||
return {
|
|
||||||
+[](Args... args, void* v)->void {
|
|
||||||
Func* f = static_cast< Func* >(v);
|
|
||||||
(*f)(std::forward<Args>(args)...);
|
|
||||||
delete f;
|
|
||||||
},
|
|
||||||
data
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
const std::string Api::_baseUrl = "https://vps.aliencat.pro:8443/";
|
|
||||||
SoupSession* Api::_session = soup_session_new();
|
SoupSession* Api::_session = soup_session_new();
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
folly::Future<T> Api::post(const std::string &method, const nlohmann::json& params) {
|
void callback(SoupSession* session, SoupMessage* message, gpointer userData) {
|
||||||
|
auto promise = reinterpret_cast<cc::result_promise<T>*>(userData);
|
||||||
|
|
||||||
|
if(message->status_code >= 200 && message->status_code < 300) {
|
||||||
|
auto responseString = std::string(message->response_body->data, message->response_body->length);
|
||||||
|
auto json = nlohmann::json::parse(responseString);
|
||||||
|
if(json["success"].get<bool>()) {
|
||||||
|
//std::cout << "response: " << responseString << std::endl;
|
||||||
|
auto data = json["data"].get<T>();
|
||||||
|
promise->set_result(data);
|
||||||
|
} else {
|
||||||
|
auto error = json["error"].get<std::string>();
|
||||||
|
promise->set_exception(std::make_exception_ptr(std::runtime_error(error)));
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
promise->set_exception(std::make_exception_ptr(std::runtime_error(message->reason_phrase)));
|
||||||
|
}
|
||||||
|
|
||||||
|
delete promise;
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
cc::result<T> Api::post(const std::string &method, const nlohmann::json& params) {
|
||||||
std::string url = _baseUrl + method;
|
std::string url = _baseUrl + method;
|
||||||
auto msg = soup_message_new(SOUP_METHOD_POST, url.c_str());
|
auto msg = soup_message_new(SOUP_METHOD_POST, url.c_str());
|
||||||
|
|
||||||
auto promise = std::make_shared<folly::Promise<T>>();
|
auto token = Settings::instance().user().token;
|
||||||
auto callback = voidify<SoupSession*, SoupMessage*>([&, promise](SoupSession* session, SoupMessage* message) {
|
if(!token.empty()) {
|
||||||
if(message->status_code >= 200 && message->status_code < 300) {
|
auto authHeader = "Bearer " + token;
|
||||||
auto responseString = std::string(message->response_body->data, message->response_body->length);
|
soup_message_headers_append(msg->request_headers, "Authorization", authHeader.c_str());
|
||||||
auto json = nlohmann::json::parse(responseString);
|
}
|
||||||
if(json["success"].get<bool>()) {
|
|
||||||
//std::cout << "response: " << responseString << std::endl;
|
auto promise = new cc::result_promise<T>();
|
||||||
auto user = json["data"].get<T>();
|
auto result = promise->get_result();
|
||||||
promise->setValue(user);
|
|
||||||
} else {
|
|
||||||
auto error = json["error"].get<std::string>();
|
|
||||||
promise->setException(std::runtime_error(error));
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
promise->setException(std::runtime_error(message->reason_phrase));
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
auto jsonStr = params.dump();
|
auto jsonStr = params.dump();
|
||||||
|
|
||||||
@ -60,12 +52,12 @@ folly::Future<T> Api::post(const std::string &method, const nlohmann::json& para
|
|||||||
jsonStr.c_str(),
|
jsonStr.c_str(),
|
||||||
jsonStr.size());
|
jsonStr.size());
|
||||||
|
|
||||||
soup_session_queue_message(_session, msg, callback.function, callback.state);
|
soup_session_queue_message(_session, msg, callback<T>, promise);
|
||||||
|
|
||||||
return promise->getFuture();
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
fc::Task<User> Api::login(std::string email, std::string password) {
|
cc::result<User> Api::login(std::string email, std::string password) {
|
||||||
|
|
||||||
nlohmann::json params = {
|
nlohmann::json params = {
|
||||||
{ "email", email },
|
{ "email", email },
|
||||||
@ -81,3 +73,12 @@ fc::Task<User> Api::login(std::string email, std::string password) {
|
|||||||
|
|
||||||
co_return user;
|
co_return user;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
cc::result<Vehicle> Api::check(const std::string& number, bool force) {
|
||||||
|
nlohmann::json params = {
|
||||||
|
{ "number", number },
|
||||||
|
{ "forceUpdate", force }
|
||||||
|
};
|
||||||
|
|
||||||
|
return post<Vehicle>("vehicles/check", params);
|
||||||
|
}
|
||||||
|
|||||||
@ -8,13 +8,13 @@
|
|||||||
#include <string>
|
#include <string>
|
||||||
#include <libsoup/soup.h>
|
#include <libsoup/soup.h>
|
||||||
#include <nlohmann/json.hpp>
|
#include <nlohmann/json.hpp>
|
||||||
#include <folly/futures/Future.h>
|
#include <concurrencpp/concurrencpp.h>
|
||||||
#include <folly/experimental/coro/Task.h>
|
|
||||||
|
|
||||||
#include "../models/User.h"
|
#include "../models/User.h"
|
||||||
|
#include "../models/Vehicle.h"
|
||||||
#include "../coro/Coro.h"
|
#include "../coro/Coro.h"
|
||||||
|
|
||||||
namespace fc = folly::coro;
|
namespace cc = concurrencpp;
|
||||||
|
|
||||||
class Api {
|
class Api {
|
||||||
private:
|
private:
|
||||||
@ -23,10 +23,11 @@ private:
|
|||||||
|
|
||||||
private:
|
private:
|
||||||
template<typename T>
|
template<typename T>
|
||||||
static folly::Future<T> post(const std::string& method, const nlohmann::json& params);
|
static cc::result<T> post(const std::string& method, const nlohmann::json& params);
|
||||||
|
|
||||||
public:
|
public:
|
||||||
static fc::Task<User> login(std::string email, std::string password);
|
static cc::result<User> login(std::string email, std::string password);
|
||||||
|
static cc::result<Vehicle> check(const std::string& number, bool force = false);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
41
services/IDBEntity.cpp
Normal file
41
services/IDBEntity.cpp
Normal file
@ -0,0 +1,41 @@
|
|||||||
|
//
|
||||||
|
// Created by selim on 09.11.22.
|
||||||
|
//
|
||||||
|
|
||||||
|
#include "IDBEntity.h"
|
||||||
|
|
||||||
|
std::string IDBEntity::readString(sqlite3_stmt *stmt, int column) {
|
||||||
|
return { reinterpret_cast<const char*>(sqlite3_column_text(stmt, column)) };
|
||||||
|
}
|
||||||
|
|
||||||
|
int IDBEntity::readInt(sqlite3_stmt *stmt, int column) {
|
||||||
|
return sqlite3_column_int(stmt, column);
|
||||||
|
}
|
||||||
|
|
||||||
|
double IDBEntity::readDouble(sqlite3_stmt *stmt, int column) {
|
||||||
|
return sqlite3_column_double(stmt, column);
|
||||||
|
}
|
||||||
|
|
||||||
|
StringOptional IDBEntity::readStringOptional(sqlite3_stmt *stmt, int column) {
|
||||||
|
if(sqlite3_column_type(stmt, column) == SQLITE_NULL) {
|
||||||
|
return std::nullopt;
|
||||||
|
} else {
|
||||||
|
return readString(stmt, column);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
IntOptional IDBEntity::readIntOptional(sqlite3_stmt *stmt, int column) {
|
||||||
|
if(sqlite3_column_type(stmt, column) == SQLITE_NULL) {
|
||||||
|
return std::nullopt;
|
||||||
|
} else {
|
||||||
|
return readInt(stmt, column);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
DoubleOptional IDBEntity::readDoubleOptional(sqlite3_stmt *stmt, int column) {
|
||||||
|
if(sqlite3_column_type(stmt, column) == SQLITE_NULL) {
|
||||||
|
return std::nullopt;
|
||||||
|
} else {
|
||||||
|
return readDouble(stmt, column);
|
||||||
|
}
|
||||||
|
}
|
||||||
31
services/IDBEntity.h
Normal file
31
services/IDBEntity.h
Normal file
@ -0,0 +1,31 @@
|
|||||||
|
//
|
||||||
|
// Created by selim on 06.11.22.
|
||||||
|
//
|
||||||
|
|
||||||
|
#ifndef AUTOCAT_GNOME_IDBENTITY_H
|
||||||
|
#define AUTOCAT_GNOME_IDBENTITY_H
|
||||||
|
|
||||||
|
#include <string>
|
||||||
|
#include <optional>
|
||||||
|
#include <variant>
|
||||||
|
#include <vector>
|
||||||
|
#include <sqlite3.h>
|
||||||
|
|
||||||
|
using StringOptional = std::optional<std::string>;
|
||||||
|
using IntOptional = std::optional<int>;
|
||||||
|
using DoubleOptional = std::optional<double>;
|
||||||
|
|
||||||
|
struct IDBEntity {
|
||||||
|
public:
|
||||||
|
virtual std::string insertQuery() = 0;
|
||||||
|
|
||||||
|
protected:
|
||||||
|
static std::string readString(sqlite3_stmt* stmt, int column);
|
||||||
|
static int readInt(sqlite3_stmt* stmt, int column);
|
||||||
|
static double readDouble(sqlite3_stmt* stmt, int column);
|
||||||
|
static StringOptional readStringOptional(sqlite3_stmt* stmt, int column);
|
||||||
|
static IntOptional readIntOptional(sqlite3_stmt* stmt, int column);
|
||||||
|
static DoubleOptional readDoubleOptional(sqlite3_stmt* stmt, int column);
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif //AUTOCAT_GNOME_IDBENTITY_H
|
||||||
@ -9,17 +9,15 @@
|
|||||||
#include <iostream>
|
#include <iostream>
|
||||||
#include <fstream>
|
#include <fstream>
|
||||||
|
|
||||||
namespace fs = std::filesystem;
|
fs::path Settings::getDataPath() {
|
||||||
|
|
||||||
fs::path getDataPath() {
|
|
||||||
auto dataDir = std::getenv("XDG_DATA_HOME");
|
auto dataDir = std::getenv("XDG_DATA_HOME");
|
||||||
if(dataDir) {
|
if(dataDir) {
|
||||||
return fs::path(dataDir);
|
return fs::path(dataDir) / "autocat";
|
||||||
}
|
}
|
||||||
|
|
||||||
auto home = std::getenv("HOME");
|
auto home = std::getenv("HOME");
|
||||||
if(home) {
|
if(home) {
|
||||||
return fs::path(home) / ".local" / "share";
|
return fs::path(home) / ".local" / "share" / "autocat";
|
||||||
}
|
}
|
||||||
|
|
||||||
throw std::runtime_error("Failed to find data home directory");
|
throw std::runtime_error("Failed to find data home directory");
|
||||||
@ -46,7 +44,7 @@ Settings Settings::instance() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
Settings::Settings() {
|
Settings::Settings() {
|
||||||
_dataPath = getDataPath() / "autocat";
|
_dataPath = getDataPath();
|
||||||
if(!fs::exists(_dataPath)) {
|
if(!fs::exists(_dataPath)) {
|
||||||
fs::create_directories(_dataPath);
|
fs::create_directories(_dataPath);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -8,6 +8,8 @@
|
|||||||
#include "../models/User.h"
|
#include "../models/User.h"
|
||||||
#include <filesystem>
|
#include <filesystem>
|
||||||
|
|
||||||
|
namespace fs = std::filesystem;
|
||||||
|
|
||||||
class Settings {
|
class Settings {
|
||||||
private:
|
private:
|
||||||
std::filesystem::path _dataPath;
|
std::filesystem::path _dataPath;
|
||||||
@ -15,6 +17,7 @@ private:
|
|||||||
public:
|
public:
|
||||||
static Settings instance();
|
static Settings instance();
|
||||||
Settings();
|
Settings();
|
||||||
|
static fs::path getDataPath();
|
||||||
|
|
||||||
[[nodiscard]] User user() const;
|
[[nodiscard]] User user() const;
|
||||||
void setUser(const User& user);
|
void setUser(const User& user);
|
||||||
|
|||||||
42
services/Storage.cpp
Normal file
42
services/Storage.cpp
Normal file
@ -0,0 +1,42 @@
|
|||||||
|
//
|
||||||
|
// Created by selim on 25.10.22.
|
||||||
|
//
|
||||||
|
|
||||||
|
#include "Storage.h"
|
||||||
|
#include "Settings.h"
|
||||||
|
|
||||||
|
#include <fmt/core.h>
|
||||||
|
|
||||||
|
Storage Storage::instance() {
|
||||||
|
static Storage instance;
|
||||||
|
return instance;
|
||||||
|
}
|
||||||
|
|
||||||
|
Storage::Storage(): _sqlite(nullptr) {
|
||||||
|
auto path = Settings::getDataPath() / "vehicles.sqlite";
|
||||||
|
int result = sqlite3_open(path.c_str(), &_sqlite);
|
||||||
|
if(result != SQLITE_OK) {
|
||||||
|
throw std::runtime_error(sqlite3_errmsg(_sqlite));
|
||||||
|
}
|
||||||
|
|
||||||
|
executeQuery(Vehicle::createTableQuery());
|
||||||
|
}
|
||||||
|
|
||||||
|
Storage::~Storage() {
|
||||||
|
if(_sqlite) {
|
||||||
|
sqlite3_close(_sqlite);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void Storage::executeQuery(const std::string& query) {
|
||||||
|
char* error = nullptr;
|
||||||
|
sqlite3_exec(_sqlite, query.c_str(), nullptr, nullptr, &error);
|
||||||
|
if(error) {
|
||||||
|
throw std::runtime_error(error);
|
||||||
|
// TODO: error buffer should be deallocated with sqlite3_free()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void Storage::insert(IDBEntity *entity) {
|
||||||
|
executeQuery(entity->insertQuery());
|
||||||
|
}
|
||||||
64
services/Storage.h
Normal file
64
services/Storage.h
Normal file
@ -0,0 +1,64 @@
|
|||||||
|
//
|
||||||
|
// Created by selim on 25.10.22.
|
||||||
|
//
|
||||||
|
|
||||||
|
#ifndef AUTOCAT_GNOME_STORAGE_H
|
||||||
|
#define AUTOCAT_GNOME_STORAGE_H
|
||||||
|
|
||||||
|
#include "../models/Vehicle.h"
|
||||||
|
#include "IDBEntity.h"
|
||||||
|
|
||||||
|
#include <utility>
|
||||||
|
#include <sqlite3.h>
|
||||||
|
|
||||||
|
class Storage {
|
||||||
|
private:
|
||||||
|
sqlite3* _sqlite;
|
||||||
|
|
||||||
|
private:
|
||||||
|
void executeQuery(const std::string& query);
|
||||||
|
|
||||||
|
public:
|
||||||
|
Storage();
|
||||||
|
~Storage();
|
||||||
|
static Storage instance();
|
||||||
|
void insert(IDBEntity* entity);
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
std::vector<T> select() {
|
||||||
|
auto sql = T::selectQuery();
|
||||||
|
sqlite3_stmt* stmt = nullptr;
|
||||||
|
std::vector<T> rows;
|
||||||
|
|
||||||
|
int result = sqlite3_prepare_v2(_sqlite, sql.c_str(), sql.size(), &stmt, nullptr);
|
||||||
|
if(result != SQLITE_OK) {
|
||||||
|
throw std::runtime_error(sqlite3_errmsg(_sqlite));
|
||||||
|
}
|
||||||
|
|
||||||
|
do {
|
||||||
|
result = sqlite3_step(stmt);
|
||||||
|
switch(result) {
|
||||||
|
case SQLITE_BUSY:
|
||||||
|
// TODO: Rollback transaction
|
||||||
|
break;
|
||||||
|
case SQLITE_ERROR:
|
||||||
|
throw std::runtime_error(sqlite3_errmsg(_sqlite));
|
||||||
|
case SQLITE_ROW:
|
||||||
|
rows.emplace_back(stmt);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
} while (result == SQLITE_ROW);
|
||||||
|
|
||||||
|
result = sqlite3_finalize(stmt);
|
||||||
|
if(result != SQLITE_OK) {
|
||||||
|
throw std::runtime_error(sqlite3_errmsg(_sqlite));
|
||||||
|
}
|
||||||
|
|
||||||
|
return rows;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
#endif //AUTOCAT_GNOME_STORAGE_H
|
||||||
Loading…
Reference in New Issue
Block a user