Skip to content

Instantly share code, notes, and snippets.

@McMartin
Last active February 13, 2018 19:31
Show Gist options
  • Save McMartin/3dafdb9362648d3990673178ad7c72fc to your computer and use it in GitHub Desktop.
Save McMartin/3dafdb9362648d3990673178ad7c72fc to your computer and use it in GitHub Desktop.
#include "Model.hpp"
#include "QtEventLoop.hpp"
#include <QApplication>
#include <QDebug>
#include <QKeyEvent>
#include <QLabel>
#include <functional>
// Example specific stuff -- BEGIN
#include "MainWindow.hpp"
void draw(QLabel* label, model m)
{
label->setText(QString::number(m.value));
}
// Example specific stuff -- END
struct store
{
store(model init,
std::function<model(model, action)> update_fn,
std::function<void(model)> view_fn)
: m_model(std::move(init))
, m_update_fn(std::move(update_fn))
, m_view_fn(std::move(view_fn))
{
m_view_fn(m_model);
}
void apply(action a)
{
m_model = m_update_fn(m_model, a);
m_view_fn(m_model);
}
private:
model m_model;
std::function<model(model, action)> m_update_fn;
std::function<void(model)> m_view_fn;
};
QEvent::Type ActionEvent::sEventType =
static_cast<QEvent::Type>(QEvent::registerEventType());
int main(int argc, char* argv[])
{
QApplication app(argc, argv);
QtEventLoop loop;
MainWindow w{&loop};
auto label = new QLabel(&w);
w.show();
auto s = store{model{}, update, [=](model m) { draw(label, m); }};
loop.setHandler([&s](const QEvent* ev) {
if (ev->type() == ActionEvent::sEventType)
{
auto ae = static_cast<const ActionEvent*>(ev);
s.apply(ae->m_action);
return true;
}
return false;
});
return app.exec();
}
#pragma once
#include "Model.hpp"
#include "QtEventLoop.hpp"
#include <QCoreApplication>
#include <QKeyEvent>
#include <QMainWindow>
class MainWindow : public QMainWindow
{
Q_OBJECT
public:
explicit MainWindow(QtEventLoop* loop, QWidget* parent = nullptr)
: QMainWindow(parent)
, m_loop(loop)
{
}
protected:
void keyPressEvent(QKeyEvent* event) override
{
if (event->text() == "+")
{
QCoreApplication::postEvent(m_loop, new ActionEvent('+'));
return;
}
if (event->text() == "-")
{
QCoreApplication::postEvent(m_loop, new ActionEvent('-'));
return;
}
if (event->text() == ".")
{
QCoreApplication::postEvent(m_loop, new ActionEvent('.'));
return;
}
QWidget::keyPressEvent(event);
}
private:
QtEventLoop* m_loop;
};
#pragma once
#include <QEvent>
struct model
{
int value = 0;
};
using action = char;
inline model update(model m, action a)
{
switch (a)
{
case '+':
return {m.value + 1};
case '-':
return {m.value - 1};
case '.':
return {0};
}
return m;
}
class ActionEvent : public QEvent
{
public:
static Type sEventType;
ActionEvent::ActionEvent(action a)
: QEvent(sEventType)
, m_action(a)
{
}
action m_action;
};
#pragma once
#include <QCoreApplication>
#include <QEvent>
#include <QObject>
#include <functional>
class QtEventLoop : public QObject
{
Q_OBJECT
public:
explicit QtEventLoop(QObject* parent = nullptr)
: QObject(parent)
{
}
bool event(QEvent* ev) override
{
if (m_handler && m_handler(ev))
{
return true;
}
return false;
}
void setHandler(std::function<bool(const QEvent*)> handler)
{
m_handler = std::move(handler);
}
private:
std::function<bool(const QEvent*)> m_handler;
};
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment