custom wrapper for GTK application and window

This commit is contained in:
Selim Mustafaev 2022-05-10 20:33:13 +03:00
parent ee12ea81d0
commit 6e948f5df0
8 changed files with 278 additions and 87 deletions

View File

@ -15,16 +15,20 @@ find_package(folly REQUIRED)
pkg_check_modules(GTKMM REQUIRED gtkmm-4.0) pkg_check_modules(GTKMM REQUIRED gtkmm-4.0)
pkg_check_modules(GLIBMM REQUIRED glibmm-2.68) pkg_check_modules(GLIBMM REQUIRED glibmm-2.68)
pkg_check_modules(LIBSOUP REQUIRED libsoup-2.4) pkg_check_modules(LIBSOUP REQUIRED libsoup-2.4)
#pkg_check_modules(LIBFOLLY REQUIRED libfolly) pkg_check_modules(LIBADWAITA REQUIRED libadwaita-1)
#pkg_check_modules(LIBADWAITA REQUIRED libadwaita-1) pkg_check_modules(LIBSIGCPP REQUIRED sigc++-3.0)
include_directories(${GTKMM_INCLUDE_DIRS} include_directories(${GTKMM_INCLUDE_DIRS}
${GLIBMM_INCLUDE_DIRS} ${GLIBMM_INCLUDE_DIRS}
${LIBSOUP_INCLUDE_DIRS}) ${LIBSOUP_INCLUDE_DIRS}
${LIBADWAITA_INCLUDE_DIRS}
${LIBSIGCPP_INCLUDE_DIRS})
link_directories(${GTKMM_LIBRARY_DIRS} link_directories(${GTKMM_LIBRARY_DIRS}
${GLIBMM_LIBRARY_DIRS} ${GLIBMM_LIBRARY_DIRS}
${LIBSOUP_LIBRARY_DIRS}) ${LIBSOUP_LIBRARY_DIRS}
${LIBADWAITA_LIBRARY_DIRS}
${LIBSIGCPP_LIBRARY_DIRS})
add_executable(autocat_gnome main.cpp add_executable(autocat_gnome main.cpp
gui/MainWindow.cpp gui/MainWindow.cpp
@ -39,10 +43,18 @@ add_executable(autocat_gnome main.cpp
services/Settings.h services/Settings.h
gui/TitleBar.cpp gui/TitleBar.cpp
gui/TitleBar.h gui/TitleBar.h
coro/Coro.h coro/GLibMainContextExecutor.cpp coro/GLibMainContextExecutor.h) coro/Coro.h
coro/GLibMainContextExecutor.cpp
coro/GLibMainContextExecutor.h
gtkpp/Application.cpp
gtkpp/Application.h
gtkpp/Window.cpp
gtkpp/Window.h)
target_link_libraries(autocat_gnome ${GTKMM_LIBRARIES} target_link_libraries(autocat_gnome ${GTKMM_LIBRARIES}
${GLIBMM_LIBRARIES} ${GLIBMM_LIBRARIES}
${LIBSOUP_LIBRARIES} ${LIBSOUP_LIBRARIES}
${LIBADWAITA_LIBRARIES}
${LIBSIGCPP_LIBRARIES}
nlohmann_json::nlohmann_json nlohmann_json::nlohmann_json
Folly::folly) Folly::folly)

36
gtkpp/Application.cpp Normal file
View File

@ -0,0 +1,36 @@
//
// Created by selim on 10.05.2022.
//
#include "Application.h"
#include "Window.h"
namespace gtkpp {
void activateCallback(GtkApplication* app, void *data) {
auto application = reinterpret_cast<Application*>(data);
application->_signalActivate.emit();
}
Application::Application(const std::string &id) {
_app = adw_application_new(id.c_str(), G_APPLICATION_FLAGS_NONE);
}
int Application::run(int argc, char **argv) {
return g_application_run(G_APPLICATION(_app), argc, argv);
}
void Application::onActivate(const std::function<void()>& callback) {
g_signal_connect(_app, "activate", G_CALLBACK(activateCallback), this);
_signalActivate.connect(callback);
}
AdwApplication *Application::gobj() const {
return _app;
}
void Application::addWindow(const std::shared_ptr<Window>& window) {
gtk_application_add_window(GTK_APPLICATION(_app), GTK_WINDOW(window->gobj()));
}
}

35
gtkpp/Application.h Normal file
View File

@ -0,0 +1,35 @@
//
// Created by selim on 10.05.2022.
//
#ifndef AUTOCAT_GNOME_APPLICATION_H
#define AUTOCAT_GNOME_APPLICATION_H
#include <adwaita.h>
#include <string>
#include <functional>
#include <sigc++/sigc++.h>
namespace gtkpp {
class Window;
class Application {
private:
AdwApplication* _app;
sigc::signal<void()> _signalActivate;
private:
friend void activateCallback(GtkApplication* app, void* data);
public:
explicit Application(const std::string& id);
int run(int argc, char* argv[]);
void onActivate(const std::function<void()>& callback);
AdwApplication* gobj() const;
void addWindow(const std::shared_ptr<Window>& window);
};
}
#endif //AUTOCAT_GNOME_APPLICATION_H

29
gtkpp/Window.cpp Normal file
View File

@ -0,0 +1,29 @@
//
// Created by selim on 10.05.2022.
//
#include "Window.h"
gtkpp::Window::Window() {
_window = ADW_WINDOW(adw_window_new());
}
gtkpp::Window::Window(std::shared_ptr<gtkpp::Application> app) {
_window = ADW_WINDOW(adw_application_window_new(GTK_APPLICATION(app->gobj())));
}
void gtkpp::Window::show() {
gtk_window_present(GTK_WINDOW(_window));
}
void gtkpp::Window::setTitle(const std::string &title) {
gtk_window_set_title(GTK_WINDOW(_window), title.c_str());
}
AdwWindow *gtkpp::Window::gobj() const {
return _window;
}
void gtkpp::Window::setDefaultSize(int width, int height) {
gtk_window_set_default_size(GTK_WINDOW(_window), width, height);
}

29
gtkpp/Window.h Normal file
View File

@ -0,0 +1,29 @@
//
// Created by selim on 10.05.2022.
//
#ifndef AUTOCAT_GNOME_WINDOW_H
#define AUTOCAT_GNOME_WINDOW_H
#include "Application.h"
#include <adwaita.h>
#include <memory>
namespace gtkpp {
class Window {
protected:
AdwWindow* _window;
public:
Window();
explicit Window(std::shared_ptr<Application> app);
void show();
void setTitle(const std::string& title);
void setDefaultSize(int width, int height);
AdwWindow* gobj() const;
};
}
#endif //AUTOCAT_GNOME_WINDOW_H

View File

@ -7,84 +7,117 @@
#include "../services/Api.h" #include "../services/Api.h"
#include "../coro/GLibMainContextExecutor.h" #include "../coro/GLibMainContextExecutor.h"
#include <gtkmm/application.h>
#include <gtkmm/box.h>
#include <iostream> #include <iostream>
#include <folly/experimental/coro/Task.h> #include <folly/experimental/coro/Task.h>
#include <folly/executors/IOThreadPoolExecutor.h> #include <folly/executors/IOThreadPoolExecutor.h>
LoginWindow::LoginWindow() { LoginWindow::LoginWindow() {
set_title("Login"); setDefaultSize(640, 480);
set_default_size(640, 480);
_emailField.set_placeholder_text("Email"); auto header = adw_header_bar_new();
_passwordField.set_placeholder_text("Password"); adw_header_bar_set_title_widget(ADW_HEADER_BAR(header), gtk_label_new("Login"));
_passwordField.set_input_purpose(Gtk::InputPurpose::PASSWORD);
_passwordField.set_visibility(false);
_emailField.signal_changed().connect(sigc::mem_fun(*this, &LoginWindow::validateFields)); auto loginField = gtk_entry_new();
_passwordField.signal_changed().connect(sigc::mem_fun(*this, &LoginWindow::validateFields)); gtk_entry_set_placeholder_text(GTK_ENTRY(loginField), "Email");
gtk_entry_set_input_purpose(GTK_ENTRY(loginField), GTK_INPUT_PURPOSE_EMAIL);
_loginButton.set_margin_top(8); auto passwordField = gtk_entry_new();
_loginButton.set_margin_bottom(8); gtk_entry_set_placeholder_text(GTK_ENTRY(passwordField), "Password");
_loginButton.set_label("Log in"); gtk_entry_set_input_purpose(GTK_ENTRY(passwordField), GTK_INPUT_PURPOSE_PASSWORD);
_loginButton.signal_clicked().connect(sigc::mem_fun(*this, &LoginWindow::loginClicked)); gtk_entry_set_visibility(GTK_ENTRY(passwordField), false);
_loginButton.set_sensitive(false);
Gtk::Box box(Gtk::Orientation::VERTICAL, 8); auto loginButton = gtk_button_new();
box.set_margin(48); gtk_button_set_label(GTK_BUTTON(loginButton), "Log in");
box.set_valign(Gtk::Align::CENTER); gtk_widget_set_margin_top(loginButton, 8);
gtk_widget_set_margin_bottom(loginButton, 8);
gtk_widget_set_sensitive(loginButton, false);
box.append(_emailField); auto spinner = gtk_spinner_new();
box.append(_passwordField);
box.append(_loginButton);
box.append(_spinner);
set_child(box); auto contentBox = gtk_box_new(GTK_ORIENTATION_VERTICAL, 8);
gtk_box_append(GTK_BOX(contentBox), loginField);
gtk_box_append(GTK_BOX(contentBox), passwordField);
gtk_box_append(GTK_BOX(contentBox), loginButton);
gtk_box_append(GTK_BOX(contentBox), spinner);
gtk_widget_set_margin_start(contentBox, 48);
gtk_widget_set_margin_end(contentBox, 48);
gtk_widget_set_valign(contentBox, GTK_ALIGN_CENTER);
gtk_widget_set_vexpand(contentBox, true);
auto rootBox = gtk_box_new(GTK_ORIENTATION_VERTICAL, 0);
gtk_box_append(GTK_BOX(rootBox), header);
gtk_box_append(GTK_BOX(rootBox), contentBox);
adw_window_set_content(ADW_WINDOW(_window), rootBox);
// _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);
} }
void LoginWindow::loginClicked() { void LoginWindow::loginClicked() {
auto email = _emailField.get_text(); // auto email = _emailField.get_text();
auto password = _passwordField.get_text(); // auto password = _passwordField.get_text();
//
enableControls(false); // enableControls(false);
_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).scheduleOn(GLibMainContextExecutor::instance());
auto app = this->get_application(); // auto app = this->get_application();
auto mainWindow = new MainWindow(); // auto mainWindow = new MainWindow();
mainWindow->show(); // mainWindow->show();
hide(); // hide();
app->add_window(*mainWindow); // app->add_window(*mainWindow);
app->remove_window(*this); // app->remove_window(*this);
} catch (std::exception& ex) { // } catch (std::exception& ex) {
enableControls(true); // enableControls(true);
_spinner.stop(); // _spinner.stop();
showError(ex.what()); // showError(ex.what());
} // }
} }
void LoginWindow::validateFields() { void LoginWindow::validateFields() {
bool buttonEnabled = _emailField.get_text_length() > 0 && _passwordField.get_text_length() > 0; // bool buttonEnabled = _emailField.get_text_length() > 0 && _passwordField.get_text_length() > 0;
_loginButton.set_sensitive(buttonEnabled); // _loginButton.set_sensitive(buttonEnabled);
} }
void LoginWindow::showError(const std::string& message) { void LoginWindow::showError(const std::string& message) {
_dialog = std::make_unique<Gtk::MessageDialog>("Error", // _dialog = std::make_unique<Gtk::MessageDialog>("Error",
false, // false,
Gtk::MessageType::ERROR, // Gtk::MessageType::ERROR,
Gtk::ButtonsType::OK, // Gtk::ButtonsType::OK,
true); // true);
_dialog->set_secondary_text(message); // _dialog->set_secondary_text(message);
_dialog->set_transient_for(*this); // _dialog->set_transient_for(*this);
_dialog->set_hide_on_close(true); // _dialog->set_hide_on_close(true);
_dialog->signal_response().connect(sigc::hide(sigc::mem_fun(*_dialog, &Gtk::Widget::hide))); // _dialog->signal_response().connect(sigc::hide(sigc::mem_fun(*_dialog, &Gtk::Widget::hide)));
_dialog->show(); // _dialog->show();
} }
void LoginWindow::enableControls(bool enable) { void LoginWindow::enableControls(bool enable) {
_loginButton.set_sensitive(enable); // _loginButton.set_sensitive(enable);
_emailField.set_sensitive(enable); // _emailField.set_sensitive(enable);
_passwordField.set_sensitive(enable); // _passwordField.set_sensitive(enable);
} }

View File

@ -5,24 +5,19 @@
#ifndef AUTOCAT_GNOME_LOGINWINDOW_H #ifndef AUTOCAT_GNOME_LOGINWINDOW_H
#define 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>
#include <gtkmm/messagedialog.h>
#include <memory> #include <memory>
#include "../gtkpp/Window.h"
class LoginWindow: public Gtk::Window { class LoginWindow: public gtkpp::Window {
private: private:
Gtk::Entry _emailField; // Gtk::Entry _emailField;
Gtk::Entry _passwordField; // Gtk::Entry _passwordField;
Gtk::Button _loginButton; // Gtk::Button _loginButton;
Gtk::Spinner _spinner; // Gtk::Spinner _spinner;
std::unique_ptr<Gtk::MessageDialog> _dialog; // std::unique_ptr<Gtk::MessageDialog> _dialog;
public: public:
LoginWindow(); LoginWindow();
~LoginWindow() override = default;
void loginClicked(); void loginClicked();
void validateFields(); void validateFields();

View File

@ -1,32 +1,54 @@
#include "gui/MainWindow.h" #include "gui/MainWindow.h"
#include "gui/LoginWindow.h" #include "gui/LoginWindow.h"
#include "services/Settings.h" #include "services/Settings.h"
#include "gtkpp/Application.h"
#include "gtkpp/Window.h"
#include <gtkmm/application.h> #include <gtkmm/application.h>
#include <glibmm.h> #include <glibmm.h>
#include <gtkmm.h> #include <gtkmm.h>
#include <memory> #include <memory>
#include <folly/init/Init.h> #include <folly/init/Init.h>
#include <iostream>
std::unique_ptr<Gtk::Window> createStartWindow() { //std::unique_ptr<Gtk::Window> createStartWindow() {
auto settings = Settings::instance(); // auto settings = Settings::instance();
if(settings.user().token.empty()) { // if(settings.user().token.empty()) {
return std::make_unique<LoginWindow>(); // return std::make_unique<LoginWindow>();
} else { // } else {
return std::make_unique<MainWindow>(); // return std::make_unique<MainWindow>();
} // }
} //}
int main(int argc, char* argv[]) { int main(int argc, char* argv[]) {
folly::init(&argc, &argv); folly::init(&argc, &argv);
auto app = Gtk::Application::create("pro.aliencat.aliencat"); // auto app = Gtk::Application::create("pro.aliencat.aliencat");
auto window = createStartWindow(); // auto window = createStartWindow();
//
// app->signal_activate().connect([&](){
// app->add_window(*window);
// window->show();
// });
// return app->run(argc, argv);
app->signal_activate().connect([&](){ auto app = std::make_shared<gtkpp::Application>("pro.aliencat.autocat");
app->add_window(*window);
window->show(); app->onActivate([&](){
auto settings = Settings::instance();
if(settings.user().token.empty()) {
auto window = std::make_shared<LoginWindow>();
app->addWindow(window);
window->setTitle("Login");
window->show();
} else {
auto window = std::make_unique<gtkpp::Window>(app);
window->setTitle("Some title");
window->show();
}
}); });
return app->run(argc, argv); return app->run(argc, argv);
} }