You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
openmw/apps/opencs/view/world/datadisplaydelegate.cpp

216 lines
5.9 KiB
C++

#include "datadisplaydelegate.hpp"
#include "../../model/prefs/state.hpp"
#include <QApplication>
#include <QIcon>
#include <QPainter>
#include <QRect>
#include <QSize>
#include <QString>
#include <QStyle>
#include <memory>
#include <apps/opencs/model/prefs/category.hpp>
#include <apps/opencs/model/prefs/setting.hpp>
#include <apps/opencs/view/world/enumdelegate.hpp>
#include <apps/opencs/view/world/util.hpp>
#include <components/misc/scalableicon.hpp>
class QModelIndex;
class QObject;
namespace CSMDoc
{
class Document;
}
namespace CSMWorld
{
class CommandDispatcher;
}
CSVWorld::DataDisplayDelegate::DataDisplayDelegate(const ValueList& values, const IconList& icons,
CSMWorld::CommandDispatcher* dispatcher, CSMDoc::Document& document, const std::string& pageName,
const std::string& settingName, QObject* parent)
: EnumDelegate(values, dispatcher, document, parent)
, mDisplayMode(Mode_TextOnly)
, mIcons(icons)
, mIconSize(QSize(16, 16))
, mHorizontalMargin(QApplication::style()->pixelMetric(QStyle::PM_FocusFrameHMargin) + 1)
, mTextLeftOffset(8)
, mPixmapsColor(QApplication::palette().text().color())
, mUiScale(static_cast<QGuiApplication*>(QGuiApplication::instance())->devicePixelRatio())
, mSettingKey(pageName + '/' + settingName)
{
if (parent)
parent->installEventFilter(this);
buildPixmaps();
if (!pageName.empty())
updateDisplayMode(CSMPrefs::get()[pageName][settingName].toString());
}
bool CSVWorld::DataDisplayDelegate::eventFilter(QObject* target, QEvent* event)
{
if (event->type() == QEvent::Resize)
{
auto uiScale = static_cast<QGuiApplication*>(QGuiApplication::instance())->devicePixelRatio();
if (mUiScale != uiScale)
{
mUiScale = uiScale;
buildPixmaps();
}
}
else if (event->type() == QEvent::PaletteChange)
{
QColor themeColor = QApplication::palette().text().color();
if (themeColor != mPixmapsColor)
{
mPixmapsColor = std::move(themeColor);
buildPixmaps();
}
}
return false;
}
void CSVWorld::DataDisplayDelegate::buildPixmaps()
{
if (!mPixmaps.empty())
mPixmaps.clear();
IconList::iterator it = mIcons.begin();
while (it != mIcons.end())
{
mPixmaps.emplace_back(it->mValue, it->mIcon.pixmap(mIconSize));
++it;
}
}
void CSVWorld::DataDisplayDelegate::setIconSize(const QSize& size)
{
mIconSize = size;
buildPixmaps();
}
void CSVWorld::DataDisplayDelegate::setTextLeftOffset(int offset)
{
mTextLeftOffset = offset;
}
QSize CSVWorld::DataDisplayDelegate::sizeHint(const QStyleOptionViewItem& option, const QModelIndex& index) const
{
QSize size = EnumDelegate::sizeHint(option, index);
int valueIndex = getValueIndex(index);
if (valueIndex != -1)
{
if (mDisplayMode == Mode_IconOnly)
{
size.setWidth(mIconSize.width() + 2 * mHorizontalMargin);
}
else if (mDisplayMode == Mode_IconAndText)
{
size.setWidth(size.width() + mIconSize.width() + mTextLeftOffset);
}
if (mDisplayMode != Mode_TextOnly)
{
size.setHeight(qMax(size.height(), mIconSize.height()));
}
}
return size;
}
void CSVWorld::DataDisplayDelegate::paint(
QPainter* painter, const QStyleOptionViewItem& option, const QModelIndex& index) const
{
painter->save();
// default to enum delegate's paint method for text-only conditions
if (mDisplayMode == Mode_TextOnly)
EnumDelegate::paint(painter, option, index);
else
{
int valueIndex = getValueIndex(index);
if (valueIndex != -1)
{
paintIcon(painter, option, valueIndex);
}
}
painter->restore();
}
void CSVWorld::DataDisplayDelegate::paintIcon(QPainter* painter, const QStyleOptionViewItem& option, int index) const
{
QRect iconRect = option.rect;
QRect textRect = iconRect;
iconRect.setLeft(iconRect.left() + mHorizontalMargin);
iconRect.setRight(option.rect.right() - mHorizontalMargin);
if (mDisplayMode == Mode_IconAndText)
{
iconRect.setWidth(mIconSize.width());
textRect.setLeft(iconRect.right() + mTextLeftOffset);
textRect.setRight(option.rect.right() - mHorizontalMargin);
QString text = option.fontMetrics.elidedText(mValues.at(index).second, option.textElideMode, textRect.width());
QApplication::style()->drawItemText(
painter, textRect, Qt::AlignLeft | Qt::AlignVCenter, option.palette, true, text);
}
QApplication::style()->drawItemPixmap(painter, iconRect, Qt::AlignCenter, mPixmaps.at(index).second);
}
void CSVWorld::DataDisplayDelegate::updateDisplayMode(const std::string& mode)
{
if (mode == "Icon and Text")
mDisplayMode = Mode_IconAndText;
else if (mode == "Icon Only")
mDisplayMode = Mode_IconOnly;
else if (mode == "Text Only")
mDisplayMode = Mode_TextOnly;
}
void CSVWorld::DataDisplayDelegate::settingChanged(const CSMPrefs::Setting* setting)
{
if (*setting == mSettingKey)
updateDisplayMode(setting->toString());
}
void CSVWorld::DataDisplayDelegateFactory::add(int enumValue, const QString& enumName, const QString& iconFilename)
{
EnumDelegateFactory::add(enumValue, enumName);
Icon icon;
icon.mValue = enumValue;
icon.mName = enumName;
icon.mIcon = Misc::ScalableIcon::load(iconFilename);
for (auto it = mIcons.begin(); it != mIcons.end(); ++it)
{
if (it->mName > enumName)
{
mIcons.insert(it, icon);
return;
}
}
mIcons.push_back(icon);
}
CSVWorld::CommandDelegate* CSVWorld::DataDisplayDelegateFactory::makeDelegate(
CSMWorld::CommandDispatcher* dispatcher, CSMDoc::Document& document, QObject* parent) const
{
return new DataDisplayDelegate(mValues, mIcons, dispatcher, document, "", "", parent);
}