/* Copyright (C) 2010 Srivats P. This file is part of "Ostinato" This is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see */ #include "portmodel.h" #include "portgrouplist.h" #include #include #include #if 0 #define DBG0(x) qDebug(x) #define DBG1(x, p1) qDebug(x, (p1)) #else #define DBG0(x) {} #define DBG1(x, p1) {} #endif PortModel::PortModel(PortGroupList *p, QObject *parent) : QAbstractItemModel(parent) { pgl = p; } int PortModel::rowCount(const QModelIndex &parent) const { // qDebug("RowCount Enter\n"); if (!parent.isValid()) { // Top Level Item //qDebug("RowCount (Top) Exit: %d\n", pgl->mPortGroups.size()); return pgl->mPortGroups.size(); } // qDebug("RowCount non top %d, %d, %llx\n", // parent.row(), parent.column(), parent.internalId()); quint16 pg = (parent.internalId() >> 16) & 0xFFFF; quint16 p = parent.internalId() & 0xFFFF; if (p == 0xFFFF) { #if 0 // wrong code? int count = 0; foreach(PortGroup *pg, pgl->mPortGroups) { count += pg->numPorts(); } //qDebug("RowCount (Mid) Exit: %d\n", count); return count; #endif if (parent.column() == 0) return pgl->mPortGroups.value(pgl->indexOfPortGroup(pg))->numPorts(); else return 0; } else { // Leaf Item return 0; } } int PortModel::columnCount(const QModelIndex &/*parent*/) const { return 1; // FIXME: hardcoding } Qt::ItemFlags PortModel::flags(const QModelIndex &index) const { return QAbstractItemModel::flags(index); // FIXME: no need for this func } QVariant PortModel::data(const QModelIndex &index, int role) const { DBG0("Enter PortModel data\n"); // Check for a valid index if (!index.isValid()) return QVariant(); DBG1("PortModel::data(index).row = %d", index.row()); DBG1("PortModel::data(index).column = %0d", index.column()); DBG1("PortModel::data(index).internalId = %08llx", index.internalId()); QModelIndex parent = index.parent(); if (!parent.isValid()) { // Top Level Item - PortGroup if (role == Qt::DisplayRole) { DBG0("Exit PortModel data 1\n"); return QString("Port Group %1: %2 [%3]:%4 (%5)"). arg(pgl->mPortGroups.at(index.row())->id()). arg(pgl->mPortGroups.at(index.row())->userAlias()). arg(pgl->mPortGroups.at(index.row())->serverName()). arg(pgl->mPortGroups.at(index.row())->serverPort()). arg(pgl->mPortGroups.value(index.row())->numPorts()); } else if (role == Qt::DecorationRole) { DBG0("Exit PortModel data 2\n"); switch(pgl->mPortGroups.at(index.row())->state()) { case QAbstractSocket::UnconnectedState: return QIcon(":/icons/bullet_red.png"); case QAbstractSocket::HostLookupState: return QIcon(":/icons/bullet_yellow.png"); case QAbstractSocket::ConnectingState: case QAbstractSocket::ClosingState: return QIcon(":/icons/bullet_orange.png"); case QAbstractSocket::ConnectedState: return QIcon(":/icons/bullet_green.png"); case QAbstractSocket::BoundState: case QAbstractSocket::ListeningState: default: return QIcon(":/icons/bullet_error.png"); } } else { DBG0("Exit PortModel data 3\n"); return QVariant(); } } else { if (pgl->mPortGroups.at(parent.row())->numPorts() == 0) { DBG0("Exit PortModel data 4\n"); return QVariant(); } Port *port = pgl->mPortGroups.at(parent.row())->mPorts[index.row()]; // Non Top Level - Port if (role == Qt::DisplayRole) { QString rsvdBy; if (!port->userName().isEmpty()) rsvdBy = "["+port->userName()+"] "; return QString("Port %1: %2 %3(%4)") .arg(port->id()) .arg(port->userAlias()) .arg(rsvdBy) .arg(port->description()); } else if (role == Qt::DecorationRole) { return statusIcon( port->linkState(), port->hasExclusiveControl(), port->isTransmitting(), port->isCapturing()); } else if (role == Qt::ForegroundRole) { return port->isDirty() ? QBrush(Qt::red) : QVariant(); } else { DBG0("Exit PortModel data 6\n"); return QVariant(); } } return QVariant(); } QVariant PortModel::headerData(int /*section*/, Qt::Orientation orientation, int role) const { if (role != Qt::DisplayRole) return QVariant(); if (orientation == Qt::Horizontal) return QVariant(); else return QString("Name"); } Qt::DropActions PortModel::supportedDropActions() const { return Qt::IgnoreAction; // read-only model, doesn't accept any data } QModelIndex PortModel::index (int row, int col, const QModelIndex & parent) const { if (!hasIndex(row, col, parent)) return QModelIndex(); //qDebug("index: R=%d, C=%d, PR=%d, PC=%d, PID=%llx\n", // row, col, parent.row(), parent.column(), parent.internalId()); if (!parent.isValid()) { // Top Level Item quint16 pg = pgl->mPortGroups.value(row)->id(), p = 0xFFFF; quint32 id = (pg << 16) | p; //qDebug("index (top) dbg: PG=%d, P=%d, ID=%x\n", pg, p, id); return createIndex(row, col, id); } else { quint16 pg = parent.internalId() >> 16; quint16 p = pgl->mPortGroups.value(parent.row())->mPorts.value(row)->id(); quint32 id = (pg << 16) | p; //qDebug("index (nontop) dbg: PG=%d, P=%d, ID=%x\n", pg, p, id); return createIndex(row, col, id); } } QModelIndex PortModel::parent(const QModelIndex &index) const { if (!index.isValid()) return QModelIndex(); //qDebug("parent: R=%d, C=%d ID=%llx\n", // index.row(), index.column(), index.internalId()); quint16 pg = index.internalId() >> 16; quint16 p = index.internalId() & 0x0000FFFF; //qDebug("parent dbg: PG=%d, P=%d\n", pg, p); if (p == 0xFFFF) { //qDebug("parent ret: NULL\n"); // Top Level Item - PG return QModelIndex(); } quint32 id = (pg << 16) | 0xFFFF; //qDebug("parent ret: R=%d, C=%d, ID=%x\n", pg, 0, id); return createIndex(pgl->indexOfPortGroup(pg), 0, id); } bool PortModel::isPortGroup(const QModelIndex& index) { if (index.isValid() && ((index.internalId() & 0xFFFF) == 0xFFFF)) return true; else return false; } bool PortModel::isPort(const QModelIndex& index) { if (index.isValid() && ((index.internalId() & 0xFFFF) != 0xFFFF)) return true; else return false; } quint32 PortModel::portGroupId(const QModelIndex& index) { return (index.internalId()) >> 16 & 0xFFFF; } quint32 PortModel::portId(const QModelIndex& index) { return (index.internalId()) & 0xFFFF; } QPixmap PortModel::statusIcon( int linkState, bool exclusive, bool transmit, bool capture) const { QPixmap pixmap; QString key = QString("$ost:portStatusIcon:%1:%2:%3:%4") .arg(linkState).arg(exclusive).arg(transmit).arg(capture); if (QPixmapCache::find(key, pixmap)) return pixmap; static int sz = QPixmap(":/icons/frag_link_up.png").width(); // All frag_* icons must be of same size and can be overlayed // on top of each other; assume square icons pixmap = QPixmap(sz, sz); pixmap.fill(Qt::transparent); QPainter painter(&pixmap); switch (linkState) { case OstProto::LinkStateUp: painter.drawPixmap(0, 0, QPixmap(":/icons/frag_link_up.png")); break; case OstProto::LinkStateDown: painter.drawPixmap(0, 0, QPixmap(":/icons/frag_link_down.png")); break; case OstProto::LinkStateUnknown: painter.drawPixmap(0, 0, QPixmap(":/icons/frag_link_unknown.png")); break; } if (exclusive) painter.drawPixmap(0, 0, QPixmap(":/icons/frag_exclusive.png")); if (transmit) painter.drawPixmap(0, 0, QPixmap(":/icons/frag_transmit.png")); if (capture) painter.drawPixmap(0, 0, QPixmap(":/icons/frag_capture.png")); QPixmapCache::insert(key, pixmap); return pixmap; } // ---------------------------------------------- // Slots // ---------------------------------------------- void PortModel::when_portGroupDataChanged(int portGroupId, int portId) { QModelIndex index; int row; qDebug("portGroupId = %d, portId = %d", portGroupId, portId); if (portId == 0xFFFF) row = pgl->indexOfPortGroup(portGroupId); else row = portId; index = createIndex(row, 0, (portGroupId << 16) | portId); emit dataChanged(index, index); } void PortModel::portGroupAboutToBeAppended() { int row; row = pgl->mPortGroups.size(); beginInsertRows(QModelIndex(), row, row); } void PortModel::portGroupAppended() { endInsertRows(); } void PortModel::portGroupAboutToBeRemoved(PortGroup *portGroup) { int row; row = pgl->mPortGroups.indexOf(portGroup); beginRemoveRows(QModelIndex(), row, row); } void PortModel::portGroupRemoved() { endRemoveRows(); } void PortModel::when_portListChanged() { // FIXME: why needed? beginResetModel(); endResetModel(); }