Compare commits
10 Commits
57edc50b6b
...
96638d6f8d
Author | SHA1 | Date | |
---|---|---|---|
96638d6f8d | |||
29b887504d | |||
872cc04a54 | |||
a1f9fa172b | |||
ddd0b3a732 | |||
ed74a4fc83 | |||
4a7082319f | |||
c19810162a | |||
039c093b15 | |||
872488d174 |
5
CMakeLists.txt
Normal file
5
CMakeLists.txt
Normal file
@ -0,0 +1,5 @@
|
||||
cmake_minimum_required(VERSION 3.5)
|
||||
|
||||
project(trainController LANGUAGES CXX)
|
||||
|
||||
add_subdirectory(src)
|
42
src/CMakeLists.txt
Normal file
42
src/CMakeLists.txt
Normal file
@ -0,0 +1,42 @@
|
||||
set(CMAKE_INCLUDE_CURRENT_DIR ON)
|
||||
|
||||
set(CMAKE_AUTOUIC ON)
|
||||
set(CMAKE_AUTOMOC ON)
|
||||
set(CMAKE_AUTORCC ON)
|
||||
|
||||
set(CMAKE_CXX_STANDARD 20)
|
||||
set(CMAKE_CXX_STANDARD_REQUIRED ON)
|
||||
|
||||
find_package(QT NAMES Qt6 Qt5 COMPONENTS Widgets Network SerialPort REQUIRED)
|
||||
find_package(Qt${QT_VERSION_MAJOR} COMPONENTS Widgets Network SerialPort REQUIRED)
|
||||
|
||||
set(COMMON_SOURCES
|
||||
../common/microcontroller.cpp
|
||||
../common/microcontroller.h
|
||||
../common/items/item.cpp
|
||||
../common/items/item.h
|
||||
../common/items/itemstore.cpp
|
||||
../common/items/itemstore.h
|
||||
../common/items/trainsignal.cpp
|
||||
../common/items/trainsignal.h
|
||||
../common/items/train.cpp
|
||||
../common/items/train.h
|
||||
../common/items/turnout.cpp
|
||||
../common/items/turnout.h
|
||||
../common/nfcuid.h
|
||||
)
|
||||
|
||||
include_directories(PRIVATE
|
||||
./common/items/
|
||||
./common
|
||||
|
||||
)
|
||||
|
||||
set(COMMON_LINK_LIBRARYS
|
||||
Qt${QT_VERSION_MAJOR}::Network
|
||||
Qt${QT_VERSION_MAJOR}::SerialPort
|
||||
)
|
||||
|
||||
add_subdirectory(trainControllerUI)
|
||||
add_subdirectory(trainOverlord)
|
||||
|
@ -1,479 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2015-2017 Alex Spataru <alex_spataru@outlook.com>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#include <QDebug>
|
||||
#include <QSettings>
|
||||
#include "QJoysticks.h"
|
||||
#include "jsbackend/SDL_Joysticks.h"
|
||||
#include "jsbackend/VirtualJoystick.h"
|
||||
|
||||
QJoysticks::QJoysticks()
|
||||
{
|
||||
/* Initialize input methods */
|
||||
m_sdlJoysticks = new SDL_Joysticks(this);
|
||||
m_virtualJoystick = new VirtualJoystick(this);
|
||||
|
||||
/* Configure SDL joysticks */
|
||||
connect(sdlJoysticks(), &SDL_Joysticks::POVEvent, this, &QJoysticks::POVEvent);
|
||||
connect(sdlJoysticks(), &SDL_Joysticks::axisEvent, this, &QJoysticks::axisEvent);
|
||||
connect(sdlJoysticks(), &SDL_Joysticks::buttonEvent, this, &QJoysticks::buttonEvent);
|
||||
connect(sdlJoysticks(), &SDL_Joysticks::countChanged, this, &QJoysticks::updateInterfaces);
|
||||
|
||||
/* Configure virtual joysticks */
|
||||
connect(virtualJoystick(), &VirtualJoystick::povEvent, this, &QJoysticks::POVEvent);
|
||||
connect(virtualJoystick(), &VirtualJoystick::axisEvent, this, &QJoysticks::axisEvent);
|
||||
connect(virtualJoystick(), &VirtualJoystick::buttonEvent, this, &QJoysticks::buttonEvent);
|
||||
connect(virtualJoystick(), &VirtualJoystick::enabledChanged, this, &QJoysticks::updateInterfaces);
|
||||
|
||||
/* React to own signals to create QML signals */
|
||||
connect(this, &QJoysticks::POVEvent, this, &QJoysticks::onPOVEvent);
|
||||
connect(this, &QJoysticks::axisEvent, this, &QJoysticks::onAxisEvent);
|
||||
connect(this, &QJoysticks::buttonEvent, this, &QJoysticks::onButtonEvent);
|
||||
|
||||
/* Configure the settings */
|
||||
m_sortJoyticks = 0;
|
||||
m_settings = new QSettings(qApp->organizationName(), qApp->applicationName());
|
||||
m_settings->beginGroup("Blacklisted Joysticks");
|
||||
}
|
||||
|
||||
QJoysticks::~QJoysticks()
|
||||
{
|
||||
delete m_settings;
|
||||
delete m_sdlJoysticks;
|
||||
delete m_virtualJoystick;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the one and only instance of this class
|
||||
*/
|
||||
QJoysticks *QJoysticks::getInstance()
|
||||
{
|
||||
static QJoysticks joysticks;
|
||||
return &joysticks;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the number of joysticks that are attached to the computer and/or
|
||||
* registered with the \c QJoysticks system.
|
||||
*
|
||||
* \note This count also includes the virtual joystick (if its enabled)
|
||||
*/
|
||||
int QJoysticks::count() const
|
||||
{
|
||||
return inputDevices().count();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the number of joysticks that are not blacklisted.
|
||||
* This can be considered the "effective" number of joysticks.
|
||||
*/
|
||||
int QJoysticks::nonBlacklistedCount()
|
||||
{
|
||||
int cnt = count();
|
||||
|
||||
for (int i = 0; i < count(); ++i)
|
||||
if (isBlacklisted(i))
|
||||
--cnt;
|
||||
|
||||
return cnt;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a list with the names of all registered joystick.
|
||||
*
|
||||
* \note This list also includes the blacklisted joysticks
|
||||
* \note This list also includes the virtual joystick (if its enabled)
|
||||
*/
|
||||
QStringList QJoysticks::deviceNames() const
|
||||
{
|
||||
QStringList names;
|
||||
|
||||
foreach (QJoystickDevice *joystick, inputDevices())
|
||||
names.append(joystick->name);
|
||||
|
||||
return names;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the POV value for the given joystick \a index and \a pov ID
|
||||
*/
|
||||
int QJoysticks::getPOV(const int index, const int pov)
|
||||
{
|
||||
if (joystickExists(index))
|
||||
return getInputDevice(index)->povs.at(pov);
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the axis value for the given joystick \a index and \a axis ID
|
||||
*/
|
||||
double QJoysticks::getAxis(const int index, const int axis)
|
||||
{
|
||||
if (joystickExists(index))
|
||||
return getInputDevice(index)->axes.at(axis);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the button value for the given joystick \a index and \a button ID
|
||||
*/
|
||||
bool QJoysticks::getButton(const int index, const int button)
|
||||
{
|
||||
if (joystickExists(index))
|
||||
return getInputDevice(index)->buttons.at(button);
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the number of axes that the joystick at the given \a index has.
|
||||
*/
|
||||
int QJoysticks::getNumAxes(const int index)
|
||||
{
|
||||
if (joystickExists(index))
|
||||
return getInputDevice(index)->axes.count();
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the number of POVs that the joystick at the given \a index has.
|
||||
*/
|
||||
int QJoysticks::getNumPOVs(const int index)
|
||||
{
|
||||
if (joystickExists(index))
|
||||
return getInputDevice(index)->povs.count();
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the number of buttons that the joystick at the given \a index has.
|
||||
*/
|
||||
int QJoysticks::getNumButtons(const int index)
|
||||
{
|
||||
if (joystickExists(index))
|
||||
return getInputDevice(index)->buttons.count();
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns \c true if the joystick at the given \a index is blacklisted.
|
||||
*/
|
||||
bool QJoysticks::isBlacklisted(const int index)
|
||||
{
|
||||
if (joystickExists(index))
|
||||
return inputDevices().at(index)->blacklisted;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns \c true if the joystick at the given \a index is valid, otherwise,
|
||||
* the function returns \c false and warns the user through the console.
|
||||
*/
|
||||
bool QJoysticks::joystickExists(const int index)
|
||||
{
|
||||
return (index >= 0) && (count() > index);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the name of the given joystick
|
||||
*/
|
||||
QString QJoysticks::getName(const int index)
|
||||
{
|
||||
if (joystickExists(index))
|
||||
return m_devices.at(index)->name;
|
||||
|
||||
return "Invalid Joystick";
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a pointer to the SDL joysticks system.
|
||||
* This can be used if you need to get more information regarding the joysticks
|
||||
* registered and managed with SDL.
|
||||
*/
|
||||
SDL_Joysticks *QJoysticks::sdlJoysticks() const
|
||||
{
|
||||
return m_sdlJoysticks;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a pointer to the virtual joystick system.
|
||||
* This can be used if you need to get more information regarding the virtual
|
||||
* joystick or want to change its properties directly.
|
||||
*
|
||||
* \note You can also change the properties of the virtual joysticks using the
|
||||
* functions of the \c QJoysticks system class
|
||||
*/
|
||||
VirtualJoystick *QJoysticks::virtualJoystick() const
|
||||
{
|
||||
return m_virtualJoystick;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a pointer to the device at the given \a index.
|
||||
*/
|
||||
QJoystickDevice *QJoysticks::getInputDevice(const int index)
|
||||
{
|
||||
if (joystickExists(index))
|
||||
return inputDevices().at(index);
|
||||
|
||||
return Q_NULLPTR;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a pointer to a list containing all registered joysticks.
|
||||
* This can be used for advanced hacks or just to get all properties of each
|
||||
* joystick.
|
||||
*/
|
||||
QList<QJoystickDevice *> QJoysticks::inputDevices() const
|
||||
{
|
||||
return m_devices;
|
||||
}
|
||||
|
||||
/**
|
||||
* If \a sort is set to true, then the device list will put all blacklisted
|
||||
* joysticks at the end of the list
|
||||
*/
|
||||
void QJoysticks::setSortJoysticksByBlacklistState(bool sort)
|
||||
{
|
||||
if (m_sortJoyticks != sort)
|
||||
{
|
||||
m_sortJoyticks = sort;
|
||||
updateInterfaces();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Blacklists or whitelists the joystick at the given \a index.
|
||||
*
|
||||
* \note This function does not have effect if the given joystick does not exist
|
||||
* \note Once the joystick is blacklisted, the joystick list will be updated
|
||||
*/
|
||||
void QJoysticks::setBlacklisted(const int index, bool blacklisted)
|
||||
{
|
||||
Q_ASSERT(joystickExists(index));
|
||||
|
||||
/* Netrualize the joystick */
|
||||
if (blacklisted)
|
||||
{
|
||||
for (int i = 0; i < getNumAxes(index); ++i)
|
||||
emit axisChanged(index, i, 0);
|
||||
|
||||
for (int i = 0; i < getNumButtons(index); ++i)
|
||||
emit buttonChanged(index, i, false);
|
||||
|
||||
for (int i = 0; i < getNumPOVs(index); ++i)
|
||||
emit povChanged(index, i, 0);
|
||||
}
|
||||
|
||||
/* See if blacklist value was actually changed */
|
||||
bool changed = m_devices.at(index)->blacklisted != blacklisted;
|
||||
|
||||
/* Save settings */
|
||||
m_devices.at(index)->blacklisted = blacklisted;
|
||||
m_settings->setValue(getName(index), blacklisted);
|
||||
|
||||
/* Re-scan joysticks if blacklist value has changed */
|
||||
if (changed)
|
||||
updateInterfaces();
|
||||
}
|
||||
|
||||
/**
|
||||
* 'Rescans' for new/removed joysticks and registers them again.
|
||||
*/
|
||||
void QJoysticks::updateInterfaces()
|
||||
{
|
||||
m_devices.clear();
|
||||
|
||||
/* Put blacklisted joysticks at the bottom of the list */
|
||||
if (m_sortJoyticks)
|
||||
{
|
||||
/* Register non-blacklisted SDL joysticks */
|
||||
foreach (QJoystickDevice *joystick, sdlJoysticks()->joysticks())
|
||||
{
|
||||
joystick->blacklisted = m_settings->value(joystick->name, false).toBool();
|
||||
if (!joystick->blacklisted)
|
||||
addInputDevice(joystick);
|
||||
}
|
||||
|
||||
/* Register the virtual joystick (if its not blacklisted) */
|
||||
if (virtualJoystick()->joystickEnabled())
|
||||
{
|
||||
QJoystickDevice *joystick = virtualJoystick()->joystick();
|
||||
joystick->blacklisted = m_settings->value(joystick->name, false).toBool();
|
||||
|
||||
if (!joystick->blacklisted)
|
||||
{
|
||||
addInputDevice(joystick);
|
||||
virtualJoystick()->setJoystickID(inputDevices().count() - 1);
|
||||
}
|
||||
}
|
||||
|
||||
/* Register blacklisted SDL joysticks */
|
||||
foreach (QJoystickDevice *joystick, sdlJoysticks()->joysticks())
|
||||
{
|
||||
joystick->blacklisted = m_settings->value(joystick->name, false).toBool();
|
||||
if (joystick->blacklisted)
|
||||
addInputDevice(joystick);
|
||||
}
|
||||
|
||||
/* Register the virtual joystick (if its blacklisted) */
|
||||
if (virtualJoystick()->joystickEnabled())
|
||||
{
|
||||
QJoystickDevice *joystick = virtualJoystick()->joystick();
|
||||
joystick->blacklisted = m_settings->value(joystick->name, false).toBool();
|
||||
|
||||
if (joystick->blacklisted)
|
||||
{
|
||||
addInputDevice(joystick);
|
||||
virtualJoystick()->setJoystickID(inputDevices().count() - 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Sort normally */
|
||||
else
|
||||
{
|
||||
/* Register SDL joysticks */
|
||||
foreach (QJoystickDevice *joystick, sdlJoysticks()->joysticks())
|
||||
{
|
||||
addInputDevice(joystick);
|
||||
joystick->blacklisted = m_settings->value(joystick->name, false).toBool();
|
||||
}
|
||||
|
||||
/* Register virtual joystick */
|
||||
if (virtualJoystick()->joystickEnabled())
|
||||
{
|
||||
QJoystickDevice *joystick = virtualJoystick()->joystick();
|
||||
joystick->blacklisted = m_settings->value(joystick->name, false).toBool();
|
||||
|
||||
addInputDevice(joystick);
|
||||
virtualJoystick()->setJoystickID(inputDevices().count() - 1);
|
||||
}
|
||||
}
|
||||
|
||||
emit countChanged();
|
||||
}
|
||||
|
||||
/**
|
||||
* Changes the axis value range of the virtual joystick.
|
||||
*
|
||||
* Take into account that maximum axis values supported by the \c QJoysticks
|
||||
* system is from \c -1 to \c 1.
|
||||
*/
|
||||
void QJoysticks::setVirtualJoystickRange(qreal range)
|
||||
{
|
||||
virtualJoystick()->setAxisRange(range);
|
||||
}
|
||||
|
||||
/**
|
||||
* Enables or disables the virtual joystick
|
||||
*/
|
||||
void QJoysticks::setVirtualJoystickEnabled(bool enabled)
|
||||
{
|
||||
virtualJoystick()->setJoystickEnabled(enabled);
|
||||
}
|
||||
|
||||
void QJoysticks::setVirtualJoystickAxisSensibility(qreal sensibility)
|
||||
{
|
||||
virtualJoystick()->setAxisSensibility(sensibility);
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes all the registered joysticks and emits appropriate signals.
|
||||
*/
|
||||
void QJoysticks::resetJoysticks()
|
||||
{
|
||||
m_devices.clear();
|
||||
emit countChanged();
|
||||
}
|
||||
|
||||
/**
|
||||
* Registers the given \a device to the \c QJoysticks system
|
||||
*/
|
||||
void QJoysticks::addInputDevice(QJoystickDevice *device)
|
||||
{
|
||||
Q_ASSERT(device);
|
||||
m_devices.append(device);
|
||||
}
|
||||
|
||||
/**
|
||||
* Configures the QML-friendly signal based on the information given by the
|
||||
* \a event data and updates the joystick values
|
||||
*/
|
||||
void QJoysticks::onPOVEvent(const QJoystickPOVEvent &e)
|
||||
{
|
||||
if (e.joystick == nullptr)
|
||||
return;
|
||||
|
||||
if (!isBlacklisted(e.joystick->id))
|
||||
{
|
||||
if (e.pov < getInputDevice(e.joystick->id)->povs.count())
|
||||
{
|
||||
getInputDevice(e.joystick->id)->povs[e.pov] = e.angle;
|
||||
emit povChanged(e.joystick->id, e.pov, e.angle);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Configures the QML-friendly signal based on the information given by the
|
||||
* \a event data and updates the joystick values
|
||||
*/
|
||||
void QJoysticks::onAxisEvent(const QJoystickAxisEvent &e)
|
||||
{
|
||||
if (e.joystick == nullptr)
|
||||
return;
|
||||
|
||||
if (!isBlacklisted(e.joystick->id))
|
||||
{
|
||||
if (e.axis < getInputDevice(e.joystick->id)->axes.count())
|
||||
{
|
||||
getInputDevice(e.joystick->id)->axes[e.axis] = e.value;
|
||||
emit axisChanged(e.joystick->id, e.axis, e.value);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Configures the QML-friendly signal based on the information given by the
|
||||
* \a event data and updates the joystick values
|
||||
*/
|
||||
void QJoysticks::onButtonEvent(const QJoystickButtonEvent &e)
|
||||
{
|
||||
if (e.joystick == nullptr)
|
||||
return;
|
||||
|
||||
if (!isBlacklisted(e.joystick->id))
|
||||
{
|
||||
if (e.button < getInputDevice(e.joystick->id)->buttons.count())
|
||||
{
|
||||
getInputDevice(e.joystick->id)->buttons[e.button] = e.pressed;
|
||||
emit buttonChanged(e.joystick->id, e.button, e.pressed);
|
||||
}
|
||||
}
|
||||
}
|
@ -1,18 +0,0 @@
|
||||
#include "auxitem.h"
|
||||
|
||||
AuxItem::AuxItem(Microcontroller* micro, uint32_t itemIdIn, QString name, uint8_t value, QObject* parent): Item(itemIdIn, name, value, parent), micro_(micro)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void AuxItem::setValue(uint8_t value)
|
||||
{
|
||||
Item::setValue(value);
|
||||
micro_->setAuxPwm(value);
|
||||
}
|
||||
|
||||
void AuxItem::store(QJsonObject &json)
|
||||
{
|
||||
json["Type"] = "Aux";
|
||||
Item::store(json);
|
||||
}
|
@ -1,20 +0,0 @@
|
||||
#pragma once
|
||||
|
||||
#include "item.h"
|
||||
#include "../microcontroller.h"
|
||||
|
||||
class AuxItem: public Item
|
||||
{
|
||||
Q_OBJECT
|
||||
private:
|
||||
Microcontroller* micro_;
|
||||
|
||||
public slots:
|
||||
|
||||
virtual void setValue(uint8_t value);
|
||||
|
||||
public:
|
||||
AuxItem(Microcontroller* micro, uint32_t itemIdIn = QRandomGenerator::global()->generate(), QString name = "", uint8_t value = 0, QObject* parent = nullptr);
|
||||
|
||||
virtual void store(QJsonObject& json);
|
||||
};
|
@ -10,28 +10,29 @@ ItemData::ItemData(uint32_t itemIdIn, QString name, int8_t value): name_(name),
|
||||
|
||||
QString ItemData::getName() const
|
||||
{
|
||||
return name_;
|
||||
return name_;
|
||||
}
|
||||
|
||||
void ItemData::setName(QString name)
|
||||
{
|
||||
name_ = name;
|
||||
name_ = name;
|
||||
}
|
||||
|
||||
int8_t ItemData::getValue() const
|
||||
{
|
||||
return value_;
|
||||
return value_;
|
||||
}
|
||||
|
||||
uint32_t ItemData::id() const
|
||||
{
|
||||
return itemId_;
|
||||
return itemId_;
|
||||
}
|
||||
|
||||
|
||||
//item
|
||||
|
||||
Item::Item(uint32_t itemIdIn, QString name, int8_t value, QObject *parent): QObject(parent), ItemData (itemIdIn, name, value)
|
||||
Item::Item(uint32_t itemIdIn, QString name, int8_t value, QObject *parent): QObject(parent), ItemData (itemIdIn, name,
|
||||
value)
|
||||
{
|
||||
|
||||
}
|
||||
@ -47,16 +48,16 @@ Item::~Item()
|
||||
|
||||
void Item::setFunction(uint8_t function, bool on)
|
||||
{
|
||||
functionChanged(function, on);
|
||||
functionChanged(function, on);
|
||||
}
|
||||
|
||||
void Item::setValue(int8_t value)
|
||||
{
|
||||
value_ = value;
|
||||
valueChanged(value_);
|
||||
value_ = value;
|
||||
valueChanged(value_);
|
||||
}
|
||||
|
||||
void Item::informValue(int8_t value)
|
||||
{
|
||||
Item::setValue(value);
|
||||
Item::setValue(value);
|
||||
}
|
@ -11,28 +11,34 @@ class Actor;
|
||||
class ItemData
|
||||
{
|
||||
protected:
|
||||
QString name_;
|
||||
QString name_;
|
||||
int8_t value_;
|
||||
uint32_t itemId_;
|
||||
uint32_t itemId_;
|
||||
|
||||
public:
|
||||
|
||||
ItemData(uint32_t itemIdIn = QRandomGenerator::global()->generate(), QString name = "Item", int8_t value = 0);
|
||||
|
||||
inline bool operator==(const ItemData& in) const{ return itemId_==in.itemId_; }
|
||||
inline bool operator!=(const ItemData& in) const{ return itemId_!=in.itemId_; }
|
||||
inline bool operator==(const ItemData& in) const
|
||||
{
|
||||
return itemId_==in.itemId_;
|
||||
}
|
||||
inline bool operator!=(const ItemData& in) const
|
||||
{
|
||||
return itemId_!=in.itemId_;
|
||||
}
|
||||
|
||||
uint32_t id() const;
|
||||
uint32_t id() const;
|
||||
|
||||
void setName(QString name);
|
||||
void setName(QString name);
|
||||
int8_t getValue() const;
|
||||
virtual QString getName() const;
|
||||
virtual QString getName() const;
|
||||
};
|
||||
|
||||
|
||||
class Item: public QObject, public ItemData
|
||||
{
|
||||
Q_OBJECT
|
||||
Q_OBJECT
|
||||
private:
|
||||
|
||||
signals:
|
||||
@ -43,16 +49,17 @@ signals:
|
||||
public slots:
|
||||
|
||||
virtual void setValue(int8_t value);
|
||||
virtual void setFunction(uint8_t funciton, bool value);
|
||||
virtual void setFunction(uint8_t funciton, bool value);
|
||||
|
||||
public:
|
||||
|
||||
Item(uint32_t itemIdIn = QRandomGenerator::global()->generate(), QString name = "Item", int8_t value = 0, QObject *parent = nullptr);
|
||||
Item(const ItemData& itemData, QObject *parent = nullptr);
|
||||
Item(uint32_t itemIdIn = QRandomGenerator::global()->generate(), QString name = "Item", int8_t value = 0,
|
||||
QObject *parent = nullptr);
|
||||
Item(const ItemData& itemData, QObject *parent = nullptr);
|
||||
|
||||
virtual ~Item();
|
||||
virtual ~Item();
|
||||
|
||||
void informValue(int8_t value);
|
||||
virtual void informValue(int8_t value);
|
||||
|
||||
};
|
||||
|
87
src/common/items/itemstore.cpp
Normal file
87
src/common/items/itemstore.cpp
Normal file
@ -0,0 +1,87 @@
|
||||
#include "itemstore.h"
|
||||
#include <QJsonArray>
|
||||
#include <QDebug>
|
||||
#include "train.h"
|
||||
|
||||
ItemStore::ItemStore(QObject *parent): QObject(parent)
|
||||
{
|
||||
}
|
||||
|
||||
void ItemStore::addItem(std::shared_ptr<Item> item)
|
||||
{
|
||||
if(!item)
|
||||
{
|
||||
qWarning()<<"invalid item";
|
||||
return;
|
||||
}
|
||||
bool mached = false;
|
||||
for(unsigned i = 0; i < items_.size(); i++ )
|
||||
if(*items_[i] == *item) mached = true;
|
||||
if(!mached)
|
||||
{
|
||||
items_.push_back(std::shared_ptr<Item>(item));
|
||||
itemAdded(std::weak_ptr<Item>(items_.back()));
|
||||
}
|
||||
}
|
||||
|
||||
void ItemStore::addItems(const std::vector<std::shared_ptr<Item>>& itemIn)
|
||||
{
|
||||
for(unsigned j = 0; j < itemIn.size(); j++)
|
||||
{
|
||||
addItem(itemIn[j]);
|
||||
Train* train = dynamic_cast<Train*>(itemIn[j].get());
|
||||
if(!train)
|
||||
continue;
|
||||
if(train->getTrainId() == 0)
|
||||
{
|
||||
const uint8_t uidBytes[] = {154, 110, 34, 218};
|
||||
train->tags.push_back(NfcUid(uidBytes, sizeof(uidBytes)));
|
||||
}
|
||||
else if(train->getTrainId() == 1)
|
||||
{
|
||||
const uint8_t uidBytes[] = {83, 118, 122, 215};
|
||||
train->tags.push_back(NfcUid(uidBytes, sizeof(uidBytes)));
|
||||
}
|
||||
else if(train->getTrainId() == 3)
|
||||
{
|
||||
train->tags.push_back(NfcUid({83, 111, 26, 174}));
|
||||
train->tags.push_back(NfcUid({83, 63, 78, 170}));
|
||||
}
|
||||
else if(train->getTrainId() == 4)
|
||||
{
|
||||
const uint8_t uidBytes[] = {55, 220, 31, 184};
|
||||
train->tags.push_back(NfcUid(uidBytes, sizeof(uidBytes)));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void ItemStore::removeItem(const ItemData& item)
|
||||
{
|
||||
for(unsigned j = 0; j < items_.size(); j++)
|
||||
{
|
||||
if(item == *items_[j])
|
||||
{
|
||||
items_.erase(items_.begin()+j);
|
||||
--j;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void ItemStore::clear()
|
||||
{
|
||||
for(size_t i = 0; i < items_.size(); ++i) itemDeleted(*items_[i]);
|
||||
items_.clear();
|
||||
}
|
||||
|
||||
void ItemStore::itemStateChanged(const ItemData& item)
|
||||
{
|
||||
for(unsigned i = 0; i < items_.size(); i++ )
|
||||
{
|
||||
if(items_[i]->operator==(item))
|
||||
{
|
||||
if(items_[i]->getValue() != item.getValue())
|
||||
items_[i]->informValue(item.getValue());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
36
src/common/items/itemstore.h
Normal file
36
src/common/items/itemstore.h
Normal file
@ -0,0 +1,36 @@
|
||||
#pragma once
|
||||
#include <vector>
|
||||
#include <memory>
|
||||
#include "item.h"
|
||||
#include "../nfcuid.h"
|
||||
|
||||
class ItemStore: public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
protected:
|
||||
std::vector< std::shared_ptr<Item> > items_;
|
||||
|
||||
public:
|
||||
|
||||
ItemStore(QObject *parent = nullptr);
|
||||
virtual ~ItemStore() {}
|
||||
|
||||
inline std::vector< std::shared_ptr<Item> >* getItems()
|
||||
{
|
||||
return &items_;
|
||||
}
|
||||
|
||||
void clear();
|
||||
|
||||
signals:
|
||||
|
||||
void itemDeleted(ItemData item);
|
||||
void itemAdded(std::weak_ptr<Item> Item);
|
||||
|
||||
public slots:
|
||||
|
||||
void removeItem(const ItemData& item);
|
||||
virtual void addItem(std::shared_ptr<Item> item);
|
||||
void addItems(const std::vector<std::shared_ptr<Item>>& itemsIn);
|
||||
void itemStateChanged(const ItemData& item);
|
||||
};
|
93
src/common/items/train.cpp
Normal file
93
src/common/items/train.cpp
Normal file
@ -0,0 +1,93 @@
|
||||
#include "train.h"
|
||||
|
||||
Train::Train(uint8_t id, uint8_t address, uint8_t functionMask, int8_t initalValue):
|
||||
Item(address, QString("Train ")+QString::number(id), initalValue),
|
||||
functionMask_(functionMask),
|
||||
train_id_(id)
|
||||
{
|
||||
}
|
||||
|
||||
Microcontroller *Train::micro = nullptr;
|
||||
|
||||
void Train::setFunction(uint8_t funciton, bool value)
|
||||
{
|
||||
Item::setFunction(funciton, value);
|
||||
if(micro)
|
||||
micro->trainSetFunction(train_id_, funciton, value);
|
||||
}
|
||||
|
||||
void Train::setValue(int8_t value)
|
||||
{
|
||||
Item::setValue(value);
|
||||
if(suspended_ && value != 0)
|
||||
{
|
||||
suspended_ = false;
|
||||
unsuspended(id(), getDirection());
|
||||
}
|
||||
if(micro)
|
||||
micro->trainSetSpeed(train_id_, value);
|
||||
}
|
||||
|
||||
void Train::informValue(int8_t value)
|
||||
{
|
||||
if(suspended_ && value != 0)
|
||||
{
|
||||
suspended_ = false;
|
||||
unsuspended(id(), getDirection());
|
||||
}
|
||||
Item::informValue(value);
|
||||
}
|
||||
|
||||
void Train::reverse()
|
||||
{
|
||||
if(micro)
|
||||
micro->trainReverse(train_id_);
|
||||
}
|
||||
|
||||
bool Train::ownsTag(NfcUid uid)
|
||||
{
|
||||
for(size_t i = 0; i < tags.size(); ++i)
|
||||
{
|
||||
if(uid == tags[i])
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool Train::suspend()
|
||||
{
|
||||
if(suspended_)
|
||||
return false;
|
||||
suspendedSpeed_ = value_;
|
||||
setValue(0);
|
||||
suspended_ = true;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Train::resume()
|
||||
{
|
||||
if(!suspended_)
|
||||
return false;
|
||||
suspended_ = false;
|
||||
setValue(suspendedSpeed_);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Train::hasBackTag()
|
||||
{
|
||||
return tags.size() > 1;
|
||||
}
|
||||
|
||||
bool Train::suspendend()
|
||||
{
|
||||
return suspended_;
|
||||
}
|
||||
|
||||
int Train::getDirection()
|
||||
{
|
||||
if(!suspended_)
|
||||
return value_ < 0 ? REVERSE : FORWARD;
|
||||
else
|
||||
return suspendedSpeed_ < 0 ? REVERSE : FORWARD;
|
||||
}
|
||||
|
51
src/common/items/train.h
Normal file
51
src/common/items/train.h
Normal file
@ -0,0 +1,51 @@
|
||||
#ifndef TRAIN_H
|
||||
#define TRAIN_H
|
||||
|
||||
#include <vector>
|
||||
#include "item.h"
|
||||
#include "microcontroller.h"
|
||||
#include "nfcuid.h"
|
||||
|
||||
class Train : public Item
|
||||
{
|
||||
Q_OBJECT
|
||||
uint8_t functionMask_;
|
||||
uint8_t train_id_;
|
||||
int lastReader_ = -1;
|
||||
int8_t suspendedSpeed_;
|
||||
bool suspended_ = false;
|
||||
public:
|
||||
static constexpr int FORWARD = 1;
|
||||
static constexpr int REVERSE = -1;
|
||||
static constexpr int TAG_FRONT = 0;
|
||||
static Microcontroller *micro;
|
||||
std::vector<NfcUid> tags;
|
||||
|
||||
Train(uint8_t id = 0, uint8_t address = 0, uint8_t functionMask = 0, int8_t initalValue = 0);
|
||||
|
||||
uint8_t getFunctionMask()
|
||||
{
|
||||
return functionMask_;
|
||||
}
|
||||
|
||||
public slots:
|
||||
void reverse();
|
||||
virtual void setFunction(uint8_t function, bool on);
|
||||
virtual void setValue(int8_t value);
|
||||
virtual void informValue(int8_t value);
|
||||
bool suspend();
|
||||
bool resume();
|
||||
bool suspendend();
|
||||
int getDirection();
|
||||
bool ownsTag(NfcUid uid);
|
||||
bool hasBackTag();
|
||||
uint8_t getTrainId()
|
||||
{
|
||||
return train_id_;
|
||||
}
|
||||
|
||||
signals:
|
||||
void unsuspended(uint32_t id, int direction);
|
||||
};
|
||||
|
||||
#endif // TRAIN_H
|
28
src/common/items/trainsignal.cpp
Normal file
28
src/common/items/trainsignal.cpp
Normal file
@ -0,0 +1,28 @@
|
||||
#include "trainsignal.h"
|
||||
|
||||
Microcontroller *Signal::micro = nullptr;
|
||||
|
||||
Signal::Signal(uint8_t id, uint8_t address, uint8_t subaddress, uint8_t type, int8_t initalValue)
|
||||
: Item(address | (subaddress << 8), QString("Turnout ")+QString::number(id), initalValue),
|
||||
subaddress_(subaddress), signalId_(id), type_(type)
|
||||
{
|
||||
itemId_ = address | (subaddress << 8);
|
||||
name_ = QString("Signal ")+QString::number(id);
|
||||
}
|
||||
|
||||
void Signal::setValue(int8_t value)
|
||||
{
|
||||
Item::setValue(value);
|
||||
if(micro)
|
||||
micro->signalSetValue(signalId_, value);
|
||||
}
|
||||
|
||||
bool Signal::hasSlow()
|
||||
{
|
||||
return type_ & TYPE_HAS_SLOW;
|
||||
}
|
||||
|
||||
bool Signal::hasExpect()
|
||||
{
|
||||
return type_ & TYPE_HAS_EXPECT;
|
||||
}
|
38
src/common/items/trainsignal.h
Normal file
38
src/common/items/trainsignal.h
Normal file
@ -0,0 +1,38 @@
|
||||
#ifndef SIGNAL_H
|
||||
#define SIGNAL_H
|
||||
|
||||
#include "item.h"
|
||||
#include "../microcontroller.h"
|
||||
|
||||
class Signal : public Item
|
||||
{
|
||||
public:
|
||||
static constexpr int GO = 0;
|
||||
static constexpr int STOP = 1;
|
||||
static constexpr int SLOW = 2;
|
||||
static constexpr int EXPECT_GO = 1 << 3;
|
||||
static constexpr int EXPECT_STOP = 2 << 3;
|
||||
static constexpr int EXPECT_SLOW = 3 << 3;
|
||||
|
||||
static constexpr uint8_t TYPE_NORMAL = 0;
|
||||
static constexpr uint8_t TYPE_RELAY = 1;
|
||||
static constexpr uint8_t TYPE_HAS_SLOW = 1 << 1;
|
||||
static constexpr uint8_t TYPE_HAS_EXPECT = 1 << 2;
|
||||
private:
|
||||
uint8_t subaddress_;
|
||||
uint8_t signalId_;
|
||||
uint8_t type_;
|
||||
public:
|
||||
static Microcontroller *micro;
|
||||
|
||||
explicit Signal(uint8_t id = 0, uint8_t address = 0, uint8_t subaddress = 0, uint8_t type = 0, int8_t initalValue = 0);
|
||||
virtual void setValue(int8_t value);
|
||||
bool hasSlow();
|
||||
bool hasExpect();
|
||||
uint8_t getSignalId()
|
||||
{
|
||||
return signalId_;
|
||||
}
|
||||
};
|
||||
|
||||
#endif // SIGNAL_H
|
@ -6,13 +6,13 @@ Turnout::Turnout(uint8_t id, uint8_t address, uint8_t subaddress, int8_t initalV
|
||||
: Item(address | (subaddress << 8), QString("Turnout ")+QString::number(id), initalValue),
|
||||
subaddress_(subaddress), turnoutId_(id)
|
||||
{
|
||||
itemId_ = address | (subaddress << 8);
|
||||
name_ = QString("Turnout ")+QString::number(id);
|
||||
itemId_ = address | (subaddress << 8);
|
||||
name_ = QString("Turnout ")+QString::number(id);
|
||||
}
|
||||
|
||||
void Turnout::setValue(int8_t value)
|
||||
{
|
||||
Item::setValue(value);
|
||||
if(micro)
|
||||
Item::setValue(value);
|
||||
if(micro)
|
||||
micro->tunoutSetDirection(turnoutId_, value > 0);
|
||||
}
|
@ -6,14 +6,17 @@
|
||||
|
||||
class Turnout : public Item
|
||||
{
|
||||
uint8_t subaddress_;
|
||||
uint8_t turnoutId_;
|
||||
uint8_t subaddress_;
|
||||
uint8_t turnoutId_;
|
||||
public:
|
||||
static Microcontroller *micro;
|
||||
static Microcontroller *micro;
|
||||
|
||||
explicit Turnout(uint8_t id = 0, uint8_t address = 0, uint8_t subaddress = 0, int8_t initalValue = 0);
|
||||
virtual void setValue(int8_t value);
|
||||
uint8_t getTurnoutId(){return turnoutId_;}
|
||||
uint8_t getTurnoutId()
|
||||
{
|
||||
return turnoutId_;
|
||||
}
|
||||
};
|
||||
|
||||
#endif // TURNOUT_H
|
253
src/common/microcontroller.cpp
Normal file
253
src/common/microcontroller.cpp
Normal file
@ -0,0 +1,253 @@
|
||||
#include "microcontroller.h"
|
||||
|
||||
#include <chrono>
|
||||
#include <thread>
|
||||
#include "train.h"
|
||||
#include "turnout.h"
|
||||
#include "trainsignal.h"
|
||||
|
||||
void Microcontroller::trainSetSpeed(uint8_t id, int8_t speed)
|
||||
{
|
||||
std::stringstream ss;
|
||||
ss<<"train "<<(unsigned)id<<" speed "<<(int)speed<<'\n';
|
||||
write(ss.str().c_str());
|
||||
}
|
||||
|
||||
void Microcontroller::trainReverse(uint8_t id)
|
||||
{
|
||||
std::stringstream ss;
|
||||
ss<<"train "<<(unsigned)id<<" reverse\n";
|
||||
write(ss.str().c_str());
|
||||
}
|
||||
|
||||
void Microcontroller::trainSetFunction(uint8_t id, uint8_t function, bool on)
|
||||
{
|
||||
std::stringstream ss;
|
||||
ss<<"train "<<(unsigned)id<<" function "<<(unsigned)function<<' '<<(on ? "on" : "off")<<'\n';
|
||||
write(ss.str().c_str());
|
||||
}
|
||||
|
||||
void Microcontroller::tunoutSetDirection(uint8_t id, bool direction)
|
||||
{
|
||||
std::stringstream ss;
|
||||
ss<<"turnout "<<(unsigned)id<<" set "<<(!direction ? "left" : "right")<<'\n';
|
||||
write(ss.str().c_str());
|
||||
}
|
||||
|
||||
void Microcontroller::signalSetValue(uint8_t id, uint8_t state)
|
||||
{
|
||||
std::stringstream ss;
|
||||
ss<<"signal "<<(unsigned)id<<" set "<<(unsigned)state<<'\n';
|
||||
write(ss.str().c_str());
|
||||
}
|
||||
|
||||
void Microcontroller::setPower(bool on)
|
||||
{
|
||||
write(on ? "power on\n" : "power off\n");
|
||||
}
|
||||
|
||||
void Microcontroller::estop()
|
||||
{
|
||||
write("stop\n");
|
||||
}
|
||||
|
||||
void Microcontroller::write(const QByteArray& buffer)
|
||||
{
|
||||
if(_port != nullptr)
|
||||
{
|
||||
_port->write(buffer);
|
||||
//_port->waitForBytesWritten(1000);
|
||||
}
|
||||
std::this_thread::sleep_for(std::chrono::milliseconds(40));
|
||||
}
|
||||
|
||||
void Microcontroller::write(char* buffer, const size_t length)
|
||||
{
|
||||
if(_port != nullptr)
|
||||
{
|
||||
_port->write(buffer, length);
|
||||
//_port->waitForBytesWritten(1000);
|
||||
}
|
||||
std::this_thread::sleep_for(std::chrono::milliseconds(40));
|
||||
}
|
||||
|
||||
bool Microcontroller::connected()
|
||||
{
|
||||
if(_port != nullptr)
|
||||
return _port->isOpen();
|
||||
else return false;
|
||||
}
|
||||
|
||||
void Microcontroller::requestState()
|
||||
{
|
||||
write("train list\n");
|
||||
write("turnout list\n");
|
||||
write("signal list\n");
|
||||
write("nfc list\n");
|
||||
}
|
||||
|
||||
//housekeeping
|
||||
|
||||
Microcontroller::Microcontroller(QIODevice* port)
|
||||
{
|
||||
setIODevice(port);
|
||||
}
|
||||
|
||||
Microcontroller::Microcontroller()
|
||||
{
|
||||
}
|
||||
|
||||
Microcontroller::~Microcontroller()
|
||||
{
|
||||
}
|
||||
|
||||
void Microcontroller::setIODevice(QIODevice* port)
|
||||
{
|
||||
_port = port;
|
||||
QObject::connect(_port, &QIODevice::readyRead, this, &Microcontroller::isReadyRead);
|
||||
}
|
||||
|
||||
std::shared_ptr<Item> Microcontroller::processTrainLine(const QString& buffer)
|
||||
{
|
||||
QStringList bufferList = buffer.split(' ');
|
||||
if(bufferList.size() >= 14 && buffer.startsWith("TRAIN NUMBER:"))
|
||||
{
|
||||
return std::shared_ptr<Item>(new Train(bufferList[2].toInt(), bufferList[4].toInt(), bufferList[13].toInt(nullptr, 2),
|
||||
bufferList[9].toInt()));
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
std::shared_ptr<Item> Microcontroller::processTurnoutLine(const QString& buffer)
|
||||
{
|
||||
QStringList bufferList = buffer.split(' ');
|
||||
if(bufferList.size() >= 11 && buffer.startsWith("TURNOUT NUMBER:"))
|
||||
{
|
||||
return std::shared_ptr<Item>(new Turnout(bufferList[2].toInt(), bufferList[4].toInt(), bufferList[6].toInt(),
|
||||
bufferList[11].toInt()));
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
std::shared_ptr<Item> Microcontroller::processSignalLine(const QString& buffer)
|
||||
{
|
||||
QStringList bufferList = buffer.split(' ');
|
||||
if(bufferList.size() >= 13 && buffer.startsWith("SIGNAL NUMBER:"))
|
||||
{
|
||||
return std::shared_ptr<Item>(new Signal(bufferList[2].toInt(), bufferList[4].toInt(), bufferList[6].toInt(),
|
||||
bufferList[8].toInt(), bufferList[13].toInt()));
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
void Microcontroller::processNfcLine(const QString& buffer)
|
||||
{
|
||||
QStringList tokens = buffer.split(" ");
|
||||
if(tokens.size() < 4)
|
||||
return;
|
||||
|
||||
if(tokens[1].startsWith("NUMBER"))
|
||||
return;
|
||||
|
||||
NfcUid uid;
|
||||
uint8_t reader = tokens[1].toUInt();
|
||||
tokens = tokens[3].split(':');
|
||||
uid.length = tokens.length();
|
||||
for(size_t i = 0; i < uid.length; ++i)
|
||||
uid.bytes[i] = tokens[i].toInt();
|
||||
gotTag(reader, uid);
|
||||
}
|
||||
|
||||
void Microcontroller::processList(const QString& buffer)
|
||||
{
|
||||
QStringList bufferList = buffer.split(' ');
|
||||
if(bufferList.size() >= 10 && buffer.contains("NUMBER:"))
|
||||
{
|
||||
std::shared_ptr<Item> item;
|
||||
if(listMode == TRAIN_LIST)
|
||||
item = processTrainLine(buffer);
|
||||
else if(listMode == TURNOUT_LIST)
|
||||
item = processTurnoutLine(buffer);
|
||||
else if(listMode == SIGNAL_LIST)
|
||||
item = processSignalLine(buffer);
|
||||
if(item)
|
||||
itemList.push_back(item);
|
||||
}
|
||||
else
|
||||
{
|
||||
listMode = false;
|
||||
if(!itemList.empty())
|
||||
{
|
||||
gotItemList(itemList);
|
||||
itemList.clear();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Microcontroller::processItemState(const QString& buffer)
|
||||
{
|
||||
std::shared_ptr<Item> item = processTrainLine(buffer);
|
||||
if(_buffer.startsWith("TRAIN NUMBER:"))
|
||||
item = processTrainLine(buffer);
|
||||
else if(_buffer.startsWith("TURNOUT NUMBER:"))
|
||||
item = processTurnoutLine(buffer);
|
||||
else if(_buffer.startsWith("SIGNAL NUMBER:"))
|
||||
item = processSignalLine(buffer);
|
||||
if(item)
|
||||
itemChanged(static_cast<ItemData>(*item));
|
||||
else
|
||||
qWarning()<<__func__<<"failed to process status line";
|
||||
}
|
||||
|
||||
|
||||
void Microcontroller::processMicroReturn()
|
||||
{
|
||||
if(listMode)
|
||||
processList(_buffer);
|
||||
else
|
||||
{
|
||||
if(_buffer.startsWith("Trains:"))
|
||||
{
|
||||
listMode = TRAIN_LIST;
|
||||
itemList.clear();
|
||||
}
|
||||
else if(_buffer.startsWith("Turnouts:"))
|
||||
{
|
||||
listMode = TURNOUT_LIST;
|
||||
}
|
||||
else if(_buffer.startsWith("Signals:"))
|
||||
{
|
||||
listMode = SIGNAL_LIST;
|
||||
}
|
||||
else if(_buffer.startsWith("TRAIN NUMBER:") || _buffer.startsWith("TURNOUT NUMBER:") ||
|
||||
_buffer.startsWith("SIGNAL NUMBER:"))
|
||||
{
|
||||
processItemState(_buffer);
|
||||
}
|
||||
else if(_buffer.startsWith("NFC"))
|
||||
{
|
||||
processNfcLine(_buffer);
|
||||
}
|
||||
else if(_buffer.startsWith("TrainController"))
|
||||
{
|
||||
requestState();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void Microcontroller::isReadyRead()
|
||||
{
|
||||
char charBuf;
|
||||
while(_port->getChar(&charBuf))
|
||||
{
|
||||
_buffer.push_back(charBuf);
|
||||
if( _buffer.endsWith('\n') )
|
||||
{
|
||||
_buffer.remove('\n');
|
||||
processMicroReturn();
|
||||
textRecived(_buffer);
|
||||
_buffer.clear();
|
||||
}
|
||||
}
|
||||
}
|
80
src/common/microcontroller.h
Normal file
80
src/common/microcontroller.h
Normal file
@ -0,0 +1,80 @@
|
||||
#ifndef MICROCONTROLLER_H
|
||||
#define MICROCONTROLLER_H
|
||||
|
||||
#include <iostream>
|
||||
|
||||
#include <QObject>
|
||||
#include <QIODevice>
|
||||
#include <QString>
|
||||
#include <QRunnable>
|
||||
#include <QDebug>
|
||||
#include <QEventLoop>
|
||||
#include <QTimer>
|
||||
#include <vector>
|
||||
#include <memory>
|
||||
#include <sstream>
|
||||
#include "items/item.h"
|
||||
#include "nfcuid.h"
|
||||
|
||||
class Microcontroller : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
private:
|
||||
|
||||
static constexpr int TRAIN_LIST = 1;
|
||||
static constexpr int TURNOUT_LIST = 2;
|
||||
static constexpr int SIGNAL_LIST = 3;
|
||||
|
||||
int listMode = 0;
|
||||
|
||||
//uint8_t _auxState = 0;
|
||||
|
||||
QIODevice* _port = nullptr;
|
||||
|
||||
std::vector< std::shared_ptr<Item> > itemList;
|
||||
|
||||
QScopedPointer<QEventLoop> loop;
|
||||
QString _buffer;
|
||||
|
||||
void processMicroReturn();
|
||||
void processList(const QString& buffer);
|
||||
void processItemState(const QString& buffer);
|
||||
std::shared_ptr<Item> processTrainLine(const QString& buffer);
|
||||
std::shared_ptr<Item> processTurnoutLine(const QString& buffer);
|
||||
std::shared_ptr<Item> processSignalLine(const QString& buffer);
|
||||
void processNfcLine(const QString& buffer);
|
||||
|
||||
void write(char *buffer, const size_t length);
|
||||
void write(const QByteArray& buffer);
|
||||
|
||||
public:
|
||||
Microcontroller(QIODevice* port);
|
||||
Microcontroller();
|
||||
~Microcontroller();
|
||||
bool connected();
|
||||
void setIODevice(QIODevice* port);
|
||||
|
||||
public slots:
|
||||
void requestState();
|
||||
|
||||
void trainSetSpeed(uint8_t id, int8_t speed);
|
||||
void trainReverse(uint8_t id);
|
||||
void trainSetFunction(uint8_t id, uint8_t function, bool on);
|
||||
void tunoutSetDirection(uint8_t id, bool direction);
|
||||
void signalSetValue(uint8_t id, uint8_t state);
|
||||
void estop();
|
||||
void setPower(bool on);
|
||||
|
||||
private slots:
|
||||
void isReadyRead();
|
||||
|
||||
signals:
|
||||
void textRecived(const QString string);
|
||||
void itemChanged(ItemData relay);
|
||||
void auxStateChanged(int value);
|
||||
void gotItemList(std::vector<std::shared_ptr<Item>>&);
|
||||
void gotTag(uint8_t reader, NfcUid uid);
|
||||
};
|
||||
|
||||
#endif // MICROCONTROLLER_H
|
53
src/common/nfcuid.h
Normal file
53
src/common/nfcuid.h
Normal file
@ -0,0 +1,53 @@
|
||||
#ifndef NFCUID_H
|
||||
#define NFCUID_H
|
||||
#include <cstdint>
|
||||
#include <string>
|
||||
|
||||
class NfcUid
|
||||
{
|
||||
public:
|
||||
uint8_t bytes[10];
|
||||
uint8_t length;
|
||||
bool operator==(const NfcUid& in) const
|
||||
{
|
||||
if(length != in.length)
|
||||
return false;
|
||||
for(uint8_t i = 0; i < length; ++i)
|
||||
{
|
||||
if(bytes[i] != in.bytes[i])
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
bool operator!=(const NfcUid& in) const
|
||||
{
|
||||
return !operator==(in);
|
||||
}
|
||||
NfcUid(){}
|
||||
NfcUid(const std::initializer_list<const uint8_t> list)
|
||||
{
|
||||
length = list.size();
|
||||
uint8_t i = 0;
|
||||
for(std::initializer_list<const uint8_t>::iterator iter = list.begin(); iter != list.end(); ++iter)
|
||||
bytes[i++] = *iter;
|
||||
}
|
||||
NfcUid(const uint8_t* const bytesIn, uint8_t lengthIn): length(lengthIn)
|
||||
{
|
||||
for(uint8_t i = 0; i < length; ++i)
|
||||
bytes[i] = bytesIn[i];
|
||||
}
|
||||
std::string toString() const
|
||||
{
|
||||
std::string str;
|
||||
for(uint8_t i = 0; i < length; ++i)
|
||||
{
|
||||
str.append(std::to_string((int)bytes[i]));
|
||||
if(i != length-1)
|
||||
str.push_back(':');
|
||||
}
|
||||
return str;
|
||||
}
|
||||
};
|
||||
|
||||
#endif // NFCUID_H
|
||||
|
@ -1,18 +0,0 @@
|
||||
#include "auxitem.h"
|
||||
|
||||
AuxItem::AuxItem(Microcontroller* micro, uint32_t itemIdIn, QString name, uint8_t value, QObject* parent): Item(itemIdIn, name, value, parent), micro_(micro)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void AuxItem::setValue(uint8_t value)
|
||||
{
|
||||
Item::setValue(value);
|
||||
micro_->setAuxPwm(value);
|
||||
}
|
||||
|
||||
void AuxItem::store(QJsonObject &json)
|
||||
{
|
||||
json["Type"] = "Aux";
|
||||
Item::store(json);
|
||||
}
|
@ -1,20 +0,0 @@
|
||||
#pragma once
|
||||
|
||||
#include "item.h"
|
||||
#include "../microcontroller.h"
|
||||
|
||||
class AuxItem: public Item
|
||||
{
|
||||
Q_OBJECT
|
||||
private:
|
||||
Microcontroller* micro_;
|
||||
|
||||
public slots:
|
||||
|
||||
virtual void setValue(uint8_t value);
|
||||
|
||||
public:
|
||||
AuxItem(Microcontroller* micro, uint32_t itemIdIn = QRandomGenerator::global()->generate(), QString name = "", uint8_t value = 0, QObject* parent = nullptr);
|
||||
|
||||
virtual void store(QJsonObject& json);
|
||||
};
|
@ -1,111 +0,0 @@
|
||||
#include "itemstore.h"
|
||||
#include <QJsonArray>
|
||||
#include <QDebug>
|
||||
#include "train.h"
|
||||
#include "../trainjs.h"
|
||||
|
||||
ItemStore::ItemStore(QObject *parent): QObject(parent)
|
||||
{
|
||||
}
|
||||
|
||||
void ItemStore::addItem(std::shared_ptr<Item> item)
|
||||
{
|
||||
if(!item)
|
||||
{
|
||||
qWarning()<<"invalid item";
|
||||
return;
|
||||
}
|
||||
bool mached = false;
|
||||
for(unsigned i = 0; i < items_.size(); i++ )
|
||||
if(*items_[i] == *item) mached = true;
|
||||
if(!mached)
|
||||
{
|
||||
items_.push_back(std::shared_ptr<Item>(item));
|
||||
|
||||
if(dynamic_cast<Train*>(item.get()))
|
||||
{
|
||||
std::vector<std::shared_ptr<TrainJs>> joysticks = TrainJs::getJsDevices();
|
||||
for(auto joystick: joysticks)
|
||||
{
|
||||
if(!joystick->itemIsSet())
|
||||
{
|
||||
joystick->setItem(item);
|
||||
connect(joystick.get(), &TrainJs::reqNewItem, this, &ItemStore::jsReqNewItem);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
itemAdded(std::weak_ptr<Item>(items_.back()));
|
||||
}
|
||||
qDebug()<<"Got item: "<<item->id()<<" matched: "<<mached;
|
||||
}
|
||||
|
||||
void ItemStore::jsReqNewItem()
|
||||
{
|
||||
if(items_.empty())
|
||||
return;
|
||||
|
||||
std::vector<std::shared_ptr<TrainJs>> joysticks = TrainJs::getJsDevices();
|
||||
for(auto joystick: joysticks)
|
||||
{
|
||||
if(joystick->getWantsNewItem())
|
||||
{
|
||||
std::shared_ptr<Item> oldItem = joystick->getItem().lock();
|
||||
for(size_t i = 0; i < items_.size(); ++i)
|
||||
{
|
||||
if(!oldItem || *items_[i] == *oldItem)
|
||||
{
|
||||
if(i+1 < items_.size())
|
||||
joystick->setItem(items_[i+1]);
|
||||
else
|
||||
joystick->setItem(items_[0]);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void ItemStore::addItems(const std::vector<std::shared_ptr<Item>>& itemIn)
|
||||
{
|
||||
for(unsigned j = 0; j < itemIn.size(); j++)
|
||||
addItem(itemIn[j]);
|
||||
|
||||
}
|
||||
|
||||
void ItemStore::removeItem(const ItemData& item)
|
||||
{
|
||||
for(unsigned j = 0; j < items_.size(); j++)
|
||||
{
|
||||
if(item == *items_[j])
|
||||
{
|
||||
items_.erase(items_.begin()+j);
|
||||
--j;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void ItemStore::clear()
|
||||
{
|
||||
for(size_t i = 0; i < items_.size(); ++i) itemDeleted(*items_[i]);
|
||||
items_.clear();
|
||||
}
|
||||
|
||||
|
||||
void ItemStore::itemStateChanged(const ItemData& item)
|
||||
{
|
||||
|
||||
for(unsigned i = 0; i < items_.size(); i++ )
|
||||
{
|
||||
if(items_[i]->operator==(item))
|
||||
{
|
||||
|
||||
if(items_[i]->getValue() != item.getValue())items_[i]->informValue(item.getValue());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -1,38 +0,0 @@
|
||||
#pragma once
|
||||
#include <vector>
|
||||
#include <memory>
|
||||
#include "item.h"
|
||||
|
||||
#include <QJsonObject>
|
||||
|
||||
class ItemStore: public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
private:
|
||||
std::vector< std::shared_ptr<Item> > items_;
|
||||
|
||||
public:
|
||||
|
||||
ItemStore(QObject *parent = nullptr);
|
||||
virtual ~ItemStore(){}
|
||||
|
||||
inline std::vector< std::shared_ptr<Item> >* getItems(){ return &items_; }
|
||||
|
||||
void clear();
|
||||
|
||||
private slots:
|
||||
|
||||
void jsReqNewItem();
|
||||
|
||||
signals:
|
||||
|
||||
void itemDeleted(ItemData item);
|
||||
void itemAdded(std::weak_ptr<Item> Item);
|
||||
|
||||
public slots:
|
||||
|
||||
void removeItem(const ItemData& item);
|
||||
void addItem(std::shared_ptr<Item> item);
|
||||
void addItems(const std::vector<std::shared_ptr<Item>>& itemsIn);
|
||||
void itemStateChanged(const ItemData& item);
|
||||
};
|
@ -1,31 +0,0 @@
|
||||
#include "train.h"
|
||||
|
||||
Train::Train(uint8_t id, uint8_t address, uint8_t functionMask, int8_t initalValue):
|
||||
Item(address, QString("Train ")+QString::number(id), initalValue),
|
||||
functionMask_(functionMask),
|
||||
train_id_(id)
|
||||
{
|
||||
}
|
||||
|
||||
Microcontroller *Train::micro = nullptr;
|
||||
|
||||
void Train::setFunction(uint8_t funciton, bool value)
|
||||
{
|
||||
Item::setFunction(funciton, value);
|
||||
if(micro)
|
||||
micro->trainSetFunction(train_id_, funciton, value);
|
||||
}
|
||||
|
||||
void Train::setValue(int8_t value)
|
||||
{
|
||||
Item::setValue(value);
|
||||
if(micro)
|
||||
micro->trainSetSpeed(train_id_, value);
|
||||
}
|
||||
|
||||
void Train::reverse()
|
||||
{
|
||||
if(micro)
|
||||
micro->trainReverse(train_id_);
|
||||
}
|
||||
|
@ -1,26 +0,0 @@
|
||||
#ifndef TRAIN_H
|
||||
#define TRAIN_H
|
||||
|
||||
#include "item.h"
|
||||
#include "../microcontroller.h"
|
||||
|
||||
class Train : public Item
|
||||
{
|
||||
Q_OBJECT
|
||||
uint8_t functionMask_;
|
||||
uint8_t train_id_;
|
||||
public:
|
||||
static Microcontroller *micro;
|
||||
|
||||
Train(uint8_t id = 0, uint8_t address = 0, uint8_t functionMask = 0, int8_t initalValue = 0);
|
||||
|
||||
uint8_t getFunctionMask() {return functionMask_;}
|
||||
|
||||
public slots:
|
||||
void reverse();
|
||||
virtual void setFunction(uint8_t function, bool on);
|
||||
virtual void setValue(int8_t value);
|
||||
uint8_t getTrainId(){return train_id_;}
|
||||
};
|
||||
|
||||
#endif // TRAIN_H
|
111
src/main.cpp
111
src/main.cpp
@ -1,111 +0,0 @@
|
||||
#include <QtWidgets/QApplication>
|
||||
#include <stdio.h>
|
||||
#include <QDebug>
|
||||
#include <QTcpSocket>
|
||||
#include <QMessageBox>
|
||||
#include <QtSerialPort/QtSerialPort>
|
||||
#include <QtSerialPort/QSerialPortInfo>
|
||||
#include <QCommandLineParser>
|
||||
|
||||
#include "microcontroller.h"
|
||||
#include "trainjs.h"
|
||||
#include "ui/mainwindow.h"
|
||||
#include "items/itemstore.h"
|
||||
#include "items/train.h"
|
||||
#include "items/turnout.h"
|
||||
|
||||
#define BAUD QSerialPort::Baud38400
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
QApplication a(argc, argv);
|
||||
|
||||
//set info
|
||||
QCoreApplication::setOrganizationName("UVOS");
|
||||
QCoreApplication::setOrganizationDomain("uvos.xyz");
|
||||
QCoreApplication::setApplicationName("traincontrollerui");
|
||||
QCoreApplication::setApplicationVersion("0.1");
|
||||
|
||||
QDir::setCurrent(a.applicationDirPath());
|
||||
|
||||
//parse comand line
|
||||
QCommandLineParser parser;
|
||||
parser.setApplicationDescription("Smart Home Interface");
|
||||
parser.addHelpOption();
|
||||
parser.addVersionOption();
|
||||
QCommandLineOption tcpOption(QStringList() << "t" << "tcp", QCoreApplication::translate("main", "Use Tcp connection"));
|
||||
parser.addOption(tcpOption);
|
||||
QCommandLineOption hostOption(QStringList() << "H" << "host", QCoreApplication::translate("main", "Set server host ip addres"), "adress");
|
||||
parser.addOption(hostOption);
|
||||
QCommandLineOption portOption(QStringList() << "p" << "port", QCoreApplication::translate("main", "Set server Port in TCP mode or Serial port in serial mode"), "port");
|
||||
parser.addOption(portOption);
|
||||
QCommandLineOption serialOption(QStringList() << "s" << "serial", QCoreApplication::translate("main", "Use serial connection"));
|
||||
parser.addOption(serialOption);
|
||||
QCommandLineOption baudOption(QStringList() << "b" << "baud", QCoreApplication::translate("main", "Set Baud Rate"));
|
||||
parser.addOption(baudOption);
|
||||
parser.process(a);
|
||||
|
||||
QIODevice* masterIODevice = nullptr;
|
||||
|
||||
if(parser.isSet(tcpOption))
|
||||
{
|
||||
QTcpSocket* microSocket = new QTcpSocket;
|
||||
|
||||
int port = 6856;
|
||||
if(parser.isSet(portOption)) port = parser.value(portOption).toInt();
|
||||
|
||||
QString host("127.0.0.1");
|
||||
if(parser.isSet(hostOption)) host = parser.value(hostOption);
|
||||
std::cout<<"connecting to "<<host.toStdString()<<':'<<port<<'\n';
|
||||
microSocket->connectToHost(host, port, QIODevice::ReadWrite);
|
||||
if(!microSocket->waitForConnected(3000))
|
||||
{
|
||||
std::cout<<"Can not connect to to Server.\n";
|
||||
QMessageBox::critical(nullptr, "Error", "Can not connect to to Server");
|
||||
return 1;
|
||||
}
|
||||
masterIODevice = microSocket;
|
||||
}
|
||||
else
|
||||
{
|
||||
QSerialPort* microPort = new QSerialPort;
|
||||
if(parser.isSet(portOption)) microPort->setPortName(parser.value(portOption));
|
||||
else microPort->setPortName("ttyUSB0");
|
||||
|
||||
if(parser.isSet(portOption)) microPort->setBaudRate(parser.value(baudOption).toInt());
|
||||
else microPort->setBaudRate(BAUD);
|
||||
|
||||
if(!microPort->open(QIODevice::ReadWrite))
|
||||
{
|
||||
QMessageBox::critical(nullptr, "Error", QString("Can not open serial port ")+microPort->portName());
|
||||
std::cout<<"Can not open serial port "<<microPort->portName().toStdString()<<". Continueing in demo mode"<<'\n';
|
||||
return 1;
|
||||
}
|
||||
masterIODevice = microPort;
|
||||
}
|
||||
|
||||
Microcontroller micro(masterIODevice);
|
||||
micro.setPower(true);
|
||||
|
||||
TrainJs::init();
|
||||
|
||||
Train::micro = µ
|
||||
Turnout::micro = µ
|
||||
ItemStore items;
|
||||
|
||||
QObject::connect(µ, &Microcontroller::gotItemList, &items, &ItemStore::addItems);
|
||||
QObject::connect(µ, &Microcontroller::itemChanged, &items, &ItemStore::itemStateChanged);
|
||||
|
||||
//mainwindow
|
||||
MainWindow w(µ, &items);
|
||||
|
||||
w.show();
|
||||
|
||||
int retVal = a.exec();
|
||||
micro.setPower(false);
|
||||
|
||||
if(masterIODevice)
|
||||
delete masterIODevice;
|
||||
return retVal;
|
||||
}
|
||||
|
@ -1,14 +0,0 @@
|
||||
#include "mainobject.h"
|
||||
|
||||
MainObject::MainObject(QIODevice* ioDevice) :
|
||||
masterIODevice(ioDevice),
|
||||
micro(masterIODevice)
|
||||
{
|
||||
//connect item store
|
||||
QObject::connect(µ, &Microcontroller::gotItemList, &items, &ItemStore::addItems);
|
||||
}
|
||||
|
||||
MainObject::~MainObject()
|
||||
{
|
||||
}
|
||||
|
@ -1,199 +0,0 @@
|
||||
#include "microcontroller.h"
|
||||
|
||||
#include <chrono>
|
||||
#include <thread>
|
||||
#include "items/train.h"
|
||||
#include "items/turnout.h"
|
||||
|
||||
void Microcontroller::trainSetSpeed(uint8_t id, int8_t speed)
|
||||
{
|
||||
qDebug()<<__func__;
|
||||
std::stringstream ss;
|
||||
ss<<"train "<<(unsigned)id<<" speed "<<(int)speed<<'\n';
|
||||
write(ss.str().c_str());
|
||||
}
|
||||
|
||||
void Microcontroller::trainReverse(uint8_t id)
|
||||
{
|
||||
std::stringstream ss;
|
||||
ss<<"train "<<(unsigned)id<<" reverse\n";
|
||||
write(ss.str().c_str());
|
||||
}
|
||||
|
||||
void Microcontroller::trainSetFunction(uint8_t id, uint8_t function, bool on)
|
||||
{
|
||||
std::stringstream ss;
|
||||
ss<<"train "<<(unsigned)id<<" function "<<(unsigned)function<<' '<<(on ? "on" : "off")<<'\n';
|
||||
write(ss.str().c_str());
|
||||
}
|
||||
|
||||
void Microcontroller::tunoutSetDirection(uint8_t id, bool direction)
|
||||
{
|
||||
std::stringstream ss;
|
||||
ss<<"turnout "<<(unsigned)id<<" set "<<(!direction ? "left" : "right")<<'\n';
|
||||
write(ss.str().c_str());
|
||||
}
|
||||
|
||||
void Microcontroller::setPower(bool on)
|
||||
{
|
||||
write(on ? "power on\n" : "power off\n");
|
||||
}
|
||||
|
||||
void Microcontroller::estop()
|
||||
{
|
||||
write("stop\n");
|
||||
}
|
||||
|
||||
void Microcontroller::write(const QByteArray& buffer)
|
||||
{
|
||||
qDebug()<<buffer;
|
||||
if(_port != nullptr)
|
||||
{
|
||||
_port->write(buffer);
|
||||
_port->waitForBytesWritten(1000);
|
||||
}
|
||||
std::this_thread::sleep_for(std::chrono::milliseconds(40));
|
||||
}
|
||||
|
||||
void Microcontroller::write(char* buffer, const size_t length)
|
||||
{
|
||||
qDebug()<<buffer;
|
||||
if(_port != nullptr)
|
||||
{
|
||||
_port->write(buffer, length);
|
||||
//_port->waitForBytesWritten(1000);
|
||||
}
|
||||
std::this_thread::sleep_for(std::chrono::milliseconds(40));
|
||||
}
|
||||
|
||||
bool Microcontroller::connected()
|
||||
{
|
||||
if(_port != nullptr)
|
||||
return _port->isOpen();
|
||||
else return false;
|
||||
}
|
||||
|
||||
void Microcontroller::requestState()
|
||||
{
|
||||
write("train list\n");
|
||||
write("turnout list\n");
|
||||
}
|
||||
|
||||
//housekeeping
|
||||
|
||||
Microcontroller::Microcontroller(QIODevice* port)
|
||||
{
|
||||
setIODevice(port);
|
||||
}
|
||||
|
||||
Microcontroller::Microcontroller()
|
||||
{
|
||||
}
|
||||
|
||||
Microcontroller::~Microcontroller()
|
||||
{
|
||||
}
|
||||
|
||||
void Microcontroller::setIODevice(QIODevice *port)
|
||||
{
|
||||
_port = port;
|
||||
QObject::connect(_port, &QIODevice::readyRead, this, &Microcontroller::isReadyRead);
|
||||
}
|
||||
|
||||
std::shared_ptr<Item> Microcontroller::processTrainLine(const QString& buffer)
|
||||
{
|
||||
QStringList bufferList = buffer.split(' ');
|
||||
if(bufferList.size() >= 14 && buffer.startsWith("TRAIN NUMBER:"))
|
||||
{
|
||||
return std::shared_ptr<Item>(new Train(bufferList[2].toInt(), bufferList[4].toInt(), bufferList[13].toInt(nullptr, 2), bufferList[9].toInt()));
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
std::shared_ptr<Item> Microcontroller::processTurnoutLine(const QString& buffer)
|
||||
{
|
||||
QStringList bufferList = buffer.split(' ');
|
||||
if(bufferList.size() >= 11 && buffer.startsWith("TURNOUT NUMBER:"))
|
||||
{
|
||||
return std::shared_ptr<Item>(new Turnout(bufferList[2].toInt(), bufferList[4].toInt(), bufferList[6].toInt(), bufferList[11].toInt()));
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
void Microcontroller::processList(const QString& buffer)
|
||||
{
|
||||
QStringList bufferList = buffer.split(' ');
|
||||
qDebug()<<__func__<<" :"<<buffer<<" list mode: "<<listMode;
|
||||
if(bufferList.size() >= 10 && buffer.contains("NUMBER:"))
|
||||
{
|
||||
std::shared_ptr<Item> item;
|
||||
if(listMode == TRAIN_LIST)
|
||||
item = processTrainLine(buffer);
|
||||
else if(listMode == TURNOUT_LIST)
|
||||
item = processTurnoutLine(buffer);
|
||||
if(item)
|
||||
itemList.push_back(item);
|
||||
}
|
||||
else
|
||||
{
|
||||
listMode = false;
|
||||
if(!itemList.empty())
|
||||
{
|
||||
qDebug()<<"got item list " << itemList.size();
|
||||
gotItemList(itemList);
|
||||
itemList.clear();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Microcontroller::processItemState(const QString& buffer)
|
||||
{
|
||||
if(_buffer.startsWith("TRAIN NUMBER:"))
|
||||
itemChanged(static_cast<ItemData>(*processTrainLine(buffer)));
|
||||
else if(_buffer.startsWith("TURNOUT NUMBER:"))
|
||||
itemChanged(static_cast<ItemData>(*processTurnoutLine(buffer)));
|
||||
}
|
||||
|
||||
|
||||
void Microcontroller::processMicroReturn()
|
||||
{
|
||||
if(listMode)
|
||||
processList(_buffer);
|
||||
else
|
||||
{
|
||||
if(_buffer.startsWith("Trains:"))
|
||||
{
|
||||
listMode = TRAIN_LIST;
|
||||
itemList.clear();
|
||||
}
|
||||
else if(_buffer.startsWith("Turnouts:"))
|
||||
{
|
||||
listMode = TURNOUT_LIST;
|
||||
}
|
||||
else if(_buffer.startsWith("TRAIN NUMBER:") || _buffer.startsWith("TURNOUT NUMBER:"))
|
||||
{
|
||||
processItemState(_buffer);
|
||||
}
|
||||
else if(_buffer.startsWith("TrainController"))
|
||||
{
|
||||
requestState();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void Microcontroller::isReadyRead()
|
||||
{
|
||||
char charBuf;
|
||||
while(_port->getChar(&charBuf))
|
||||
{
|
||||
_buffer.push_back(charBuf);
|
||||
if( _buffer.endsWith('\n') )
|
||||
{
|
||||
_buffer.remove('\n');
|
||||
processMicroReturn();
|
||||
textRecived(_buffer);
|
||||
_buffer.clear();
|
||||
}
|
||||
}
|
||||
}
|
@ -1,83 +0,0 @@
|
||||
#ifndef MICROCONTROLLER_H
|
||||
#define MICROCONTROLLER_H
|
||||
|
||||
#include <iostream>
|
||||
|
||||
#include <QObject>
|
||||
#include <QColor>
|
||||
#include <QIODevice>
|
||||
#include <QString>
|
||||
#include <QRunnable>
|
||||
#include <QDebug>
|
||||
#include <QEventLoop>
|
||||
#include <QTimer>
|
||||
#include <QAbstractButton>
|
||||
#include <vector>
|
||||
#include <memory>
|
||||
#include <sstream>
|
||||
#include "items/item.h"
|
||||
|
||||
class Microcontroller : public QObject
|
||||
{
|
||||
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
|
||||
static constexpr char AMP_RELAY = 0;
|
||||
static constexpr char SENSOR_TEMPERATURE = 1;
|
||||
static constexpr char SENSOR_DOOR = 0 ;
|
||||
|
||||
private:
|
||||
|
||||
static constexpr int TRAIN_LIST = 1;
|
||||
static constexpr int TURNOUT_LIST = 2;
|
||||
|
||||
int listMode = 0;
|
||||
|
||||
//uint8_t _auxState = 0;
|
||||
|
||||
QIODevice* _port = nullptr;
|
||||
|
||||
std::vector< std::shared_ptr<Item> > itemList;
|
||||
|
||||
QScopedPointer<QEventLoop> loop;
|
||||
QString _buffer;
|
||||
|
||||
void processMicroReturn();
|
||||
void processList(const QString& buffer);
|
||||
void processItemState(const QString& buffer);
|
||||
std::shared_ptr<Item> processTrainLine(const QString& buffer);
|
||||
std::shared_ptr<Item> processTurnoutLine(const QString& buffer);
|
||||
|
||||
void write(char *buffer, const size_t length);
|
||||
void write(const QByteArray& buffer);
|
||||
|
||||
public:
|
||||
Microcontroller(QIODevice* port);
|
||||
Microcontroller();
|
||||
~Microcontroller();
|
||||
bool connected();
|
||||
void setIODevice(QIODevice* port);
|
||||
|
||||
public slots:
|
||||
void requestState();
|
||||
|
||||
void trainSetSpeed(uint8_t id, int8_t speed);
|
||||
void trainReverse(uint8_t id);
|
||||
void trainSetFunction(uint8_t id, uint8_t function, bool on);
|
||||
void tunoutSetDirection(uint8_t id, bool direction);
|
||||
void estop();
|
||||
void setPower(bool on);
|
||||
|
||||
private slots:
|
||||
void isReadyRead();
|
||||
|
||||
signals:
|
||||
void textRecived(const QString string);
|
||||
void itemChanged(ItemData relay);
|
||||
void auxStateChanged(int value);
|
||||
void gotItemList(std::vector< std::shared_ptr<Item> >&);
|
||||
};
|
||||
|
||||
#endif // MICROCONTROLLER_H
|
28
src/trainControllerUI/CMakeLists.txt
Normal file
28
src/trainControllerUI/CMakeLists.txt
Normal file
@ -0,0 +1,28 @@
|
||||
set(UI_SOURCES
|
||||
traincontrollerui.cpp
|
||||
mainobject.cpp
|
||||
QJoysticks.cpp
|
||||
trainjs.cpp
|
||||
ui/itemscrollbox.cpp
|
||||
ui/itemscrollbox.h
|
||||
ui/itemwidget.cpp
|
||||
ui/itemwidget.h
|
||||
ui/mainwindow.cpp
|
||||
ui/mainwindow.h
|
||||
ui/mainwindow.ui
|
||||
ui/relayscrollbox.ui
|
||||
ui/signalwidget.cpp
|
||||
ui/signalwidget.h
|
||||
ui/signalwidget.ui
|
||||
ui/trainwidget.cpp
|
||||
ui/trainwidget.h
|
||||
ui/trainwidget.ui
|
||||
jsbackend/SDL_Joysticks.cpp
|
||||
jsbackend/VirtualJoystick.cpp
|
||||
)
|
||||
|
||||
find_package(SDL2 REQUIRED)
|
||||
|
||||
add_executable(traincontrollerui ${UI_SOURCES} ${COMMON_SOURCES})
|
||||
target_link_libraries(traincontrollerui PRIVATE ${COMMON_LINK_LIBRARYS} Qt${QT_VERSION_MAJOR}::Widgets ${SDL2_LIBRARIES})
|
||||
target_include_directories(traincontrollerui PRIVATE ./ ./ui ./jsbackend ${SDL2_INCLUDE_DIRS})
|
479
src/trainControllerUI/QJoysticks.cpp
Normal file
479
src/trainControllerUI/QJoysticks.cpp
Normal file
@ -0,0 +1,479 @@
|
||||
/*
|
||||
* Copyright (c) 2015-2017 Alex Spataru <alex_spataru@outlook.com>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#include <QDebug>
|
||||
#include <QSettings>
|
||||
#include "QJoysticks.h"
|
||||
#include "jsbackend/SDL_Joysticks.h"
|
||||
#include "jsbackend/VirtualJoystick.h"
|
||||
|
||||
QJoysticks::QJoysticks()
|
||||
{
|
||||
/* Initialize input methods */
|
||||
m_sdlJoysticks = new SDL_Joysticks(this);
|
||||
m_virtualJoystick = new VirtualJoystick(this);
|
||||
|
||||
/* Configure SDL joysticks */
|
||||
connect(sdlJoysticks(), &SDL_Joysticks::POVEvent, this, &QJoysticks::POVEvent);
|
||||
connect(sdlJoysticks(), &SDL_Joysticks::axisEvent, this, &QJoysticks::axisEvent);
|
||||
connect(sdlJoysticks(), &SDL_Joysticks::buttonEvent, this, &QJoysticks::buttonEvent);
|
||||
connect(sdlJoysticks(), &SDL_Joysticks::countChanged, this, &QJoysticks::updateInterfaces);
|
||||
|
||||
/* Configure virtual joysticks */
|
||||
connect(virtualJoystick(), &VirtualJoystick::povEvent, this, &QJoysticks::POVEvent);
|
||||
connect(virtualJoystick(), &VirtualJoystick::axisEvent, this, &QJoysticks::axisEvent);
|
||||
connect(virtualJoystick(), &VirtualJoystick::buttonEvent, this, &QJoysticks::buttonEvent);
|
||||
connect(virtualJoystick(), &VirtualJoystick::enabledChanged, this, &QJoysticks::updateInterfaces);
|
||||
|
||||
/* React to own signals to create QML signals */
|
||||
connect(this, &QJoysticks::POVEvent, this, &QJoysticks::onPOVEvent);
|
||||
connect(this, &QJoysticks::axisEvent, this, &QJoysticks::onAxisEvent);
|
||||
connect(this, &QJoysticks::buttonEvent, this, &QJoysticks::onButtonEvent);
|
||||
|
||||
/* Configure the settings */
|
||||
m_sortJoyticks = 0;
|
||||
m_settings = new QSettings(qApp->organizationName(), qApp->applicationName());
|
||||
m_settings->beginGroup("Blacklisted Joysticks");
|
||||
}
|
||||
|
||||
QJoysticks::~QJoysticks()
|
||||
{
|
||||
delete m_settings;
|
||||
delete m_sdlJoysticks;
|
||||
delete m_virtualJoystick;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the one and only instance of this class
|
||||
*/
|
||||
QJoysticks *QJoysticks::getInstance()
|
||||
{
|
||||
static QJoysticks joysticks;
|
||||
return &joysticks;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the number of joysticks that are attached to the computer and/or
|
||||
* registered with the \c QJoysticks system.
|
||||
*
|
||||
* \note This count also includes the virtual joystick (if its enabled)
|
||||
*/
|
||||
int QJoysticks::count() const
|
||||
{
|
||||
return inputDevices().count();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the number of joysticks that are not blacklisted.
|
||||
* This can be considered the "effective" number of joysticks.
|
||||
*/
|
||||
int QJoysticks::nonBlacklistedCount()
|
||||
{
|
||||
int cnt = count();
|
||||
|
||||
for (int i = 0; i < count(); ++i)
|
||||
if (isBlacklisted(i))
|
||||
--cnt;
|
||||
|
||||
return cnt;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a list with the names of all registered joystick.
|
||||
*
|
||||
* \note This list also includes the blacklisted joysticks
|
||||
* \note This list also includes the virtual joystick (if its enabled)
|
||||
*/
|
||||
QStringList QJoysticks::deviceNames() const
|
||||
{
|
||||
QStringList names;
|
||||
|
||||
foreach (QJoystickDevice *joystick, inputDevices())
|
||||
names.append(joystick->name);
|
||||
|
||||
return names;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the POV value for the given joystick \a index and \a pov ID
|
||||
*/
|
||||
int QJoysticks::getPOV(const int index, const int pov)
|
||||
{
|
||||
if (joystickExists(index))
|
||||
return getInputDevice(index)->povs.at(pov);
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the axis value for the given joystick \a index and \a axis ID
|
||||
*/
|
||||
double QJoysticks::getAxis(const int index, const int axis)
|
||||
{
|
||||
if (joystickExists(index))
|
||||
return getInputDevice(index)->axes.at(axis);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the button value for the given joystick \a index and \a button ID
|
||||
*/
|
||||
bool QJoysticks::getButton(const int index, const int button)
|
||||
{
|
||||
if (joystickExists(index))
|
||||
return getInputDevice(index)->buttons.at(button);
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the number of axes that the joystick at the given \a index has.
|
||||
*/
|
||||
int QJoysticks::getNumAxes(const int index)
|
||||
{
|
||||
if (joystickExists(index))
|
||||
return getInputDevice(index)->axes.count();
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the number of POVs that the joystick at the given \a index has.
|
||||
*/
|
||||
int QJoysticks::getNumPOVs(const int index)
|
||||
{
|
||||
if (joystickExists(index))
|
||||
return getInputDevice(index)->povs.count();
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the number of buttons that the joystick at the given \a index has.
|
||||
*/
|
||||
int QJoysticks::getNumButtons(const int index)
|
||||
{
|
||||
if (joystickExists(index))
|
||||
return getInputDevice(index)->buttons.count();
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns \c true if the joystick at the given \a index is blacklisted.
|
||||
*/
|
||||
bool QJoysticks::isBlacklisted(const int index)
|
||||
{
|
||||
if (joystickExists(index))
|
||||
return inputDevices().at(index)->blacklisted;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns \c true if the joystick at the given \a index is valid, otherwise,
|
||||
* the function returns \c false and warns the user through the console.
|
||||
*/
|
||||
bool QJoysticks::joystickExists(const int index)
|
||||
{
|
||||
return (index >= 0) && (count() > index);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the name of the given joystick
|
||||
*/
|
||||
QString QJoysticks::getName(const int index)
|
||||
{
|
||||
if (joystickExists(index))
|
||||
return m_devices.at(index)->name;
|
||||
|
||||
return "Invalid Joystick";
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a pointer to the SDL joysticks system.
|
||||
* This can be used if you need to get more information regarding the joysticks
|
||||
* registered and managed with SDL.
|
||||
*/
|
||||
SDL_Joysticks *QJoysticks::sdlJoysticks() const
|
||||
{
|
||||
return m_sdlJoysticks;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a pointer to the virtual joystick system.
|
||||
* This can be used if you need to get more information regarding the virtual
|
||||
* joystick or want to change its properties directly.
|
||||
*
|
||||
* \note You can also change the properties of the virtual joysticks using the
|
||||
* functions of the \c QJoysticks system class
|
||||
*/
|
||||
VirtualJoystick *QJoysticks::virtualJoystick() const
|
||||
{
|
||||
return m_virtualJoystick;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a pointer to the device at the given \a index.
|
||||
*/
|
||||
QJoystickDevice *QJoysticks::getInputDevice(const int index)
|
||||
{
|
||||
if (joystickExists(index))
|
||||
return inputDevices().at(index);
|
||||
|
||||
return Q_NULLPTR;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a pointer to a list containing all registered joysticks.
|
||||
* This can be used for advanced hacks or just to get all properties of each
|
||||
* joystick.
|
||||
*/
|
||||
QList<QJoystickDevice *> QJoysticks::inputDevices() const
|
||||
{
|
||||
return m_devices;
|
||||
}
|
||||
|
||||
/**
|
||||
* If \a sort is set to true, then the device list will put all blacklisted
|
||||
* joysticks at the end of the list
|
||||
*/
|
||||
void QJoysticks::setSortJoysticksByBlacklistState(bool sort)
|
||||
{
|
||||
if (m_sortJoyticks != sort)
|
||||
{
|
||||
m_sortJoyticks = sort;
|
||||
updateInterfaces();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Blacklists or whitelists the joystick at the given \a index.
|
||||
*
|
||||
* \note This function does not have effect if the given joystick does not exist
|
||||
* \note Once the joystick is blacklisted, the joystick list will be updated
|
||||
*/
|
||||
void QJoysticks::setBlacklisted(const int index, bool blacklisted)
|
||||
{
|
||||
Q_ASSERT(joystickExists(index));
|
||||
|
||||
/* Netrualize the joystick */
|
||||
if (blacklisted)
|
||||
{
|
||||
for (int i = 0; i < getNumAxes(index); ++i)
|
||||
emit axisChanged(index, i, 0);
|
||||
|
||||
for (int i = 0; i < getNumButtons(index); ++i)
|
||||
emit buttonChanged(index, i, false);
|
||||
|
||||
for (int i = 0; i < getNumPOVs(index); ++i)
|
||||
emit povChanged(index, i, 0);
|
||||
}
|
||||
|
||||
/* See if blacklist value was actually changed */
|
||||
bool changed = m_devices.at(index)->blacklisted != blacklisted;
|
||||
|
||||
/* Save settings */
|
||||
m_devices.at(index)->blacklisted = blacklisted;
|
||||
m_settings->setValue(getName(index), blacklisted);
|
||||
|
||||
/* Re-scan joysticks if blacklist value has changed */
|
||||
if (changed)
|
||||
updateInterfaces();
|
||||
}
|
||||
|
||||
/**
|
||||
* 'Rescans' for new/removed joysticks and registers them again.
|
||||
*/
|
||||
void QJoysticks::updateInterfaces()
|
||||
{
|
||||
m_devices.clear();
|
||||
|
||||
/* Put blacklisted joysticks at the bottom of the list */
|
||||
if (m_sortJoyticks)
|
||||
{
|
||||
/* Register non-blacklisted SDL joysticks */
|
||||
foreach (QJoystickDevice *joystick, sdlJoysticks()->joysticks())
|
||||
{
|
||||
joystick->blacklisted = m_settings->value(joystick->name, false).toBool();
|
||||
if (!joystick->blacklisted)
|
||||
addInputDevice(joystick);
|
||||
}
|
||||
|
||||
/* Register the virtual joystick (if its not blacklisted) */
|
||||
if (virtualJoystick()->joystickEnabled())
|
||||
{
|
||||
QJoystickDevice *joystick = virtualJoystick()->joystick();
|
||||
joystick->blacklisted = m_settings->value(joystick->name, false).toBool();
|
||||
|
||||
if (!joystick->blacklisted)
|
||||
{
|
||||
addInputDevice(joystick);
|
||||
virtualJoystick()->setJoystickID(inputDevices().count() - 1);
|
||||
}
|
||||
}
|
||||
|
||||
/* Register blacklisted SDL joysticks */
|
||||
foreach (QJoystickDevice *joystick, sdlJoysticks()->joysticks())
|
||||
{
|
||||
joystick->blacklisted = m_settings->value(joystick->name, false).toBool();
|
||||
if (joystick->blacklisted)
|
||||
addInputDevice(joystick);
|
||||
}
|
||||
|
||||
/* Register the virtual joystick (if its blacklisted) */
|
||||
if (virtualJoystick()->joystickEnabled())
|
||||
{
|
||||
QJoystickDevice *joystick = virtualJoystick()->joystick();
|
||||
joystick->blacklisted = m_settings->value(joystick->name, false).toBool();
|
||||
|
||||
if (joystick->blacklisted)
|
||||
{
|
||||
addInputDevice(joystick);
|
||||
virtualJoystick()->setJoystickID(inputDevices().count() - 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Sort normally */
|
||||
else
|
||||
{
|
||||
/* Register SDL joysticks */
|
||||
foreach (QJoystickDevice *joystick, sdlJoysticks()->joysticks())
|
||||
{
|
||||
addInputDevice(joystick);
|
||||
joystick->blacklisted = m_settings->value(joystick->name, false).toBool();
|
||||
}
|
||||
|
||||
/* Register virtual joystick */
|
||||
if (virtualJoystick()->joystickEnabled())
|
||||
{
|
||||
QJoystickDevice *joystick = virtualJoystick()->joystick();
|
||||
joystick->blacklisted = m_settings->value(joystick->name, false).toBool();
|
||||
|
||||
addInputDevice(joystick);
|
||||
virtualJoystick()->setJoystickID(inputDevices().count() - 1);
|
||||
}
|
||||
}
|
||||
|
||||
emit countChanged();
|
||||
}
|
||||
|
||||
/**
|
||||
* Changes the axis value range of the virtual joystick.
|
||||
*
|
||||
* Take into account that maximum axis values supported by the \c QJoysticks
|
||||
* system is from \c -1 to \c 1.
|
||||
*/
|
||||
void QJoysticks::setVirtualJoystickRange(qreal range)
|
||||
{
|
||||
virtualJoystick()->setAxisRange(range);
|
||||
}
|
||||
|
||||
/**
|
||||
* Enables or disables the virtual joystick
|
||||
*/
|
||||
void QJoysticks::setVirtualJoystickEnabled(bool enabled)
|
||||
{
|
||||
virtualJoystick()->setJoystickEnabled(enabled);
|
||||
}
|
||||
|
||||
void QJoysticks::setVirtualJoystickAxisSensibility(qreal sensibility)
|
||||
{
|
||||
virtualJoystick()->setAxisSensibility(sensibility);
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes all the registered joysticks and emits appropriate signals.
|
||||
*/
|
||||
void QJoysticks::resetJoysticks()
|
||||
{
|
||||
m_devices.clear();
|
||||
emit countChanged();
|
||||
}
|
||||
|
||||
/**
|
||||
* Registers the given \a device to the \c QJoysticks system
|
||||
*/
|
||||
void QJoysticks::addInputDevice(QJoystickDevice *device)
|
||||
{
|
||||
Q_ASSERT(device);
|
||||
m_devices.append(device);
|
||||
}
|
||||
|
||||
/**
|
||||
* Configures the QML-friendly signal based on the information given by the
|
||||
* \a event data and updates the joystick values
|
||||
*/
|
||||
void QJoysticks::onPOVEvent(const QJoystickPOVEvent &e)
|
||||
{
|
||||
if (e.joystick == nullptr)
|
||||
return;
|
||||
|
||||
if (!isBlacklisted(e.joystick->id))
|
||||
{
|
||||
if (e.pov < getInputDevice(e.joystick->id)->povs.count())
|
||||
{
|
||||
getInputDevice(e.joystick->id)->povs[e.pov] = e.angle;
|
||||
emit povChanged(e.joystick->id, e.pov, e.angle);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Configures the QML-friendly signal based on the information given by the
|
||||
* \a event data and updates the joystick values
|
||||
*/
|
||||
void QJoysticks::onAxisEvent(const QJoystickAxisEvent &e)
|
||||
{
|
||||
if (e.joystick == nullptr)
|
||||
return;
|
||||
|
||||
if (!isBlacklisted(e.joystick->id))
|
||||
{
|
||||
if (e.axis < getInputDevice(e.joystick->id)->axes.count())
|
||||
{
|
||||
getInputDevice(e.joystick->id)->axes[e.axis] = e.value;
|
||||
emit axisChanged(e.joystick->id, e.axis, e.value);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Configures the QML-friendly signal based on the information given by the
|
||||
* \a event data and updates the joystick values
|
||||
*/
|
||||
void QJoysticks::onButtonEvent(const QJoystickButtonEvent &e)
|
||||
{
|
||||
if (e.joystick == nullptr)
|
||||
return;
|
||||
|
||||
if (!isBlacklisted(e.joystick->id))
|
||||
{
|
||||
if (e.button < getInputDevice(e.joystick->id)->buttons.count())
|
||||
{
|
||||
getInputDevice(e.joystick->id)->buttons[e.button] = e.pressed;
|
||||
emit buttonChanged(e.joystick->id, e.button, e.pressed);
|
||||
}
|
||||
}
|
||||
}
|
@ -50,73 +50,73 @@ class VirtualJoystick;
|
||||
*/
|
||||
class QJoysticks : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
Q_PROPERTY(int count READ count NOTIFY countChanged)
|
||||
Q_PROPERTY(int nonBlacklistedCount READ nonBlacklistedCount NOTIFY countChanged)
|
||||
Q_PROPERTY(QStringList deviceNames READ deviceNames NOTIFY countChanged)
|
||||
Q_OBJECT
|
||||
Q_PROPERTY(int count READ count NOTIFY countChanged)
|
||||
Q_PROPERTY(int nonBlacklistedCount READ nonBlacklistedCount NOTIFY countChanged)
|
||||
Q_PROPERTY(QStringList deviceNames READ deviceNames NOTIFY countChanged)
|
||||
|
||||
friend class Test_QJoysticks;
|
||||
friend class Test_QJoysticks;
|
||||
|
||||
signals:
|
||||
void countChanged();
|
||||
void enabledChanged(const bool enabled);
|
||||
void POVEvent(const QJoystickPOVEvent &event);
|
||||
void axisEvent(const QJoystickAxisEvent &event);
|
||||
void buttonEvent(const QJoystickButtonEvent &event);
|
||||
void povChanged(const int js, const int pov, const int angle);
|
||||
void axisChanged(const int js, const int axis, const qreal value);
|
||||
void buttonChanged(const int js, const int button, const bool pressed);
|
||||
void countChanged();
|
||||
void enabledChanged(const bool enabled);
|
||||
void POVEvent(const QJoystickPOVEvent &event);
|
||||
void axisEvent(const QJoystickAxisEvent &event);
|
||||
void buttonEvent(const QJoystickButtonEvent &event);
|
||||
void povChanged(const int js, const int pov, const int angle);
|
||||
void axisChanged(const int js, const int axis, const qreal value);
|
||||
void buttonChanged(const int js, const int button, const bool pressed);
|
||||
|
||||
public:
|
||||
static QJoysticks *getInstance();
|
||||
static QJoysticks *getInstance();
|
||||
|
||||
int count() const;
|
||||
int nonBlacklistedCount();
|
||||
QStringList deviceNames() const;
|
||||
int count() const;
|
||||
int nonBlacklistedCount();
|
||||
QStringList deviceNames() const;
|
||||
|
||||
Q_INVOKABLE int getPOV(const int index, const int pov);
|
||||
Q_INVOKABLE double getAxis(const int index, const int axis);
|
||||
Q_INVOKABLE bool getButton(const int index, const int button);
|
||||
Q_INVOKABLE int getPOV(const int index, const int pov);
|
||||
Q_INVOKABLE double getAxis(const int index, const int axis);
|
||||
Q_INVOKABLE bool getButton(const int index, const int button);
|
||||
|
||||
Q_INVOKABLE int getNumAxes(const int index);
|
||||
Q_INVOKABLE int getNumPOVs(const int index);
|
||||
Q_INVOKABLE int getNumButtons(const int index);
|
||||
Q_INVOKABLE bool isBlacklisted(const int index);
|
||||
Q_INVOKABLE bool joystickExists(const int index);
|
||||
Q_INVOKABLE QString getName(const int index);
|
||||
Q_INVOKABLE int getNumAxes(const int index);
|
||||
Q_INVOKABLE int getNumPOVs(const int index);
|
||||
Q_INVOKABLE int getNumButtons(const int index);
|
||||
Q_INVOKABLE bool isBlacklisted(const int index);
|
||||
Q_INVOKABLE bool joystickExists(const int index);
|
||||
Q_INVOKABLE QString getName(const int index);
|
||||
|
||||
SDL_Joysticks *sdlJoysticks() const;
|
||||
VirtualJoystick *virtualJoystick() const;
|
||||
QJoystickDevice *getInputDevice(const int index);
|
||||
QList<QJoystickDevice *> inputDevices() const;
|
||||
SDL_Joysticks *sdlJoysticks() const;
|
||||
VirtualJoystick *virtualJoystick() const;
|
||||
QJoystickDevice *getInputDevice(const int index);
|
||||
QList<QJoystickDevice *> inputDevices() const;
|
||||
|
||||
public slots:
|
||||
void updateInterfaces();
|
||||
void setVirtualJoystickRange(qreal range);
|
||||
void setVirtualJoystickEnabled(bool enabled);
|
||||
void setVirtualJoystickAxisSensibility(qreal sensibility);
|
||||
void setSortJoysticksByBlacklistState(bool sort);
|
||||
void setBlacklisted(int index, bool blacklisted);
|
||||
void updateInterfaces();
|
||||
void setVirtualJoystickRange(qreal range);
|
||||
void setVirtualJoystickEnabled(bool enabled);
|
||||
void setVirtualJoystickAxisSensibility(qreal sensibility);
|
||||
void setSortJoysticksByBlacklistState(bool sort);
|
||||
void setBlacklisted(int index, bool blacklisted);
|
||||
|
||||
protected:
|
||||
explicit QJoysticks();
|
||||
~QJoysticks();
|
||||
explicit QJoysticks();
|
||||
~QJoysticks();
|
||||
|
||||
private slots:
|
||||
void resetJoysticks();
|
||||
void addInputDevice(QJoystickDevice *device);
|
||||
void onPOVEvent(const QJoystickPOVEvent &e);
|
||||
void onAxisEvent(const QJoystickAxisEvent &e);
|
||||
void onButtonEvent(const QJoystickButtonEvent &e);
|
||||
void resetJoysticks();
|
||||
void addInputDevice(QJoystickDevice *device);
|
||||
void onPOVEvent(const QJoystickPOVEvent &e);
|
||||
void onAxisEvent(const QJoystickAxisEvent &e);
|
||||
void onButtonEvent(const QJoystickButtonEvent &e);
|
||||
|
||||
private:
|
||||
bool m_sortJoyticks;
|
||||
bool m_sortJoyticks;
|
||||
|
||||
QSettings *m_settings;
|
||||
SDL_Joysticks *m_sdlJoysticks;
|
||||
VirtualJoystick *m_virtualJoystick;
|
||||
QSettings *m_settings;
|
||||
SDL_Joysticks *m_sdlJoysticks;
|
||||
VirtualJoystick *m_virtualJoystick;
|
||||
|
||||
QList<QJoystickDevice *> m_devices;
|
||||
QList<QJoystickDevice *> m_devices;
|
||||
};
|
||||
|
||||
#endif
|
@ -44,7 +44,7 @@ SDL_Joysticks::SDL_Joysticks(QObject *parent)
|
||||
for (int i = 0; i < count; ++i)
|
||||
configureJoystick(i);
|
||||
|
||||
QTimer::singleShot(100, Qt::PreciseTimer, this, SLOT(update()));
|
||||
QTimer::singleShot(10, Qt::PreciseTimer, this, SLOT(update()));
|
||||
}
|
||||
|
||||
SDL_Joysticks::~SDL_Joysticks()
|
14
src/trainControllerUI/mainobject.cpp
Normal file
14
src/trainControllerUI/mainobject.cpp
Normal file
@ -0,0 +1,14 @@
|
||||
#include "mainobject.h"
|
||||
|
||||
MainObject::MainObject(QIODevice* ioDevice) :
|
||||
masterIODevice(ioDevice),
|
||||
micro(masterIODevice)
|
||||
{
|
||||
//connect item store
|
||||
QObject::connect(µ, &Microcontroller::gotItemList, &items, &ItemStore::addItems);
|
||||
}
|
||||
|
||||
MainObject::~MainObject()
|
||||
{
|
||||
}
|
||||
|
@ -7,9 +7,6 @@
|
||||
#include <QDebug>
|
||||
#include <QString>
|
||||
#include <QTcpSocket>
|
||||
#include <QFileInfo>
|
||||
#include <QJsonDocument>
|
||||
#include <QStandardPaths>
|
||||
#include <memory>
|
||||
|
||||
|
||||
@ -22,26 +19,25 @@
|
||||
#include "microcontroller.h"
|
||||
#include "ui/mainwindow.h"
|
||||
#include "items/itemstore.h"
|
||||
#include "items/auxitem.h"
|
||||
|
||||
class MainObject : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
Q_OBJECT
|
||||
public:
|
||||
|
||||
//io
|
||||
QIODevice * const masterIODevice = nullptr;
|
||||
//io
|
||||
QIODevice * const masterIODevice = nullptr;
|
||||
|
||||
Microcontroller micro;
|
||||
Microcontroller micro;
|
||||
|
||||
const QString settingsPath;
|
||||
const QString settingsPath;
|
||||
|
||||
//items
|
||||
ItemStore items;
|
||||
//items
|
||||
ItemStore items;
|
||||
|
||||
public:
|
||||
explicit MainObject(QIODevice* ioDevice);
|
||||
~MainObject();
|
||||
explicit MainObject(QIODevice* ioDevice);
|
||||
~MainObject();
|
||||
};
|
||||
|
||||
#endif // MAINOBJECT_H
|
116
src/trainControllerUI/traincontrollerui.cpp
Normal file
116
src/trainControllerUI/traincontrollerui.cpp
Normal file
@ -0,0 +1,116 @@
|
||||
#include <QtWidgets/QApplication>
|
||||
#include <stdio.h>
|
||||
#include <QDebug>
|
||||
#include <QTcpSocket>
|
||||
#include <QMessageBox>
|
||||
#include <QtSerialPort/QtSerialPort>
|
||||
#include <QtSerialPort/QSerialPortInfo>
|
||||
#include <QCommandLineParser>
|
||||
|
||||
#include "microcontroller.h"
|
||||
#include "trainjs.h"
|
||||
#include "ui/mainwindow.h"
|
||||
#include "itemstore.h"
|
||||
#include "train.h"
|
||||
#include "turnout.h"
|
||||
#include "trainsignal.h"
|
||||
|
||||
#define BAUD QSerialPort::Baud38400
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
QApplication a(argc, argv);
|
||||
|
||||
//set info
|
||||
QCoreApplication::setOrganizationName("UVOS");
|
||||
QCoreApplication::setOrganizationDomain("uvos.xyz");
|
||||
QCoreApplication::setApplicationName("traincontrollerui");
|
||||
QCoreApplication::setApplicationVersion("0.1");
|
||||
|
||||
QDir::setCurrent(a.applicationDirPath());
|
||||
|
||||
//parse comand line
|
||||
QCommandLineParser parser;
|
||||
parser.setApplicationDescription("Train control gui");
|
||||
parser.addHelpOption();
|
||||
parser.addVersionOption();
|
||||
QCommandLineOption tcpOption(QStringList() << "t" << "tcp", QCoreApplication::translate("main", "Use Tcp connection"));
|
||||
parser.addOption(tcpOption);
|
||||
QCommandLineOption hostOption(QStringList() << "H" << "host", QCoreApplication::translate("main",
|
||||
"Set server host ip addres"), "adress");
|
||||
parser.addOption(hostOption);
|
||||
QCommandLineOption portOption(QStringList() << "p" << "port", QCoreApplication::translate("main",
|
||||
"Set server Port in TCP mode or Serial port in serial mode"), "port");
|
||||
parser.addOption(portOption);
|
||||
QCommandLineOption serialOption(QStringList() << "s" << "serial", QCoreApplication::translate("main",
|
||||
"Use serial connection"));
|
||||
parser.addOption(serialOption);
|
||||
QCommandLineOption baudOption(QStringList() << "b" << "baud", QCoreApplication::translate("main", "Set Baud Rate"));
|
||||
parser.addOption(baudOption);
|
||||
parser.process(a);
|
||||
|
||||
QIODevice* masterIODevice = nullptr;
|
||||
|
||||
if(parser.isSet(tcpOption))
|
||||
{
|
||||
QTcpSocket* microSocket = new QTcpSocket;
|
||||
|
||||
int port = 6856;
|
||||
if(parser.isSet(portOption)) port = parser.value(portOption).toInt();
|
||||
|
||||
QString host("127.0.0.1");
|
||||
if(parser.isSet(hostOption)) host = parser.value(hostOption);
|
||||
std::cout<<"connecting to "<<host.toStdString()<<':'<<port<<'\n';
|
||||
microSocket->connectToHost(host, port, QIODevice::ReadWrite);
|
||||
if(!microSocket->waitForConnected(3000))
|
||||
{
|
||||
std::cout<<"Can not connect to to Server.\n";
|
||||
QMessageBox::critical(nullptr, "Error", "Can not connect to to Server");
|
||||
return 1;
|
||||
}
|
||||
masterIODevice = microSocket;
|
||||
}
|
||||
else
|
||||
{
|
||||
QSerialPort* microPort = new QSerialPort;
|
||||
if(parser.isSet(portOption)) microPort->setPortName(parser.value(portOption));
|
||||
else microPort->setPortName("ttyUSB0");
|
||||
|
||||
if(parser.isSet(portOption)) microPort->setBaudRate(parser.value(baudOption).toInt());
|
||||
else microPort->setBaudRate(BAUD);
|
||||
|
||||
if(!microPort->open(QIODevice::ReadWrite))
|
||||
{
|
||||
QMessageBox::critical(nullptr, "Error", QString("Can not open serial port ")+microPort->portName());
|
||||
std::cout<<"Can not open serial port "<<microPort->portName().toStdString()<<". Continueing in demo mode"<<'\n';
|
||||
return 1;
|
||||
}
|
||||
masterIODevice = microPort;
|
||||
}
|
||||
|
||||
Microcontroller micro(masterIODevice);
|
||||
micro.setPower(true);
|
||||
|
||||
TrainJs::init();
|
||||
|
||||
Train::micro = µ
|
||||
Turnout::micro = µ
|
||||
Signal::micro = µ
|
||||
ItemStore items;
|
||||
|
||||
QObject::connect(µ, &Microcontroller::gotItemList, &items, &ItemStore::addItems);
|
||||
QObject::connect(µ, &Microcontroller::itemChanged, &items, &ItemStore::itemStateChanged);
|
||||
|
||||
//mainwindow
|
||||
MainWindow w(µ, &items);
|
||||
|
||||
w.show();
|
||||
|
||||
int retVal = a.exec();
|
||||
micro.setPower(false);
|
||||
|
||||
if(masterIODevice)
|
||||
delete masterIODevice;
|
||||
return retVal;
|
||||
}
|
||||
|
@ -41,7 +41,10 @@ public:
|
||||
std::weak_ptr<Item> getItem();
|
||||
void setItem(std::weak_ptr<Item>);
|
||||
bool itemIsSet();
|
||||
bool getWantsNewItem() {return wantsNewItem;}
|
||||
bool getWantsNewItem()
|
||||
{
|
||||
return wantsNewItem;
|
||||
}
|
||||
};
|
||||
|
||||
#endif // TRAINJS_H
|
140
src/trainControllerUI/ui/itemscrollbox.cpp
Normal file
140
src/trainControllerUI/ui/itemscrollbox.cpp
Normal file
@ -0,0 +1,140 @@
|
||||
#include "itemscrollbox.h"
|
||||
#include "ui_relayscrollbox.h"
|
||||
#include "ui_relayscrollbox.h"
|
||||
#include "train.h"
|
||||
#include "turnout.h"
|
||||
#include "trainsignal.h"
|
||||
#include "trainjs.h"
|
||||
#include "trainwidget.h"
|
||||
#include "signalwidget.h"
|
||||
|
||||
ItemScrollBox::ItemScrollBox(QWidget *parent) :
|
||||
QWidget(parent),
|
||||
ui(new Ui::RelayScrollBox)
|
||||
{
|
||||
ui->setupUi(this);
|
||||
QScroller::grabGesture(ui->scrollArea, QScroller::TouchGesture);
|
||||
QScroller::grabGesture(ui->scrollArea, QScroller::LeftMouseButtonGesture);
|
||||
}
|
||||
|
||||
ItemScrollBox::~ItemScrollBox()
|
||||
{
|
||||
delete ui;
|
||||
}
|
||||
|
||||
void ItemScrollBox::addItem(std::weak_ptr<Item> item)
|
||||
{
|
||||
if(auto workItem = item.lock())
|
||||
{
|
||||
Train* train = dynamic_cast<Train*>(workItem.get());
|
||||
Turnout* turnout = dynamic_cast<Turnout*>(workItem.get());
|
||||
Signal* signal = dynamic_cast<Signal*>(workItem.get());
|
||||
if(train)
|
||||
{
|
||||
TrainWidget *widget = new TrainWidget(item, this);
|
||||
widgets_.push_back(widget);
|
||||
if(train->getTrainId() == 0)
|
||||
widget->setShortcuts(QKeySequence(Qt::Key_Q), QKeySequence(Qt::Key_A), QKeySequence(Qt::Key_Z));
|
||||
else if(train->getTrainId() == 1)
|
||||
widget->setShortcuts(QKeySequence(Qt::Key_W), QKeySequence(Qt::Key_S), QKeySequence(Qt::Key_X));
|
||||
else if(train->getTrainId() == 2)
|
||||
widget->setShortcuts(QKeySequence(Qt::Key_E), QKeySequence(Qt::Key_D), QKeySequence(Qt::Key_C));
|
||||
else if(train->getTrainId() == 3)
|
||||
widget->setShortcuts(QKeySequence(Qt::Key_R), QKeySequence(Qt::Key_F), QKeySequence(Qt::Key_V));
|
||||
else if(train->getTrainId() == 4)
|
||||
widget->setShortcuts(QKeySequence(Qt::Key_T), QKeySequence(Qt::Key_G), QKeySequence(Qt::Key_B));
|
||||
|
||||
std::vector<std::shared_ptr<TrainJs>> joysticks = TrainJs::getJsDevices();
|
||||
for(auto joystick: joysticks)
|
||||
{
|
||||
if(!joystick->itemIsSet())
|
||||
{
|
||||
joystick->setItem(item);
|
||||
connect(joystick.get(), &TrainJs::reqNewItem, this, &ItemScrollBox::jsReqNewItem);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
else if(turnout)
|
||||
{
|
||||
TrainWidget *widget = new TrainWidget(item, this);
|
||||
widgets_.push_back(widget);
|
||||
if(turnout->getTurnoutId() == 0)
|
||||
widget->setShortcuts(QKeySequence(), QKeySequence(), QKeySequence(Qt::Key_1));
|
||||
else if(turnout->getTurnoutId() == 1)
|
||||
widget->setShortcuts(QKeySequence(), QKeySequence(), QKeySequence(Qt::Key_2));
|
||||
else if(turnout->getTurnoutId() == 2)
|
||||
widget->setShortcuts(QKeySequence(), QKeySequence(), QKeySequence(Qt::Key_3));
|
||||
else if(turnout->getTurnoutId() == 3)
|
||||
widget->setShortcuts(QKeySequence(), QKeySequence(), QKeySequence(Qt::Key_4));
|
||||
else if(turnout->getTurnoutId() == 4)
|
||||
widget->setShortcuts(QKeySequence(), QKeySequence(), QKeySequence(Qt::Key_5));
|
||||
else if(turnout->getTurnoutId() == 5)
|
||||
widget->setShortcuts(QKeySequence(), QKeySequence(), QKeySequence(Qt::Key_6));
|
||||
else if(turnout->getTurnoutId() == 6)
|
||||
widget->setShortcuts(QKeySequence(), QKeySequence(), QKeySequence(Qt::Key_7));
|
||||
else if(turnout->getTurnoutId() == 7)
|
||||
widget->setShortcuts(QKeySequence(), QKeySequence(), QKeySequence(Qt::Key_8));
|
||||
else if(turnout->getTurnoutId() == 8)
|
||||
widget->setShortcuts(QKeySequence(), QKeySequence(), QKeySequence(Qt::Key_9));
|
||||
else if(turnout->getTurnoutId() == 9)
|
||||
widget->setShortcuts(QKeySequence(), QKeySequence(), QKeySequence(Qt::Key_0));
|
||||
}
|
||||
else if(signal)
|
||||
{
|
||||
SignalWidget *widget = new SignalWidget(item, this);
|
||||
widgets_.push_back(widget);
|
||||
}
|
||||
ui->relayWidgetVbox->addWidget(widgets_.back());
|
||||
connect(widgets_.back(), &ItemWidget::deleteRequest, this, &ItemScrollBox::deleteRequest);
|
||||
connect(widgets_.back(), &ItemWidget::deleteRequest, this, &ItemScrollBox::removeItem);
|
||||
}
|
||||
}
|
||||
|
||||
void ItemScrollBox::jsReqNewItem()
|
||||
{
|
||||
if(widgets_.empty())
|
||||
return;
|
||||
|
||||
std::vector<std::shared_ptr<TrainJs>> joysticks = TrainJs::getJsDevices();
|
||||
for(auto joystick: joysticks)
|
||||
{
|
||||
if(joystick->getWantsNewItem())
|
||||
{
|
||||
std::shared_ptr<Item> oldItem = joystick->getItem().lock();
|
||||
for(size_t i = 0; i < widgets_.size(); ++i)
|
||||
{
|
||||
std::shared_ptr<Item> item = widgets_[i]->getItem().lock();
|
||||
if(item && (!oldItem || *item == *oldItem))
|
||||
{
|
||||
for(size_t j = 1; j < widgets_.size(); ++j)
|
||||
{
|
||||
ItemWidget* widget = widgets_[(i+j) % widgets_.size()];
|
||||
std::shared_ptr<Item> item = widgets_[i]->getItem().lock();
|
||||
if(item && dynamic_cast<Train*>(item.get()))
|
||||
{
|
||||
joystick->setItem(item);
|
||||
break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void ItemScrollBox::removeItem(const ItemData& item)
|
||||
{
|
||||
for(unsigned i = 0; i < widgets_.size(); i++)
|
||||
{
|
||||
if(widgets_[i]->controles(item))
|
||||
{
|
||||
ui->relayWidgetVbox->removeWidget(widgets_[i]);
|
||||
delete widgets_[i];
|
||||
widgets_.erase(widgets_.begin()+i);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -10,32 +10,32 @@
|
||||
#include "../items/itemstore.h"
|
||||
|
||||
|
||||
namespace Ui {
|
||||
namespace Ui
|
||||
{
|
||||
class RelayScrollBox;
|
||||
}
|
||||
|
||||
class ItemScrollBox : public QWidget
|
||||
{
|
||||
Q_OBJECT
|
||||
Q_OBJECT
|
||||
private:
|
||||
std::vector< ItemWidget* > widgets_;
|
||||
std::vector< ItemWidget* > widgets_;
|
||||
|
||||
signals:
|
||||
void deleteRequest(const ItemData& item);
|
||||
void deleteRequest(const ItemData& item);
|
||||
|
||||
public:
|
||||
explicit ItemScrollBox(QWidget *parent = nullptr);
|
||||
~ItemScrollBox();
|
||||
|
||||
void setItemStore(ItemStore* itemStore);
|
||||
explicit ItemScrollBox(QWidget *parent = nullptr);
|
||||
~ItemScrollBox();
|
||||
|
||||
public slots:
|
||||
|
||||
void addItem(std::weak_ptr<Item> item);
|
||||
void removeItem(const ItemData& item);
|
||||
void addItem(std::weak_ptr<Item> item);
|
||||
void removeItem(const ItemData& item);
|
||||
void jsReqNewItem();
|
||||
|
||||
private:
|
||||
Ui::RelayScrollBox *ui;
|
||||
Ui::RelayScrollBox *ui;
|
||||
};
|
||||
|
||||
#endif // RELAYSCROLLBOX_H
|
36
src/trainControllerUI/ui/itemwidget.cpp
Normal file
36
src/trainControllerUI/ui/itemwidget.cpp
Normal file
@ -0,0 +1,36 @@
|
||||
#include "itemwidget.h"
|
||||
|
||||
#include <QCheckBox>
|
||||
#include <QDebug>
|
||||
#include <QSlider>
|
||||
#include "../items/train.h"
|
||||
#include "../items/turnout.h"
|
||||
|
||||
ItemWidget::ItemWidget(std::weak_ptr<Item> item, QWidget *parent) :
|
||||
QWidget(parent),
|
||||
item_(item)
|
||||
{
|
||||
qDebug()<<__func__<<" "<<(bool)item_.lock();
|
||||
|
||||
}
|
||||
|
||||
bool ItemWidget::controles(const ItemData& relay)
|
||||
{
|
||||
if(auto workingRelay = item_.lock())
|
||||
{
|
||||
if(relay == *workingRelay)
|
||||
return true;
|
||||
else
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
std::weak_ptr<Item> ItemWidget::getItem()
|
||||
{
|
||||
return item_;
|
||||
}
|
||||
|
||||
ItemWidget::~ItemWidget()
|
||||
{
|
||||
}
|
30
src/trainControllerUI/ui/itemwidget.h
Normal file
30
src/trainControllerUI/ui/itemwidget.h
Normal file
@ -0,0 +1,30 @@
|
||||
#pragma once
|
||||
|
||||
#include <QWidget>
|
||||
#include <memory>
|
||||
#include <QShortcut>
|
||||
#include "../items/item.h"
|
||||
|
||||
class ItemWidget : public QWidget
|
||||
{
|
||||
Q_OBJECT
|
||||
protected:
|
||||
std::weak_ptr<Item> item_;
|
||||
|
||||
virtual void disable(){}
|
||||
|
||||
signals:
|
||||
|
||||
void deleteRequest(const ItemData& item);
|
||||
|
||||
public:
|
||||
explicit ItemWidget(std::weak_ptr<Item> item, QWidget *parent);
|
||||
std::weak_ptr<Item> getItem();
|
||||
bool controles(const ItemData& relay);
|
||||
~ItemWidget();
|
||||
|
||||
public slots:
|
||||
|
||||
virtual void stateChanged(int state){(void)state;}
|
||||
};
|
||||
|
45
src/trainControllerUI/ui/mainwindow.cpp
Normal file
45
src/trainControllerUI/ui/mainwindow.cpp
Normal file
@ -0,0 +1,45 @@
|
||||
#include "mainwindow.h"
|
||||
#include "ui_mainwindow.h"
|
||||
#include "itemscrollbox.h"
|
||||
|
||||
MainWindow::MainWindow(Microcontroller * const micro, ItemStore* items, QWidget *parent) :
|
||||
QMainWindow(parent),
|
||||
stopShort(QKeySequence(Qt::Key_Space), this),
|
||||
ui(new Ui::MainWindow),
|
||||
_micro(micro)
|
||||
{
|
||||
ui->setupUi(this);
|
||||
|
||||
connect(&stopShort, &QShortcut::activated, _micro, &Microcontroller::estop);
|
||||
connect(ui->pushButton_stop, &QPushButton::clicked, _micro, &Microcontroller::estop);
|
||||
connect(ui->pushButton_refesh, &QPushButton::clicked, _micro, &Microcontroller::requestState);
|
||||
|
||||
connect(items, &ItemStore::itemAdded, ui->relayList, &ItemScrollBox::addItem);
|
||||
connect(items, &ItemStore::itemDeleted, ui->relayList, &ItemScrollBox::removeItem);
|
||||
|
||||
for(size_t i = 0; i < items->getItems()->size(); ++i)
|
||||
{
|
||||
ui->relayList->addItem(items->getItems()->at(i));
|
||||
}
|
||||
|
||||
connect(ui->relayList, &ItemScrollBox::deleteRequest, items, &ItemStore::removeItem);
|
||||
|
||||
ui->pushButton_addItem->hide();
|
||||
}
|
||||
|
||||
MainWindow::~MainWindow()
|
||||
{
|
||||
delete ui;
|
||||
}
|
||||
|
||||
/*
|
||||
void MainWindow::showItemCreationDialog()
|
||||
{
|
||||
ItemCreationDialog diag(this);
|
||||
diag.show();
|
||||
if(diag.exec())
|
||||
{
|
||||
createdItem(diag.item);
|
||||
}
|
||||
}
|
||||
*/
|
@ -20,25 +20,25 @@ class MainWindow;
|
||||
|
||||
class MainWindow : public QMainWindow
|
||||
{
|
||||
Q_OBJECT
|
||||
QShortcut stopShort;
|
||||
Q_OBJECT
|
||||
QShortcut stopShort;
|
||||
|
||||
public:
|
||||
explicit MainWindow(Microcontroller * const micro, ItemStore* items, QWidget *parent = nullptr);
|
||||
~MainWindow();
|
||||
explicit MainWindow(Microcontroller * const micro, ItemStore* items, QWidget *parent = nullptr);
|
||||
~MainWindow();
|
||||
|
||||
private:
|
||||
Ui::MainWindow *ui;
|
||||
Ui::MainWindow *ui;
|
||||
|
||||
Microcontroller *_micro;
|
||||
Microcontroller *_micro;
|
||||
|
||||
signals:
|
||||
|
||||
void createdItem(std::shared_ptr<Item> item);
|
||||
void createdItem(std::shared_ptr<Item> item);
|
||||
|
||||
private slots:
|
||||
|
||||
//void showItemCreationDialog();
|
||||
//void showItemCreationDialog();
|
||||
|
||||
};
|
||||
|
96
src/trainControllerUI/ui/signalwidget.cpp
Normal file
96
src/trainControllerUI/ui/signalwidget.cpp
Normal file
@ -0,0 +1,96 @@
|
||||
#include "signalwidget.h"
|
||||
#include "ui_signalwidget.h"
|
||||
|
||||
#include <QDebug>
|
||||
#include <QRadioButton>
|
||||
#include <memory>
|
||||
#include "trainsignal.h"
|
||||
|
||||
SignalWidget::SignalWidget(std::weak_ptr<Item> item, QWidget *parent) :
|
||||
ItemWidget(item, parent),
|
||||
ui(new Ui::SignalWidget)
|
||||
{
|
||||
ui->setupUi(this);
|
||||
|
||||
if(auto workingItem = item_.lock())
|
||||
{
|
||||
std::shared_ptr<Signal> signal = std::dynamic_pointer_cast<Signal>(workingItem);
|
||||
if(signal)
|
||||
{
|
||||
|
||||
ui->label->setText(workingItem->getName());
|
||||
|
||||
connect(ui->radioButton_go, &QRadioButton::clicked, this, [this]()
|
||||
{
|
||||
setValue(Signal::GO);
|
||||
});
|
||||
connect(ui->radioButton_slow, &QRadioButton::clicked, this, [this]()
|
||||
{
|
||||
setValue(Signal::SLOW);
|
||||
});
|
||||
connect(ui->radioButton_stop, &QRadioButton::clicked, this, [this]()
|
||||
{
|
||||
setValue(Signal::STOP);
|
||||
});
|
||||
|
||||
connect(signal.get(), &Item::valueChanged, this, &SignalWidget::moveToValue);
|
||||
|
||||
if(!signal->hasSlow())
|
||||
ui->radioButton_slow->hide();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
qWarning("SignalWidget got invalid item");
|
||||
SignalWidget::disable();
|
||||
}
|
||||
}
|
||||
|
||||
void SignalWidget::deleteItem()
|
||||
{
|
||||
if(auto workingItem = item_.lock())
|
||||
{
|
||||
deleteRequest(*workingItem);
|
||||
}
|
||||
}
|
||||
|
||||
void SignalWidget::setValue(int8_t value)
|
||||
{
|
||||
if(auto workingItem = item_.lock())
|
||||
workingItem->setValue(value);
|
||||
else
|
||||
disable();
|
||||
}
|
||||
|
||||
void SignalWidget::moveToValue(int8_t value)
|
||||
{
|
||||
qDebug()<<"got value"<<value;
|
||||
ui->radioButton_go->blockSignals(true);
|
||||
ui->radioButton_slow->blockSignals(true);
|
||||
ui->radioButton_stop->blockSignals(true);
|
||||
|
||||
ui->radioButton_go->setChecked(value == Signal::GO);
|
||||
ui->radioButton_slow->setChecked(value == Signal::SLOW);
|
||||
ui->radioButton_stop->setChecked(value == Signal::STOP);
|
||||
|
||||
ui->radioButton_go->blockSignals(false);
|
||||
ui->radioButton_slow->blockSignals(false);
|
||||
ui->radioButton_stop->blockSignals(false);
|
||||
}
|
||||
|
||||
void SignalWidget::disable()
|
||||
{
|
||||
ui->radioButton_go->setEnabled(false);
|
||||
ui->radioButton_slow->setEnabled(false);
|
||||
ui->radioButton_stop->setEnabled(false);
|
||||
}
|
||||
|
||||
void SignalWidget::stateChanged(int state)
|
||||
{
|
||||
moveToValue(state);
|
||||
}
|
||||
|
||||
SignalWidget::~SignalWidget()
|
||||
{
|
||||
delete ui;
|
||||
}
|
36
src/trainControllerUI/ui/signalwidget.h
Normal file
36
src/trainControllerUI/ui/signalwidget.h
Normal file
@ -0,0 +1,36 @@
|
||||
#pragma once
|
||||
|
||||
#include <QWidget>
|
||||
#include <memory>
|
||||
#include <QShortcut>
|
||||
#include "../items/trainsignal.h"
|
||||
#include "itemwidget.h"
|
||||
|
||||
namespace Ui
|
||||
{
|
||||
class SignalWidget;
|
||||
}
|
||||
|
||||
class SignalWidget : public ItemWidget
|
||||
{
|
||||
Q_OBJECT
|
||||
protected:
|
||||
|
||||
virtual void disable();
|
||||
|
||||
private slots:
|
||||
void moveToValue(int8_t value);
|
||||
void setValue(int8_t value);
|
||||
void deleteItem();
|
||||
|
||||
public:
|
||||
explicit SignalWidget(std::weak_ptr<Item> item, QWidget *parent);
|
||||
~SignalWidget();
|
||||
|
||||
public slots:
|
||||
|
||||
virtual void stateChanged(int state);
|
||||
|
||||
private:
|
||||
Ui::SignalWidget *ui;
|
||||
};
|
98
src/trainControllerUI/ui/signalwidget.ui
Normal file
98
src/trainControllerUI/ui/signalwidget.ui
Normal file
@ -0,0 +1,98 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<ui version="4.0">
|
||||
<class>SignalWidget</class>
|
||||
<widget class="QWidget" name="SignalWidget">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>312</width>
|
||||
<height>78</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Expanding" vsizetype="Preferred">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
<string>Form</string>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout_2">
|
||||
<property name="spacing">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="leftMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="topMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="rightMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="bottomMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<item>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout_3">
|
||||
<property name="spacing">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<item>
|
||||
<widget class="QLabel" name="label">
|
||||
<property name="text">
|
||||
<string>TextLabel</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<layout class="QVBoxLayout" name="verticalLayout">
|
||||
<item>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout_2">
|
||||
<item>
|
||||
<widget class="QRadioButton" name="radioButton_go">
|
||||
<property name="text">
|
||||
<string>Go</string>
|
||||
</property>
|
||||
<property name="checked">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QRadioButton" name="radioButton_slow">
|
||||
<property name="text">
|
||||
<string>Slow</string>
|
||||
</property>
|
||||
<property name="checked">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QRadioButton" name="radioButton_stop">
|
||||
<property name="text">
|
||||
<string>Stop</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="Line" name="line_2">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<resources/>
|
||||
<connections/>
|
||||
</ui>
|
194
src/trainControllerUI/ui/trainwidget.cpp
Normal file
194
src/trainControllerUI/ui/trainwidget.cpp
Normal file
@ -0,0 +1,194 @@
|
||||
#include "trainwidget.h"
|
||||
#include "ui_trainwidget.h"
|
||||
|
||||
#include <QCheckBox>
|
||||
#include <QDebug>
|
||||
#include <QSlider>
|
||||
#include "../items/train.h"
|
||||
#include "../items/turnout.h"
|
||||
|
||||
TrainWidget::TrainWidget(std::weak_ptr<Item> item, QWidget *parent) :
|
||||
ItemWidget(item, parent),
|
||||
ui(new Ui::TrainWidget)
|
||||
{
|
||||
ui->setupUi(this);
|
||||
if(auto workingItem = item_.lock())
|
||||
{
|
||||
ui->label->setText(workingItem->getName());
|
||||
|
||||
connect(ui->slider, &QSlider::valueChanged, this, &TrainWidget::setValue);
|
||||
connect(ui->checkBox_f1, &QCheckBox::stateChanged, this, &TrainWidget::f1);
|
||||
connect(ui->checkBox_f2, &QCheckBox::stateChanged, this, &TrainWidget::f2);
|
||||
connect(ui->checkBox_f3, &QCheckBox::stateChanged, this, &TrainWidget::f3);
|
||||
connect(ui->checkBox_f4, &QCheckBox::stateChanged, this, &TrainWidget::f4);
|
||||
connect(ui->pushButton_reverse, &QPushButton::clicked, this, &TrainWidget::reverse);
|
||||
connect(ui->radioButton_left, &QRadioButton::clicked, this, [this]()
|
||||
{
|
||||
setValue(0);
|
||||
});
|
||||
connect(ui->radioButton_right, &QRadioButton::clicked, this, [this]()
|
||||
{
|
||||
setValue(1);
|
||||
});
|
||||
|
||||
connect(workingItem.get(), &Item::valueChanged, this, &TrainWidget::moveToValue);
|
||||
|
||||
Train* train = dynamic_cast<Train*>(workingItem.get());
|
||||
Turnout* turnout = dynamic_cast<Turnout*>(workingItem.get());
|
||||
|
||||
if(turnout)
|
||||
{
|
||||
ui->checkBox_f1->hide();
|
||||
ui->checkBox_f2->hide();
|
||||
ui->checkBox_f3->hide();
|
||||
ui->checkBox_f4->hide();
|
||||
ui->slider->hide();
|
||||
}
|
||||
|
||||
if(!train)
|
||||
{
|
||||
ui->pushButton_reverse->hide();
|
||||
}
|
||||
else
|
||||
{
|
||||
ui->radioButton_left->hide();
|
||||
ui->radioButton_right->hide();
|
||||
uint8_t functionMask = train->getFunctionMask();
|
||||
qDebug()<<"functionMask: "<<(int)functionMask;
|
||||
if(!(functionMask & (1 << 0)))
|
||||
ui->checkBox_f1->hide();
|
||||
if(!(functionMask & (1 << 1)))
|
||||
ui->checkBox_f2->hide();
|
||||
if(!(functionMask & (1 << 2)))
|
||||
ui->checkBox_f3->hide();
|
||||
if(!(functionMask & (1 << 3)))
|
||||
ui->checkBox_f4->hide();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
qWarning("TrainWidget got invalid item");
|
||||
TrainWidget::disable();
|
||||
}
|
||||
}
|
||||
|
||||
void TrainWidget::deleteItem()
|
||||
{
|
||||
if(auto workingItem = item_.lock())
|
||||
{
|
||||
deleteRequest(*workingItem);
|
||||
}
|
||||
}
|
||||
|
||||
void TrainWidget::setValue(int8_t value)
|
||||
{
|
||||
if(auto workingItem = item_.lock())
|
||||
workingItem->setValue(value);
|
||||
else
|
||||
disable();
|
||||
}
|
||||
|
||||
void TrainWidget::moveToValue(int8_t value)
|
||||
{
|
||||
ui->slider->blockSignals(true);
|
||||
ui->radioButton_left->blockSignals(true);
|
||||
ui->radioButton_right->blockSignals(true);
|
||||
|
||||
ui->pushButton_reverse->setText(value == 0 ? "Reverse" : "Stop");
|
||||
ui->slider->setValue(value);
|
||||
ui->radioButton_left->setChecked(!value);
|
||||
ui->radioButton_right->setChecked(value);
|
||||
|
||||
ui->slider->blockSignals(false);
|
||||
ui->radioButton_left->blockSignals(false);
|
||||
ui->radioButton_right->blockSignals(false);
|
||||
}
|
||||
|
||||
void TrainWidget::f1(int value)
|
||||
{
|
||||
if(auto workingItem = item_.lock())
|
||||
workingItem->setFunction(0, value == Qt::Checked);
|
||||
else disable();
|
||||
}
|
||||
|
||||
void TrainWidget::f2(int value)
|
||||
{
|
||||
if(auto workingItem = item_.lock())
|
||||
workingItem->setFunction(1, value == Qt::Checked);
|
||||
else disable();
|
||||
}
|
||||
|
||||
|
||||
void TrainWidget::f3(int value)
|
||||
{
|
||||
if(auto workingItem = item_.lock())
|
||||
workingItem->setFunction(2, value == Qt::Checked);
|
||||
else disable();
|
||||
}
|
||||
|
||||
void TrainWidget::f4(int value)
|
||||
{
|
||||
if(auto workingItem = item_.lock())
|
||||
workingItem->setFunction(3, value == Qt::Checked);
|
||||
else disable();
|
||||
}
|
||||
|
||||
void TrainWidget::reverse()
|
||||
{
|
||||
if(auto workingItem = item_.lock())
|
||||
{
|
||||
Train* train = dynamic_cast<Train*>(workingItem.get());
|
||||
if(train && workingItem->getValue() == 0)
|
||||
train->reverse();
|
||||
else
|
||||
{
|
||||
setValue(!((bool)workingItem->getValue()));
|
||||
}
|
||||
}
|
||||
else disable();
|
||||
}
|
||||
|
||||
void TrainWidget::disable()
|
||||
{
|
||||
ui->checkBox_f1->setEnabled(false);
|
||||
ui->checkBox_f2->setEnabled(false);
|
||||
ui->checkBox_f3->setEnabled(false);
|
||||
ui->checkBox_f4->setEnabled(false);
|
||||
ui->label->setEnabled(false);
|
||||
ui->slider->setEnabled(false);
|
||||
ui->pushButton_reverse->setEnabled(false);
|
||||
}
|
||||
|
||||
void TrainWidget::stepUp()
|
||||
{
|
||||
setValue(ui->slider->value()+1);
|
||||
}
|
||||
|
||||
void TrainWidget::stepDown()
|
||||
{
|
||||
setValue(ui->slider->value()-1);
|
||||
}
|
||||
|
||||
void TrainWidget::setShortcuts(QKeySequence up, QKeySequence down, QKeySequence rev)
|
||||
{
|
||||
shortcuts_.clear();
|
||||
shortcuts_.push_back(std::unique_ptr<QShortcut>(new QShortcut(up, this)));
|
||||
connect(shortcuts_.back().get(), &QShortcut::activated, this, &TrainWidget::stepUp);
|
||||
shortcuts_.push_back(std::unique_ptr<QShortcut>(new QShortcut(down, this)));
|
||||
connect(shortcuts_.back().get(), &QShortcut::activated, this, &TrainWidget::stepDown);
|
||||
shortcuts_.push_back(std::unique_ptr<QShortcut>(new QShortcut(rev, this)));
|
||||
connect(shortcuts_.back().get(), &QShortcut::activated, this, &TrainWidget::reverse);
|
||||
}
|
||||
|
||||
void TrainWidget::stateChanged(int state)
|
||||
{
|
||||
qDebug()<<"widget got state "<<state;
|
||||
ui->slider->blockSignals(true);
|
||||
ui->slider->setValue(state);
|
||||
ui->slider->blockSignals(false);
|
||||
}
|
||||
|
||||
TrainWidget::~TrainWidget()
|
||||
{
|
||||
delete ui;
|
||||
}
|
48
src/trainControllerUI/ui/trainwidget.h
Normal file
48
src/trainControllerUI/ui/trainwidget.h
Normal file
@ -0,0 +1,48 @@
|
||||
#pragma once
|
||||
|
||||
#include <QWidget>
|
||||
#include <memory>
|
||||
#include <QShortcut>
|
||||
#include "../items/item.h"
|
||||
#include "itemwidget.h"
|
||||
|
||||
namespace Ui
|
||||
{
|
||||
class TrainWidget;
|
||||
}
|
||||
|
||||
class TrainWidget : public ItemWidget
|
||||
{
|
||||
Q_OBJECT
|
||||
protected:
|
||||
std::vector< std::unique_ptr<QShortcut> > shortcuts_;
|
||||
|
||||
void disable();
|
||||
|
||||
private slots:
|
||||
void setValue(int8_t value);
|
||||
void moveToValue(int8_t value);
|
||||
void deleteItem();
|
||||
|
||||
void stepUp();
|
||||
void stepDown();
|
||||
|
||||
void f1(int state);
|
||||
void f2(int state);
|
||||
void f3(int state);
|
||||
void f4(int state);
|
||||
void reverse();
|
||||
|
||||
public:
|
||||
explicit TrainWidget(std::weak_ptr<Item> item, QWidget *parent);
|
||||
~TrainWidget();
|
||||
void setShortcuts(QKeySequence up, QKeySequence down, QKeySequence rev);
|
||||
|
||||
public slots:
|
||||
|
||||
virtual void stateChanged(int state);
|
||||
|
||||
private:
|
||||
Ui::TrainWidget *ui;
|
||||
};
|
||||
|
@ -1,7 +1,7 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<ui version="4.0">
|
||||
<class>ItemWidget</class>
|
||||
<widget class="QWidget" name="ItemWidget">
|
||||
<class>TrainWidget</class>
|
||||
<widget class="QWidget" name="TrainWidget">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
15
src/trainOverlord/CMakeLists.txt
Normal file
15
src/trainOverlord/CMakeLists.txt
Normal file
@ -0,0 +1,15 @@
|
||||
set(UI_SOURCES
|
||||
trainoverlord.cpp
|
||||
overlorditemstore.cpp
|
||||
overlorditemstore.h
|
||||
blockborder.cpp
|
||||
blockborder.h
|
||||
block.cpp
|
||||
block.h
|
||||
layout.h
|
||||
layout.cpp
|
||||
)
|
||||
|
||||
add_executable(trainoverlord ${UI_SOURCES} ${COMMON_SOURCES})
|
||||
target_link_libraries(trainoverlord PRIVATE ${COMMON_LINK_LIBRARYS})
|
||||
target_include_directories(trainoverlord PRIVATE ./)
|
308
src/trainOverlord/block.cpp
Normal file
308
src/trainOverlord/block.cpp
Normal file
@ -0,0 +1,308 @@
|
||||
#include "block.h"
|
||||
#include <QJsonArray>
|
||||
#include <QTimer>
|
||||
#include <layout.h>
|
||||
#include "nfcuid.h"
|
||||
|
||||
|
||||
Block::Block(OverlordItemStore* items, uint32_t id):
|
||||
items_(items), id_(id)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void Block::addBorder(std::shared_ptr<BlockBorder> border)
|
||||
{
|
||||
borders_.push_back(border);
|
||||
std::shared_ptr<Block> block = border->getOtherBlock(this);
|
||||
if(!block || block.get() == this)
|
||||
return;
|
||||
connect(block.get(), &Block::blockedChanged, this, &Block::checkWaits);
|
||||
}
|
||||
|
||||
bool Block::blocked()
|
||||
{
|
||||
if(tags_.empty() && waits_.empty())
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Block::ownsTag(const NfcUid& tag)
|
||||
{
|
||||
for(const NfcUid& candiate : tags_)
|
||||
{
|
||||
if(candiate == tag)
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool Block::tagIsOfOwnedTrain(const NfcUid& tag)
|
||||
{
|
||||
std::shared_ptr<Train> train = items_->getTrainThatOwns(tag);
|
||||
if(!train)
|
||||
return false;
|
||||
for(const NfcUid& canidate : tags_)
|
||||
{
|
||||
std::shared_ptr<Train> canidateTrain = items_->getTrainThatOwns(canidate);
|
||||
if(*canidateTrain == *train)
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool Block::ownsBorder(std::shared_ptr<BlockBorder> border)
|
||||
{
|
||||
if(!border)
|
||||
return false;
|
||||
for(std::shared_ptr<BlockBorder> borderTest : borders_)
|
||||
{
|
||||
if(borderTest == border)
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void Block::checkWaits(bool isBlocked)
|
||||
{
|
||||
if(isBlocked)
|
||||
return;
|
||||
bool wasBlocked = blocked();
|
||||
for(std::vector<Wait>::iterator iter = waits_.begin(); iter != waits_.end();)
|
||||
{
|
||||
if(iter->type != WAIT_TYPE_BLOCK)
|
||||
{
|
||||
++iter;
|
||||
continue;
|
||||
}
|
||||
|
||||
std::shared_ptr<Block> block = iter->targetBlock.lock();
|
||||
std::shared_ptr<Train> train = iter->train.lock();
|
||||
qDebug()<<__func__<<"trying to push train"<<train->getTrainId()<<"to block"<<block->id();
|
||||
if(block && train && train->suspendend() && block->pushTag(iter->tag))
|
||||
{
|
||||
train->resume();
|
||||
std::shared_ptr<BlockBorder> border = iter->border.lock();
|
||||
if(border)
|
||||
border->updateSignals();
|
||||
iter = waits_.erase(iter);
|
||||
}
|
||||
else if(!block || !train || !train->suspendend())
|
||||
{
|
||||
iter = waits_.erase(iter);
|
||||
}
|
||||
else
|
||||
{
|
||||
++iter;
|
||||
}
|
||||
}
|
||||
if(wasBlocked != blocked())
|
||||
blockedChanged(!wasBlocked);
|
||||
}
|
||||
|
||||
bool Block::pushTag(const NfcUid& tag)
|
||||
{
|
||||
if(!blocked() || tagIsOfOwnedTrain(tag))
|
||||
{
|
||||
addTag(tag);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void Block::removeTraverse(std::shared_ptr<Train> train)
|
||||
{
|
||||
bool wasBlocked = blocked();
|
||||
for(std::vector<Wait>::iterator iter = waits_.begin(); iter != waits_.end();)
|
||||
{
|
||||
if(iter->type == WAIT_TYPE_TIMED_TRAVERSE)
|
||||
{
|
||||
std::shared_ptr<Train> iterTrain = iter->train.lock();
|
||||
if(!iterTrain)
|
||||
{
|
||||
iter = waits_.erase(iter);
|
||||
continue;
|
||||
}
|
||||
if(*iterTrain == *train)
|
||||
{
|
||||
qDebug()<<"Train"<<iterTrain->getTrainId()<<"removed from traverse wait for block"<<id_;
|
||||
iter = waits_.erase(iter);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
++iter;
|
||||
}
|
||||
if(wasBlocked != blocked())
|
||||
blockedChanged(!wasBlocked);
|
||||
}
|
||||
|
||||
void Block::addTraverseWait(const NfcUid& tag)
|
||||
{
|
||||
std::shared_ptr<Train> train = items_->getTrainThatOwns(tag);
|
||||
if(!train)
|
||||
return;
|
||||
if(!train->hasBackTag())
|
||||
{
|
||||
qDebug()<<"Train"<<train->getTrainId()<<"added as timed traverse wait for block"<<id_;
|
||||
Wait wait;
|
||||
wait.tag = tag;
|
||||
wait.train = train;
|
||||
wait.type = WAIT_TYPE_TIMED_TRAVERSE;
|
||||
waits_.push_back(wait);
|
||||
QTimer::singleShot(5000, this, [this, train](){removeTraverse(train);});
|
||||
}
|
||||
}
|
||||
|
||||
void Block::addBlockWait(const NfcUid& tag, std::shared_ptr<Block> block, std::shared_ptr<BlockBorder> border)
|
||||
{
|
||||
std::shared_ptr<Train> train = items_->getTrainThatOwns(tag);
|
||||
if(!train)
|
||||
return;
|
||||
Wait wait;
|
||||
wait.type = WAIT_TYPE_BLOCK;
|
||||
wait.train = train;
|
||||
wait.direction = train->getDirection();
|
||||
wait.targetBlock = block;
|
||||
wait.border = border;
|
||||
wait.tag = tag;
|
||||
connect(train.get(), &Train::unsuspended, this, &Block::unsuspendedTrain);
|
||||
waits_.push_back(wait);
|
||||
qDebug()<<"Train"<<train->getTrainId()<<"is wating at border for block"<<block->id();
|
||||
}
|
||||
|
||||
void Block::addTag(const NfcUid& tag)
|
||||
{
|
||||
bool wasBlocked = blocked();
|
||||
tags_.push_back(tag);
|
||||
if(wasBlocked != blocked())
|
||||
blockedChanged(!wasBlocked);
|
||||
}
|
||||
|
||||
void Block::unsuspendedTrain(uint32_t id, int direction)
|
||||
{
|
||||
qDebug()<<"Train with item id"<<id<<"reports unsuspended";
|
||||
bool wasBlocked = blocked();
|
||||
for(std::vector<Wait>::iterator iter = waits_.begin(); iter != waits_.end(); ++iter)
|
||||
{
|
||||
std::shared_ptr<Train> workTrain = iter->train.lock();
|
||||
if(!workTrain)
|
||||
{
|
||||
waits_.erase(iter);
|
||||
unsuspendedTrain(id, direction);
|
||||
break;
|
||||
}
|
||||
if(workTrain->id() == id)
|
||||
{
|
||||
std::shared_ptr<Block> block = iter->targetBlock.lock();
|
||||
disconnect(workTrain.get(), &Train::unsuspended, this, &Block::unsuspendedTrain);
|
||||
if(block)
|
||||
block->addTag(iter->tag);
|
||||
waits_.erase(iter);
|
||||
break;
|
||||
}
|
||||
}
|
||||
if(wasBlocked != blocked())
|
||||
blockedChanged(!wasBlocked);
|
||||
}
|
||||
|
||||
void Block::removeTag(const NfcUid& tag)
|
||||
{
|
||||
for(std::vector<NfcUid>::iterator iter = tags_.begin(); iter != tags_.end(); ++iter)
|
||||
{
|
||||
if(*iter == tag)
|
||||
{
|
||||
tags_.erase(iter);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Block::purgeTag(const NfcUid& tag)
|
||||
{
|
||||
bool wasBlocked = blocked();
|
||||
removeTag(tag);
|
||||
std::shared_ptr<Train> train = items_->getTrainThatOwns(tag);
|
||||
if(train)
|
||||
removeTraverse(train);
|
||||
if(wasBlocked != blocked())
|
||||
blockedChanged(!wasBlocked);
|
||||
}
|
||||
|
||||
void Block::tagArrivedAtBorder(NfcUid tag, std::weak_ptr<BlockBorder> borderIn)
|
||||
{
|
||||
bool wasBlocked = blocked();
|
||||
qDebug()<<__func__<<"block"<<id();
|
||||
std::shared_ptr<BlockBorder> border = borderIn.lock();
|
||||
if(!border)
|
||||
{
|
||||
qWarning()<<"border has expired in"<<__func__;
|
||||
return;
|
||||
}
|
||||
|
||||
if(!ownsBorder(border))
|
||||
return;
|
||||
|
||||
qDebug()<<"Block"<<id_<<"owns subject border";
|
||||
|
||||
if(!ownsTag(tag))
|
||||
return;
|
||||
|
||||
qDebug()<<"Block"<<id_<<"owns subject tag";
|
||||
|
||||
std::shared_ptr block = border->getOtherBlock(this);
|
||||
if(block)
|
||||
{
|
||||
if(!block->pushTag(tag))
|
||||
{
|
||||
std::shared_ptr<Train> train = items_->getTrainThatOwns(tag);
|
||||
train->suspend();
|
||||
addBlockWait(tag, block, border);
|
||||
}
|
||||
else
|
||||
{
|
||||
addTraverseWait(tag);
|
||||
}
|
||||
removeTag(tag);
|
||||
}
|
||||
if(wasBlocked != blocked())
|
||||
blockedChanged(!wasBlocked);
|
||||
}
|
||||
|
||||
void Block::store(QJsonObject &json)
|
||||
{
|
||||
json["Id"] = static_cast<double>(id_);
|
||||
QJsonArray borders;
|
||||
for(auto& border : borders_)
|
||||
{
|
||||
QJsonObject borderObject;
|
||||
borderObject["BorderId"] = static_cast<double>(border->id());
|
||||
borders.append(borderObject);
|
||||
}
|
||||
json["Borders"] = borders;
|
||||
}
|
||||
|
||||
void Block::load(const QJsonObject &json)
|
||||
{
|
||||
id_ = static_cast<uint32_t>(json["Id"].toDouble(0));
|
||||
}
|
||||
|
||||
void Block::populate(const QJsonObject& json, Layout* layout)
|
||||
{
|
||||
borders_.clear();
|
||||
const QJsonArray bordersArray(json["Borders"].toArray(QJsonArray()));
|
||||
for(const auto& arrayObj : bordersArray)
|
||||
{
|
||||
if(arrayObj.isObject())
|
||||
{
|
||||
uint32_t borderId = static_cast<uint32_t>(arrayObj.toObject()["BorderId"].toDouble(INT32_MAX));
|
||||
std::shared_ptr<BlockBorder> border = layout->getBorder(borderId);
|
||||
if(border)
|
||||
addBorder(border);
|
||||
else if(borderId == INT32_MAX)
|
||||
qWarning()<<"BorderId field is missing in border array for block"<<id_;
|
||||
else
|
||||
qWarning()<<"border"<<borderId<<"dosent exist but is needed by block"<<id_;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
75
src/trainOverlord/block.h
Normal file
75
src/trainOverlord/block.h
Normal file
@ -0,0 +1,75 @@
|
||||
#ifndef BLOCK_H
|
||||
#define BLOCK_H
|
||||
#include <vector>
|
||||
#include <memory>
|
||||
#include <QObject>
|
||||
#include <QRandomGenerator>
|
||||
#include <QJsonObject>
|
||||
#include "blockborder.h"
|
||||
#include "train.h"
|
||||
#include "overlorditemstore.h"
|
||||
|
||||
class BlockBorder;
|
||||
class Layout;
|
||||
|
||||
class Block: public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
protected:
|
||||
static constexpr int WAIT_TYPE_BLOCK = 0;
|
||||
static constexpr int WAIT_TYPE_TIMED_TRAVERSE = 1;
|
||||
|
||||
struct Wait
|
||||
{
|
||||
int type;
|
||||
int direction;
|
||||
NfcUid tag;
|
||||
std::weak_ptr<Train> train;
|
||||
std::weak_ptr<Block> targetBlock;
|
||||
std::weak_ptr<BlockBorder> border;
|
||||
};
|
||||
|
||||
std::vector< std::shared_ptr<BlockBorder> > borders_;
|
||||
std::vector<NfcUid> tags_;
|
||||
std::vector<Wait> waits_;
|
||||
uint32_t id_;
|
||||
OverlordItemStore* items_;
|
||||
|
||||
protected slots:
|
||||
void unsuspendedTrain(uint32_t id, int direction);
|
||||
void removeTraverse(std::shared_ptr<Train> train);
|
||||
|
||||
protected:
|
||||
void checkWaits(bool blocked = false);
|
||||
void addTraverseWait(const NfcUid& tag);
|
||||
void addBlockWait(const NfcUid& tag, std::shared_ptr<Block> block, std::shared_ptr<BlockBorder> border);
|
||||
void removeTag(const NfcUid& tag);
|
||||
bool tagIsOfOwnedTrain(const NfcUid& tag);
|
||||
|
||||
public:
|
||||
Block(OverlordItemStore* items, uint32_t id = QRandomGenerator::global()->generate());
|
||||
uint32_t id(){return id_;}
|
||||
|
||||
void addBorder(std::shared_ptr<BlockBorder> border);
|
||||
std::vector< std::shared_ptr<BlockBorder> > getBorders(){return borders_;}
|
||||
bool ownsBorder(std::shared_ptr<BlockBorder> border);
|
||||
|
||||
bool pushTag(const NfcUid& tag);
|
||||
void addTag(const NfcUid& tag);
|
||||
void purgeTag(const NfcUid& tag);
|
||||
bool ownsTag(const NfcUid& tag);
|
||||
|
||||
bool blocked();
|
||||
|
||||
void store(QJsonObject& json);
|
||||
void load(const QJsonObject& json);
|
||||
void populate(const QJsonObject& json, Layout* layout);
|
||||
|
||||
public slots:
|
||||
void tagArrivedAtBorder(NfcUid tag, std::weak_ptr<BlockBorder> border);
|
||||
|
||||
signals:
|
||||
void blockedChanged(bool blocked);
|
||||
};
|
||||
|
||||
#endif // BLOCK_H
|
172
src/trainOverlord/blockborder.cpp
Normal file
172
src/trainOverlord/blockborder.cpp
Normal file
@ -0,0 +1,172 @@
|
||||
#include "blockborder.h"
|
||||
#include <QJsonArray>
|
||||
#include <layout.h>
|
||||
|
||||
BlockBorder::BlockBorder(uint8_t reader, std::pair<std::weak_ptr<Block>, std::weak_ptr<Block>> blocks, uint32_t id): reader_(reader), id_(id)
|
||||
{
|
||||
setBlocks(blocks);
|
||||
}
|
||||
|
||||
bool BlockBorder::isReader(uint8_t reader)
|
||||
{
|
||||
return reader == reader_;
|
||||
}
|
||||
|
||||
uint8_t BlockBorder::getReader()
|
||||
{
|
||||
return reader_;
|
||||
}
|
||||
|
||||
void BlockBorder::setBlocks(std::pair<std::weak_ptr<Block>, std::weak_ptr<Block>> blocks)
|
||||
{
|
||||
blocks_ = blocks;
|
||||
std::shared_ptr<Block> first = blocks.first.lock();
|
||||
if(first)
|
||||
connect(first.get(), &Block::blockedChanged, this, &BlockBorder::blockedChanged);
|
||||
std::shared_ptr<Block> second = blocks.second.lock();
|
||||
if(second)
|
||||
connect(second.get(), &Block::blockedChanged, this, &BlockBorder::blockedChanged);
|
||||
}
|
||||
|
||||
void BlockBorder::setSignal(std::weak_ptr<Signal> signalWeak, int8_t value)
|
||||
{
|
||||
std::shared_ptr<Signal> signal = signalWeak.lock();
|
||||
if(signal)
|
||||
{
|
||||
signal->setValue(value);
|
||||
}
|
||||
}
|
||||
|
||||
void BlockBorder::blockedChanged(bool blocked)
|
||||
{
|
||||
(void)blocked;
|
||||
updateSignals();
|
||||
}
|
||||
|
||||
void BlockBorder::updateSignals()
|
||||
{
|
||||
for(size_t i = 0; i < signals_.size(); ++i)
|
||||
{
|
||||
std::shared_ptr<Signal> signal = signals_[i].lock();
|
||||
if(signal)
|
||||
{
|
||||
std::shared_ptr<Block> block = signalDirections_[i] ? blocks_.first.lock() : blocks_.second.lock();
|
||||
if(block && block->blocked())
|
||||
{
|
||||
if(signal->getValue() != Signal::STOP)
|
||||
{
|
||||
std::weak_ptr<Signal> signalWeak = signal;
|
||||
QTimer::singleShot(500, signal.get(), [signalWeak](){BlockBorder::setSignal(signalWeak, Signal::STOP);});
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if(signal->getValue() != Signal::GO)
|
||||
{
|
||||
std::weak_ptr<Signal> signalWeak = signal;
|
||||
QTimer::singleShot(500, signal.get(), [signalWeak](){BlockBorder::setSignal(signalWeak, Signal::GO);});
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
signals_.erase(signals_.begin()+i);
|
||||
updateSignals();
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void BlockBorder::addSignal(std::weak_ptr<Signal> signal, std::shared_ptr<Block> block)
|
||||
{
|
||||
signals_.push_back(signal);
|
||||
signalDirections_.push_back(block == blocks_.first.lock());
|
||||
}
|
||||
|
||||
std::shared_ptr<Block> BlockBorder::getOtherBlock(Block* block)
|
||||
{
|
||||
std::shared_ptr<Block> first = blocks_.first.lock();
|
||||
std::shared_ptr<Block> second = blocks_.second.lock();
|
||||
|
||||
if(first && first.get() == block)
|
||||
return second;
|
||||
if(second && second.get() == block)
|
||||
return first;
|
||||
return std::shared_ptr<Block>();
|
||||
}
|
||||
|
||||
std::shared_ptr<Block> BlockBorder::getOverlap(BlockBorder* border)
|
||||
{
|
||||
if(border->getBlocks().first.lock() == blocks_.first.lock() || border->getBlocks().first.lock() == blocks_.second.lock())
|
||||
{
|
||||
return border->getBlocks().first.lock();
|
||||
}
|
||||
else if(border->getBlocks().second.lock() == blocks_.first.lock() || border->getBlocks().second.lock() == blocks_.second.lock())
|
||||
{
|
||||
return border->getBlocks().second.lock();
|
||||
}
|
||||
return std::shared_ptr<Block>();
|
||||
}
|
||||
|
||||
void BlockBorder::store(QJsonObject& json)
|
||||
{
|
||||
json["Id"] = static_cast<double>(id_);
|
||||
json["Reader"] = static_cast<double>(reader_);
|
||||
QJsonArray signalArray;
|
||||
for(size_t i = 0; i < signals_.size(); ++i)
|
||||
{
|
||||
std::shared_ptr<Signal> signalPtr = signals_[i].lock();
|
||||
if(signalPtr)
|
||||
{
|
||||
QJsonObject signalObject;
|
||||
signalObject["SignalId"] = static_cast<double>(signalPtr->getSignalId());
|
||||
signalObject["Direction"] = static_cast<double>(signalDirections_[i]);
|
||||
signalArray.append(signalObject);
|
||||
}
|
||||
}
|
||||
json["Signals"] = signalArray;
|
||||
}
|
||||
|
||||
void BlockBorder::load(const QJsonObject& json)
|
||||
{
|
||||
id_ = static_cast<uint32_t>(json["Id"].toDouble(0));
|
||||
reader_ = json["Reader"].toDouble(0);
|
||||
const QJsonArray signalArray(json["Signals"].toArray(QJsonArray()));
|
||||
for(const auto& arrayObj : signalArray)
|
||||
{
|
||||
if(arrayObj.isObject())
|
||||
{
|
||||
QJsonObject arrayObjObj = arrayObj.toObject();
|
||||
signalIds_.push_back(std::pair<uint32_t, bool>(static_cast<uint32_t>(arrayObjObj["SignalId"].toDouble(INT32_MAX)), static_cast<bool>(arrayObjObj["Direction"].toDouble(0))));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool BlockBorder::hasMissingSingal()
|
||||
{
|
||||
for(auto& signal : signalIds_)
|
||||
{
|
||||
qDebug()<<"Missing signal id:"<<signal.first<<"Direction:"<<signal.second;
|
||||
}
|
||||
return !signalIds_.empty();
|
||||
}
|
||||
|
||||
void BlockBorder::informOfItem(std::weak_ptr<Item> item)
|
||||
{
|
||||
std::shared_ptr<Item> workItem = item.lock();
|
||||
if(!workItem)
|
||||
return;
|
||||
std::shared_ptr<Signal> signal = std::dynamic_pointer_cast<Signal>(workItem);
|
||||
if(!signal)
|
||||
return;
|
||||
for(const std::pair<uint32_t, bool>& signalPair : signalIds_)
|
||||
{
|
||||
if(signalPair.first == signal->getSignalId())
|
||||
{
|
||||
signals_.push_back(signal);
|
||||
signalDirections_.push_back(signalPair.second);
|
||||
qDebug()<<"Border"<<id_<<"got Signal"<<signal->getSignalId();
|
||||
}
|
||||
}
|
||||
std::erase_if(signalIds_, [signal](std::pair<uint32_t, bool> pair) -> bool{return pair.first == signal->getSignalId();});
|
||||
}
|
44
src/trainOverlord/blockborder.h
Normal file
44
src/trainOverlord/blockborder.h
Normal file
@ -0,0 +1,44 @@
|
||||
#ifndef BLOCKBORDER_H
|
||||
#define BLOCKBORDER_H
|
||||
#include "trainsignal.h"
|
||||
#include "block.h"
|
||||
#include <QJsonObject>
|
||||
#include <QObject>
|
||||
|
||||
class Block;
|
||||
class Layout;
|
||||
|
||||
class BlockBorder: public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
private:
|
||||
uint64_t reader_;
|
||||
uint32_t id_;
|
||||
std::vector<std::pair<uint32_t, bool>> signalIds_;
|
||||
std::vector<std::weak_ptr<Signal>> signals_;
|
||||
std::vector<bool> signalDirections_;
|
||||
std::pair<std::weak_ptr<Block>, std::weak_ptr<Block>> blocks_;
|
||||
|
||||
static void setSignal(std::weak_ptr<Signal> signalWeak, int8_t value);
|
||||
|
||||
public:
|
||||
BlockBorder(uint8_t reader = 0, std::pair<std::weak_ptr<Block>, std::weak_ptr<Block>> blocks = std::pair<std::weak_ptr<Block>, std::weak_ptr<Block>>(), uint32_t id = QRandomGenerator::global()->generate());
|
||||
bool isReader(uint8_t reader);
|
||||
uint8_t getReader();
|
||||
void updateSignals();
|
||||
std::shared_ptr<Block> getOtherBlock(Block* block);
|
||||
std::pair<std::weak_ptr<Block>, std::weak_ptr<Block>> getBlocks(){return blocks_;}
|
||||
void setBlocks(std::pair<std::weak_ptr<Block>, std::weak_ptr<Block>> blocks);
|
||||
void addSignal(std::weak_ptr<Signal> signal, std::shared_ptr<Block> block);
|
||||
void informOfItem(std::weak_ptr<Item> item);
|
||||
bool hasMissingSingal();
|
||||
std::shared_ptr<Block> getOverlap(BlockBorder* border);
|
||||
uint32_t id() {return id_;}
|
||||
void store(QJsonObject& json);
|
||||
void load(const QJsonObject& json);
|
||||
|
||||
public slots:
|
||||
void blockedChanged(bool blocked);
|
||||
};
|
||||
|
||||
#endif // BLOCKBORDER_H
|
221
src/trainOverlord/layout.cpp
Normal file
221
src/trainOverlord/layout.cpp
Normal file
@ -0,0 +1,221 @@
|
||||
#include "layout.h"
|
||||
#include <memory>
|
||||
#include <QJsonArray>
|
||||
|
||||
Layout::Layout(OverlordItemStore* items, QObject *parent): QObject{parent}, items_(items)
|
||||
{
|
||||
}
|
||||
|
||||
void Layout::removeTagFromAllBlocks(const NfcUid& tag)
|
||||
{
|
||||
for(std::shared_ptr<Block> block : blocks_)
|
||||
{
|
||||
block->purgeTag(tag);
|
||||
}
|
||||
}
|
||||
|
||||
void Layout::registerTagInLimbo(const NfcUid& tag, std::shared_ptr<BlockBorder> border)
|
||||
{
|
||||
for(auto iter = limbo_.begin(); iter != limbo_.end(); ++iter)
|
||||
{
|
||||
NfcUid limboTag = iter->first;
|
||||
std::shared_ptr<BlockBorder> limboBorder = iter->second.lock();
|
||||
if(!limboBorder)
|
||||
{
|
||||
limbo_.erase(iter);
|
||||
registerTagInLimbo(tag, border);
|
||||
return;
|
||||
}
|
||||
|
||||
if(limboTag == tag)
|
||||
{
|
||||
if(border == limboBorder)
|
||||
return;
|
||||
|
||||
std::shared_ptr<Block> overlap = border->getOverlap(limboBorder.get());
|
||||
if(overlap)
|
||||
{
|
||||
qDebug()<<"Tag"<<tag.toString().c_str()<<"removed from limbo and added to block"<<overlap->id()<<"while crossing border"<<border->id();
|
||||
overlap->addTag(tag);
|
||||
overlap->tagArrivedAtBorder(tag, border);
|
||||
limbo_.erase(iter);
|
||||
return;
|
||||
}
|
||||
else
|
||||
{
|
||||
iter->second = border;
|
||||
return;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
std::shared_ptr<Block> first = border->getBlocks().first.lock();
|
||||
std::shared_ptr<Block> second = border->getBlocks().second.lock();
|
||||
|
||||
qDebug()<<"Tag"<<tag.toString().c_str()<<"added to limbo between block"<<
|
||||
(first ? QString::number(first->id()) : "invalid")<<"and block"<<(second ? QString::number(second->id()) : "invalid");
|
||||
limbo_.push_back(std::pair<NfcUid, std::weak_ptr<BlockBorder>>(tag, border));
|
||||
}
|
||||
|
||||
void Layout::tagArrivedAtReader(uint8_t reader, NfcUid tag)
|
||||
{
|
||||
std::shared_ptr<BlockBorder> border;
|
||||
for(std::shared_ptr<BlockBorder> borderTest : borders_)
|
||||
{
|
||||
if(borderTest->getReader() == reader)
|
||||
{
|
||||
border = borderTest;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if(!border)
|
||||
{
|
||||
qWarning()<<"reader "<<reader<<"is not registerd with any border";
|
||||
return;
|
||||
}
|
||||
|
||||
std::shared_ptr<Train> train = items_->getTrainThatOwns(tag);
|
||||
qDebug()<<"Train"<<(train ? train->getTrainId() : -1)<<"Tag"<<tag.toString().c_str()<<"arrived at border"<<border->id();
|
||||
|
||||
bool tagHandled = false;
|
||||
for(std::shared_ptr<Block>& block : blocks_)
|
||||
{
|
||||
if(block->ownsTag(tag))
|
||||
{
|
||||
tagHandled = true;
|
||||
if(block->ownsBorder(border))
|
||||
{
|
||||
block->tagArrivedAtBorder(tag, border);
|
||||
}
|
||||
else
|
||||
{
|
||||
removeTagFromAllBlocks(tag);
|
||||
registerTagInLimbo(tag, border);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if(!tagHandled)
|
||||
registerTagInLimbo(tag, border);
|
||||
}
|
||||
|
||||
void Layout::addBlock(std::shared_ptr<Block> block)
|
||||
{
|
||||
blocks_.push_back(block);
|
||||
}
|
||||
|
||||
void Layout::addBorder(std::shared_ptr<BlockBorder> border)
|
||||
{
|
||||
borders_.push_back(border);
|
||||
}
|
||||
|
||||
std::shared_ptr<BlockBorder> Layout::getBorder(uint32_t id)
|
||||
{
|
||||
for(const std::shared_ptr<BlockBorder>& border : borders_)
|
||||
{
|
||||
if(border->id() == id)
|
||||
return border;
|
||||
}
|
||||
return std::shared_ptr<BlockBorder>();
|
||||
}
|
||||
|
||||
std::shared_ptr<Block> Layout::getBlock(uint32_t id)
|
||||
{
|
||||
for(const std::shared_ptr<Block>& block : blocks_)
|
||||
{
|
||||
if(block->id() == id)
|
||||
return block;
|
||||
}
|
||||
return std::shared_ptr<Block>();
|
||||
}
|
||||
|
||||
void Layout::store(QJsonObject& json)
|
||||
{
|
||||
QJsonArray blockArray;
|
||||
for(const std::shared_ptr<Block>& block : blocks_)
|
||||
{
|
||||
QJsonObject object;
|
||||
block->store(object);
|
||||
blockArray.append(object);
|
||||
}
|
||||
json["Blocks"] = blockArray;
|
||||
|
||||
QJsonArray borderArray;
|
||||
for(const std::shared_ptr<BlockBorder>& border : borders_)
|
||||
{
|
||||
QJsonObject object;
|
||||
border->store(object);
|
||||
borderArray.append(object);
|
||||
}
|
||||
json["Borders"] = borderArray;
|
||||
}
|
||||
|
||||
void Layout::load(const QJsonObject& json)
|
||||
{
|
||||
std::vector<QJsonObject> blockJsonObjects;
|
||||
const QJsonArray blockArray(json["Blocks"].toArray(QJsonArray()));
|
||||
for(const auto& object : blockArray)
|
||||
{
|
||||
if(object.isObject())
|
||||
{
|
||||
const QJsonObject jsonObject = object.toObject();
|
||||
blockJsonObjects.push_back(jsonObject);
|
||||
std::shared_ptr<Block> block(new Block(items_));
|
||||
block->load(jsonObject);
|
||||
blocks_.push_back(block);
|
||||
}
|
||||
}
|
||||
|
||||
std::vector<QJsonObject> borderJsonObjects;
|
||||
const QJsonArray borderArray(json["Borders"].toArray(QJsonArray()));
|
||||
for(const auto& object : borderArray)
|
||||
{
|
||||
if(object.isObject())
|
||||
{
|
||||
const QJsonObject jsonObject = object.toObject();
|
||||
borderJsonObjects.push_back(jsonObject);
|
||||
std::shared_ptr<BlockBorder> border(new BlockBorder);
|
||||
border->load(object.toObject());
|
||||
borders_.push_back(border);
|
||||
}
|
||||
}
|
||||
|
||||
for(size_t i = 0; i < blocks_.size(); ++i)
|
||||
{
|
||||
blocks_[i]->populate(blockJsonObjects[i], this);
|
||||
}
|
||||
|
||||
for(std::shared_ptr<BlockBorder>& border : borders_)
|
||||
{
|
||||
std::shared_ptr<Block> first;
|
||||
std::shared_ptr<Block> second;
|
||||
for(std::shared_ptr<Block>& block : blocks_)
|
||||
{
|
||||
if(block->ownsBorder(border))
|
||||
{
|
||||
if(!first)
|
||||
first = block;
|
||||
else if(!second)
|
||||
second = block;
|
||||
else
|
||||
qWarning()<<"border with id"<<border->id()<<"is assigned to more than 2 blocks";
|
||||
}
|
||||
}
|
||||
if(!first || !second)
|
||||
qWarning()<<"border with id"<<border->id()<<"is assigned to less than than 2 blocks";
|
||||
border->setBlocks(std::pair<std::weak_ptr<Block>, std::weak_ptr<Block>>(first, second));
|
||||
|
||||
for(std::shared_ptr<Item>& item : *items_->getItems())
|
||||
border->informOfItem(item);
|
||||
|
||||
connect(items_, &ItemStore::itemAdded, border.get(), &BlockBorder::informOfItem);
|
||||
}
|
||||
|
||||
for(size_t i = 0; i < blocks_.size(); ++i)
|
||||
{
|
||||
blocks_[i]->populate(blockJsonObjects[i], this);
|
||||
if(blocks_[i]->getBorders().empty())
|
||||
qWarning()<<"block with id"<<blocks_[i]->id()<<"doset have at least one border";
|
||||
}
|
||||
}
|
42
src/trainOverlord/layout.h
Normal file
42
src/trainOverlord/layout.h
Normal file
@ -0,0 +1,42 @@
|
||||
#ifndef BLOCKSTORE_H
|
||||
#define BLOCKSTORE_H
|
||||
|
||||
#include <QObject>
|
||||
#include <memory>
|
||||
#include <vector>
|
||||
|
||||
#include "block.h"
|
||||
#include "overlorditemstore.h"
|
||||
#include "blockborder.h"
|
||||
#include "microcontroller.h"
|
||||
#include "itemstore.h"
|
||||
|
||||
class Layout : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
private:
|
||||
|
||||
private:
|
||||
std::vector<std::shared_ptr<Block>> blocks_;
|
||||
std::vector<std::shared_ptr<BlockBorder>> borders_;
|
||||
std::vector<std::pair<NfcUid, std::weak_ptr<BlockBorder>>> limbo_;
|
||||
|
||||
void removeTagFromAllBlocks(const NfcUid& tag);
|
||||
void registerTagInLimbo(const NfcUid& tag, std::shared_ptr<BlockBorder>);
|
||||
|
||||
OverlordItemStore *items_;
|
||||
|
||||
public:
|
||||
explicit Layout(OverlordItemStore *items, QObject *parent = nullptr);
|
||||
void addBlock(std::shared_ptr<Block> block);
|
||||
void addBorder(std::shared_ptr<BlockBorder> border);
|
||||
void store(QJsonObject& json);
|
||||
void load(const QJsonObject& json);
|
||||
std::shared_ptr<BlockBorder> getBorder(uint32_t id);
|
||||
std::shared_ptr<Block> getBlock(uint32_t id);
|
||||
|
||||
public slots:
|
||||
void tagArrivedAtReader(uint8_t reader, NfcUid tag);
|
||||
};
|
||||
|
||||
#endif // BLOCKSTORE_H
|
20
src/trainOverlord/overlorditemstore.cpp
Normal file
20
src/trainOverlord/overlorditemstore.cpp
Normal file
@ -0,0 +1,20 @@
|
||||
#include "overlorditemstore.h"
|
||||
#include <QDebug>
|
||||
#include "train.h"
|
||||
|
||||
OverlordItemStore::OverlordItemStore(QObject *parent): ItemStore(parent)
|
||||
{
|
||||
}
|
||||
|
||||
std::shared_ptr<Train> OverlordItemStore::getTrainThatOwns(const NfcUid& uid)
|
||||
{
|
||||
for(std::shared_ptr<Item> item : items_)
|
||||
{
|
||||
std::shared_ptr<Train> train = std::dynamic_pointer_cast<Train>(item);
|
||||
if(!train)
|
||||
continue;
|
||||
if(train->ownsTag(uid))
|
||||
return train;
|
||||
}
|
||||
return std::shared_ptr<Train>();
|
||||
}
|
11
src/trainOverlord/overlorditemstore.h
Normal file
11
src/trainOverlord/overlorditemstore.h
Normal file
@ -0,0 +1,11 @@
|
||||
#pragma once
|
||||
#include "itemstore.h"
|
||||
#include "train.h"
|
||||
|
||||
class OverlordItemStore: public ItemStore
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
OverlordItemStore(QObject *parent = nullptr);
|
||||
std::shared_ptr<Train> getTrainThatOwns(const NfcUid& uid);
|
||||
};
|
166
src/trainOverlord/trainoverlord.cpp
Normal file
166
src/trainOverlord/trainoverlord.cpp
Normal file
@ -0,0 +1,166 @@
|
||||
#include <QCoreApplication>
|
||||
#include <QCommandLineParser>
|
||||
#include <QIODevice>
|
||||
#include <QTcpSocket>
|
||||
#include <iostream>
|
||||
#include <QJsonObject>
|
||||
#include <QJsonDocument>
|
||||
#include <QStandardPaths>
|
||||
#include <QFile>
|
||||
#include <QTimer>
|
||||
#include <signal.h>
|
||||
|
||||
#include "microcontroller.h"
|
||||
#include "nfcuid.h"
|
||||
#include "overlorditemstore.h"
|
||||
#include "train.h"
|
||||
#include "turnout.h"
|
||||
#include "layout.h"
|
||||
|
||||
void sigHandler(int sig)
|
||||
{
|
||||
QCoreApplication::quit();
|
||||
}
|
||||
|
||||
QJsonObject getJsonObjectFromDisk(const QString& filePath, bool* error)
|
||||
{
|
||||
QFile file;
|
||||
|
||||
if(filePath.size() > 0)
|
||||
file.setFileName(filePath);
|
||||
else
|
||||
file.setFileName(QStandardPaths::writableLocation(QStandardPaths::ConfigLocation) + "/trainoverloard.json");
|
||||
|
||||
file.open(QIODevice::ReadOnly);
|
||||
if(!file.isOpen())
|
||||
{
|
||||
std::cerr<<"Can not open config file: "<<filePath.toLatin1().data()<<std::endl;
|
||||
}
|
||||
else
|
||||
{
|
||||
QJsonParseError qerror;
|
||||
QJsonDocument document(QJsonDocument::fromJson(file.readAll(), &qerror));
|
||||
file.close();
|
||||
if(qerror.error != QJsonParseError::NoError)
|
||||
{
|
||||
qDebug()<<filePath<<" "<<qerror.errorString();
|
||||
if(error)
|
||||
(*error) = true;
|
||||
}
|
||||
return document.object();
|
||||
}
|
||||
return QJsonObject();
|
||||
}
|
||||
|
||||
bool storeJsonObjectToDisk(const QJsonObject& json, QString filePath = QString())
|
||||
{
|
||||
if(filePath.size() == 0)
|
||||
{
|
||||
filePath = QStandardPaths::writableLocation(QStandardPaths::ConfigLocation) + "/trainoverloard.json";
|
||||
}
|
||||
QFile file(filePath + ".out");
|
||||
|
||||
qDebug()<<"config file: "<<filePath;
|
||||
file.open(QIODevice::WriteOnly);
|
||||
if(!file.isOpen())
|
||||
{
|
||||
std::cerr<<"Can not open config file: "<<filePath.toLatin1().data()<<std::endl;
|
||||
return false;
|
||||
}
|
||||
else
|
||||
{
|
||||
QJsonDocument document(json);
|
||||
file.write(document.toJson());
|
||||
file.close();
|
||||
QFile::remove(filePath);
|
||||
file.rename(filePath);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
void getItemsCb(QTimer* timer, ItemStore* items, Microcontroller* micro)
|
||||
{
|
||||
if(items->getItems()->empty())
|
||||
{
|
||||
micro->requestState();
|
||||
timer->start(1000);
|
||||
}
|
||||
}
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
QCoreApplication a(argc, argv);
|
||||
|
||||
signal(SIGINT, &sigHandler);
|
||||
|
||||
//set info
|
||||
QCoreApplication::setOrganizationName("UVOS");
|
||||
QCoreApplication::setOrganizationDomain("uvos.xyz");
|
||||
QCoreApplication::setApplicationName("TrainOverlord");
|
||||
QCoreApplication::setApplicationVersion("0.1");
|
||||
|
||||
//parse comand line
|
||||
QCommandLineParser parser;
|
||||
parser.setApplicationDescription("Train control application");
|
||||
parser.addHelpOption();
|
||||
parser.addVersionOption();
|
||||
QCommandLineOption hostOption(QStringList() << "H" << "host", QCoreApplication::translate("main",
|
||||
"Set server host ip addres"), "adress");
|
||||
parser.addOption(hostOption);
|
||||
QCommandLineOption portOption(QStringList() << "p" << "port", QCoreApplication::translate("main",
|
||||
"Set server Port in TCP mode or Serial port in serial mode"), "port");
|
||||
parser.addOption(portOption);
|
||||
parser.process(a);
|
||||
|
||||
QTcpSocket microSocket;
|
||||
|
||||
int port = 6856;
|
||||
if(parser.isSet(portOption))
|
||||
port = parser.value(portOption).toInt();
|
||||
|
||||
QString host("127.0.0.1");
|
||||
if(parser.isSet(hostOption)) host = parser.value(hostOption);
|
||||
std::cout<<"connecting to "<<host.toStdString()<<':'<<port<<'\n';
|
||||
microSocket.connectToHost(host, port, QIODevice::ReadWrite);
|
||||
if(!microSocket.waitForConnected(3000))
|
||||
{
|
||||
std::cout<<"Can not connect to to Server.\n";
|
||||
return 1;
|
||||
}
|
||||
|
||||
OverlordItemStore items;
|
||||
Layout layout(&items);
|
||||
|
||||
Microcontroller micro(µSocket);
|
||||
QObject::connect(µ, &Microcontroller::gotTag, &layout, &Layout::tagArrivedAtReader);
|
||||
QObject::connect(µ, &Microcontroller::gotItemList, &items, &OverlordItemStore::addItems);
|
||||
QObject::connect(µ, &Microcontroller::itemChanged, &items, &OverlordItemStore::itemStateChanged);
|
||||
|
||||
Train::micro = µ
|
||||
Turnout::micro = µ
|
||||
Signal::micro = µ
|
||||
|
||||
QTimer timer;
|
||||
timer.setSingleShot(false);
|
||||
QObject::connect(&timer, &QTimer::timeout, &timer, [µ, &timer, &items](){getItemsCb(&timer, &items, µ);});
|
||||
getItemsCb(&timer, &items, µ);
|
||||
|
||||
{
|
||||
bool err = false;
|
||||
QJsonObject json = getJsonObjectFromDisk(QString(), &err);
|
||||
if(err)
|
||||
{
|
||||
std::cerr<<"Could not load config file\n";
|
||||
return -1;
|
||||
}
|
||||
layout.load(json);
|
||||
}
|
||||
|
||||
int ret = a.exec();
|
||||
/*
|
||||
QJsonObject jsonStore;
|
||||
layout.store(jsonStore);
|
||||
storeJsonObjectToDisk(jsonStore);
|
||||
*/
|
||||
return ret;
|
||||
}
|
@ -1,142 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<ui version="4.0">
|
||||
<class>AlarmSettingsDialog</class>
|
||||
<widget class="QDialog" name="AlarmSettingsDialog">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>423</width>
|
||||
<height>281</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
<string>Dialog</string>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout">
|
||||
<item>
|
||||
<widget class="QLabel" name="label">
|
||||
<property name="text">
|
||||
<string>Sound File:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout">
|
||||
<property name="leftMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="topMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<item>
|
||||
<widget class="QLineEdit" name="lineEdit">
|
||||
<property name="enabled">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="pushButton">
|
||||
<property name="text">
|
||||
<string>Change</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout_2">
|
||||
<property name="topMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<item>
|
||||
<widget class="QLabel" name="label_2">
|
||||
<property name="text">
|
||||
<string>Sunrise</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<spacer name="horizontalSpacer">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>40</width>
|
||||
<height>20</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QCheckBox" name="checkBox">
|
||||
<property name="text">
|
||||
<string>Enable</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item>
|
||||
<spacer name="verticalSpacer">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Vertical</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>20</width>
|
||||
<height>40</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QDialogButtonBox" name="buttonBox">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="standardButtons">
|
||||
<set>QDialogButtonBox::Cancel|QDialogButtonBox::Ok</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<resources/>
|
||||
<connections>
|
||||
<connection>
|
||||
<sender>buttonBox</sender>
|
||||
<signal>accepted()</signal>
|
||||
<receiver>AlarmSettingsDialog</receiver>
|
||||
<slot>accept()</slot>
|
||||
<hints>
|
||||
<hint type="sourcelabel">
|
||||
<x>248</x>
|
||||
<y>254</y>
|
||||
</hint>
|
||||
<hint type="destinationlabel">
|
||||
<x>157</x>
|
||||
<y>274</y>
|
||||
</hint>
|
||||
</hints>
|
||||
</connection>
|
||||
<connection>
|
||||
<sender>buttonBox</sender>
|
||||
<signal>rejected()</signal>
|
||||
<receiver>AlarmSettingsDialog</receiver>
|
||||
<slot>reject()</slot>
|
||||
<hints>
|
||||
<hint type="sourcelabel">
|
||||
<x>316</x>
|
||||
<y>260</y>
|
||||
</hint>
|
||||
<hint type="destinationlabel">
|
||||
<x>286</x>
|
||||
<y>274</y>
|
||||
</hint>
|
||||
</hints>
|
||||
</connection>
|
||||
</connections>
|
||||
</ui>
|
@ -1,30 +0,0 @@
|
||||
#include "itemcreationdialog.h"
|
||||
#include "ui_itemcreationdialog.h"
|
||||
|
||||
ItemCreationDialog::ItemCreationDialog(QWidget *parent) :
|
||||
QDialog(parent),
|
||||
ui(new Ui::ItemCreationDialog)
|
||||
{
|
||||
ui->setupUi(this);
|
||||
connect(ui->comboBox, &QComboBox::currentTextChanged, this, &ItemCreationDialog::itemTypeChanged);
|
||||
connect(ui->lineEdit, &QLineEdit::textChanged, this, &ItemCreationDialog::itemNameChanged);
|
||||
}
|
||||
|
||||
ItemCreationDialog::~ItemCreationDialog()
|
||||
{
|
||||
delete ui;
|
||||
}
|
||||
|
||||
void ItemCreationDialog::itemTypeChanged(const QString& type)
|
||||
{
|
||||
ui->verticalLayout->removeWidget(widget);
|
||||
}
|
||||
|
||||
void ItemCreationDialog::itemNameChanged(const QString& name)
|
||||
{
|
||||
if(item)
|
||||
{
|
||||
item->setName(name);
|
||||
}
|
||||
}
|
||||
|
@ -1,33 +0,0 @@
|
||||
#ifndef ITEMCREATIONDIALOG_H
|
||||
#define ITEMCREATIONDIALOG_H
|
||||
|
||||
#include <QDialog>
|
||||
#include <memory>
|
||||
#include "../items/item.h"
|
||||
|
||||
namespace Ui {
|
||||
class ItemCreationDialog;
|
||||
}
|
||||
|
||||
class ItemCreationDialog : public QDialog
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
QWidget* widget;
|
||||
|
||||
public:
|
||||
explicit ItemCreationDialog(QWidget *parent = nullptr);
|
||||
~ItemCreationDialog();
|
||||
|
||||
std::shared_ptr<Item> item;
|
||||
|
||||
private slots:
|
||||
|
||||
void itemTypeChanged(const QString& type);
|
||||
void itemNameChanged(const QString& name);
|
||||
|
||||
private:
|
||||
Ui::ItemCreationDialog *ui;
|
||||
};
|
||||
|
||||
#endif // ITEMCREATIONDIALOG_H
|
@ -1,116 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<ui version="4.0">
|
||||
<class>ItemCreationDialog</class>
|
||||
<widget class="QDialog" name="ItemCreationDialog">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>400</width>
|
||||
<height>140</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
<string>Create Item</string>
|
||||
</property>
|
||||
<property name="windowIcon">
|
||||
<iconset resource="../../resources.qrc">
|
||||
<normaloff>:/images/UVOSicon.bmp</normaloff>:/images/UVOSicon.bmp</iconset>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout_2">
|
||||
<item>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout">
|
||||
<item>
|
||||
<widget class="QLabel" name="label">
|
||||
<property name="text">
|
||||
<string>Type</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QComboBox" name="comboBox">
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>Message</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>System</string>
|
||||
</property>
|
||||
</item>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout_2">
|
||||
<item>
|
||||
<widget class="QLabel" name="label_2">
|
||||
<property name="text">
|
||||
<string>Name</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLineEdit" name="lineEdit">
|
||||
<property name="text">
|
||||
<string>Item</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item>
|
||||
<layout class="QVBoxLayout" name="verticalLayout"/>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QDialogButtonBox" name="buttonBox">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="standardButtons">
|
||||
<set>QDialogButtonBox::Cancel|QDialogButtonBox::Ok</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<resources>
|
||||
<include location="../../resources.qrc"/>
|
||||
</resources>
|
||||
<connections>
|
||||
<connection>
|
||||
<sender>buttonBox</sender>
|
||||
<signal>accepted()</signal>
|
||||
<receiver>ItemCreationDialog</receiver>
|
||||
<slot>accept()</slot>
|
||||
<hints>
|
||||
<hint type="sourcelabel">
|
||||
<x>248</x>
|
||||
<y>254</y>
|
||||
</hint>
|
||||
<hint type="destinationlabel">
|
||||
<x>157</x>
|
||||
<y>274</y>
|
||||
</hint>
|
||||
</hints>
|
||||
</connection>
|
||||
<connection>
|
||||
<sender>buttonBox</sender>
|
||||
<signal>rejected()</signal>
|
||||
<receiver>ItemCreationDialog</receiver>
|
||||
<slot>reject()</slot>
|
||||
<hints>
|
||||
<hint type="sourcelabel">
|
||||
<x>316</x>
|
||||
<y>260</y>
|
||||
</hint>
|
||||
<hint type="destinationlabel">
|
||||
<x>286</x>
|
||||
<y>274</y>
|
||||
</hint>
|
||||
</hints>
|
||||
</connection>
|
||||
</connections>
|
||||
</ui>
|
@ -1,84 +0,0 @@
|
||||
#include "itemscrollbox.h"
|
||||
#include "ui_relayscrollbox.h"
|
||||
#include "ui_relayscrollbox.h"
|
||||
#include "../items/train.h"
|
||||
#include "../items/turnout.h"
|
||||
#include "../trainjs.h"
|
||||
|
||||
ItemScrollBox::ItemScrollBox(QWidget *parent) :
|
||||
QWidget(parent),
|
||||
ui(new Ui::RelayScrollBox)
|
||||
{
|
||||
ui->setupUi(this);
|
||||
QScroller::grabGesture(ui->scrollArea, QScroller::TouchGesture);
|
||||
QScroller::grabGesture(ui->scrollArea, QScroller::LeftMouseButtonGesture);
|
||||
}
|
||||
|
||||
ItemScrollBox::~ItemScrollBox()
|
||||
{
|
||||
delete ui;
|
||||
}
|
||||
|
||||
void ItemScrollBox::addItem(std::weak_ptr<Item> item)
|
||||
{
|
||||
if(auto workItem = item.lock())
|
||||
{
|
||||
widgets_.push_back(new ItemWidget(item, this));
|
||||
Train* train = dynamic_cast<Train*>(workItem.get());
|
||||
Turnout* turnout = dynamic_cast<Turnout*>(workItem.get());
|
||||
if(train)
|
||||
{
|
||||
if(train->getTrainId() == 0)
|
||||
widgets_.back()->setShortcuts(QKeySequence(Qt::Key_Q), QKeySequence(Qt::Key_A), QKeySequence(Qt::Key_Z));
|
||||
else if(train->getTrainId() == 1)
|
||||
widgets_.back()->setShortcuts(QKeySequence(Qt::Key_W), QKeySequence(Qt::Key_S), QKeySequence(Qt::Key_X));
|
||||
else if(train->getTrainId() == 2)
|
||||
widgets_.back()->setShortcuts(QKeySequence(Qt::Key_E), QKeySequence(Qt::Key_D), QKeySequence(Qt::Key_C));
|
||||
else if(train->getTrainId() == 3)
|
||||
widgets_.back()->setShortcuts(QKeySequence(Qt::Key_R), QKeySequence(Qt::Key_F), QKeySequence(Qt::Key_V));
|
||||
else if(train->getTrainId() == 4)
|
||||
widgets_.back()->setShortcuts(QKeySequence(Qt::Key_T), QKeySequence(Qt::Key_G), QKeySequence(Qt::Key_B));
|
||||
}
|
||||
else if(turnout)
|
||||
{
|
||||
if(turnout->getTurnoutId() == 0)
|
||||
widgets_.back()->setShortcuts(QKeySequence(), QKeySequence(), QKeySequence(Qt::Key_1));
|
||||
else if(turnout->getTurnoutId() == 1)
|
||||
widgets_.back()->setShortcuts(QKeySequence(), QKeySequence(), QKeySequence(Qt::Key_2));
|
||||
else if(turnout->getTurnoutId() == 2)
|
||||
widgets_.back()->setShortcuts(QKeySequence(), QKeySequence(), QKeySequence(Qt::Key_3));
|
||||
else if(turnout->getTurnoutId() == 3)
|
||||
widgets_.back()->setShortcuts(QKeySequence(), QKeySequence(), QKeySequence(Qt::Key_4));
|
||||
else if(turnout->getTurnoutId() == 4)
|
||||
widgets_.back()->setShortcuts(QKeySequence(), QKeySequence(), QKeySequence(Qt::Key_5));
|
||||
else if(turnout->getTurnoutId() == 5)
|
||||
widgets_.back()->setShortcuts(QKeySequence(), QKeySequence(), QKeySequence(Qt::Key_6));
|
||||
else if(turnout->getTurnoutId() == 6)
|
||||
widgets_.back()->setShortcuts(QKeySequence(), QKeySequence(), QKeySequence(Qt::Key_7));
|
||||
else if(turnout->getTurnoutId() == 7)
|
||||
widgets_.back()->setShortcuts(QKeySequence(), QKeySequence(), QKeySequence(Qt::Key_8));
|
||||
else if(turnout->getTurnoutId() == 8)
|
||||
widgets_.back()->setShortcuts(QKeySequence(), QKeySequence(), QKeySequence(Qt::Key_9));
|
||||
else if(turnout->getTurnoutId() == 9)
|
||||
widgets_.back()->setShortcuts(QKeySequence(), QKeySequence(), QKeySequence(Qt::Key_0));
|
||||
}
|
||||
ui->relayWidgetVbox->addWidget(widgets_.back());
|
||||
connect(widgets_.back(), &ItemWidget::deleteRequest, this, &ItemScrollBox::deleteRequest);
|
||||
connect(widgets_.back(), &ItemWidget::deleteRequest, this, &ItemScrollBox::removeItem);
|
||||
}
|
||||
}
|
||||
|
||||
void ItemScrollBox::removeItem(const ItemData& item)
|
||||
{
|
||||
for(unsigned i = 0; i < widgets_.size(); i++)
|
||||
{
|
||||
if(widgets_[i]->controles(item))
|
||||
{
|
||||
ui->relayWidgetVbox->removeWidget(widgets_[i]);
|
||||
delete widgets_[i];
|
||||
widgets_.erase(widgets_.begin()+i);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1,176 +0,0 @@
|
||||
#include "itemsettingsdialog.h"
|
||||
#include "ui_itemsettingsdialog.h"
|
||||
#include<memory>
|
||||
|
||||
ItemSettingsDialog::ItemSettingsDialog(std::shared_ptr<Item> item, QWidget *parent) :
|
||||
QDialog(parent),
|
||||
item_(item),
|
||||
ui(new Ui::ItemSettingsDialog)
|
||||
{
|
||||
ui->setupUi(this);
|
||||
|
||||
setModal(false);
|
||||
|
||||
ui->label_name->setText(item_->getName());
|
||||
ui->checkBox_Override->setChecked(item_->getOverride());
|
||||
|
||||
|
||||
if(std::shared_ptr<Relay> relay = std::dynamic_pointer_cast<Relay>(item_))
|
||||
{
|
||||
itemSpecificWidget_ = new RelayItemSettingsWidget(relay);
|
||||
}
|
||||
else if(std::shared_ptr<MessageItem> msgItem = std::dynamic_pointer_cast<MessageItem>(item_))
|
||||
{
|
||||
itemSpecificWidget_ = new MessageItemSettingsWidget(msgItem);
|
||||
}
|
||||
else if(std::shared_ptr<SystemItem> sysItem = std::dynamic_pointer_cast<SystemItem>(item_))
|
||||
{
|
||||
itemSpecificWidget_ = new SystemItemSettingsWidget(sysItem);
|
||||
}
|
||||
|
||||
if(itemSpecificWidget_)
|
||||
{
|
||||
ui->verticalLayout_2->addWidget(itemSpecificWidget_);
|
||||
}
|
||||
|
||||
connect(ui->pushButton_add, &QPushButton::clicked, this, &ItemSettingsDialog::addActor);
|
||||
connect(ui->pushButton_remove, &QPushButton::clicked, this, &ItemSettingsDialog::removeActor);
|
||||
connect(ui->pushButton_edit, &QPushButton::clicked, this, &ItemSettingsDialog::editActor);
|
||||
connect(ui->checkBox_Override, &QPushButton::clicked, this, &ItemSettingsDialog::changeOverride);
|
||||
|
||||
|
||||
ui->tableWidget->setHorizontalHeaderItem(0, new QTableWidgetItem("Actor"));
|
||||
ui->tableWidget->setHorizontalHeaderItem(1, new QTableWidgetItem("Action"));
|
||||
ui->tableWidget->setHorizontalHeaderItem(2, new QTableWidgetItem("Enabled"));
|
||||
ui->tableWidget->horizontalHeader()->setSectionResizeMode(0, QHeaderView::Stretch);
|
||||
ui->tableWidget->horizontalHeader()->resizeSection(1, 60);
|
||||
ui->tableWidget->horizontalHeader()->resizeSection(2, 75);
|
||||
loadActorList();
|
||||
}
|
||||
|
||||
ItemSettingsDialog::~ItemSettingsDialog()
|
||||
{
|
||||
if(itemSpecificWidget_) delete itemSpecificWidget_;
|
||||
delete ui;
|
||||
}
|
||||
|
||||
void ItemSettingsDialog::changeOverride()
|
||||
{
|
||||
item_->setOverride(ui->checkBox_Override->isChecked());
|
||||
}
|
||||
|
||||
void ItemSettingsDialog::loadActorList()
|
||||
{
|
||||
//ui->listWidget->clear();
|
||||
ui->tableWidget->setRowCount(item_->getActors().size());
|
||||
|
||||
for(unsigned i = 0; i < item_->getActors().size(); i++)
|
||||
{
|
||||
ui->tableWidget->setItem(i, 0, new QTableWidgetItem(item_->getActors()[i]->getName()));
|
||||
ui->tableWidget->setItem(i, 1, new QTableWidgetItem(item_->getActors()[i]->actionName()));
|
||||
ui->tableWidget->setItem(i, 2, new QTableWidgetItem(item_->getActors()[i]->isActive() ? "Y" : "N"));
|
||||
}
|
||||
}
|
||||
|
||||
void ItemSettingsDialog::addActor()
|
||||
{
|
||||
ActorSettingsDialog* dialog = nullptr;
|
||||
std::shared_ptr<Actor> actor = nullptr;
|
||||
|
||||
if(ui->comboBox->currentText() == "Alarm")
|
||||
{
|
||||
std::shared_ptr<AlarmTime> alarm = std::shared_ptr<AlarmTime>(new AlarmTime);
|
||||
actor = alarm;
|
||||
dialog = new ActorSettingsDialog(alarm, this);
|
||||
}
|
||||
else if(ui->comboBox->currentText() == "Sensor")
|
||||
{
|
||||
std::shared_ptr<SensorActor> sensorActor = std::shared_ptr<SensorActor>(new SensorActor);
|
||||
actor = sensorActor;
|
||||
dialog = new ActorSettingsDialog(sensorActor, this);
|
||||
}
|
||||
else if(ui->comboBox->currentText() == "Timer" )
|
||||
{
|
||||
std::shared_ptr<TimerActor> timerActor = std::shared_ptr<TimerActor>(new TimerActor);
|
||||
actor = timerActor;
|
||||
dialog = new ActorSettingsDialog(timerActor, this);
|
||||
}
|
||||
else if(ui->comboBox->currentText() == "Regulator")
|
||||
{
|
||||
std::shared_ptr<Regulator> regulator = std::shared_ptr<Regulator>(new Regulator);
|
||||
actor = regulator;
|
||||
dialog = new ActorSettingsDialog(regulator, this);
|
||||
}
|
||||
|
||||
else if(ui->comboBox->currentText() == "Polynomal")
|
||||
{
|
||||
std::shared_ptr<PolynomalActor> polynomalActor = std::shared_ptr<PolynomalActor>(new PolynomalActor);
|
||||
actor = polynomalActor;
|
||||
dialog = new ActorSettingsDialog(polynomalActor, this);
|
||||
}
|
||||
|
||||
else if(ui->comboBox->currentText() == "Multi Factor")
|
||||
{
|
||||
std::shared_ptr<MultiFactorActor> polynomalActor = std::shared_ptr<MultiFactorActor>(new MultiFactorActor);
|
||||
actor = polynomalActor;
|
||||
dialog = new ActorSettingsDialog(polynomalActor, this);
|
||||
}
|
||||
|
||||
|
||||
if(dialog != nullptr)
|
||||
{
|
||||
dialog->setParent(this);
|
||||
dialog->show();
|
||||
if(dialog->exec() == QDialog::Accepted)
|
||||
{
|
||||
item_->addActor(actor);
|
||||
loadActorList();
|
||||
}
|
||||
delete dialog;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void ItemSettingsDialog::removeActor()
|
||||
{
|
||||
if(item_->getActors().size() > ui->tableWidget->currentRow())
|
||||
{
|
||||
item_->removeActor(item_->getActors().at(ui->tableWidget->currentRow()));
|
||||
loadActorList();
|
||||
}
|
||||
}
|
||||
|
||||
void ItemSettingsDialog::editActor()
|
||||
{
|
||||
if(item_->getActors().size() > ui->tableWidget->currentRow())
|
||||
{
|
||||
std::shared_ptr<Actor> actor = item_->getActors()[ui->tableWidget->currentRow()];
|
||||
|
||||
std::shared_ptr<AlarmTime> alarmTime = std::dynamic_pointer_cast<AlarmTime>(actor);
|
||||
std::shared_ptr<Regulator> regulator = std::dynamic_pointer_cast<Regulator>(actor);
|
||||
std::shared_ptr<SensorActor> sensorActor = std::dynamic_pointer_cast<SensorActor>(actor);
|
||||
std::shared_ptr<TimerActor> timerActor = std::dynamic_pointer_cast<TimerActor>(actor);
|
||||
std::shared_ptr<PolynomalActor> polynomalActor = std::dynamic_pointer_cast<PolynomalActor>(actor);
|
||||
std::shared_ptr<MultiFactorActor> factorActor = std::dynamic_pointer_cast<MultiFactorActor>(actor);
|
||||
|
||||
ActorSettingsDialog* dialog;
|
||||
|
||||
if(alarmTime) dialog = new ActorSettingsDialog(alarmTime, this);
|
||||
else if(regulator) dialog = new ActorSettingsDialog(regulator, this);
|
||||
else if(sensorActor) dialog = new ActorSettingsDialog(sensorActor, this);
|
||||
else if(timerActor) dialog = new ActorSettingsDialog(timerActor, this);
|
||||
else if(polynomalActor) dialog = new ActorSettingsDialog(polynomalActor, this);
|
||||
else if(factorActor) dialog = new ActorSettingsDialog(factorActor, this);
|
||||
else dialog = new ActorSettingsDialog(actor, this);
|
||||
dialog->setParent(this);
|
||||
dialog->show();
|
||||
dialog->exec();
|
||||
|
||||
for(int i = 0; i < ui->tableWidget->rowCount() && i < item_->getActors().size(); ++i)
|
||||
{
|
||||
ui->tableWidget->item(i, 0)->setText(item_->getActors()[i]->getName());
|
||||
ui->tableWidget->item(i, 1)->setText(item_->getActors()[i]->actionName());
|
||||
ui->tableWidget->item(i, 2)->setText(item_->getActors()[i]->isActive() ? "Y" : "N");
|
||||
}
|
||||
}
|
||||
}
|
@ -1,37 +0,0 @@
|
||||
#ifndef RELAYSETTINGSDIALOG_H
|
||||
#define RELAYSETTINGSDIALOG_H
|
||||
|
||||
#include <QDialog>
|
||||
#include <QSettings>
|
||||
#include <memory>
|
||||
#include "../items/item.h"
|
||||
|
||||
namespace Ui {
|
||||
class ItemSettingsDialog;
|
||||
}
|
||||
|
||||
class ItemSettingsDialog : public QDialog
|
||||
{
|
||||
Q_OBJECT
|
||||
std::shared_ptr<Item> item_;
|
||||
QWidget* itemSpecificWidget_ = nullptr;
|
||||
|
||||
private:
|
||||
void loadActorList();
|
||||
|
||||
public:
|
||||
explicit ItemSettingsDialog(std::shared_ptr<Item> item, QWidget *parent = nullptr);
|
||||
~ItemSettingsDialog();
|
||||
|
||||
private slots:
|
||||
|
||||
void removeActor();
|
||||
void addActor();
|
||||
void editActor();
|
||||
void changeOverride();
|
||||
|
||||
private:
|
||||
Ui::ItemSettingsDialog *ui;
|
||||
};
|
||||
|
||||
#endif // RELAYSETTINGSDIALOG_H
|
@ -1,274 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<ui version="4.0">
|
||||
<class>ItemSettingsDialog</class>
|
||||
<widget class="QDialog" name="ItemSettingsDialog">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>577</width>
|
||||
<height>390</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
<string>Item Settings</string>
|
||||
</property>
|
||||
<property name="windowIcon">
|
||||
<iconset resource="../../resources.qrc">
|
||||
<normaloff>:/images/UVOSicon.bmp</normaloff>:/images/UVOSicon.bmp</iconset>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout">
|
||||
<item>
|
||||
<layout class="QFormLayout" name="formLayout">
|
||||
<property name="fieldGrowthPolicy">
|
||||
<enum>QFormLayout::AllNonFixedFieldsGrow</enum>
|
||||
</property>
|
||||
<property name="rightMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="bottomMargin">
|
||||
<number>10</number>
|
||||
</property>
|
||||
<item row="1" column="0">
|
||||
<widget class="QLabel" name="label">
|
||||
<property name="text">
|
||||
<string>Name:</string>
|
||||
</property>
|
||||
<property name="alignment">
|
||||
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="1">
|
||||
<widget class="QLabel" name="label_name">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Preferred" vsizetype="Preferred">
|
||||
<horstretch>5</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="layoutDirection">
|
||||
<enum>Qt::LeftToRight</enum>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>TextLabel</string>
|
||||
</property>
|
||||
<property name="alignment">
|
||||
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item>
|
||||
<layout class="QVBoxLayout" name="verticalLayout_2"/>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QCheckBox" name="checkBox_Override">
|
||||
<property name="text">
|
||||
<string>Override</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QTableWidget" name="tableWidget">
|
||||
<property name="frameShape">
|
||||
<enum>QFrame::StyledPanel</enum>
|
||||
</property>
|
||||
<property name="verticalScrollBarPolicy">
|
||||
<enum>Qt::ScrollBarAsNeeded</enum>
|
||||
</property>
|
||||
<property name="horizontalScrollBarPolicy">
|
||||
<enum>Qt::ScrollBarAlwaysOff</enum>
|
||||
</property>
|
||||
<property name="autoScroll">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
<property name="editTriggers">
|
||||
<set>QAbstractItemView::NoEditTriggers</set>
|
||||
</property>
|
||||
<property name="tabKeyNavigation">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
<property name="showDropIndicator" stdset="0">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
<property name="dragDropOverwriteMode">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
<property name="selectionBehavior">
|
||||
<enum>QAbstractItemView::SelectRows</enum>
|
||||
</property>
|
||||
<property name="showGrid">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
<property name="gridStyle">
|
||||
<enum>Qt::SolidLine</enum>
|
||||
</property>
|
||||
<property name="cornerButtonEnabled">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
<property name="rowCount">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="columnCount">
|
||||
<number>3</number>
|
||||
</property>
|
||||
<attribute name="horizontalHeaderVisible">
|
||||
<bool>false</bool>
|
||||
</attribute>
|
||||
<attribute name="horizontalHeaderMinimumSectionSize">
|
||||
<number>32</number>
|
||||
</attribute>
|
||||
<attribute name="horizontalHeaderHighlightSections">
|
||||
<bool>true</bool>
|
||||
</attribute>
|
||||
<attribute name="verticalHeaderVisible">
|
||||
<bool>false</bool>
|
||||
</attribute>
|
||||
<attribute name="verticalHeaderDefaultSectionSize">
|
||||
<number>32</number>
|
||||
</attribute>
|
||||
<column/>
|
||||
<column/>
|
||||
<column/>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout_2">
|
||||
<property name="leftMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="topMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<item>
|
||||
<widget class="QPushButton" name="pushButton_remove">
|
||||
<property name="text">
|
||||
<string>Remove</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="pushButton_edit">
|
||||
<property name="text">
|
||||
<string>Edit</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout">
|
||||
<item>
|
||||
<widget class="QLabel" name="label_3">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Fixed" vsizetype="Preferred">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Act on</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QComboBox" name="comboBox">
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>Sensor</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>Polynomal</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>Regulator</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>Alarm</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>Timer</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>Multi Factor</string>
|
||||
</property>
|
||||
</item>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="pushButton_add">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Fixed" vsizetype="Fixed">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Add</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QDialogButtonBox" name="buttonBox">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="standardButtons">
|
||||
<set>QDialogButtonBox::Ok</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<resources>
|
||||
<include location="../../resources.qrc"/>
|
||||
</resources>
|
||||
<connections>
|
||||
<connection>
|
||||
<sender>buttonBox</sender>
|
||||
<signal>accepted()</signal>
|
||||
<receiver>ItemSettingsDialog</receiver>
|
||||
<slot>accept()</slot>
|
||||
<hints>
|
||||
<hint type="sourcelabel">
|
||||
<x>248</x>
|
||||
<y>254</y>
|
||||
</hint>
|
||||
<hint type="destinationlabel">
|
||||
<x>157</x>
|
||||
<y>274</y>
|
||||
</hint>
|
||||
</hints>
|
||||
</connection>
|
||||
<connection>
|
||||
<sender>buttonBox</sender>
|
||||
<signal>rejected()</signal>
|
||||
<receiver>ItemSettingsDialog</receiver>
|
||||
<slot>reject()</slot>
|
||||
<hints>
|
||||
<hint type="sourcelabel">
|
||||
<x>316</x>
|
||||
<y>260</y>
|
||||
</hint>
|
||||
<hint type="destinationlabel">
|
||||
<x>286</x>
|
||||
<y>274</y>
|
||||
</hint>
|
||||
</hints>
|
||||
</connection>
|
||||
</connections>
|
||||
</ui>
|
@ -1,203 +0,0 @@
|
||||
#include "itemwidget.h"
|
||||
#include "ui_itemwidget.h"
|
||||
|
||||
#include <QCheckBox>
|
||||
#include <QDebug>
|
||||
#include <QSlider>
|
||||
#include "../items/train.h"
|
||||
#include "../items/turnout.h"
|
||||
|
||||
ItemWidget::ItemWidget(std::weak_ptr<Item> item, QWidget *parent) :
|
||||
QWidget(parent),
|
||||
item_(item),
|
||||
ui(new Ui::ItemWidget)
|
||||
{
|
||||
ui->setupUi(this);
|
||||
|
||||
if(auto workingItem = item_.lock())
|
||||
{
|
||||
ui->label->setText(workingItem->getName());
|
||||
|
||||
connect(ui->slider, &QSlider::valueChanged, this, &ItemWidget::setValue);
|
||||
connect(ui->checkBox_f1, &QCheckBox::stateChanged, this, &ItemWidget::f1);
|
||||
connect(ui->checkBox_f2, &QCheckBox::stateChanged, this, &ItemWidget::f2);
|
||||
connect(ui->checkBox_f3, &QCheckBox::stateChanged, this, &ItemWidget::f3);
|
||||
connect(ui->checkBox_f4, &QCheckBox::stateChanged, this, &ItemWidget::f4);
|
||||
connect(ui->pushButton_reverse, &QPushButton::clicked, this, &ItemWidget::reverse);
|
||||
connect(ui->radioButton_left, &QRadioButton::clicked, this, [this](){setValue(0);});
|
||||
connect(ui->radioButton_right, &QRadioButton::clicked, this, [this](){setValue(1);});
|
||||
|
||||
connect(workingItem.get(), &Item::valueChanged, this, &ItemWidget::moveToValue);
|
||||
|
||||
Train* train = dynamic_cast<Train*>(workingItem.get());
|
||||
Turnout* turnout = dynamic_cast<Turnout*>(workingItem.get());
|
||||
|
||||
if(turnout)
|
||||
{
|
||||
ui->checkBox_f1->hide();
|
||||
ui->checkBox_f2->hide();
|
||||
ui->checkBox_f3->hide();
|
||||
ui->checkBox_f4->hide();
|
||||
ui->slider->hide();
|
||||
}
|
||||
|
||||
if(!train)
|
||||
{
|
||||
ui->pushButton_reverse->hide();
|
||||
}
|
||||
else
|
||||
{
|
||||
ui->radioButton_left->hide();
|
||||
ui->radioButton_right->hide();
|
||||
uint8_t functionMask = train->getFunctionMask();
|
||||
qDebug()<<"functionMask: "<<(int)functionMask;
|
||||
if(!(functionMask & (1 << 0)))
|
||||
ui->checkBox_f1->hide();
|
||||
if(!(functionMask & (1 << 1)))
|
||||
ui->checkBox_f2->hide();
|
||||
if(!(functionMask & (1 << 2)))
|
||||
ui->checkBox_f3->hide();
|
||||
if(!(functionMask & (1 << 3)))
|
||||
ui->checkBox_f4->hide();
|
||||
}
|
||||
}
|
||||
else disable();
|
||||
}
|
||||
|
||||
void ItemWidget::deleteItem()
|
||||
{
|
||||
if(auto workingItem = item_.lock())
|
||||
{
|
||||
deleteRequest(*workingItem);
|
||||
}
|
||||
}
|
||||
|
||||
void ItemWidget::setValue(int8_t value)
|
||||
{
|
||||
if(auto workingItem = item_.lock())
|
||||
workingItem->setValue(value);
|
||||
else
|
||||
disable();
|
||||
}
|
||||
|
||||
void ItemWidget::moveToValue(int8_t value)
|
||||
{
|
||||
ui->slider->blockSignals(true);
|
||||
ui->radioButton_left->blockSignals(true);
|
||||
ui->radioButton_right->blockSignals(true);
|
||||
|
||||
ui->pushButton_reverse->setText(value == 0 ? "Reverse" : "Stop");
|
||||
ui->slider->setValue(value);
|
||||
ui->radioButton_left->setChecked(!value);
|
||||
ui->radioButton_right->setChecked(value);
|
||||
|
||||
ui->slider->blockSignals(false);
|
||||
ui->radioButton_left->blockSignals(false);
|
||||
ui->radioButton_right->blockSignals(false);
|
||||
}
|
||||
|
||||
void ItemWidget::f1(int value)
|
||||
{
|
||||
if(auto workingItem = item_.lock())
|
||||
workingItem->setFunction(0, value == Qt::Checked);
|
||||
else disable();
|
||||
}
|
||||
|
||||
void ItemWidget::f2(int value)
|
||||
{
|
||||
if(auto workingItem = item_.lock())
|
||||
workingItem->setFunction(1, value == Qt::Checked);
|
||||
else disable();
|
||||
}
|
||||
|
||||
|
||||
void ItemWidget::f3(int value)
|
||||
{
|
||||
if(auto workingItem = item_.lock())
|
||||
workingItem->setFunction(2, value == Qt::Checked);
|
||||
else disable();
|
||||
}
|
||||
|
||||
void ItemWidget::f4(int value)
|
||||
{
|
||||
if(auto workingItem = item_.lock())
|
||||
workingItem->setFunction(3, value == Qt::Checked);
|
||||
else disable();
|
||||
}
|
||||
|
||||
void ItemWidget::reverse()
|
||||
{
|
||||
if(auto workingItem = item_.lock())
|
||||
{
|
||||
Train* train = dynamic_cast<Train*>(workingItem.get());
|
||||
if(train && workingItem->getValue() == 0)
|
||||
train->reverse();
|
||||
else
|
||||
{
|
||||
setValue(!((bool)workingItem->getValue()));
|
||||
}
|
||||
}
|
||||
else disable();
|
||||
}
|
||||
|
||||
void ItemWidget::disable()
|
||||
{
|
||||
ui->checkBox_f1->setEnabled(false);
|
||||
ui->checkBox_f2->setEnabled(false);
|
||||
ui->checkBox_f3->setEnabled(false);
|
||||
ui->checkBox_f4->setEnabled(false);
|
||||
ui->label->setEnabled(false);
|
||||
ui->slider->setEnabled(false);
|
||||
ui->pushButton_reverse->setEnabled(false);
|
||||
}
|
||||
|
||||
bool ItemWidget::controles(const ItemData& relay)
|
||||
{
|
||||
if(auto workingRelay = item_.lock())
|
||||
{
|
||||
if(relay == *workingRelay)
|
||||
return true;
|
||||
else
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
void ItemWidget::stepUp()
|
||||
{
|
||||
setValue(ui->slider->value()+1);
|
||||
}
|
||||
|
||||
void ItemWidget::stepDown()
|
||||
{
|
||||
setValue(ui->slider->value()-1);
|
||||
}
|
||||
|
||||
void ItemWidget::setShortcuts(QKeySequence up, QKeySequence down, QKeySequence rev)
|
||||
{
|
||||
shortcuts_.clear();
|
||||
shortcuts_.push_back(std::unique_ptr<QShortcut>(new QShortcut(up, this)));
|
||||
connect(shortcuts_.back().get(), &QShortcut::activated, this, &ItemWidget::stepUp);
|
||||
shortcuts_.push_back(std::unique_ptr<QShortcut>(new QShortcut(down, this)));
|
||||
connect(shortcuts_.back().get(), &QShortcut::activated, this, &ItemWidget::stepDown);
|
||||
shortcuts_.push_back(std::unique_ptr<QShortcut>(new QShortcut(rev, this)));
|
||||
connect(shortcuts_.back().get(), &QShortcut::activated, this, &ItemWidget::reverse);
|
||||
}
|
||||
|
||||
std::weak_ptr<Item> ItemWidget::getItem()
|
||||
{
|
||||
return item_;
|
||||
}
|
||||
|
||||
void ItemWidget::stateChanged(int state)
|
||||
{
|
||||
qDebug()<<"widget got state "<<state;
|
||||
ui->slider->blockSignals(true);
|
||||
ui->slider->setValue(state);
|
||||
ui->slider->blockSignals(false);
|
||||
}
|
||||
|
||||
ItemWidget::~ItemWidget()
|
||||
{
|
||||
delete ui;
|
||||
}
|
@ -1,57 +0,0 @@
|
||||
#ifndef RELAYWIDGET_H
|
||||
#define RELAYWIDGET_H
|
||||
|
||||
#include <QWidget>
|
||||
#include <memory>
|
||||
#include <QShortcut>
|
||||
#include "itemsettingsdialog.h"
|
||||
#include "../items/item.h"
|
||||
|
||||
namespace Ui {
|
||||
class ItemWidget;
|
||||
}
|
||||
|
||||
class ItemWidget : public QWidget
|
||||
{
|
||||
Q_OBJECT
|
||||
private:
|
||||
std::weak_ptr<Item> item_;
|
||||
|
||||
std::vector< std::unique_ptr<QShortcut> > shortcuts_;
|
||||
|
||||
void disable();
|
||||
|
||||
signals:
|
||||
|
||||
void deleteRequest(const ItemData& item);
|
||||
|
||||
private slots:
|
||||
void setValue(int8_t value);
|
||||
void moveToValue(int8_t value);
|
||||
void deleteItem();
|
||||
|
||||
void stepUp();
|
||||
void stepDown();
|
||||
|
||||
void f1(int state);
|
||||
void f2(int state);
|
||||
void f3(int state);
|
||||
void f4(int state);
|
||||
void reverse();
|
||||
|
||||
public:
|
||||
explicit ItemWidget(std::weak_ptr<Item> item, QWidget *parent);
|
||||
std::weak_ptr<Item> getItem();
|
||||
bool controles(const ItemData& relay);
|
||||
~ItemWidget();
|
||||
void setShortcuts(QKeySequence up, QKeySequence down, QKeySequence rev);
|
||||
|
||||
public slots:
|
||||
|
||||
void stateChanged(int state);
|
||||
|
||||
private:
|
||||
Ui::ItemWidget *ui;
|
||||
};
|
||||
|
||||
#endif // RELAYWIDGET_H
|
@ -1,45 +0,0 @@
|
||||
#include "mainwindow.h"
|
||||
#include "ui_mainwindow.h"
|
||||
#include "itemscrollbox.h"
|
||||
#include "itemsettingsdialog.h"
|
||||
#include "itemcreationdialog.h"
|
||||
|
||||
MainWindow::MainWindow(Microcontroller * const micro, ItemStore* items, QWidget *parent) :
|
||||
QMainWindow(parent),
|
||||
stopShort(QKeySequence(Qt::Key_Space), this),
|
||||
ui(new Ui::MainWindow),
|
||||
_micro(micro)
|
||||
{
|
||||
ui->setupUi(this);
|
||||
|
||||
connect(&stopShort, &QShortcut::activated, _micro, &Microcontroller::estop);
|
||||
connect(ui->pushButton_stop, &QPushButton::clicked, _micro, &Microcontroller::estop);
|
||||
connect(ui->pushButton_refesh, &QPushButton::clicked, _micro, &Microcontroller::requestState);
|
||||
|
||||
connect(items, &ItemStore::itemAdded, ui->relayList, &ItemScrollBox::addItem);
|
||||
connect(items, &ItemStore::itemDeleted, ui->relayList, &ItemScrollBox::removeItem);
|
||||
|
||||
for(size_t i = 0; i < items->getItems()->size(); ++i)
|
||||
{
|
||||
ui->relayList->addItem(items->getItems()->at(i));
|
||||
}
|
||||
|
||||
connect(ui->relayList, &ItemScrollBox::deleteRequest, items, &ItemStore::removeItem);
|
||||
}
|
||||
|
||||
MainWindow::~MainWindow()
|
||||
{
|
||||
delete ui;
|
||||
}
|
||||
|
||||
/*
|
||||
void MainWindow::showItemCreationDialog()
|
||||
{
|
||||
ItemCreationDialog diag(this);
|
||||
diag.show();
|
||||
if(diag.exec())
|
||||
{
|
||||
createdItem(diag.item);
|
||||
}
|
||||
}
|
||||
*/
|
@ -1,65 +0,0 @@
|
||||
#-------------------------------------------------
|
||||
#
|
||||
# Project created by QtCreator 2017-06-01T22:31:38
|
||||
#
|
||||
#-------------------------------------------------
|
||||
|
||||
QT += core gui widgets network serialport
|
||||
|
||||
TARGET = traincontrollerui
|
||||
TEMPLATE = app
|
||||
|
||||
INCLUDEPATH += /usr/include/libnl3/
|
||||
INCLUDEPATH += /usr/include/SDL2/
|
||||
|
||||
LIBS += -lnl-3 -lnl-genl-3 -lSDL2
|
||||
|
||||
# The following define makes your compiler emit warnings if you use
|
||||
# any feature of Qt which as been marked as deprecated (the exact warnings
|
||||
# depend on your compiler). Please consult the documentation of the
|
||||
# deprecated API in order to know how to port your code away from it.
|
||||
DEFINES += QT_DEPRECATED_WARNINGS
|
||||
DEFINES += SDL_SUPPORTED
|
||||
|
||||
QMAKE_CXXFLAGS += -std=c++17 -O2
|
||||
|
||||
SOURCES += \
|
||||
src/items/train.cpp \
|
||||
src/items/turnout.cpp \
|
||||
src/mainobject.cpp \
|
||||
src/trainjs.cpp \
|
||||
src/QJoysticks.cpp \
|
||||
src/jsbackend/SDL_Joysticks.cpp \
|
||||
src/jsbackend/VirtualJoystick.cpp \
|
||||
src/ui/itemwidget.cpp \
|
||||
src/ui/itemscrollbox.cpp \
|
||||
src/ui/mainwindow.cpp \
|
||||
src/items/item.cpp \
|
||||
src/items/itemstore.cpp\
|
||||
src/main.cpp \
|
||||
src/microcontroller.cpp
|
||||
|
||||
HEADERS += \
|
||||
src/items/train.h \
|
||||
src/items/turnout.h \
|
||||
src/mainobject.h \
|
||||
src/trainjs.h \
|
||||
src/QJoysticks.h \
|
||||
src/jsbackend/SDL_Joysticks.h \
|
||||
src/jsbackend/VirtualJoystick.h \
|
||||
src/jsbackend/JoysticksCommon.h \
|
||||
src/ui/itemwidget.h \
|
||||
src/ui/itemscrollbox.h \
|
||||
src/ui/mainwindow.h \
|
||||
src/items/item.h \
|
||||
src/items/itemstore.h
|
||||
|
||||
HEADERS += \
|
||||
src/microcontroller.h \
|
||||
|
||||
INCLUDEPATH += src/ui/
|
||||
|
||||
FORMS += \
|
||||
src/ui/mainwindow.ui \
|
||||
src/ui/relayscrollbox.ui \
|
||||
src/ui/itemwidget.ui
|
Loading…
x
Reference in New Issue
Block a user