#include "devicemodel.h" #include "telldusgui.h" #include #include #include #include #include #include #ifdef _WINDOWS inline double round(double x) { return floor(x + 0.5); } #endif const int SUPPORTED_METHODS = TELLSTICK_TURNON | TELLSTICK_TURNOFF | TELLSTICK_BELL | TELLSTICK_DIM | TELLSTICK_LEARN | TELLSTICK_EXECUTE | TELLSTICK_UP | TELLSTICK_DOWN | TELLSTICK_STOP; DeviceModel::DeviceModel(QObject *parent) :QAbstractTableModel(parent) { connect(this, SIGNAL(deviceChange(int,int,int)), this, SLOT(deviceChanged(int,int,int)), Qt::QueuedConnection); int numberOfDevices = tdGetNumberOfDevices(); errorNo = 0; if (numberOfDevices < 0) { //Error errorNo = numberOfDevices; } for( int i = 0; i < numberOfDevices; ++i ) { int id = tdGetDeviceId(i); Device *device = new Device(id, SUPPORTED_METHODS, this); connect(device, SIGNAL(showMessage(QString,QString,QString)), this, SIGNAL(showMessage(QString,QString,QString))); devices.append(device); connect(device, SIGNAL(stateChanged(int)), this, SLOT(deviceStateChanged(int)), Qt::QueuedConnection); connect(device, SIGNAL(nameChanged(int,QString)), this, SLOT(nameChanged(int,QString)), Qt::QueuedConnection); } deviceChangeCallbackId = tdRegisterDeviceChangeEvent( reinterpret_cast(&DeviceModel::deviceChangeEvent), this); } DeviceModel::~DeviceModel() { tdUnregisterCallback(deviceChangeCallbackId); } int DeviceModel::rowCount(const QModelIndex &) const { return devices.size(); } int DeviceModel::columnCount(const QModelIndex &) const { return 3; } QVariant DeviceModel::data(const QModelIndex &index, int role) const { if (index.column() > 2) { return QVariant(); } if (index.row() >= devices.size()) { return QVariant(); } if (index.column() == 0) { if (role == Qt::DisplayRole) { Device *device = devices[index.row()]; switch( device->lastSentCommand() ) { case TELLSTICK_TURNON: return tr("on"); case TELLSTICK_TURNOFF: return tr("off"); case TELLSTICK_UP: return tr("up"); case TELLSTICK_DOWN: return tr("down"); case TELLSTICK_STOP: return tr("stopped"); case TELLSTICK_DIM: int value = (int)round(device->lastSentValue().toFloat()/255*100); return tr("%1%").arg(value); } return tr("unknown %1").arg(device->lastSentCommand()); } else if (role == Qt::DecorationRole) { Device *device = devices[index.row()]; int lastSentCommand = device->lastSentCommand(); return QIcon( QString(":/images/state_%1.png").arg(lastSentCommand) ); } else if (role == Qt::TextAlignmentRole) { return Qt::AlignCenter; } } else if (index.column() == 1) { if (role == Qt::DisplayRole) { return devices[index.row()]->name(); } // } else if (index.column() == 2) { // if (role == Qt::DisplayRole) { // return devices[index.row()]->methods(); // } } return QVariant(); } QVariant DeviceModel::headerData ( int section, Qt::Orientation orientation, int role ) const { if (orientation != Qt::Horizontal) { return QVariant(); } if (role != Qt::DisplayRole) { return QVariant(); } switch (section) { case 0: return tr("State"); case 1: return tr("Device name"); case 2: return tr("Action"); } return QVariant(); } bool DeviceModel::haveError() const { return errorNo != 0; } QString DeviceModel::errorString() const { char *error = tdGetErrorString(errorNo); QString errorStr = QString::fromUtf8( error ); tdReleaseString(error); return errorStr; } Device *DeviceModel::device( const QModelIndex &index ) { if (index.row() >= devices.size()) { return 0; } return devices[index.row()]; } int DeviceModel::deviceId( const QModelIndex &index ) { if (index.row() >= devices.size()) { return 0; } return devices[index.row()]->id(); } void DeviceModel::deviceStateChanged( int deviceId ) { int row = rowForId(deviceId); if (row >= 0) { triggerCellUpdate(row, 0); } } void DeviceModel::deviceChanged( int deviceId, int eventType, int changeType ) { if (eventType == TELLSTICK_DEVICE_ADDED) { int deviceCount = devices.size(); beginInsertRows( QModelIndex(), deviceCount, deviceCount ); Device *device = new Device(deviceId, SUPPORTED_METHODS); //We are not running in the DeviceModel-thread here. Move the device to the correct thread device->moveToThread(this->thread()); device->setParent(this); connect(device, SIGNAL(showMessage(QString,QString,QString)), this, SIGNAL(showMessage(QString,QString,QString))); devices.append(device); connect(device, SIGNAL(stateChanged(int)), this, SLOT(deviceStateChanged(int))); connect(device, SIGNAL(nameChanged(int,QString)), this, SLOT(nameChanged(int,QString))); endInsertRows(); } else if (eventType == TELLSTICK_DEVICE_REMOVED) { int row = rowForId(deviceId); if (row >= 0) { beginRemoveRows( QModelIndex(), row, row ); Device *d = devices.takeAt(row); delete d; endRemoveRows(); } } } void DeviceModel::nameChanged(int deviceId, const QString &) { int row = rowForId(deviceId); if (row >= 0) { triggerCellUpdate(row, 1); } } void DeviceModel::triggerCellUpdate(int row, int column) { QModelIndex index = this->index(row, column); emit dataChanged( index, index ); } int DeviceModel::rowForId( int deviceId ) const { for (int i = 0; i < devices.size(); ++i) { if (devices.at(i)->id() == deviceId) { return i; } } return -1; } void WINAPI DeviceModel::deviceChangeEvent(int deviceId, int eventId, int changeType, int, void *context) { DeviceModel *model = reinterpret_cast(context); if (!model) { return; } emit model->deviceChange(deviceId, eventId, changeType); } /*void DeviceModel::connectDeviceSignals( Device *device ) const { connect(device, SIGNAL(showMessage(const QString &, const QString &, const QString &)), this, SIGNAL(showMessage(const QString &, const QString &, const QString &))); connect(device, SIGNAL(eventTriggered(const QString &, const QString &)), this, SIGNAL(eventTriggered(const QString &, const QString &))); connect(device, SIGNAL(stateChanged(int, int)), this, SLOT(deviceStateChanged(int,int))); connect(device, SIGNAL(deviceChanged(int,int,int)), this, SLOT(deviceChanged(int,int,int))); }*/