Initial commit

This commit is contained in:
Selim Mustafaev 2022-01-05 22:36:47 +03:00
commit 8caa12b4ce
12 changed files with 359 additions and 0 deletions

2
.gitignore vendored Normal file
View File

@ -0,0 +1,2 @@
.idea/
cmake-build-*

20
CMakeLists.txt Normal file
View File

@ -0,0 +1,20 @@
cmake_minimum_required(VERSION 3.0)
project(autocat_gnome)
set(CMAKE_CXX_STANDARD 20)
#if (CMAKE_CXX_COMPILER_ID MATCHES "Clang")
# add_compile_options(-stdlib=libc++)
#endif()
find_package(PkgConfig)
pkg_check_modules(GTKMM REQUIRED gtkmm-4.0)
pkg_check_modules(GLIBMM REQUIRED glibmm-2.68)
pkg_check_modules(LIBSOUP REQUIRED libsoup-2.4)
include_directories(${GTKMM_INCLUDE_DIRS} ${GLIBMM_INCLUDE_DIRS} ${LIBSOUP_INCLUDE_DIRS})
link_directories(${GTKMM_LIBRARY_DIRS} ${GLIBMM_LIBRARY_DIRS} ${LIBSOUP_LIBRARY_DIRS})
add_executable(autocat_gnome main.cpp gui/MainWindow.cpp gui/MainWindow.h gui/LoginWindow.cpp gui/LoginWindow.h services/Api.cpp services/Api.h coro/Task.h models/User.cpp models/User.h)
target_link_libraries(autocat_gnome ${GTKMM_LIBRARIES} ${GLIBMM_LIBRARIES} ${LIBSOUP_LIBRARIES})

101
coro/Task.h Normal file
View File

@ -0,0 +1,101 @@
//
// Created by selim on 03.01.2022.
//
#ifndef AUTOCAT_GNOME_TASK_H
#define AUTOCAT_GNOME_TASK_H
#include <coroutine>
#include <iostream>
#include <optional>
template<typename T>
class Task {
public:
struct promise_type {
auto initial_suspend() const noexcept {
std::cout << "initial_suspend" << std::endl;
return std::suspend_never();
}
auto final_suspend() const noexcept {
std::cout << "final_suspend" << std::endl;
return std::suspend_never();
}
Task<T> get_return_object() {
std::cout << "get_return_object" << std::endl;
return Task<T>{ std::coroutine_handle<promise_type>::from_promise(*this) };
}
void return_value(const T& value) noexcept(std::is_nothrow_copy_constructible_v<T>) {
std::cout << "return_value: " << value << std::endl;
_value = value;
}
// void return_void() {
// std::cout << "return_void" << std::endl;
// }
void unhandled_exception() {
std::cout << "unhandled_exception" << std::endl;
throw;
}
};
private:
std::optional<T> _value = std::nullopt;
std::coroutine_handle<promise_type> _handle;
//public:
// bool await_ready() const noexcept {
// std::cout << "Awaiter::await_ready" << std::endl;
// return false;
// }
//
// void await_suspend(std::coroutine_handle<promise_type> handle) const {
// std::cout << "Awaiter::await_suspend" << std::endl;
// _handle = handle;
// }
//
// T await_resume() {
// std::cout << "Awaiter::await_resume" << std::endl;
// return _value.value();
// }
public:
void set_result(T result) {
_value = result;
_handle();
}
};
template<typename U> struct Awaiter {
public:
bool await_ready() const noexcept {
std::cout << "Awaiter::await_ready" << std::endl;
return false;
}
void await_suspend(std::coroutine_handle<typename Task<U>::promise_type> cont) const {
std::cout << "Awaiter::await_suspend" << std::endl;
}
U await_resume() {
std::cout << "Awaiter::await_resume" << std::endl;
return _task.value();
}
private:
Task<U> _task;
public:
explicit Awaiter(Task<U> task): _task(task) {}
};
template<typename T>
auto operator co_await(Task<T> task) noexcept /*requires(!std::is_reference_v<T>)*/ {
return Awaiter<T>(task);
}
#endif //AUTOCAT_GNOME_TASK_H

69
gui/LoginWindow.cpp Normal file
View File

@ -0,0 +1,69 @@
//
// Created by selim on 03.01.2022.
//
#include "LoginWindow.h"
#include "../services/Api.h"
#include <gtkmm/box.h>
#include <iostream>
LoginWindow::LoginWindow() {
set_title("Login");
set_default_size(640, 480);
_emailField.set_placeholder_text("Email");
_passwordField.set_placeholder_text("Password");
_passwordField.set_input_purpose(Gtk::InputPurpose::PASSWORD);
_passwordField.set_visibility(false);
_emailField.signal_changed().connect(sigc::mem_fun(*this, &LoginWindow::ValidateFields));
_passwordField.signal_changed().connect(sigc::mem_fun(*this, &LoginWindow::ValidateFields));
_loginButton.set_margin_top(8);
_loginButton.set_margin_bottom(8);
_loginButton.set_label("Log in");
_loginButton.signal_clicked().connect(sigc::mem_fun(*this, &LoginWindow::LoginClicked));
_loginButton.set_sensitive(false);
Gtk::Box box(Gtk::Orientation::VERTICAL, 8);
box.set_margin(48);
box.set_valign(Gtk::Align::CENTER);
box.append(_emailField);
box.append(_passwordField);
box.append(_loginButton);
box.append(_spinner);
set_child(box);
}
//Task<int> foo() {
// co_return 42;
//}
//
//Task<int> bar() {
// auto xxx = co_await foo();
// std::cout << "xxx: " << xxx << std::endl;
//}
void LoginWindow::LoginClicked() {
auto email = _emailField.get_text();
auto password = _passwordField.get_text();
_loginButton.set_sensitive(false);
_emailField.set_sensitive(false);
_passwordField.set_sensitive(false);
_spinner.start();
std::cout << "Login clicked" << std::endl;
std::cout << "Login: " << email << std::endl;
std::cout << "Password: " << password << std::endl;
User user = co_await Api::login(email, password);
}
void LoginWindow::ValidateFields() {
bool buttonEnabled = _emailField.get_text_length() > 0 && _passwordField.get_text_length() > 0;
_loginButton.set_sensitive(buttonEnabled);
}

29
gui/LoginWindow.h Normal file
View File

@ -0,0 +1,29 @@
//
// Created by selim on 03.01.2022.
//
#ifndef AUTOCAT_GNOME_LOGINWINDOW_H
#define AUTOCAT_GNOME_LOGINWINDOW_H
#include <gtkmm/window.h>
#include <gtkmm/entry.h>
#include <gtkmm/button.h>
#include <gtkmm/spinner.h>
class LoginWindow: public Gtk::Window {
private:
Gtk::Entry _emailField;
Gtk::Entry _passwordField;
Gtk::Button _loginButton;
Gtk::Spinner _spinner;
public:
LoginWindow();
~LoginWindow() override = default;
void LoginClicked();
void ValidateFields();
};
#endif //AUTOCAT_GNOME_LOGINWINDOW_H

10
gui/MainWindow.cpp Normal file
View File

@ -0,0 +1,10 @@
//
// Created by selim on 03.01.2022.
//
#include "MainWindow.h"
MainWindow::MainWindow() {
set_title("Main window");
set_default_size(640, 480);
}

16
gui/MainWindow.h Normal file
View File

@ -0,0 +1,16 @@
//
// Created by selim on 03.01.2022.
//
#ifndef AUTOCAT_GNOME_MAINWINDOW_H
#define AUTOCAT_GNOME_MAINWINDOW_H
#include <gtkmm/window.h>
class MainWindow: public Gtk::Window {
public:
MainWindow();
};
#endif //AUTOCAT_GNOME_MAINWINDOW_H

8
main.cpp Normal file
View File

@ -0,0 +1,8 @@
#include "gui/MainWindow.h"
#include "gui/LoginWindow.h"
#include <gtkmm/application.h>
int main(int argc, char* argv[]) {
auto app = Gtk::Application::create("pro.aliencat.aliencat");
return app->make_window_and_run<LoginWindow>(argc, argv);
}

9
models/User.cpp Normal file
View File

@ -0,0 +1,9 @@
//
// Created by selim on 05.01.2022.
//
#include "User.h"
User::User(std::string_view login, std::string_view token): login(login), token(token) {
}

23
models/User.h Normal file
View File

@ -0,0 +1,23 @@
//
// Created by selim on 05.01.2022.
//
#ifndef AUTOCAT_GNOME_USER_H
#define AUTOCAT_GNOME_USER_H
#include <string>
#include <optional>
class User {
public:
std::string login;
std::string token;
std::optional<std::string> googleIdToken;
std::optional<std::string> googleRefreshToken;
public:
User(std::string_view login, std::string_view token);
};
#endif //AUTOCAT_GNOME_USER_H

49
services/Api.cpp Normal file
View File

@ -0,0 +1,49 @@
//
// Created by selim on 03.01.2022.
//
#include "Api.h"
#include <memory>
template<class...Args>
struct callback {
void(*function)(Args..., void*) = nullptr;
std::unique_ptr<void, void(*)(void*)> state;
};
template<typename... Args, typename Lambda>
callback<Args...> voidify(Lambda&& l) {
using Func = typename std::decay<Lambda>::type;
std::unique_ptr<void, void(*)(void*)> data(
new Func(std::forward<Lambda>(l)),
+[](void* ptr){
std::cout << "!!!!!!!!!!!!!!!!! Deleting data" << std::endl;
delete (Func*)ptr;
}
);
return {
+[](Args... args, void* v)->void {
Func* f = static_cast< Func* >(v);
(*f)(std::forward<Args>(args)...);
},
std::move(data)
};
}
const std::string Api::_baseUrl = "https://vps.aliencat.pro:8443/";
SoupSession* Api::_session = soup_session_new();
Task<User> Api::login(std::string email, std::string password) {
std::string url = _baseUrl + "user/login";
auto msg = soup_message_new(SOUP_METHOD_POST, url.c_str());
auto task = Task<User>();
auto callback = voidify<SoupSession*, SoupMessage*>([&](SoupSession* session, SoupMessage* message) {
std::cout << "Callback called" << std::endl;
task.set_result(User("qwe", "asdf"));
});
soup_session_queue_message(_session, msg, callback.function, callback.state.get());
return task;
}

23
services/Api.h Normal file
View File

@ -0,0 +1,23 @@
//
// Created by selim on 03.01.2022.
//
#ifndef AUTOCAT_GNOME_API_H
#define AUTOCAT_GNOME_API_H
#include <string>
#include <libsoup/soup.h>
#include "../models/User.h"
#include "../coro/Task.h"
class Api {
private:
static const std::string _baseUrl;
static SoupSession* _session;
public:
static Task<User> login(std::string email, std::string password);
};
#endif //AUTOCAT_GNOME_API_H