mirror of https://github.com/OpenMW/openmw.git
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.
216 lines
5.9 KiB
C++
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);
|
|
}
|