Merge remote-tracking branch 'smbas/feature-color-picking'

pull/35/head
Marc Zinnschlag 10 years ago
commit d5bc561d17

@ -70,11 +70,12 @@ opencs_units (view/world
opencs_units_noqt (view/world
subviews enumdelegate vartypedelegate recordstatusdelegate idtypedelegate datadisplaydelegate
scripthighlighter idvalidator dialoguecreator physicssystem idcompletiondelegate
colordelegate
)
opencs_units (view/widget
scenetoolbar scenetool scenetoolmode pushbutton scenetooltoggle scenetoolrun modebutton
scenetooltoggle2 completerpopup
scenetooltoggle2 completerpopup coloreditor colorpickerpopup
)
opencs_units (view/render

@ -694,7 +694,7 @@ namespace CSMWorld
QColor colour = data.value<QColor>();
record2.mMapColor = colour.rgb() & 0xffffff;
record2.mMapColor = (colour.blue() << 16) | (colour.green() << 8) | colour.red();
record.setModified (record2);
}

@ -21,6 +21,7 @@
#include "../world/recordstatusdelegate.hpp"
#include "../world/idtypedelegate.hpp"
#include "../world/idcompletiondelegate.hpp"
#include "../world/colordelegate.hpp"
#include "../../model/settings/usersettings.hpp"
@ -61,6 +62,9 @@ CSVDoc::ViewManager::ViewManager (CSMDoc::DocumentManager& documentManager)
mDelegateFactories->add (CSMWorld::ColumnBase::Display_RefRecordType,
new CSVWorld::IdTypeDelegateFactory());
mDelegateFactories->add (CSMWorld::ColumnBase::Display_Colour,
new CSVWorld::ColorDelegateFactory());
std::vector<CSMWorld::ColumnBase::Display> idCompletionColumns = CSMWorld::IdCompletionManager::getDisplayTypes();
for (std::vector<CSMWorld::ColumnBase::Display>::const_iterator current = idCompletionColumns.begin();
current != idCompletionColumns.end();

@ -0,0 +1,113 @@
#include "coloreditor.hpp"
#include <QApplication>
#include <QColor>
#include <QColorDialog>
#include <QDesktopWidget>
#include <QPainter>
#include <QRect>
#include <QShowEvent>
#include "colorpickerpopup.hpp"
CSVWidget::ColorEditor::ColorEditor(const QColor &color, QWidget *parent, bool popupOnStart)
: QPushButton(parent),
mColor(color),
mColorPicker(new ColorPickerPopup(this)),
mPopupOnStart(popupOnStart)
{
setCheckable(true);
connect(this, SIGNAL(clicked()), this, SLOT(showPicker()));
connect(mColorPicker, SIGNAL(hid()), this, SLOT(pickerHid()));
connect(mColorPicker, SIGNAL(colorChanged(const QColor &)), this, SLOT(pickerColorChanged(const QColor &)));
}
void CSVWidget::ColorEditor::paintEvent(QPaintEvent *event)
{
QPushButton::paintEvent(event);
QRect buttonRect = rect();
QRect coloredRect(buttonRect.x() + qRound(buttonRect.width() / 4.0),
buttonRect.y() + qRound(buttonRect.height() / 4.0),
buttonRect.width() / 2,
buttonRect.height() / 2);
QPainter painter(this);
painter.fillRect(coloredRect, mColor);
painter.setPen(Qt::black);
painter.drawRect(coloredRect);
}
void CSVWidget::ColorEditor::showEvent(QShowEvent *event)
{
QPushButton::showEvent(event);
if (isVisible() && mPopupOnStart)
{
setChecked(true);
showPicker();
mPopupOnStart = false;
}
}
QColor CSVWidget::ColorEditor::color() const
{
return mColor;
}
void CSVWidget::ColorEditor::setColor(const QColor &color)
{
mColor = color;
update();
}
void CSVWidget::ColorEditor::showPicker()
{
if (isChecked())
{
mColorPicker->showPicker(calculatePopupPosition(), mColor);
}
else
{
mColorPicker->hide();
}
}
void CSVWidget::ColorEditor::pickerHid()
{
setChecked(false);
emit pickingFinished();
}
void CSVWidget::ColorEditor::pickerColorChanged(const QColor &color)
{
mColor = color;
update();
}
QPoint CSVWidget::ColorEditor::calculatePopupPosition()
{
QRect editorGeometry = geometry();
QRect popupGeometry = mColorPicker->geometry();
QRect screenGeometry = QApplication::desktop()->screenGeometry();
// Center the popup horizontally relative to the editor
int localPopupX = (editorGeometry.width() - popupGeometry.width()) / 2;
// Popup position need to be specified in global coords
QPoint popupPosition = mapToGlobal(QPoint(localPopupX, editorGeometry.height()));
// Make sure that the popup isn't out of the screen
if (popupPosition.x() < screenGeometry.left())
{
popupPosition.setX(screenGeometry.left() + 1);
}
else if (popupPosition.x() + popupGeometry.width() > screenGeometry.right())
{
popupPosition.setX(screenGeometry.right() - popupGeometry.width() - 1);
}
if (popupPosition.y() + popupGeometry.height() > screenGeometry.bottom())
{
// Place the popup above the editor
popupPosition.setY(popupPosition.y() - popupGeometry.height() - editorGeometry.height() - 1);
}
return popupPosition;
}

@ -0,0 +1,44 @@
#ifndef CSV_WIDGET_COLOREDITOR_HPP
#define CSV_WIDGET_COLOREDITOR_HPP
#include <QPushButton>
class QColor;
class QPoint;
class QSize;
namespace CSVWidget
{
class ColorPickerPopup;
class ColorEditor : public QPushButton
{
Q_OBJECT
QColor mColor;
ColorPickerPopup *mColorPicker;
bool mPopupOnStart;
QPoint calculatePopupPosition();
public:
ColorEditor(const QColor &color, QWidget *parent = 0, bool popupOnStart = false);
QColor color() const;
void setColor(const QColor &color);
protected:
virtual void paintEvent(QPaintEvent *event);
virtual void showEvent(QShowEvent *event);
private slots:
void showPicker();
void pickerHid();
void pickerColorChanged(const QColor &color);
signals:
void pickingFinished();
};
}
#endif

@ -0,0 +1,86 @@
#include "colorpickerpopup.hpp"
#include <QColorDialog>
#include <QPushButton>
#include <QEvent>
#include <QKeyEvent>
#include <QMouseEvent>
#include <QLayout>
#include <QStyleOption>
CSVWidget::ColorPickerPopup::ColorPickerPopup(QWidget *parent)
: QFrame(parent)
{
setWindowFlags(Qt::Popup);
setFrameStyle(QFrame::Box | QFrame::Plain);
hide();
mColorPicker = new QColorDialog(this);
mColorPicker->setWindowFlags(Qt::Widget);
mColorPicker->setOptions(QColorDialog::NoButtons | QColorDialog::DontUseNativeDialog);
mColorPicker->installEventFilter(this);
mColorPicker->open();
connect(mColorPicker,
SIGNAL(currentColorChanged(const QColor &)),
this,
SIGNAL(colorChanged(const QColor &)));
QVBoxLayout *layout = new QVBoxLayout(this);
layout->addWidget(mColorPicker);
layout->setAlignment(Qt::AlignTop | Qt::AlignLeft);
layout->setContentsMargins(0, 0, 0, 0);
setLayout(layout);
setFixedSize(mColorPicker->size());
}
void CSVWidget::ColorPickerPopup::showPicker(const QPoint &position, const QColor &initialColor)
{
QRect geometry = this->geometry();
geometry.moveTo(position);
setGeometry(geometry);
mColorPicker->setCurrentColor(initialColor);
show();
}
void CSVWidget::ColorPickerPopup::mousePressEvent(QMouseEvent *event)
{
QPushButton *button = qobject_cast<QPushButton *>(parentWidget());
if (button != NULL)
{
QStyleOptionButton option;
option.init(button);
QRect buttonRect = option.rect;
buttonRect.moveTo(button->mapToGlobal(buttonRect.topLeft()));
// If the mouse is pressed above the pop-up parent,
// the pop-up will be hidden and the pressed signal won't be repeated for the parent
if (buttonRect.contains(event->globalPos()) || buttonRect.contains(event->pos()))
{
setAttribute(Qt::WA_NoMouseReplay);
}
}
QFrame::mousePressEvent(event);
}
void CSVWidget::ColorPickerPopup::hideEvent(QHideEvent *event)
{
QFrame::hideEvent(event);
emit hid();
}
bool CSVWidget::ColorPickerPopup::eventFilter(QObject *object, QEvent *event)
{
if (object == mColorPicker && event->type() == QEvent::KeyPress)
{
QKeyEvent *keyEvent = static_cast<QKeyEvent *>(event);
// Prevent QColorDialog from closing when Escape is pressed.
// Instead, hide the popup.
if (keyEvent->key() == Qt::Key_Escape)
{
hide();
return true;
}
}
return QFrame::eventFilter(object, event);
}

@ -0,0 +1,32 @@
#ifndef CSVWIDGET_COLORPICKERPOPUP_HPP
#define CSVWIDGET_COLORPICKERPOPUP_HPP
#include <QFrame>
class QColorDialog;
namespace CSVWidget
{
class ColorPickerPopup : public QFrame
{
Q_OBJECT
QColorDialog *mColorPicker;
public:
explicit ColorPickerPopup(QWidget *parent);
void showPicker(const QPoint &position, const QColor &initialColor);
protected:
virtual void mousePressEvent(QMouseEvent *event);
virtual void hideEvent(QHideEvent *event);
virtual bool eventFilter(QObject *object, QEvent *event);
signals:
void hid();
void colorChanged(const QColor &color);
};
}
#endif

@ -0,0 +1,36 @@
#include "colordelegate.hpp"
#include <QPainter>
#include <QPushButton>
#include "../widget/coloreditor.hpp"
CSVWorld::ColorDelegate::ColorDelegate(CSMWorld::CommandDispatcher *dispatcher,
CSMDoc::Document& document,
QObject *parent)
: CommandDelegate(dispatcher, document, parent)
{}
void CSVWorld::ColorDelegate::paint(QPainter *painter,
const QStyleOptionViewItem &option,
const QModelIndex &index) const
{
QRect coloredRect(option.rect.x() + qRound(option.rect.width() / 4.0),
option.rect.y() + qRound(option.rect.height() / 4.0),
option.rect.width() / 2,
option.rect.height() / 2);
painter->save();
painter->fillRect(coloredRect, index.data().value<QColor>());
painter->setPen(Qt::black);
painter->drawRect(coloredRect);
painter->restore();
}
CSVWorld::CommandDelegate *CSVWorld::ColorDelegateFactory::makeDelegate(CSMWorld::CommandDispatcher *dispatcher,
CSMDoc::Document &document,
QObject *parent) const
{
return new ColorDelegate(dispatcher, document, parent);
}

@ -0,0 +1,37 @@
#ifndef CSV_WORLD_COLORDELEGATE_HPP
#define CSV_WORLD_COLORDELEGATE_HPP
#include "util.hpp"
class QRect;
namespace CSVWidget
{
class ColorEditButton;
}
namespace CSVWorld
{
class ColorDelegate : public CommandDelegate
{
public:
ColorDelegate(CSMWorld::CommandDispatcher *dispatcher,
CSMDoc::Document& document,
QObject *parent);
virtual void paint(QPainter *painter,
const QStyleOptionViewItem &option,
const QModelIndex &index) const;
};
class ColorDelegateFactory : public CommandDelegateFactory
{
public:
virtual CommandDelegate *makeDelegate(CSMWorld::CommandDispatcher *dispatcher,
CSMDoc::Document &document,
QObject *parent) const;
///< The ownership of the returned CommandDelegate is transferred to the caller.
};
}
#endif

@ -33,6 +33,8 @@
#include "../../model/world/commands.hpp"
#include "../../model/doc/document.hpp"
#include "../widget/coloreditor.hpp"
#include "recordstatusdelegate.hpp"
#include "util.hpp"
#include "tablebottombox.hpp"
@ -331,6 +333,10 @@ QWidget* CSVWorld::DialogueDelegateDispatcher::makeEditor(CSMWorld::ColumnBase::
{
connect(editor, SIGNAL(editingFinished()), proxy, SLOT(editorDataCommited()));
}
else if (qobject_cast<CSVWidget::ColorEditor *>(editor))
{
connect(editor, SIGNAL(pickingFinished()), proxy, SLOT(editorDataCommited()));
}
else // throw an exception because this is a coding error
throw std::logic_error ("Dialogue editor type missing");

@ -17,6 +17,7 @@
#include "../../model/world/commands.hpp"
#include "../../model/world/tablemimedata.hpp"
#include "../../model/world/commanddispatcher.hpp"
#include "../widget/coloreditor.hpp"
#include "dialoguespinbox.hpp"
#include "scriptedit.hpp"
@ -123,10 +124,19 @@ void CSVWorld::CommandDelegate::setModelDataImp (QWidget *editor, QAbstractItemM
if (!mCommandDispatcher)
return;
NastyTableModelHack hack (*model);
QStyledItemDelegate::setModelData (editor, &hack, index);
QVariant new_ = hack.getData();
QVariant new_;
// Color columns use a custom editor, so we need explicitly extract a data from it
CSVWidget::ColorEditor *colorEditor = qobject_cast<CSVWidget::ColorEditor *>(editor);
if (colorEditor != NULL)
{
new_ = colorEditor->color();
}
else
{
NastyTableModelHack hack (*model);
QStyledItemDelegate::setModelData (editor, &hack, index);
new_ = hack.getData();
}
if ((model->data (index)!=new_) && (model->flags(index) & Qt::ItemIsEditable))
mCommandDispatcher->executeModify (model, index, new_);
@ -162,6 +172,12 @@ QWidget *CSVWorld::CommandDelegate::createEditor (QWidget *parent, const QStyleO
{
return QStyledItemDelegate::createEditor(parent, option, index);
}
// For tables the pop-up of the color editor should appear immediately after the editor creation
// (the third parameter of ColorEditor's constructor)
else if (display == CSMWorld::ColumnBase::Display_Colour)
{
return new CSVWidget::ColorEditor(index.data().value<QColor>(), parent, true);
}
return createEditor (parent, option, index, display);
}
@ -184,7 +200,7 @@ QWidget *CSVWorld::CommandDelegate::createEditor (QWidget *parent, const QStyleO
{
case CSMWorld::ColumnBase::Display_Colour:
return new QLineEdit(parent);
return new CSVWidget::ColorEditor(index.data().value<QColor>(), parent);
case CSMWorld::ColumnBase::Display_Integer:
{
@ -284,6 +300,14 @@ void CSVWorld::CommandDelegate::setEditorData (QWidget *editor, const QModelInde
}
}
// Color columns use a custom editor, so we need explicitly set a data for it
CSVWidget::ColorEditor *colorEditor = qobject_cast<CSVWidget::ColorEditor *>(editor);
if (colorEditor != NULL)
{
colorEditor->setColor(index.data().value<QColor>());
return;
}
QByteArray n = editor->metaObject()->userProperty().name();
if (n == "dateTime") {

Loading…
Cancel
Save