Skip to content

Commit

Permalink
Issue #68: Added a colored box around an item to indicate an error
Browse files Browse the repository at this point in the history
This along with the text displayed in red when not selected, indicates there is an error in the item.
  • Loading branch information
christophe-calmejane committed Jul 30, 2019
1 parent bc61ad6 commit 26fe660
Show file tree
Hide file tree
Showing 13 changed files with 122 additions and 62 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Expand Up @@ -29,6 +29,7 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.
### Fixed
- [Splashscreen displayed on the same screen than Hive will be shown](https://github.com/christophe-calmejane/Hive/issues/20)
- Refresh issue when gPTP changes for some non-milan devices
- [Red text no longer applied when item is selected (fixed by using a colored box around the item)](https://github.com/christophe-calmejane/Hive/issues/68)

## [1.1.0] - 2019-05-21
### Added
Expand Down
4 changes: 2 additions & 2 deletions src/CMakeLists.txt
Expand Up @@ -127,7 +127,7 @@ set(HEADER_FILES_COMMON
controlledEntityTreeWidget.hpp
entityInspector.hpp
entityLogoCache.hpp
highlightForegroundItemDelegate.hpp
errorItemDelegate.hpp
imageItemDelegate.hpp
mappingMatrix.hpp
activeNetworkInterfaceModel.hpp
Expand Down Expand Up @@ -206,7 +206,7 @@ set(SOURCE_FILES_COMMON
settingsDialog.cpp
aecpCommandComboBox.cpp
entityLogoCache.cpp
highlightForegroundItemDelegate.cpp
errorItemDelegate.cpp
imageItemDelegate.cpp
controlledEntityTreeWidget.cpp
entityInspector.cpp
Expand Down
40 changes: 26 additions & 14 deletions src/avdecc/controllerModel.cpp
Expand Up @@ -19,16 +19,21 @@

#include "controllerModel.hpp"
#include "helper.hpp"
#include <la/avdecc/utils.hpp>
#include <la/avdecc/logger.hpp>
#include "entityLogoCache.hpp"
#include "imageItemDelegate.hpp"
#include "errorItemDelegate.hpp"
#include "avdecc/controllerManager.hpp"
#include "avdecc/mcDomainManager.hpp"
#include "entityLogoCache.hpp"
#include "settingsManager/settings.hpp"
#include "toolkit/material/color.hpp"

#include <la/avdecc/utils.hpp>
#include <la/avdecc/logger.hpp>

#include <QFont>

#include <algorithm>
#include <array>
#include <QFont>
#include <set>
#include <unordered_map>
#include <unordered_set>
Expand Down Expand Up @@ -318,15 +323,22 @@ class ControllerModelPrivate : public QObject, private settings::SettingsManager
}
else if (column == ControllerModel::Column::EntityID)
{
if (role == Qt::ForegroundRole)
if (role == ErrorItemDelegate::ErrorRole || role == Qt::ForegroundRole)
{
auto const it = _entitiesWithErrorCounter.find(entityID);
if (it != std::end(_entitiesWithErrorCounter))
{
auto const& entityWithErrorCounter{ it->second };
if (entityWithErrorCounter.hasError())
{
return qt::toolkit::material::color::value(qt::toolkit::material::color::Name::Red);
if (role == ErrorItemDelegate::ErrorRole)
{
return true;
}
else if (role == Qt::ForegroundRole)
{
return qt::toolkit::material::color::value(qt::toolkit::material::color::Name::Red);
}
}
}
}
Expand All @@ -339,7 +351,7 @@ class ControllerModelPrivate : public QObject, private settings::SettingsManager
}
else if (column == ControllerModel::Column::EntityLogo)
{
if (role == Qt::UserRole)
if (role == ImageItemDelegate::ImageRole)
{
if (data.aemSupported)
{
Expand All @@ -356,7 +368,7 @@ class ControllerModelPrivate : public QObject, private settings::SettingsManager
{
switch (role)
{
case Qt::UserRole:
case ImageItemDelegate::ImageRole:
{
try
{
Expand Down Expand Up @@ -389,7 +401,7 @@ class ControllerModelPrivate : public QObject, private settings::SettingsManager
{
switch (role)
{
case Qt::UserRole:
case ImageItemDelegate::ImageRole:
{
try
{
Expand All @@ -411,7 +423,7 @@ class ControllerModelPrivate : public QObject, private settings::SettingsManager
{
switch (role)
{
case Qt::UserRole:
case ImageItemDelegate::ImageRole:
{
try
{
Expand Down Expand Up @@ -722,7 +734,7 @@ class ControllerModelPrivate : public QObject, private settings::SettingsManager
data.acquireState = computeAcquireState(acquireState);
data.acquireStateTooltip = helper::acquireStateToString(acquireState, owningEntity);

dataChanged(*row, ControllerModel::Column::AcquireState, { Qt::UserRole });
dataChanged(*row, ControllerModel::Column::AcquireState, { ImageItemDelegate::ImageRole });
}
}

Expand All @@ -735,7 +747,7 @@ class ControllerModelPrivate : public QObject, private settings::SettingsManager
data.lockState = computeLockState(lockState);
data.lockStateTooltip = helper::lockStateToString(lockState, lockingEntity);

dataChanged(*row, ControllerModel::Column::LockState, { Qt::UserRole });
dataChanged(*row, ControllerModel::Column::LockState, { ImageItemDelegate::ImageRole });
}
}

Expand Down Expand Up @@ -847,7 +859,7 @@ class ControllerModelPrivate : public QObject, private settings::SettingsManager
{
if (auto const row = entityRow(entityID))
{
dataChanged(*row, ControllerModel::Column::EntityLogo, { Qt::UserRole });
dataChanged(*row, ControllerModel::Column::EntityLogo, { ImageItemDelegate::ImageRole });
}
}
}
Expand All @@ -866,7 +878,7 @@ class ControllerModelPrivate : public QObject, private settings::SettingsManager
auto const topLeft = q->createIndex(0, column, nullptr);
auto const bottomRight = q->createIndex(rowCount(), column, nullptr);

emit q->dataChanged(topLeft, bottomRight, { Qt::UserRole });
emit q->dataChanged(topLeft, bottomRight, { ImageItemDelegate::ImageRole });
}
}
}
Expand Down
2 changes: 1 addition & 1 deletion src/connectionMatrix/model.hpp
Expand Up @@ -20,7 +20,7 @@
#pragma once

// Debugging options
#define ENABLE_CONNECTION_MATRIX_DEBUG 1
//#define ENABLE_CONNECTION_MATRIX_DEBUG 1
#define ENABLE_CONNECTION_MATRIX_HIGHLIGHT_DATA_CHANGED 1
#define ENABLE_CONNECTION_MATRIX_TOOLTIP 1

Expand Down
9 changes: 5 additions & 4 deletions src/controlledEntityTreeWidget.cpp
Expand Up @@ -18,13 +18,13 @@
*/

#include "controlledEntityTreeWidget.hpp"

#include <la/avdecc/controller/internals/avdeccControlledEntity.hpp>
#include "avdecc/controllerManager.hpp"
#include "avdecc/helper.hpp"

#include "errorItemDelegate.hpp"
#include "nodeVisitor.hpp"

#include <la/avdecc/controller/internals/avdeccControlledEntity.hpp>

#include <QHeaderView>
#include <QMenu>

Expand Down Expand Up @@ -54,6 +54,7 @@ class NodeItem : public QObject, public QTreeWidgetItem
void setHasError(bool const hasError)
{
_hasError = hasError;
setData(0, ErrorItemDelegate::ErrorRole, _hasError);
setForeground(0, _hasError ? Qt::red : Qt::black);

// Also update the parent node
Expand Down Expand Up @@ -236,7 +237,7 @@ class ControlledEntityTreeWidgetPrivate : public QObject, public la::avdecc::con
return;
}

if (auto* item = findItem({ la::avdecc::entity::model::DescriptorType::Entity, descriptorIndex }))
if (auto* item = findItem({ la::avdecc::entity::model::DescriptorType::StreamInput, descriptorIndex }))
{
item->setHasError(!errorCounters.empty());
}
Expand Down
4 changes: 3 additions & 1 deletion src/entityInspector.cpp
Expand Up @@ -31,12 +31,14 @@ EntityInspector::EntityInspector(QWidget* parent)
_layout.setContentsMargins(0, 0, 0, 0);
_layout.addWidget(&_splitter);

_controlledEntityTreeWiget.setItemDelegate(&_itemDelegate);
_nodeTreeWiget.setItemDelegate(&_itemDelegate);

_splitter.addWidget(&_controlledEntityTreeWiget);
_splitter.addWidget(&_nodeTreeWiget);
_splitter.setStretchFactor(0, 0); // Descriptors List has less weight than
_splitter.setStretchFactor(1, 1); // the Descriptor itself, as far as expand is concerned


_nodeTreeWiget.setColumnCount(2);
_nodeTreeWiget.setHeaderLabels({ "", "" });

Expand Down
1 change: 1 addition & 0 deletions src/entityInspector.hpp
Expand Up @@ -53,4 +53,5 @@ class EntityInspector : public QWidget
QSplitter _splitter{ Qt::Vertical, this };
ControlledEntityTreeWidget _controlledEntityTreeWiget{ this };
NodeTreeWidget _nodeTreeWiget{ this };
ErrorItemDelegate _itemDelegate{ this };
};
63 changes: 63 additions & 0 deletions src/errorItemDelegate.cpp
@@ -0,0 +1,63 @@
/*
* Copyright (C) 2017-2019, Emilien Vallot, Christophe Calmejane and other contributors
* This file is part of Hive.
* Hive is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
* Hive 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 Lesser General Public License for more details.
* You should have received a copy of the GNU Lesser General Public License
* along with Hive. If not, see <http://www.gnu.org/licenses/>.
*/

#include "errorItemDelegate.hpp"
#include "toolkit/material/color.hpp"

ErrorItemDelegate::ErrorItemDelegate(QObject* parent) noexcept
: QStyledItemDelegate(parent)
{
// Configure settings observers
auto& settings = settings::SettingsManager::getInstance();
settings.registerSettingObserver(settings::ThemeColorIndex.name, this);
}

ErrorItemDelegate::~ErrorItemDelegate() noexcept
{
// Remove settings observers
auto& settings = settings::SettingsManager::getInstance();
settings.unregisterSettingObserver(settings::ThemeColorIndex.name, this);
}

void ErrorItemDelegate::paint(QPainter* painter, QStyleOptionViewItem const& option, QModelIndex const& index) const
{
QStyledItemDelegate::paint(painter, option, index);

if (index.data(ErrorRole).toBool())
{
if (option.state & QStyle::StateFlag::State_Selected)
{
painter->setPen(QPen{ qt::toolkit::material::color::complementatyValue(_colorName, qt::toolkit::material::color::Shade::Shade600), 2 });
painter->drawRect(option.rect.adjusted(1, 1, -1, -1));
}
else
{
painter->setPen(qt::toolkit::material::color::value(qt::toolkit::material::color::Name::Red));
painter->drawRect(option.rect.adjusted(0, 0, -1, -1));
}
}
}

void ErrorItemDelegate::onSettingChanged(settings::SettingsManager::Setting const& name, QVariant const& value) noexcept
{
if (name == settings::ThemeColorIndex.name)
{
_colorName = qt::toolkit::material::color::Palette::name(value.toInt());
}
}
Expand Up @@ -19,14 +19,26 @@

#pragma once

#include "settingsManager/settings.hpp"

#include <QStyledItemDelegate>

// This custom delegate allows to keep the Qt::ForegroundRole visible even when a cell is highlighted
class HighlightForegroundItemDelegate : public QStyledItemDelegate
// This custom delegate allows to indicate a cell is on error
class ErrorItemDelegate : public QStyledItemDelegate, private settings::SettingsManager::Observer
{
public:
using QStyledItemDelegate::QStyledItemDelegate;
static constexpr auto ErrorRole = Qt::UserRole + 1;

explicit ErrorItemDelegate(QObject* parent = nullptr) noexcept;
~ErrorItemDelegate() noexcept;

protected:
virtual void paint(QPainter* painter, QStyleOptionViewItem const& option, QModelIndex const& index) const override;

private:
// settings::SettingsManager::Observer overrides
virtual void onSettingChanged(settings::SettingsManager::Setting const& name, QVariant const& value) noexcept override;

// Private members
qt::toolkit::material::color::Name _colorName{ qt::toolkit::material::color::DefaultColor };
};
33 changes: 0 additions & 33 deletions src/highlightForegroundItemDelegate.cpp

This file was deleted.

2 changes: 1 addition & 1 deletion src/imageItemDelegate.cpp
Expand Up @@ -24,7 +24,7 @@ void ImageItemDelegate::paint(QPainter* painter, QStyleOptionViewItem const& opt
{
QStyledItemDelegate::paint(painter, option, index);

auto const userData{ index.data(Qt::UserRole) };
auto const userData{ index.data(ImageRole) };
if (!userData.canConvert<QImage>())
{
return;
Expand Down
1 change: 1 addition & 0 deletions src/imageItemDelegate.hpp
Expand Up @@ -25,6 +25,7 @@ class ImageItemDelegate : public QStyledItemDelegate
{
public:
using QStyledItemDelegate::QStyledItemDelegate;
static constexpr auto ImageRole = Qt::UserRole + 1;

protected:
virtual void paint(QPainter* painter, QStyleOptionViewItem const& option, QModelIndex const& index) const override;
Expand Down
6 changes: 3 additions & 3 deletions src/mainWindow.cpp
Expand Up @@ -54,7 +54,7 @@
#include "aboutDialog.hpp"
#include "deviceDetailsDialog.hpp"
#include "entityLogoCache.hpp"
#include "highlightForegroundItemDelegate.hpp"
#include "errorItemDelegate.hpp"
#include "imageItemDelegate.hpp"
#include "nodeVisitor.hpp"
#include "settingsDialog.hpp"
Expand Down Expand Up @@ -401,8 +401,8 @@ void MainWindowImpl::createControllerView()
controllerTableView->setItemDelegateForColumn(la::avdecc::utils::to_integral(avdecc::ControllerModel::Column::AcquireState), imageItemDelegate);
controllerTableView->setItemDelegateForColumn(la::avdecc::utils::to_integral(avdecc::ControllerModel::Column::LockState), imageItemDelegate);

auto* highlightForegroundItemDelegate{ new HighlightForegroundItemDelegate{ _parent } };
controllerTableView->setItemDelegateForColumn(la::avdecc::utils::to_integral(avdecc::ControllerModel::Column::EntityID), highlightForegroundItemDelegate);
auto* errorItemDelegate{ new ErrorItemDelegate{ _parent } };
controllerTableView->setItemDelegateForColumn(la::avdecc::utils::to_integral(avdecc::ControllerModel::Column::EntityID), errorItemDelegate);

_controllerDynamicHeaderView.setHighlightSections(false);
_controllerDynamicHeaderView.setMandatorySection(la::avdecc::utils::to_integral(avdecc::ControllerModel::Column::EntityID));
Expand Down

0 comments on commit 26fe660

Please sign in to comment.