From d7fb49725569e6fed93672f86036e6037cd112b8 Mon Sep 17 00:00:00 2001 From: Stanislav Bas Date: Mon, 8 Jun 2015 21:33:23 +0300 Subject: [PATCH 01/30] Color values are displayed as colored rectangles in tables --- apps/opencs/CMakeLists.txt | 1 + apps/opencs/view/doc/viewmanager.cpp | 4 ++ .../opencs/view/world/colorpickerdelegate.cpp | 50 +++++++++++++++++++ .../opencs/view/world/colorpickerdelegate.hpp | 45 +++++++++++++++++ 4 files changed, 100 insertions(+) create mode 100644 apps/opencs/view/world/colorpickerdelegate.cpp create mode 100644 apps/opencs/view/world/colorpickerdelegate.hpp diff --git a/apps/opencs/CMakeLists.txt b/apps/opencs/CMakeLists.txt index 37d13223a..4a5a64f60 100644 --- a/apps/opencs/CMakeLists.txt +++ b/apps/opencs/CMakeLists.txt @@ -70,6 +70,7 @@ opencs_units (view/world opencs_units_noqt (view/world subviews enumdelegate vartypedelegate recordstatusdelegate idtypedelegate datadisplaydelegate scripthighlighter idvalidator dialoguecreator physicssystem idcompletiondelegate + colorpickerdelegate ) opencs_units (view/widget diff --git a/apps/opencs/view/doc/viewmanager.cpp b/apps/opencs/view/doc/viewmanager.cpp index b2f681df1..e5bb7fe81 100644 --- a/apps/opencs/view/doc/viewmanager.cpp +++ b/apps/opencs/view/doc/viewmanager.cpp @@ -19,6 +19,7 @@ #include "../world/recordstatusdelegate.hpp" #include "../world/idtypedelegate.hpp" #include "../world/idcompletiondelegate.hpp" +#include "../world/colorpickerdelegate.hpp" #include "../../model/settings/usersettings.hpp" @@ -63,6 +64,9 @@ CSVDoc::ViewManager::ViewManager (CSMDoc::DocumentManager& documentManager) mDelegateFactories->add (CSMWorld::ColumnBase::Display_RefRecordType, new CSVWorld::IdTypeDelegateFactory()); + mDelegateFactories->add (CSMWorld::ColumnBase::Display_Colour, + new CSVWorld::ColorPickerDelegateFactory()); + std::vector idCompletionColumns = CSMWorld::IdCompletionManager::getDisplayTypes(); for (std::vector::const_iterator current = idCompletionColumns.begin(); current != idCompletionColumns.end(); diff --git a/apps/opencs/view/world/colorpickerdelegate.cpp b/apps/opencs/view/world/colorpickerdelegate.cpp new file mode 100644 index 000000000..aa9f2e937 --- /dev/null +++ b/apps/opencs/view/world/colorpickerdelegate.cpp @@ -0,0 +1,50 @@ +#include "colorpickerdelegate.hpp" + +#include +#include + +CSVWorld::ColorPickerDelegate::ColorPickerDelegate(CSMWorld::CommandDispatcher *dispatcher, + CSMDoc::Document& document, + QObject *parent) + : CommandDelegate(dispatcher, document, parent) +{} + +QWidget *CSVWorld::ColorPickerDelegate::createEditor(QWidget *parent, + const QStyleOptionViewItem &option, + const QModelIndex &index) const +{ + return createEditor(parent, option, index, getDisplayTypeFromIndex(index)); +} + +QWidget *CSVWorld::ColorPickerDelegate::createEditor(QWidget *parent, + const QStyleOptionViewItem &option, + const QModelIndex &index, + CSMWorld::ColumnBase::Display display) const +{ + if (display != CSMWorld::ColumnBase::Display_Colour) + { + throw std::logic_error("Wrong column for ColorPickerDelegate"); + } + + return CommandDelegate::createEditor(parent, option, index, display); +} + +void CSVWorld::ColorPickerDelegate::paint(QPainter *painter, + const QStyleOptionViewItem &option, + const QModelIndex &index) const +{ + QColor color = index.data().value(); + QRect rect(option.rect.x() + option.rect.width() / 4, + option.rect.y() + option.rect.height() / 4, + option.rect.width() / 2, + option.rect.height() / 2); + + painter->fillRect(rect, color); +} + +CSVWorld::CommandDelegate *CSVWorld::ColorPickerDelegateFactory::makeDelegate(CSMWorld::CommandDispatcher *dispatcher, + CSMDoc::Document &document, + QObject *parent) const +{ + return new ColorPickerDelegate(dispatcher, document, parent); +} \ No newline at end of file diff --git a/apps/opencs/view/world/colorpickerdelegate.hpp b/apps/opencs/view/world/colorpickerdelegate.hpp new file mode 100644 index 000000000..e93e0e87d --- /dev/null +++ b/apps/opencs/view/world/colorpickerdelegate.hpp @@ -0,0 +1,45 @@ +#ifndef CSV_WORLD_COLORPICKERDELEGATE_HPP +#define CSV_WORLD_COLORPICKERDELEGATE_HPP + +#include "util.hpp" + +namespace CSVWorld +{ + class ColorPickerDelegate : public CommandDelegate + { + public: + ColorPickerDelegate(CSMWorld::CommandDispatcher *dispatcher, + CSMDoc::Document& document, + QObject *parent); + + virtual QWidget *createEditor(QWidget *parent, + const QStyleOptionViewItem &option, + const QModelIndex &index) const; + + virtual QWidget *createEditor(QWidget *parent, + const QStyleOptionViewItem &option, + const QModelIndex &index, + CSMWorld::ColumnBase::Display display) const; + + virtual void paint(QPainter *painter, + const QStyleOptionViewItem &option, + const QModelIndex &index) const;/* + + virtual void setEditorData(QWidget *editor, const QModelIndex &index) const; + + virtual void setModelData(QWidget *editor, + QAbstractItemModel &model, + const QModelIndex &index) const;*/ + }; + + class ColorPickerDelegateFactory : 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 From ef88b28c26c8031ba29a4f81a44eb6a4391f362c Mon Sep 17 00:00:00 2001 From: Stanislav Bas Date: Tue, 9 Jun 2015 15:20:50 +0300 Subject: [PATCH 02/30] Create a custom item editor for color columns --- apps/opencs/CMakeLists.txt | 2 +- apps/opencs/view/widget/coloreditbutton.cpp | 42 +++++++++++++++++++ apps/opencs/view/widget/coloreditbutton.hpp | 30 +++++++++++++ .../opencs/view/world/colorpickerdelegate.cpp | 26 ++++++++---- .../opencs/view/world/colorpickerdelegate.hpp | 17 ++++---- 5 files changed, 100 insertions(+), 17 deletions(-) create mode 100644 apps/opencs/view/widget/coloreditbutton.cpp create mode 100644 apps/opencs/view/widget/coloreditbutton.hpp diff --git a/apps/opencs/CMakeLists.txt b/apps/opencs/CMakeLists.txt index 4a5a64f60..f8f3ea036 100644 --- a/apps/opencs/CMakeLists.txt +++ b/apps/opencs/CMakeLists.txt @@ -75,7 +75,7 @@ opencs_units_noqt (view/world opencs_units (view/widget scenetoolbar scenetool scenetoolmode pushbutton scenetooltoggle scenetoolrun modebutton - scenetooltoggle2 completerpopup + scenetooltoggle2 completerpopup coloreditbutton ) opencs_units (view/render diff --git a/apps/opencs/view/widget/coloreditbutton.cpp b/apps/opencs/view/widget/coloreditbutton.cpp new file mode 100644 index 000000000..4960d1ef1 --- /dev/null +++ b/apps/opencs/view/widget/coloreditbutton.cpp @@ -0,0 +1,42 @@ +#include "coloreditbutton.hpp" + +#include +#include +#include + +CSVWidget::ColorEditButton::ColorEditButton(const QColor &color, + const QSize &coloredRectSize, + QWidget *parent) + : QPushButton(parent), + mColor(color), + mColoredRectSize(coloredRectSize) + +{} + +void CSVWidget::ColorEditButton::paintEvent(QPaintEvent *event) +{ + QPushButton::paintEvent(event); + + QRect buttonRect = rect(); + QRect coloredRect(buttonRect.x() + (buttonRect.width() - mColoredRectSize.width()) / 2, + buttonRect.y() + (buttonRect.height() - mColoredRectSize.height()) / 2, + mColoredRectSize.width(), + mColoredRectSize.height()); + QPainter painter(this); + painter.fillRect(coloredRect, mColor); +} + +QColor CSVWidget::ColorEditButton::color() const +{ + return mColor; +} + +void CSVWidget::ColorEditButton::setColor(const QColor &color) +{ + mColor = color; +} + +void CSVWidget::ColorEditButton::setColoredRectSize(const QSize &size) +{ + mColoredRectSize = size; +} \ No newline at end of file diff --git a/apps/opencs/view/widget/coloreditbutton.hpp b/apps/opencs/view/widget/coloreditbutton.hpp new file mode 100644 index 000000000..e1a8cce9d --- /dev/null +++ b/apps/opencs/view/widget/coloreditbutton.hpp @@ -0,0 +1,30 @@ +#ifndef CSV_WIDGET_COLOREDITBUTTON_HPP +#define CSV_WIDGET_COLOREDITBUTTON_HPP + +#include + +class QColor; +class QSize; + +namespace CSVWidget +{ + class ColorEditButton : public QPushButton + { + QColor mColor; + QSize mColoredRectSize; + + public: + ColorEditButton(const QColor &color, + const QSize &coloredRectSize, + QWidget *parent = 0); + + QColor color() const; + void setColor(const QColor &color); + void setColoredRectSize(const QSize &size); + + protected: + void paintEvent(QPaintEvent *event); + }; +} + +#endif diff --git a/apps/opencs/view/world/colorpickerdelegate.cpp b/apps/opencs/view/world/colorpickerdelegate.cpp index aa9f2e937..c74a1828f 100644 --- a/apps/opencs/view/world/colorpickerdelegate.cpp +++ b/apps/opencs/view/world/colorpickerdelegate.cpp @@ -3,6 +3,8 @@ #include #include +#include "../widget/coloreditbutton.hpp" + CSVWorld::ColorPickerDelegate::ColorPickerDelegate(CSMWorld::CommandDispatcher *dispatcher, CSMDoc::Document& document, QObject *parent) @@ -26,20 +28,24 @@ QWidget *CSVWorld::ColorPickerDelegate::createEditor(QWidget *parent, throw std::logic_error("Wrong column for ColorPickerDelegate"); } - return CommandDelegate::createEditor(parent, option, index, display); + return new CSVWidget::ColorEditButton(index.data().value(), + getColoredRect(option).size(), + parent); } void CSVWorld::ColorPickerDelegate::paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const { - QColor color = index.data().value(); - QRect rect(option.rect.x() + option.rect.width() / 4, - option.rect.y() + option.rect.height() / 4, - option.rect.width() / 2, - option.rect.height() / 2); - - painter->fillRect(rect, color); + painter->fillRect(getColoredRect(option), index.data().value()); +} + +QRect CSVWorld::ColorPickerDelegate::getColoredRect(const QStyleOptionViewItem &option) const +{ + return QRect(option.rect.x() + option.rect.width() / 4, + option.rect.y() + option.rect.height() / 4, + option.rect.width() / 2, + option.rect.height() / 2); } CSVWorld::CommandDelegate *CSVWorld::ColorPickerDelegateFactory::makeDelegate(CSMWorld::CommandDispatcher *dispatcher, @@ -47,4 +53,6 @@ CSVWorld::CommandDelegate *CSVWorld::ColorPickerDelegateFactory::makeDelegate(CS QObject *parent) const { return new ColorPickerDelegate(dispatcher, document, parent); -} \ No newline at end of file +} + + diff --git a/apps/opencs/view/world/colorpickerdelegate.hpp b/apps/opencs/view/world/colorpickerdelegate.hpp index e93e0e87d..147c2f424 100644 --- a/apps/opencs/view/world/colorpickerdelegate.hpp +++ b/apps/opencs/view/world/colorpickerdelegate.hpp @@ -3,10 +3,19 @@ #include "util.hpp" +class QRect; + +namespace CSVWidget +{ + class ColorEditButton; +} + namespace CSVWorld { class ColorPickerDelegate : public CommandDelegate { + QRect getColoredRect(const QStyleOptionViewItem &option) const; + public: ColorPickerDelegate(CSMWorld::CommandDispatcher *dispatcher, CSMDoc::Document& document, @@ -23,13 +32,7 @@ namespace CSVWorld virtual void paint(QPainter *painter, const QStyleOptionViewItem &option, - const QModelIndex &index) const;/* - - virtual void setEditorData(QWidget *editor, const QModelIndex &index) const; - - virtual void setModelData(QWidget *editor, - QAbstractItemModel &model, - const QModelIndex &index) const;*/ + const QModelIndex &index) const; }; class ColorPickerDelegateFactory : public CommandDelegateFactory From e257c915bfc75db5474d0e31d307664bbe745e60 Mon Sep 17 00:00:00 2001 From: Stanislav Bas Date: Fri, 12 Jun 2015 00:00:23 +0300 Subject: [PATCH 03/30] Add color picker popup to choose color --- apps/opencs/CMakeLists.txt | 2 +- apps/opencs/view/widget/coloreditor.cpp | 111 ++++++++++++++++++ apps/opencs/view/widget/coloreditor.hpp | 43 +++++++ apps/opencs/view/widget/colorpickerpopup.cpp | 63 ++++++++++ apps/opencs/view/widget/colorpickerpopup.hpp | 31 +++++ .../opencs/view/world/colorpickerdelegate.cpp | 8 +- 6 files changed, 253 insertions(+), 5 deletions(-) create mode 100644 apps/opencs/view/widget/coloreditor.cpp create mode 100644 apps/opencs/view/widget/coloreditor.hpp create mode 100644 apps/opencs/view/widget/colorpickerpopup.cpp create mode 100644 apps/opencs/view/widget/colorpickerpopup.hpp diff --git a/apps/opencs/CMakeLists.txt b/apps/opencs/CMakeLists.txt index f8f3ea036..83a20ecaa 100644 --- a/apps/opencs/CMakeLists.txt +++ b/apps/opencs/CMakeLists.txt @@ -75,7 +75,7 @@ opencs_units_noqt (view/world opencs_units (view/widget scenetoolbar scenetool scenetoolmode pushbutton scenetooltoggle scenetoolrun modebutton - scenetooltoggle2 completerpopup coloreditbutton + scenetooltoggle2 completerpopup coloreditor colorpickerpopup ) opencs_units (view/render diff --git a/apps/opencs/view/widget/coloreditor.cpp b/apps/opencs/view/widget/coloreditor.cpp new file mode 100644 index 000000000..bab98fcd5 --- /dev/null +++ b/apps/opencs/view/widget/coloreditor.cpp @@ -0,0 +1,111 @@ +#include "coloreditor.hpp" + +#include +#include +#include +#include +#include +#include + +#include "colorpickerpopup.hpp" + +CSVWidget::ColorEditor::ColorEditor(const QColor &color, + const QSize &coloredRectSize, + QWidget *parent) + : QPushButton(parent), + mColor(color), + mColoredRectSize(coloredRectSize), + mColorPicker(new ColorPickerPopup(this)) +{ + 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() + (buttonRect.width() - mColoredRectSize.width()) / 2, + buttonRect.y() + (buttonRect.height() - mColoredRectSize.height()) / 2, + mColoredRectSize.width(), + mColoredRectSize.height()); + QPainter painter(this); + painter.fillRect(coloredRect, mColor); +} + +QColor CSVWidget::ColorEditor::color() const +{ + return mColor; +} + +void CSVWidget::ColorEditor::setColor(const QColor &color) +{ + mColor = color; +} + +void CSVWidget::ColorEditor::setColoredRectSize(const QSize &size) +{ + mColoredRectSize = size; +} + +void CSVWidget::ColorEditor::showPicker() +{ + if (isChecked()) + { + mColorPicker->showPicker(calculatePopupPosition(), mColor); + } + else + { + mColorPicker->hide(); + } +} + +void CSVWidget::ColorEditor::pickerHid() +{ + // If the popup is hidden and mouse isn't above the editor, + // reset the editor checked state manually + QPoint globalEditorPosition = mapToGlobal(QPoint(0, 0)); + QRect globalEditorRect(globalEditorPosition, geometry().size()); + if (!globalEditorRect.contains(QCursor::pos())) + { + setChecked(false); + } +} + +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; +} diff --git a/apps/opencs/view/widget/coloreditor.hpp b/apps/opencs/view/widget/coloreditor.hpp new file mode 100644 index 000000000..a0fa497b6 --- /dev/null +++ b/apps/opencs/view/widget/coloreditor.hpp @@ -0,0 +1,43 @@ +#ifndef CSV_WIDGET_COLOREDITOR_HPP +#define CSV_WIDGET_COLOREDITOR_HPP + +#include + +class QColor; +class QPoint; +class QSize; + +namespace CSVWidget +{ + class ColorPickerPopup; + + class ColorEditor : public QPushButton + { + Q_OBJECT + + QColor mColor; + QSize mColoredRectSize; + ColorPickerPopup *mColorPicker; + + QPoint calculatePopupPosition(); + + public: + ColorEditor(const QColor &color, + const QSize &coloredRectSize, + QWidget *parent = 0); + + QColor color() const; + void setColor(const QColor &color); + void setColoredRectSize(const QSize &size); + + protected: + void paintEvent(QPaintEvent *event); + + private slots: + void showPicker(); + void pickerHid(); + void pickerColorChanged(const QColor &color); + }; +} + +#endif diff --git a/apps/opencs/view/widget/colorpickerpopup.cpp b/apps/opencs/view/widget/colorpickerpopup.cpp new file mode 100644 index 000000000..dd53f1bec --- /dev/null +++ b/apps/opencs/view/widget/colorpickerpopup.cpp @@ -0,0 +1,63 @@ +#include "colorpickerpopup.hpp" + +#include +#include +#include +#include + +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::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(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); +} diff --git a/apps/opencs/view/widget/colorpickerpopup.hpp b/apps/opencs/view/widget/colorpickerpopup.hpp new file mode 100644 index 000000000..a7aec3bad --- /dev/null +++ b/apps/opencs/view/widget/colorpickerpopup.hpp @@ -0,0 +1,31 @@ +#ifndef CSVWIDGET_COLORPICKERPOPUP_HPP +#define CSVWIDGET_COLORPICKERPOPUP_HPP + +#include + +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 hideEvent(QHideEvent *event); + virtual bool eventFilter(QObject *object, QEvent *event); + + signals: + void hid(); + void colorChanged(const QColor &color); + }; +} + +#endif diff --git a/apps/opencs/view/world/colorpickerdelegate.cpp b/apps/opencs/view/world/colorpickerdelegate.cpp index c74a1828f..4491f392c 100644 --- a/apps/opencs/view/world/colorpickerdelegate.cpp +++ b/apps/opencs/view/world/colorpickerdelegate.cpp @@ -3,7 +3,7 @@ #include #include -#include "../widget/coloreditbutton.hpp" +#include "../widget/coloreditor.hpp" CSVWorld::ColorPickerDelegate::ColorPickerDelegate(CSMWorld::CommandDispatcher *dispatcher, CSMDoc::Document& document, @@ -28,9 +28,9 @@ QWidget *CSVWorld::ColorPickerDelegate::createEditor(QWidget *parent, throw std::logic_error("Wrong column for ColorPickerDelegate"); } - return new CSVWidget::ColorEditButton(index.data().value(), - getColoredRect(option).size(), - parent); + return new CSVWidget::ColorEditor(index.data().value(), + getColoredRect(option).size(), + parent); } void CSVWorld::ColorPickerDelegate::paint(QPainter *painter, From 4096d2851c66a574743c4a6d2ca4c61305affdab Mon Sep 17 00:00:00 2001 From: Stanislav Bas Date: Fri, 12 Jun 2015 14:09:25 +0300 Subject: [PATCH 04/30] Remove outdated ColorEditButton files --- apps/opencs/view/widget/coloreditbutton.cpp | 42 --------------------- apps/opencs/view/widget/coloreditbutton.hpp | 30 --------------- 2 files changed, 72 deletions(-) delete mode 100644 apps/opencs/view/widget/coloreditbutton.cpp delete mode 100644 apps/opencs/view/widget/coloreditbutton.hpp diff --git a/apps/opencs/view/widget/coloreditbutton.cpp b/apps/opencs/view/widget/coloreditbutton.cpp deleted file mode 100644 index 4960d1ef1..000000000 --- a/apps/opencs/view/widget/coloreditbutton.cpp +++ /dev/null @@ -1,42 +0,0 @@ -#include "coloreditbutton.hpp" - -#include -#include -#include - -CSVWidget::ColorEditButton::ColorEditButton(const QColor &color, - const QSize &coloredRectSize, - QWidget *parent) - : QPushButton(parent), - mColor(color), - mColoredRectSize(coloredRectSize) - -{} - -void CSVWidget::ColorEditButton::paintEvent(QPaintEvent *event) -{ - QPushButton::paintEvent(event); - - QRect buttonRect = rect(); - QRect coloredRect(buttonRect.x() + (buttonRect.width() - mColoredRectSize.width()) / 2, - buttonRect.y() + (buttonRect.height() - mColoredRectSize.height()) / 2, - mColoredRectSize.width(), - mColoredRectSize.height()); - QPainter painter(this); - painter.fillRect(coloredRect, mColor); -} - -QColor CSVWidget::ColorEditButton::color() const -{ - return mColor; -} - -void CSVWidget::ColorEditButton::setColor(const QColor &color) -{ - mColor = color; -} - -void CSVWidget::ColorEditButton::setColoredRectSize(const QSize &size) -{ - mColoredRectSize = size; -} \ No newline at end of file diff --git a/apps/opencs/view/widget/coloreditbutton.hpp b/apps/opencs/view/widget/coloreditbutton.hpp deleted file mode 100644 index e1a8cce9d..000000000 --- a/apps/opencs/view/widget/coloreditbutton.hpp +++ /dev/null @@ -1,30 +0,0 @@ -#ifndef CSV_WIDGET_COLOREDITBUTTON_HPP -#define CSV_WIDGET_COLOREDITBUTTON_HPP - -#include - -class QColor; -class QSize; - -namespace CSVWidget -{ - class ColorEditButton : public QPushButton - { - QColor mColor; - QSize mColoredRectSize; - - public: - ColorEditButton(const QColor &color, - const QSize &coloredRectSize, - QWidget *parent = 0); - - QColor color() const; - void setColor(const QColor &color); - void setColoredRectSize(const QSize &size); - - protected: - void paintEvent(QPaintEvent *event); - }; -} - -#endif From eb5180ba8696f043cf91381728a36a86f41f9d44 Mon Sep 17 00:00:00 2001 From: Stanislav Bas Date: Fri, 12 Jun 2015 18:33:55 +0300 Subject: [PATCH 05/30] Save selected color in a model when picking is finished --- apps/opencs/view/widget/coloreditor.cpp | 19 ++++------- apps/opencs/view/widget/coloreditor.hpp | 9 +++-- .../opencs/view/world/colorpickerdelegate.cpp | 33 ++++--------------- .../opencs/view/world/colorpickerdelegate.hpp | 9 ----- apps/opencs/view/world/dialoguesubview.cpp | 6 ++++ apps/opencs/view/world/util.cpp | 28 +++++++++++++--- 6 files changed, 45 insertions(+), 59 deletions(-) diff --git a/apps/opencs/view/widget/coloreditor.cpp b/apps/opencs/view/widget/coloreditor.cpp index bab98fcd5..eaef0f6d3 100644 --- a/apps/opencs/view/widget/coloreditor.cpp +++ b/apps/opencs/view/widget/coloreditor.cpp @@ -9,12 +9,9 @@ #include "colorpickerpopup.hpp" -CSVWidget::ColorEditor::ColorEditor(const QColor &color, - const QSize &coloredRectSize, - QWidget *parent) +CSVWidget::ColorEditor::ColorEditor(const QColor &color, QWidget *parent) : QPushButton(parent), mColor(color), - mColoredRectSize(coloredRectSize), mColorPicker(new ColorPickerPopup(this)) { setCheckable(true); @@ -28,10 +25,10 @@ void CSVWidget::ColorEditor::paintEvent(QPaintEvent *event) QPushButton::paintEvent(event); QRect buttonRect = rect(); - QRect coloredRect(buttonRect.x() + (buttonRect.width() - mColoredRectSize.width()) / 2, - buttonRect.y() + (buttonRect.height() - mColoredRectSize.height()) / 2, - mColoredRectSize.width(), - mColoredRectSize.height()); + QRect coloredRect(qRound(buttonRect.x() + buttonRect.width() / 4.0), + qRound(buttonRect.y() + buttonRect.height() / 4.0), + qRound(buttonRect.width() / 2.0), + qRound(buttonRect.height() / 2.0)); QPainter painter(this); painter.fillRect(coloredRect, mColor); } @@ -46,11 +43,6 @@ void CSVWidget::ColorEditor::setColor(const QColor &color) mColor = color; } -void CSVWidget::ColorEditor::setColoredRectSize(const QSize &size) -{ - mColoredRectSize = size; -} - void CSVWidget::ColorEditor::showPicker() { if (isChecked()) @@ -73,6 +65,7 @@ void CSVWidget::ColorEditor::pickerHid() { setChecked(false); } + emit pickingFinished(); } void CSVWidget::ColorEditor::pickerColorChanged(const QColor &color) diff --git a/apps/opencs/view/widget/coloreditor.hpp b/apps/opencs/view/widget/coloreditor.hpp index a0fa497b6..cca26fade 100644 --- a/apps/opencs/view/widget/coloreditor.hpp +++ b/apps/opencs/view/widget/coloreditor.hpp @@ -16,19 +16,15 @@ namespace CSVWidget Q_OBJECT QColor mColor; - QSize mColoredRectSize; ColorPickerPopup *mColorPicker; QPoint calculatePopupPosition(); public: - ColorEditor(const QColor &color, - const QSize &coloredRectSize, - QWidget *parent = 0); + ColorEditor(const QColor &color, QWidget *parent = 0); QColor color() const; void setColor(const QColor &color); - void setColoredRectSize(const QSize &size); protected: void paintEvent(QPaintEvent *event); @@ -37,6 +33,9 @@ namespace CSVWidget void showPicker(); void pickerHid(); void pickerColorChanged(const QColor &color); + + signals: + void pickingFinished(); }; } diff --git a/apps/opencs/view/world/colorpickerdelegate.cpp b/apps/opencs/view/world/colorpickerdelegate.cpp index 4491f392c..7490c07f5 100644 --- a/apps/opencs/view/world/colorpickerdelegate.cpp +++ b/apps/opencs/view/world/colorpickerdelegate.cpp @@ -11,41 +11,20 @@ CSVWorld::ColorPickerDelegate::ColorPickerDelegate(CSMWorld::CommandDispatcher * : CommandDelegate(dispatcher, document, parent) {} -QWidget *CSVWorld::ColorPickerDelegate::createEditor(QWidget *parent, - const QStyleOptionViewItem &option, - const QModelIndex &index) const -{ - return createEditor(parent, option, index, getDisplayTypeFromIndex(index)); -} - -QWidget *CSVWorld::ColorPickerDelegate::createEditor(QWidget *parent, - const QStyleOptionViewItem &option, - const QModelIndex &index, - CSMWorld::ColumnBase::Display display) const -{ - if (display != CSMWorld::ColumnBase::Display_Colour) - { - throw std::logic_error("Wrong column for ColorPickerDelegate"); - } - - return new CSVWidget::ColorEditor(index.data().value(), - getColoredRect(option).size(), - parent); -} - void CSVWorld::ColorPickerDelegate::paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const { - painter->fillRect(getColoredRect(option), index.data().value()); + QRect coloredRect = getColoredRect(option); + painter->fillRect(coloredRect, index.data().value()); } QRect CSVWorld::ColorPickerDelegate::getColoredRect(const QStyleOptionViewItem &option) const { - return QRect(option.rect.x() + option.rect.width() / 4, - option.rect.y() + option.rect.height() / 4, - option.rect.width() / 2, - option.rect.height() / 2); + return QRect(qRound(option.rect.x() + option.rect.width() / 4.0), + qRound(option.rect.y() + option.rect.height() / 4.0), + qRound(option.rect.width() / 2.0), + qRound(option.rect.height() / 2.0)); } CSVWorld::CommandDelegate *CSVWorld::ColorPickerDelegateFactory::makeDelegate(CSMWorld::CommandDispatcher *dispatcher, diff --git a/apps/opencs/view/world/colorpickerdelegate.hpp b/apps/opencs/view/world/colorpickerdelegate.hpp index 147c2f424..f17923648 100644 --- a/apps/opencs/view/world/colorpickerdelegate.hpp +++ b/apps/opencs/view/world/colorpickerdelegate.hpp @@ -21,15 +21,6 @@ namespace CSVWorld CSMDoc::Document& document, QObject *parent); - virtual QWidget *createEditor(QWidget *parent, - const QStyleOptionViewItem &option, - const QModelIndex &index) const; - - virtual QWidget *createEditor(QWidget *parent, - const QStyleOptionViewItem &option, - const QModelIndex &index, - CSMWorld::ColumnBase::Display display) const; - virtual void paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const; diff --git a/apps/opencs/view/world/dialoguesubview.cpp b/apps/opencs/view/world/dialoguesubview.cpp index 66e8fcb7a..541cf050f 100644 --- a/apps/opencs/view/world/dialoguesubview.cpp +++ b/apps/opencs/view/world/dialoguesubview.cpp @@ -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(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"); diff --git a/apps/opencs/view/world/util.cpp b/apps/opencs/view/world/util.cpp index e1d165a24..de088bffc 100644 --- a/apps/opencs/view/world/util.cpp +++ b/apps/opencs/view/world/util.cpp @@ -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(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_); @@ -184,7 +194,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(), parent); case CSMWorld::ColumnBase::Display_Integer: { @@ -284,6 +294,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(editor); + if (colorEditor != NULL) + { + colorEditor->setColor(index.data().value()); + return; + } + QByteArray n = editor->metaObject()->userProperty().name(); if (n == "dateTime") { From caeba1b8878a91504ac39ceba9eff2d96b6ff1ba Mon Sep 17 00:00:00 2001 From: Stanislav Bas Date: Fri, 12 Jun 2015 20:34:35 +0300 Subject: [PATCH 06/30] Draw the frame around rect in ColorEditor and ColorPickerDelegate --- apps/opencs/view/widget/coloreditor.cpp | 2 ++ apps/opencs/view/world/colorpickerdelegate.cpp | 17 ++++++++--------- apps/opencs/view/world/colorpickerdelegate.hpp | 2 -- 3 files changed, 10 insertions(+), 11 deletions(-) diff --git a/apps/opencs/view/widget/coloreditor.cpp b/apps/opencs/view/widget/coloreditor.cpp index eaef0f6d3..e6e3264be 100644 --- a/apps/opencs/view/widget/coloreditor.cpp +++ b/apps/opencs/view/widget/coloreditor.cpp @@ -31,6 +31,8 @@ void CSVWidget::ColorEditor::paintEvent(QPaintEvent *event) qRound(buttonRect.height() / 2.0)); QPainter painter(this); painter.fillRect(coloredRect, mColor); + painter.setPen(Qt::black); + painter.drawRect(coloredRect); } QColor CSVWidget::ColorEditor::color() const diff --git a/apps/opencs/view/world/colorpickerdelegate.cpp b/apps/opencs/view/world/colorpickerdelegate.cpp index 7490c07f5..4feaa170e 100644 --- a/apps/opencs/view/world/colorpickerdelegate.cpp +++ b/apps/opencs/view/world/colorpickerdelegate.cpp @@ -15,16 +15,15 @@ void CSVWorld::ColorPickerDelegate::paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const { - QRect coloredRect = getColoredRect(option); + QRect coloredRect(qRound(option.rect.x() + option.rect.width() / 4.0), + qRound(option.rect.y() + option.rect.height() / 4.0), + qRound(option.rect.width() / 2.0), + qRound(option.rect.height() / 2.0)); + painter->save(); painter->fillRect(coloredRect, index.data().value()); -} - -QRect CSVWorld::ColorPickerDelegate::getColoredRect(const QStyleOptionViewItem &option) const -{ - return QRect(qRound(option.rect.x() + option.rect.width() / 4.0), - qRound(option.rect.y() + option.rect.height() / 4.0), - qRound(option.rect.width() / 2.0), - qRound(option.rect.height() / 2.0)); + painter->setPen(Qt::black); + painter->drawRect(coloredRect); + painter->restore(); } CSVWorld::CommandDelegate *CSVWorld::ColorPickerDelegateFactory::makeDelegate(CSMWorld::CommandDispatcher *dispatcher, diff --git a/apps/opencs/view/world/colorpickerdelegate.hpp b/apps/opencs/view/world/colorpickerdelegate.hpp index f17923648..a8e6d87fc 100644 --- a/apps/opencs/view/world/colorpickerdelegate.hpp +++ b/apps/opencs/view/world/colorpickerdelegate.hpp @@ -14,8 +14,6 @@ namespace CSVWorld { class ColorPickerDelegate : public CommandDelegate { - QRect getColoredRect(const QStyleOptionViewItem &option) const; - public: ColorPickerDelegate(CSMWorld::CommandDispatcher *dispatcher, CSMDoc::Document& document, From e516d37cbf22e047cca941c2be7f48deab75dccd Mon Sep 17 00:00:00 2001 From: Stanislav Bas Date: Fri, 12 Jun 2015 22:03:47 +0300 Subject: [PATCH 07/30] MapColourColumn::set() uses the correct color value --- apps/opencs/model/world/columnimp.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/opencs/model/world/columnimp.hpp b/apps/opencs/model/world/columnimp.hpp index 8758d924b..a8ae5dfa1 100644 --- a/apps/opencs/model/world/columnimp.hpp +++ b/apps/opencs/model/world/columnimp.hpp @@ -694,7 +694,7 @@ namespace CSMWorld QColor colour = data.value(); - record2.mMapColor = colour.rgb() & 0xffffff; + record2.mMapColor = (colour.blue() << 16) | (colour.green() << 8) | colour.red(); record.setModified (record2); } From f19d07b4047daad44c7add15784659c167c1531e Mon Sep 17 00:00:00 2001 From: Stanislav Bas Date: Fri, 12 Jun 2015 23:09:31 +0300 Subject: [PATCH 08/30] Rename ColorPickerDelegate to ColorDelegate --- apps/opencs/CMakeLists.txt | 2 +- apps/opencs/view/doc/viewmanager.cpp | 4 +-- apps/opencs/view/world/colordelegate.cpp | 36 +++++++++++++++++++ ...orpickerdelegate.hpp => colordelegate.hpp} | 14 ++++---- .../opencs/view/world/colorpickerdelegate.cpp | 36 ------------------- 5 files changed, 46 insertions(+), 46 deletions(-) create mode 100644 apps/opencs/view/world/colordelegate.cpp rename apps/opencs/view/world/{colorpickerdelegate.hpp => colordelegate.hpp} (64%) delete mode 100644 apps/opencs/view/world/colorpickerdelegate.cpp diff --git a/apps/opencs/CMakeLists.txt b/apps/opencs/CMakeLists.txt index 83a20ecaa..88edf7bb1 100644 --- a/apps/opencs/CMakeLists.txt +++ b/apps/opencs/CMakeLists.txt @@ -70,7 +70,7 @@ opencs_units (view/world opencs_units_noqt (view/world subviews enumdelegate vartypedelegate recordstatusdelegate idtypedelegate datadisplaydelegate scripthighlighter idvalidator dialoguecreator physicssystem idcompletiondelegate - colorpickerdelegate + colordelegate ) opencs_units (view/widget diff --git a/apps/opencs/view/doc/viewmanager.cpp b/apps/opencs/view/doc/viewmanager.cpp index e5bb7fe81..969914851 100644 --- a/apps/opencs/view/doc/viewmanager.cpp +++ b/apps/opencs/view/doc/viewmanager.cpp @@ -19,7 +19,7 @@ #include "../world/recordstatusdelegate.hpp" #include "../world/idtypedelegate.hpp" #include "../world/idcompletiondelegate.hpp" -#include "../world/colorpickerdelegate.hpp" +#include "../world/colordelegate.hpp" #include "../../model/settings/usersettings.hpp" @@ -65,7 +65,7 @@ CSVDoc::ViewManager::ViewManager (CSMDoc::DocumentManager& documentManager) new CSVWorld::IdTypeDelegateFactory()); mDelegateFactories->add (CSMWorld::ColumnBase::Display_Colour, - new CSVWorld::ColorPickerDelegateFactory()); + new CSVWorld::ColorDelegateFactory()); std::vector idCompletionColumns = CSMWorld::IdCompletionManager::getDisplayTypes(); for (std::vector::const_iterator current = idCompletionColumns.begin(); diff --git a/apps/opencs/view/world/colordelegate.cpp b/apps/opencs/view/world/colordelegate.cpp new file mode 100644 index 000000000..ae71f965a --- /dev/null +++ b/apps/opencs/view/world/colordelegate.cpp @@ -0,0 +1,36 @@ +#include "colordelegate.hpp" + +#include +#include + +#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(qRound(option.rect.x() + option.rect.width() / 4.0), + qRound(option.rect.y() + option.rect.height() / 4.0), + qRound(option.rect.width() / 2.0), + qRound(option.rect.height() / 2.0)); + painter->save(); + painter->fillRect(coloredRect, index.data().value()); + 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); +} + + diff --git a/apps/opencs/view/world/colorpickerdelegate.hpp b/apps/opencs/view/world/colordelegate.hpp similarity index 64% rename from apps/opencs/view/world/colorpickerdelegate.hpp rename to apps/opencs/view/world/colordelegate.hpp index a8e6d87fc..87051e86d 100644 --- a/apps/opencs/view/world/colorpickerdelegate.hpp +++ b/apps/opencs/view/world/colordelegate.hpp @@ -1,5 +1,5 @@ -#ifndef CSV_WORLD_COLORPICKERDELEGATE_HPP -#define CSV_WORLD_COLORPICKERDELEGATE_HPP +#ifndef CSV_WORLD_COLORDELEGATE_HPP +#define CSV_WORLD_COLORDELEGATE_HPP #include "util.hpp" @@ -12,19 +12,19 @@ namespace CSVWidget namespace CSVWorld { - class ColorPickerDelegate : public CommandDelegate + class ColorDelegate : public CommandDelegate { public: - ColorPickerDelegate(CSMWorld::CommandDispatcher *dispatcher, - CSMDoc::Document& document, - QObject *parent); + ColorDelegate(CSMWorld::CommandDispatcher *dispatcher, + CSMDoc::Document& document, + QObject *parent); virtual void paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const; }; - class ColorPickerDelegateFactory : public CommandDelegateFactory + class ColorDelegateFactory : public CommandDelegateFactory { public: virtual CommandDelegate *makeDelegate(CSMWorld::CommandDispatcher *dispatcher, diff --git a/apps/opencs/view/world/colorpickerdelegate.cpp b/apps/opencs/view/world/colorpickerdelegate.cpp deleted file mode 100644 index 4feaa170e..000000000 --- a/apps/opencs/view/world/colorpickerdelegate.cpp +++ /dev/null @@ -1,36 +0,0 @@ -#include "colorpickerdelegate.hpp" - -#include -#include - -#include "../widget/coloreditor.hpp" - -CSVWorld::ColorPickerDelegate::ColorPickerDelegate(CSMWorld::CommandDispatcher *dispatcher, - CSMDoc::Document& document, - QObject *parent) - : CommandDelegate(dispatcher, document, parent) -{} - -void CSVWorld::ColorPickerDelegate::paint(QPainter *painter, - const QStyleOptionViewItem &option, - const QModelIndex &index) const -{ - QRect coloredRect(qRound(option.rect.x() + option.rect.width() / 4.0), - qRound(option.rect.y() + option.rect.height() / 4.0), - qRound(option.rect.width() / 2.0), - qRound(option.rect.height() / 2.0)); - painter->save(); - painter->fillRect(coloredRect, index.data().value()); - painter->setPen(Qt::black); - painter->drawRect(coloredRect); - painter->restore(); -} - -CSVWorld::CommandDelegate *CSVWorld::ColorPickerDelegateFactory::makeDelegate(CSMWorld::CommandDispatcher *dispatcher, - CSMDoc::Document &document, - QObject *parent) const -{ - return new ColorPickerDelegate(dispatcher, document, parent); -} - - From b06d1f008f0aed4a6152ef7d0b28a99ad6c5b7eb Mon Sep 17 00:00:00 2001 From: Stanislav Bas Date: Fri, 12 Jun 2015 23:34:08 +0300 Subject: [PATCH 09/30] Redraw the color editor immediately after the color is updated --- apps/opencs/view/widget/coloreditor.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/apps/opencs/view/widget/coloreditor.cpp b/apps/opencs/view/widget/coloreditor.cpp index e6e3264be..f06187992 100644 --- a/apps/opencs/view/widget/coloreditor.cpp +++ b/apps/opencs/view/widget/coloreditor.cpp @@ -43,6 +43,7 @@ QColor CSVWidget::ColorEditor::color() const void CSVWidget::ColorEditor::setColor(const QColor &color) { mColor = color; + update(); } void CSVWidget::ColorEditor::showPicker() From a294e24a85672ee7c31c9d08f22d7aab6a4f6902 Mon Sep 17 00:00:00 2001 From: Stanislav Bas Date: Sat, 13 Jun 2015 00:37:10 +0300 Subject: [PATCH 10/30] Reset ColorEditor checked state after the popup is hidden --- apps/opencs/view/widget/coloreditor.cpp | 9 +------- apps/opencs/view/widget/colorpickerpopup.cpp | 23 ++++++++++++++++++++ apps/opencs/view/widget/colorpickerpopup.hpp | 1 + 3 files changed, 25 insertions(+), 8 deletions(-) diff --git a/apps/opencs/view/widget/coloreditor.cpp b/apps/opencs/view/widget/coloreditor.cpp index f06187992..b31225962 100644 --- a/apps/opencs/view/widget/coloreditor.cpp +++ b/apps/opencs/view/widget/coloreditor.cpp @@ -60,14 +60,7 @@ void CSVWidget::ColorEditor::showPicker() void CSVWidget::ColorEditor::pickerHid() { - // If the popup is hidden and mouse isn't above the editor, - // reset the editor checked state manually - QPoint globalEditorPosition = mapToGlobal(QPoint(0, 0)); - QRect globalEditorRect(globalEditorPosition, geometry().size()); - if (!globalEditorRect.contains(QCursor::pos())) - { - setChecked(false); - } + setChecked(false); emit pickingFinished(); } diff --git a/apps/opencs/view/widget/colorpickerpopup.cpp b/apps/opencs/view/widget/colorpickerpopup.cpp index dd53f1bec..8e71ce39e 100644 --- a/apps/opencs/view/widget/colorpickerpopup.cpp +++ b/apps/opencs/view/widget/colorpickerpopup.cpp @@ -1,9 +1,12 @@ #include "colorpickerpopup.hpp" #include +#include #include #include +#include #include +#include CSVWidget::ColorPickerPopup::ColorPickerPopup(QWidget *parent) : QFrame(parent) @@ -40,6 +43,26 @@ void CSVWidget::ColorPickerPopup::showPicker(const QPoint &position, const QColo show(); } +void CSVWidget::ColorPickerPopup::mousePressEvent(QMouseEvent *event) +{ + QPushButton *button = qobject_cast(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); diff --git a/apps/opencs/view/widget/colorpickerpopup.hpp b/apps/opencs/view/widget/colorpickerpopup.hpp index a7aec3bad..602bbdb6d 100644 --- a/apps/opencs/view/widget/colorpickerpopup.hpp +++ b/apps/opencs/view/widget/colorpickerpopup.hpp @@ -19,6 +19,7 @@ namespace CSVWidget 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); From ed0942422370e5e99dc3f4eb6dfd4e74e38c0aff Mon Sep 17 00:00:00 2001 From: Stanislav Bas Date: Wed, 17 Jun 2015 00:45:43 +0300 Subject: [PATCH 11/30] Correct the position of the colored rectangle in ColorEditor and ColorDelegate --- apps/opencs/view/widget/coloreditor.cpp | 8 ++++---- apps/opencs/view/world/colordelegate.cpp | 8 ++++---- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/apps/opencs/view/widget/coloreditor.cpp b/apps/opencs/view/widget/coloreditor.cpp index b31225962..798502196 100644 --- a/apps/opencs/view/widget/coloreditor.cpp +++ b/apps/opencs/view/widget/coloreditor.cpp @@ -25,10 +25,10 @@ void CSVWidget::ColorEditor::paintEvent(QPaintEvent *event) QPushButton::paintEvent(event); QRect buttonRect = rect(); - QRect coloredRect(qRound(buttonRect.x() + buttonRect.width() / 4.0), - qRound(buttonRect.y() + buttonRect.height() / 4.0), - qRound(buttonRect.width() / 2.0), - qRound(buttonRect.height() / 2.0)); + 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); diff --git a/apps/opencs/view/world/colordelegate.cpp b/apps/opencs/view/world/colordelegate.cpp index ae71f965a..1a89fc675 100644 --- a/apps/opencs/view/world/colordelegate.cpp +++ b/apps/opencs/view/world/colordelegate.cpp @@ -15,10 +15,10 @@ void CSVWorld::ColorDelegate::paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const { - QRect coloredRect(qRound(option.rect.x() + option.rect.width() / 4.0), - qRound(option.rect.y() + option.rect.height() / 4.0), - qRound(option.rect.width() / 2.0), - qRound(option.rect.height() / 2.0)); + 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()); painter->setPen(Qt::black); From cf487581f79a917c4c68b1fe3b65d38110a3d520 Mon Sep 17 00:00:00 2001 From: Stanislav Bas Date: Thu, 18 Jun 2015 12:50:46 +0300 Subject: [PATCH 12/30] Show the pop-up of ColorEditor immediately after the editor creation in tables --- apps/opencs/view/widget/coloreditor.cpp | 17 +++++++++++++++-- apps/opencs/view/widget/coloreditor.hpp | 6 ++++-- apps/opencs/view/world/util.cpp | 6 ++++++ 3 files changed, 25 insertions(+), 4 deletions(-) diff --git a/apps/opencs/view/widget/coloreditor.cpp b/apps/opencs/view/widget/coloreditor.cpp index 798502196..7ef1ec7b1 100644 --- a/apps/opencs/view/widget/coloreditor.cpp +++ b/apps/opencs/view/widget/coloreditor.cpp @@ -6,13 +6,15 @@ #include #include #include +#include #include "colorpickerpopup.hpp" -CSVWidget::ColorEditor::ColorEditor(const QColor &color, QWidget *parent) +CSVWidget::ColorEditor::ColorEditor(const QColor &color, QWidget *parent, bool popupOnStart) : QPushButton(parent), mColor(color), - mColorPicker(new ColorPickerPopup(this)) + mColorPicker(new ColorPickerPopup(this)), + mPopupOnStart(popupOnStart) { setCheckable(true); connect(this, SIGNAL(clicked()), this, SLOT(showPicker())); @@ -35,6 +37,17 @@ void CSVWidget::ColorEditor::paintEvent(QPaintEvent *event) 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; diff --git a/apps/opencs/view/widget/coloreditor.hpp b/apps/opencs/view/widget/coloreditor.hpp index cca26fade..61232cb13 100644 --- a/apps/opencs/view/widget/coloreditor.hpp +++ b/apps/opencs/view/widget/coloreditor.hpp @@ -17,17 +17,19 @@ namespace CSVWidget QColor mColor; ColorPickerPopup *mColorPicker; + bool mPopupOnStart; QPoint calculatePopupPosition(); public: - ColorEditor(const QColor &color, QWidget *parent = 0); + ColorEditor(const QColor &color, QWidget *parent = 0, bool popupOnStart = false); QColor color() const; void setColor(const QColor &color); protected: - void paintEvent(QPaintEvent *event); + virtual void paintEvent(QPaintEvent *event); + virtual void showEvent(QShowEvent *event); private slots: void showPicker(); diff --git a/apps/opencs/view/world/util.cpp b/apps/opencs/view/world/util.cpp index de088bffc..5974987c0 100644 --- a/apps/opencs/view/world/util.cpp +++ b/apps/opencs/view/world/util.cpp @@ -172,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(), parent, true); + } return createEditor (parent, option, index, display); } From 88d1f158d0978df8793af92069fbd128481451cb Mon Sep 17 00:00:00 2001 From: Marc Zinnschlag Date: Thu, 18 Jun 2015 16:36:27 +0200 Subject: [PATCH 13/30] made double click behaviour in report tables configurable (Fixes #2622) --- apps/opencs/model/settings/usersettings.cpp | 41 +++++++++++++++ apps/opencs/view/tools/reporttable.cpp | 57 +++++++++++++++++++-- apps/opencs/view/tools/reporttable.hpp | 11 ++++ 3 files changed, 104 insertions(+), 5 deletions(-) diff --git a/apps/opencs/model/settings/usersettings.cpp b/apps/opencs/model/settings/usersettings.cpp index 5b6e7ab8b..d1dddf8ba 100644 --- a/apps/opencs/model/settings/usersettings.cpp +++ b/apps/opencs/model/settings/usersettings.cpp @@ -234,6 +234,47 @@ void CSMSettings::UserSettings::buildSettingModelDefaults() jumpToAdded->setDeclaredValues (jumpValues); } + declareSection ("report-input", "Report Input"); + { + QString none ("None"); + QString edit ("Edit"); + QString remove ("Remove"); + QString editAndRemove ("Edit And Remove"); + + QStringList values; + values << none << edit << remove << editAndRemove; + + QString toolTip = "
    " + "
  • None
  • " + "
  • Edit: Open a table or dialogue suitable for addressing the listed report
  • " + "
  • Remove: Remove the report from the report table
  • " + "
  • Edit and Remove: Open a table or dialogue suitable for addressing the listed report, then remove the report from the report table
  • " + "
"; + + Setting *doubleClick = createSetting (Type_ComboBox, "double", "Double Click"); + doubleClick->setDeclaredValues (values); + doubleClick->setDefaultValue (edit); + doubleClick->setToolTip ("Action on double click in report table:

" + toolTip); + + Setting *shiftDoubleClick = createSetting (Type_ComboBox, "double-s", + "Shift Double Click"); + shiftDoubleClick->setDeclaredValues (values); + shiftDoubleClick->setDefaultValue (remove); + shiftDoubleClick->setToolTip ("Action on shift double click in report table:

" + toolTip); + + Setting *ctrlDoubleClick = createSetting (Type_ComboBox, "double-c", + "Control Double Click"); + ctrlDoubleClick->setDeclaredValues (values); + ctrlDoubleClick->setDefaultValue (editAndRemove); + ctrlDoubleClick->setToolTip ("Action on control double click in report table:

" + toolTip); + + Setting *shiftCtrlDoubleClick = createSetting (Type_ComboBox, "double-sc", + "Shift Control Double Click"); + shiftCtrlDoubleClick->setDeclaredValues (values); + shiftCtrlDoubleClick->setDefaultValue (none); + shiftCtrlDoubleClick->setToolTip ("Action on shift control double click in report table:

" + toolTip); + } + declareSection ("search", "Search & Replace"); { Setting *before = createSetting (Type_SpinBox, "char-before", diff --git a/apps/opencs/view/tools/reporttable.cpp b/apps/opencs/view/tools/reporttable.cpp index c1c8a35dd..e530e1159 100644 --- a/apps/opencs/view/tools/reporttable.cpp +++ b/apps/opencs/view/tools/reporttable.cpp @@ -96,21 +96,35 @@ void CSVTools::ReportTable::mouseDoubleClickEvent (QMouseEvent *event) selectionModel()->select (index, QItemSelectionModel::Clear | QItemSelectionModel::Select | QItemSelectionModel::Rows); - switch (modifiers) + std::map::iterator iter = + mDoubleClickActions.find (modifiers); + + if (iter==mDoubleClickActions.end()) + { + event->accept(); + return; + } + + switch (iter->second) { - case 0: + case Action_None: + + event->accept(); + break; + + case Action_Edit: event->accept(); showSelection(); break; - case Qt::ShiftModifier: + case Action_Remove: event->accept(); removeSelection(); break; - case Qt::ControlModifier: + case Action_EditAndRemove: event->accept(); showSelection(); @@ -155,7 +169,11 @@ CSVTools::ReportTable::ReportTable (CSMDoc::Document& document, mReplaceAction = new QAction (tr ("Replace"), this); connect (mReplaceAction, SIGNAL (triggered()), this, SIGNAL (replaceRequest())); - addAction (mReplaceAction); + addAction (mReplaceAction); + + mDoubleClickActions.insert (std::make_pair (Qt::NoModifier, Action_Edit)); + mDoubleClickActions.insert (std::make_pair (Qt::ShiftModifier, Action_Remove)); + mDoubleClickActions.insert (std::make_pair (Qt::ControlModifier, Action_EditAndRemove)); } std::vector CSVTools::ReportTable::getDraggedRecords() const @@ -176,6 +194,35 @@ std::vector CSVTools::ReportTable::getDraggedRecords() co void CSVTools::ReportTable::updateUserSetting (const QString& name, const QStringList& list) { mIdTypeDelegate->updateUserSetting (name, list); + + QString base ("report-input/double"); + if (name.startsWith (base)) + { + QString modifierString = name.mid (base.size()); + Qt::KeyboardModifiers modifiers = 0; + + if (modifierString=="-s") + modifiers = Qt::ShiftModifier; + else if (modifierString=="-c") + modifiers = Qt::ControlModifier; + else if (modifierString=="-sc") + modifiers = Qt::ShiftModifier | Qt::ControlModifier; + + DoubleClickAction action = Action_None; + + QString value = list.at (0); + + if (value=="Edit") + action = Action_Edit; + else if (value=="Remove") + action = Action_Remove; + else if (value=="Edit And Remove") + action = Action_EditAndRemove; + + mDoubleClickActions[modifiers] = action; + + return; + } } std::vector CSVTools::ReportTable::getReplaceIndices (bool selection) const diff --git a/apps/opencs/view/tools/reporttable.hpp b/apps/opencs/view/tools/reporttable.hpp index c4d5b414e..95ab07cbb 100644 --- a/apps/opencs/view/tools/reporttable.hpp +++ b/apps/opencs/view/tools/reporttable.hpp @@ -1,6 +1,8 @@ #ifndef CSV_TOOLS_REPORTTABLE_H #define CSV_TOOLS_REPORTTABLE_H +#include + #include "../world/dragrecordtable.hpp" class QAction; @@ -21,11 +23,20 @@ namespace CSVTools { Q_OBJECT + enum DoubleClickAction + { + Action_None, + Action_Edit, + Action_Remove, + Action_EditAndRemove + }; + CSMTools::ReportModel *mModel; CSVWorld::CommandDelegate *mIdTypeDelegate; QAction *mShowAction; QAction *mRemoveAction; QAction *mReplaceAction; + std::map mDoubleClickActions; private: From 36271f25ec1d228f7f990c15b509bafbb82df703 Mon Sep 17 00:00:00 2001 From: Stanislav Bas Date: Thu, 18 Jun 2015 22:59:40 +0300 Subject: [PATCH 14/30] Rework creator factories to accept Document as a parameter --- apps/opencs/view/world/creator.cpp | 4 ++-- apps/opencs/view/world/creator.hpp | 25 ++++++++-------------- apps/opencs/view/world/dialoguecreator.cpp | 14 ++++++------ apps/opencs/view/world/dialoguecreator.hpp | 6 ++---- apps/opencs/view/world/dialoguesubview.cpp | 3 +-- apps/opencs/view/world/genericcreator.hpp | 2 ++ apps/opencs/view/world/scenesubview.cpp | 4 +--- apps/opencs/view/world/tablebottombox.cpp | 8 ++++--- apps/opencs/view/world/tablebottombox.hpp | 11 +++++----- apps/opencs/view/world/tablesubview.cpp | 2 +- 10 files changed, 37 insertions(+), 42 deletions(-) diff --git a/apps/opencs/view/world/creator.cpp b/apps/opencs/view/world/creator.cpp index 2e7c7fe22..7a8c8d48f 100644 --- a/apps/opencs/view/world/creator.cpp +++ b/apps/opencs/view/world/creator.cpp @@ -15,8 +15,8 @@ void CSVWorld::Creator::setScope (unsigned int scope) CSVWorld::CreatorFactoryBase::~CreatorFactoryBase() {} -CSVWorld::Creator *CSVWorld::NullCreatorFactory::makeCreator (CSMWorld::Data& data, - QUndoStack& undoStack, const CSMWorld::UniversalId& id) const +CSVWorld::Creator *CSVWorld::NullCreatorFactory::makeCreator (CSMDoc::Document& document, + const CSMWorld::UniversalId& id) const { return 0; } diff --git a/apps/opencs/view/world/creator.hpp b/apps/opencs/view/world/creator.hpp index 506bdab2c..b2d80cf2f 100644 --- a/apps/opencs/view/world/creator.hpp +++ b/apps/opencs/view/world/creator.hpp @@ -5,16 +5,12 @@ #include -#include "../../model/world/universalid.hpp" - #include "../../model/world/scope.hpp" +#include "../../model/world/universalid.hpp" -class QUndoStack; - -namespace CSMWorld +namespace CSMDoc { - class Data; - class UniversalId; + class Document; } namespace CSVWorld @@ -59,8 +55,7 @@ namespace CSVWorld virtual ~CreatorFactoryBase(); - virtual Creator *makeCreator (CSMWorld::Data& data, QUndoStack& undoStack, - const CSMWorld::UniversalId& id) const = 0; + virtual Creator *makeCreator (CSMDoc::Document& document, const CSMWorld::UniversalId& id) const = 0; ///< The ownership of the returned Creator is transferred to the caller. /// /// \note The function can return a 0-pointer, which means no UI for creating/deleting @@ -72,8 +67,7 @@ namespace CSVWorld { public: - virtual Creator *makeCreator (CSMWorld::Data& data, QUndoStack& undoStack, - const CSMWorld::UniversalId& id) const; + virtual Creator *makeCreator (CSMDoc::Document& document, const CSMWorld::UniversalId& id) const; ///< The ownership of the returned Creator is transferred to the caller. /// /// \note The function always returns 0. @@ -84,8 +78,7 @@ namespace CSVWorld { public: - virtual Creator *makeCreator (CSMWorld::Data& data, QUndoStack& undoStack, - const CSMWorld::UniversalId& id) const; + virtual Creator *makeCreator (CSMDoc::Document& document, const CSMWorld::UniversalId& id) const; ///< The ownership of the returned Creator is transferred to the caller. /// /// \note The function can return a 0-pointer, which means no UI for creating/deleting @@ -93,10 +86,10 @@ namespace CSVWorld }; template - Creator *CreatorFactory::makeCreator (CSMWorld::Data& data, QUndoStack& undoStack, - const CSMWorld::UniversalId& id) const + Creator *CreatorFactory::makeCreator (CSMDoc::Document& document, + const CSMWorld::UniversalId& id) const { - std::auto_ptr creator (new CreatorT (data, undoStack, id)); + std::auto_ptr creator (new CreatorT (document.getData(), document.getUndoStack(), id)); creator->setScope (scope); diff --git a/apps/opencs/view/world/dialoguecreator.cpp b/apps/opencs/view/world/dialoguecreator.cpp index 956cd26df..3d451ed2d 100644 --- a/apps/opencs/view/world/dialoguecreator.cpp +++ b/apps/opencs/view/world/dialoguecreator.cpp @@ -3,6 +3,8 @@ #include +#include "../../model/doc/document.hpp" + #include "../../model/world/data.hpp" #include "../../model/world/commands.hpp" #include "../../model/world/columns.hpp" @@ -22,14 +24,14 @@ CSVWorld::DialogueCreator::DialogueCreator (CSMWorld::Data& data, QUndoStack& un : GenericCreator (data, undoStack, id, true), mType (type) {} -CSVWorld::Creator *CSVWorld::TopicCreatorFactory::makeCreator (CSMWorld::Data& data, - QUndoStack& undoStack, const CSMWorld::UniversalId& id) const +CSVWorld::Creator *CSVWorld::TopicCreatorFactory::makeCreator (CSMDoc::Document& document, + const CSMWorld::UniversalId& id) const { - return new DialogueCreator (data, undoStack, id, ESM::Dialogue::Topic); + return new DialogueCreator (document.getData(), document.getUndoStack(), id, ESM::Dialogue::Topic); } -CSVWorld::Creator *CSVWorld::JournalCreatorFactory::makeCreator (CSMWorld::Data& data, - QUndoStack& undoStack, const CSMWorld::UniversalId& id) const +CSVWorld::Creator *CSVWorld::JournalCreatorFactory::makeCreator (CSMDoc::Document& document, + const CSMWorld::UniversalId& id) const { - return new DialogueCreator (data, undoStack, id, ESM::Dialogue::Journal); + return new DialogueCreator (document.getData(), document.getUndoStack(), id, ESM::Dialogue::Journal); } diff --git a/apps/opencs/view/world/dialoguecreator.hpp b/apps/opencs/view/world/dialoguecreator.hpp index 26f866909..20430fdb6 100644 --- a/apps/opencs/view/world/dialoguecreator.hpp +++ b/apps/opencs/view/world/dialoguecreator.hpp @@ -23,8 +23,7 @@ namespace CSVWorld { public: - virtual Creator *makeCreator (CSMWorld::Data& data, QUndoStack& undoStack, - const CSMWorld::UniversalId& id) const; + virtual Creator *makeCreator (CSMDoc::Document& document, const CSMWorld::UniversalId& id) const; ///< The ownership of the returned Creator is transferred to the caller. }; @@ -32,8 +31,7 @@ namespace CSVWorld { public: - virtual Creator *makeCreator (CSMWorld::Data& data, QUndoStack& undoStack, - const CSMWorld::UniversalId& id) const; + virtual Creator *makeCreator (CSMDoc::Document& document, const CSMWorld::UniversalId& id) const; ///< The ownership of the returned Creator is transferred to the caller. }; } diff --git a/apps/opencs/view/world/dialoguesubview.cpp b/apps/opencs/view/world/dialoguesubview.cpp index ab466dfcd..5d9eda3f2 100644 --- a/apps/opencs/view/world/dialoguesubview.cpp +++ b/apps/opencs/view/world/dialoguesubview.cpp @@ -685,8 +685,7 @@ CSVWorld::DialogueSubView::DialogueSubView (const CSMWorld::UniversalId& id, CSM mMainLayout->addWidget(mEditWidget); mEditWidget->setSizePolicy(QSizePolicy::MinimumExpanding, QSizePolicy::MinimumExpanding); - mMainLayout->addWidget (mBottom = - new TableBottomBox (creatorFactory, document.getData(), document.getUndoStack(), id, this)); + mMainLayout->addWidget (mBottom = new TableBottomBox (creatorFactory, document, id, this)); mBottom->setSizePolicy(QSizePolicy::Ignored, QSizePolicy::Fixed); diff --git a/apps/opencs/view/world/genericcreator.hpp b/apps/opencs/view/world/genericcreator.hpp index 1f854c69e..0d2a40486 100644 --- a/apps/opencs/view/world/genericcreator.hpp +++ b/apps/opencs/view/world/genericcreator.hpp @@ -13,10 +13,12 @@ class QLineEdit; class QHBoxLayout; class QComboBox; class QLabel; +class QUndoStack; namespace CSMWorld { class CreateCommand; + class Data; } namespace CSVWorld diff --git a/apps/opencs/view/world/scenesubview.cpp b/apps/opencs/view/world/scenesubview.cpp index aa2161259..397d24929 100644 --- a/apps/opencs/view/world/scenesubview.cpp +++ b/apps/opencs/view/world/scenesubview.cpp @@ -33,9 +33,7 @@ CSVWorld::SceneSubView::SceneSubView (const CSMWorld::UniversalId& id, CSMDoc::D layout->setContentsMargins (QMargins (0, 0, 0, 0)); - layout->addWidget (mBottom = - new TableBottomBox (NullCreatorFactory(), document.getData(), document.getUndoStack(), id, - this), 0); + layout->addWidget (mBottom = new TableBottomBox (NullCreatorFactory(), document, id, this), 0); mLayout->setContentsMargins (QMargins (0, 0, 0, 0)); diff --git a/apps/opencs/view/world/tablebottombox.cpp b/apps/opencs/view/world/tablebottombox.cpp index e9d644f61..dc3a6cc76 100644 --- a/apps/opencs/view/world/tablebottombox.cpp +++ b/apps/opencs/view/world/tablebottombox.cpp @@ -39,8 +39,10 @@ void CSVWorld::TableBottomBox::updateStatus() } } -CSVWorld::TableBottomBox::TableBottomBox (const CreatorFactoryBase& creatorFactory, - CSMWorld::Data& data, QUndoStack& undoStack, const CSMWorld::UniversalId& id, QWidget *parent) +CSVWorld::TableBottomBox::TableBottomBox (const CreatorFactoryBase& creatorFactory, + CSMDoc::Document& document, + const CSMWorld::UniversalId& id, + QWidget *parent) : QWidget (parent), mShowStatusBar (false), mCreating (false) { for (int i=0; i<4; ++i) @@ -61,7 +63,7 @@ CSVWorld::TableBottomBox::TableBottomBox (const CreatorFactoryBase& creatorFacto setLayout (mLayout); - mCreator = creatorFactory.makeCreator (data, undoStack, id); + mCreator = creatorFactory.makeCreator (document, id); if (mCreator) { diff --git a/apps/opencs/view/world/tablebottombox.hpp b/apps/opencs/view/world/tablebottombox.hpp index 8f0d85163..a7d009c42 100644 --- a/apps/opencs/view/world/tablebottombox.hpp +++ b/apps/opencs/view/world/tablebottombox.hpp @@ -9,10 +9,9 @@ class QStackedLayout; class QStatusBar; class QUndoStack; -namespace CSMWorld +namespace CSMDoc { - class Data; - class UniversalId; + class Document; } namespace CSVWorld @@ -42,8 +41,10 @@ namespace CSVWorld public: - TableBottomBox (const CreatorFactoryBase& creatorFactory, CSMWorld::Data& data, - QUndoStack& undoStack, const CSMWorld::UniversalId& id, QWidget *parent = 0); + TableBottomBox (const CreatorFactoryBase& creatorFactory, + CSMDoc::Document& document, + const CSMWorld::UniversalId& id, + QWidget *parent = 0); virtual ~TableBottomBox(); diff --git a/apps/opencs/view/world/tablesubview.cpp b/apps/opencs/view/world/tablesubview.cpp index faff4c429..75671a50c 100644 --- a/apps/opencs/view/world/tablesubview.cpp +++ b/apps/opencs/view/world/tablesubview.cpp @@ -26,7 +26,7 @@ CSVWorld::TableSubView::TableSubView (const CSMWorld::UniversalId& id, CSMDoc::D layout->setContentsMargins (QMargins (0, 0, 0, 0)); layout->addWidget (mBottom = - new TableBottomBox (creatorFactory, document.getData(), document.getUndoStack(), id, this), 0); + new TableBottomBox (creatorFactory, document, id, this), 0); layout->insertWidget (0, mTable = new Table (id, mBottom->canCreateAndDelete(), sorting, document), 2); From a6734a0ea4857f28c5569e3bc9650b0e8f1e810a Mon Sep 17 00:00:00 2001 From: Stanislav Bas Date: Fri, 19 Jun 2015 11:50:02 +0300 Subject: [PATCH 15/30] Add Cell Id completion to ReferenceCreator --- apps/opencs/view/world/referencecreator.cpp | 15 ++++++++++++++- apps/opencs/view/world/referencecreator.hpp | 16 +++++++++++++++- apps/opencs/view/world/subviews.cpp | 4 ++-- 3 files changed, 31 insertions(+), 4 deletions(-) diff --git a/apps/opencs/view/world/referencecreator.cpp b/apps/opencs/view/world/referencecreator.cpp index e9bb04ba7..81efb17ab 100644 --- a/apps/opencs/view/world/referencecreator.cpp +++ b/apps/opencs/view/world/referencecreator.cpp @@ -4,10 +4,13 @@ #include #include +#include "../../model/doc/document.hpp" + #include "../../model/world/data.hpp" #include "../../model/world/commands.hpp" #include "../../model/world/columns.hpp" #include "../../model/world/idtable.hpp" +#include "../../model/world/idcompletionmanager.hpp" std::string CSVWorld::ReferenceCreator::getId() const { @@ -71,13 +74,14 @@ int CSVWorld::ReferenceCreator::getRefNumCount() const } CSVWorld::ReferenceCreator::ReferenceCreator (CSMWorld::Data& data, QUndoStack& undoStack, - const CSMWorld::UniversalId& id) + const CSMWorld::UniversalId& id, CSMWorld::IdCompletionManager &completionManager) : GenericCreator (data, undoStack, id) { QLabel *label = new QLabel ("Cell", this); insertBeforeButtons (label, false); mCell = new QLineEdit (this); + mCell->setCompleter(completionManager.getCompleter(CSMWorld::ColumnBase::Display_Cell).get()); insertBeforeButtons (mCell, true); setManualEditing (false); @@ -142,3 +146,12 @@ void CSVWorld::ReferenceCreator::cloneMode(const std::string& originId, CSVWorld::GenericCreator::cloneMode(originId, type); cellChanged(); //otherwise ok button will remain disabled } + +CSVWorld::Creator *CSVWorld::ReferenceCreatorFactory::makeCreator (CSMDoc::Document& document, + const CSMWorld::UniversalId& id) const +{ + return new ReferenceCreator(document.getData(), + document.getUndoStack(), + id, + document.getIdCompletionManager()); +} diff --git a/apps/opencs/view/world/referencecreator.hpp b/apps/opencs/view/world/referencecreator.hpp index 877307c29..7f56143c9 100644 --- a/apps/opencs/view/world/referencecreator.hpp +++ b/apps/opencs/view/world/referencecreator.hpp @@ -5,8 +5,14 @@ class QLineEdit; +namespace CSMWorld +{ + class IdCompletionManager; +} + namespace CSVWorld { + class ReferenceCreator : public GenericCreator { Q_OBJECT @@ -28,7 +34,7 @@ namespace CSVWorld public: ReferenceCreator (CSMWorld::Data& data, QUndoStack& undoStack, - const CSMWorld::UniversalId& id); + const CSMWorld::UniversalId& id, CSMWorld::IdCompletionManager &completionManager); virtual void cloneMode(const std::string& originId, const CSMWorld::UniversalId::Type type); @@ -46,6 +52,14 @@ namespace CSVWorld void cellChanged(); }; + + class ReferenceCreatorFactory : public CreatorFactoryBase + { + public: + + virtual Creator *makeCreator (CSMDoc::Document& document, const CSMWorld::UniversalId& id) const; + ///< The ownership of the returned Creator is transferred to the caller. + }; } #endif diff --git a/apps/opencs/view/world/subviews.cpp b/apps/opencs/view/world/subviews.cpp index e81da23e1..fa1b7cdc7 100644 --- a/apps/opencs/view/world/subviews.cpp +++ b/apps/opencs/view/world/subviews.cpp @@ -59,7 +59,7 @@ void CSVWorld::addSubViewFactories (CSVDoc::SubViewFactoryManager& manager) new CSVDoc::SubViewFactoryWithCreator >); manager.add (CSMWorld::UniversalId::Type_References, - new CSVDoc::SubViewFactoryWithCreator >); + new CSVDoc::SubViewFactoryWithCreator); manager.add (CSMWorld::UniversalId::Type_Topics, new CSVDoc::SubViewFactoryWithCreator); @@ -147,7 +147,7 @@ void CSVWorld::addSubViewFactories (CSVDoc::SubViewFactoryManager& manager) new CSVDoc::SubViewFactoryWithCreator > (false)); manager.add (CSMWorld::UniversalId::Type_Reference, - new CSVDoc::SubViewFactoryWithCreator > (false)); + new CSVDoc::SubViewFactoryWithCreator (false)); manager.add (CSMWorld::UniversalId::Type_Cell, new CSVDoc::SubViewFactoryWithCreator > (false)); From 581ba55db9f60e3edd027b7d5d18d6825b7ee9b8 Mon Sep 17 00:00:00 2001 From: Stanislav Bas Date: Fri, 19 Jun 2015 12:51:50 +0300 Subject: [PATCH 16/30] Add Topic/Journal Id completion to InfoCreator --- .../model/world/idcompletionmanager.cpp | 2 ++ apps/opencs/view/world/infocreator.cpp | 21 ++++++++++++++++++- apps/opencs/view/world/infocreator.hpp | 11 +++++++++- apps/opencs/view/world/subviews.cpp | 8 +++---- 4 files changed, 36 insertions(+), 6 deletions(-) diff --git a/apps/opencs/model/world/idcompletionmanager.cpp b/apps/opencs/model/world/idcompletionmanager.cpp index b59987cba..20cd8652c 100644 --- a/apps/opencs/model/world/idcompletionmanager.cpp +++ b/apps/opencs/model/world/idcompletionmanager.cpp @@ -24,6 +24,7 @@ namespace types[CSMWorld::ColumnBase::Display_Faction ] = CSMWorld::UniversalId::Type_Faction; types[CSMWorld::ColumnBase::Display_GlobalVariable ] = CSMWorld::UniversalId::Type_Global; types[CSMWorld::ColumnBase::Display_Icon ] = CSMWorld::UniversalId::Type_Icon; + types[CSMWorld::ColumnBase::Display_Journal ] = CSMWorld::UniversalId::Type_Journal; types[CSMWorld::ColumnBase::Display_Mesh ] = CSMWorld::UniversalId::Type_Mesh; types[CSMWorld::ColumnBase::Display_Miscellaneous ] = CSMWorld::UniversalId::Type_Referenceable; types[CSMWorld::ColumnBase::Display_Npc ] = CSMWorld::UniversalId::Type_Referenceable; @@ -37,6 +38,7 @@ namespace types[CSMWorld::ColumnBase::Display_Spell ] = CSMWorld::UniversalId::Type_Spell; types[CSMWorld::ColumnBase::Display_Static ] = CSMWorld::UniversalId::Type_Referenceable; types[CSMWorld::ColumnBase::Display_Texture ] = CSMWorld::UniversalId::Type_Texture; + types[CSMWorld::ColumnBase::Display_Topic ] = CSMWorld::UniversalId::Type_Topic; types[CSMWorld::ColumnBase::Display_Weapon ] = CSMWorld::UniversalId::Type_Referenceable; return types; diff --git a/apps/opencs/view/world/infocreator.cpp b/apps/opencs/view/world/infocreator.cpp index f88b9f0b9..7b8390900 100644 --- a/apps/opencs/view/world/infocreator.cpp +++ b/apps/opencs/view/world/infocreator.cpp @@ -9,10 +9,13 @@ #include +#include "../../model/doc/document.hpp" + #include "../../model/world/data.hpp" #include "../../model/world/commands.hpp" #include "../../model/world/columns.hpp" #include "../../model/world/idtable.hpp" +#include "../../model/world/idcompletionmanager.hpp" std::string CSVWorld::InfoCreator::getId() const { @@ -39,13 +42,20 @@ void CSVWorld::InfoCreator::configureCreateCommand (CSMWorld::CreateCommand& com } CSVWorld::InfoCreator::InfoCreator (CSMWorld::Data& data, QUndoStack& undoStack, - const CSMWorld::UniversalId& id) + const CSMWorld::UniversalId& id, CSMWorld::IdCompletionManager& completionManager) : GenericCreator (data, undoStack, id) { QLabel *label = new QLabel ("Topic", this); insertBeforeButtons (label, false); mTopic = new QLineEdit (this); + CSMWorld::ColumnBase::Display displayType = CSMWorld::ColumnBase::Display_Topic; + if (id.getType() == CSMWorld::UniversalId::Type_JournalInfo || // For Dialogue SubView + id.getType() == CSMWorld::UniversalId::Type_JournalInfos) // For Table SubView + { + displayType = CSMWorld::ColumnBase::Display_Journal; + } + mTopic->setCompleter(completionManager.getCompleter(displayType).get()); insertBeforeButtons (mTopic, true); setManualEditing (false); @@ -100,3 +110,12 @@ void CSVWorld::InfoCreator::topicChanged() { update(); } + +CSVWorld::Creator *CSVWorld::InfoCreatorFactory::makeCreator(CSMDoc::Document& document, + const CSMWorld::UniversalId& id) const +{ + return new InfoCreator(document.getData(), + document.getUndoStack(), + id, + document.getIdCompletionManager()); +} diff --git a/apps/opencs/view/world/infocreator.hpp b/apps/opencs/view/world/infocreator.hpp index edc12975c..1928004bb 100644 --- a/apps/opencs/view/world/infocreator.hpp +++ b/apps/opencs/view/world/infocreator.hpp @@ -8,6 +8,7 @@ class QLineEdit; namespace CSMWorld { class InfoCollection; + class IdCompletionManager; } namespace CSVWorld @@ -25,7 +26,7 @@ namespace CSVWorld public: InfoCreator (CSMWorld::Data& data, QUndoStack& undoStack, - const CSMWorld::UniversalId& id); + const CSMWorld::UniversalId& id, CSMWorld::IdCompletionManager& completionManager); virtual void cloneMode (const std::string& originId, const CSMWorld::UniversalId::Type type); @@ -43,6 +44,14 @@ namespace CSVWorld void topicChanged(); }; + + class InfoCreatorFactory : public CreatorFactoryBase + { + public: + + virtual Creator *makeCreator (CSMDoc::Document& document, const CSMWorld::UniversalId& id) const; + ///< The ownership of the returned Creator is transferred to the caller. + }; } #endif diff --git a/apps/opencs/view/world/subviews.cpp b/apps/opencs/view/world/subviews.cpp index fa1b7cdc7..ba3ab1358 100644 --- a/apps/opencs/view/world/subviews.cpp +++ b/apps/opencs/view/world/subviews.cpp @@ -68,10 +68,10 @@ void CSVWorld::addSubViewFactories (CSVDoc::SubViewFactoryManager& manager) new CSVDoc::SubViewFactoryWithCreator); manager.add (CSMWorld::UniversalId::Type_TopicInfos, - new CSVDoc::SubViewFactoryWithCreator >); + new CSVDoc::SubViewFactoryWithCreator); manager.add (CSMWorld::UniversalId::Type_JournalInfos, - new CSVDoc::SubViewFactoryWithCreator >); + new CSVDoc::SubViewFactoryWithCreator); // Subviews for resources tables manager.add (CSMWorld::UniversalId::Type_Meshes, @@ -153,10 +153,10 @@ void CSVWorld::addSubViewFactories (CSVDoc::SubViewFactoryManager& manager) new CSVDoc::SubViewFactoryWithCreator > (false)); manager.add (CSMWorld::UniversalId::Type_JournalInfo, - new CSVDoc::SubViewFactoryWithCreator > (false)); + new CSVDoc::SubViewFactoryWithCreator (false)); manager.add (CSMWorld::UniversalId::Type_TopicInfo, - new CSVDoc::SubViewFactoryWithCreator >(false)); + new CSVDoc::SubViewFactoryWithCreator(false)); manager.add (CSMWorld::UniversalId::Type_Topic, new CSVDoc::SubViewFactoryWithCreator (false)); From e212414bc7825febb7f90b9a0aa47bd3d45f10b3 Mon Sep 17 00:00:00 2001 From: Stanislav Bas Date: Fri, 19 Jun 2015 13:48:58 +0300 Subject: [PATCH 17/30] Use an ID parent type as the collection ID in GenericCreator. Fix impossibility of creation/cloning records from Dialogue subviews in Info tables --- apps/opencs/view/world/genericcreator.cpp | 9 +++++++++ apps/opencs/view/world/infocreator.cpp | 3 +-- 2 files changed, 10 insertions(+), 2 deletions(-) diff --git a/apps/opencs/view/world/genericcreator.cpp b/apps/opencs/view/world/genericcreator.cpp index a123e127f..c64109608 100644 --- a/apps/opencs/view/world/genericcreator.cpp +++ b/apps/opencs/view/world/genericcreator.cpp @@ -133,6 +133,15 @@ CSVWorld::GenericCreator::GenericCreator (CSMWorld::Data& data, QUndoStack& undo mClonedType (CSMWorld::UniversalId::Type_None), mScopes (CSMWorld::Scope_Content), mScope (0), mScopeLabel (0), mCloneMode (false) { + // If the collection ID has a parent type, use it instead. + // It will change IDs with Record/SubRecord class (used for creators in Dialogue subviews) + // to IDs with general RecordList class (used for creators in Table subviews). + CSMWorld::UniversalId::Type listParentType = CSMWorld::UniversalId::getParentType(mListId.getType()); + if (listParentType != CSMWorld::UniversalId::Type_None) + { + mListId = listParentType; + } + mLayout = new QHBoxLayout; mLayout->setContentsMargins (0, 0, 0, 0); diff --git a/apps/opencs/view/world/infocreator.cpp b/apps/opencs/view/world/infocreator.cpp index 7b8390900..916427fc2 100644 --- a/apps/opencs/view/world/infocreator.cpp +++ b/apps/opencs/view/world/infocreator.cpp @@ -50,8 +50,7 @@ CSVWorld::InfoCreator::InfoCreator (CSMWorld::Data& data, QUndoStack& undoStack, mTopic = new QLineEdit (this); CSMWorld::ColumnBase::Display displayType = CSMWorld::ColumnBase::Display_Topic; - if (id.getType() == CSMWorld::UniversalId::Type_JournalInfo || // For Dialogue SubView - id.getType() == CSMWorld::UniversalId::Type_JournalInfos) // For Table SubView + if (getCollectionId().getType() == CSMWorld::UniversalId::Type_JournalInfos) { displayType = CSMWorld::ColumnBase::Display_Journal; } From 8aba52170f000c47960bbe854481c58a1050a6fd Mon Sep 17 00:00:00 2001 From: Marc Zinnschlag Date: Sat, 20 Jun 2015 11:34:32 +0200 Subject: [PATCH 18/30] fixed a build error --- apps/opencs/view/world/creator.hpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/apps/opencs/view/world/creator.hpp b/apps/opencs/view/world/creator.hpp index b2d80cf2f..b76348199 100644 --- a/apps/opencs/view/world/creator.hpp +++ b/apps/opencs/view/world/creator.hpp @@ -5,6 +5,8 @@ #include +#include "../../model/doc/document.hpp" + #include "../../model/world/scope.hpp" #include "../../model/world/universalid.hpp" From 1ee1934053e389f2e18f1c1e7bb67b1d239854c7 Mon Sep 17 00:00:00 2001 From: Marc Zinnschlag Date: Sat, 20 Jun 2015 14:21:52 +0200 Subject: [PATCH 19/30] framework for accessing user settings in operation stages --- apps/opencs/model/doc/operation.cpp | 32 ++++++++++++++++++++--- apps/opencs/model/doc/operation.hpp | 11 ++++++++ apps/opencs/model/doc/operationholder.cpp | 5 ++++ apps/opencs/model/doc/stage.cpp | 2 ++ apps/opencs/model/doc/stage.hpp | 5 ++++ 5 files changed, 52 insertions(+), 3 deletions(-) diff --git a/apps/opencs/model/doc/operation.cpp b/apps/opencs/model/doc/operation.cpp index 3f1674f50..4a39d2911 100644 --- a/apps/opencs/model/doc/operation.cpp +++ b/apps/opencs/model/doc/operation.cpp @@ -7,6 +7,7 @@ #include #include "../world/universalid.hpp" +#include "../settings/usersettings.hpp" #include "state.hpp" #include "stage.hpp" @@ -23,13 +24,16 @@ void CSMDoc::Operation::prepareStages() { iter->second = iter->first->setup(); mTotalSteps += iter->second; + + for (std::map::const_iterator iter2 (mSettings.begin()); iter2!=mSettings.end(); ++iter2) + iter->first->updateUserSetting (iter2->first, iter2->second); } } CSMDoc::Operation::Operation (int type, bool ordered, bool finalAlways) : mType (type), mStages(std::vector >()), mCurrentStage(mStages.begin()), mCurrentStep(0), mCurrentStepTotal(0), mTotalSteps(0), mOrdered (ordered), - mFinalAlways (finalAlways), mError(false), mConnected (false) + mFinalAlways (finalAlways), mError(false), mConnected (false), mPrepared (false) { mTimer = new QTimer (this); } @@ -49,8 +53,8 @@ void CSMDoc::Operation::run() connect (mTimer, SIGNAL (timeout()), this, SLOT (executeStage())); mConnected = true; } - - prepareStages(); + + mPrepared = false; mTimer->start (0); } @@ -60,6 +64,14 @@ void CSMDoc::Operation::appendStage (Stage *stage) mStages.push_back (std::make_pair (stage, 0)); } +void CSMDoc::Operation::configureSettings (const std::vector& settings) +{ + for (std::vector::const_iterator iter (settings.begin()); iter!=settings.end(); ++iter) + { + mSettings.insert (std::make_pair (*iter, CSMSettings::UserSettings::instance().definitions (*iter))); + } +} + bool CSMDoc::Operation::hasError() const { return mError; @@ -84,8 +96,22 @@ void CSMDoc::Operation::abort() mCurrentStage = mStages.end(); } +void CSMDoc::Operation::updateUserSetting (const QString& name, const QStringList& value) +{ + std::map::iterator iter = mSettings.find (name); + + if (iter!=mSettings.end()) + iter->second = value; +} + void CSMDoc::Operation::executeStage() { + if (!mPrepared) + { + prepareStages(); + mPrepared = true; + } + Messages messages; while (mCurrentStage!=mStages.end()) diff --git a/apps/opencs/model/doc/operation.hpp b/apps/opencs/model/doc/operation.hpp index a6217fe2d..6d6ed112b 100644 --- a/apps/opencs/model/doc/operation.hpp +++ b/apps/opencs/model/doc/operation.hpp @@ -2,9 +2,11 @@ #define CSM_DOC_OPERATION_H #include +#include #include #include +#include namespace CSMWorld { @@ -30,6 +32,8 @@ namespace CSMDoc bool mError; bool mConnected; QTimer *mTimer; + std::map mSettings; + bool mPrepared; void prepareStages(); @@ -46,6 +50,11 @@ namespace CSMDoc /// /// \attention Do no call this function while this Operation is running. + /// Specify settings to be passed on to stages. + /// + /// \attention Do no call this function while this Operation is running. + void configureSettings (const std::vector& settings); + bool hasError() const; signals: @@ -63,6 +72,8 @@ namespace CSMDoc void run(); + void updateUserSetting (const QString& name, const QStringList& value); + private slots: void executeStage(); diff --git a/apps/opencs/model/doc/operationholder.cpp b/apps/opencs/model/doc/operationholder.cpp index d79e14023..5157fd80c 100644 --- a/apps/opencs/model/doc/operationholder.cpp +++ b/apps/opencs/model/doc/operationholder.cpp @@ -1,6 +1,8 @@ #include "operationholder.hpp" +#include "../settings/usersettings.hpp" + #include "operation.hpp" CSMDoc::OperationHolder::OperationHolder (Operation *operation) : mRunning (false) @@ -29,6 +31,9 @@ void CSMDoc::OperationHolder::setOperation (Operation *operation) connect (this, SIGNAL (abortSignal()), mOperation, SLOT (abort())); connect (&mThread, SIGNAL (started()), mOperation, SLOT (run())); + + connect (&CSMSettings::UserSettings::instance(), SIGNAL (userSettingUpdated (const QString&, const QStringList&)), + mOperation, SLOT (updateUserSetting (const QString&, const QStringList&))); } bool CSMDoc::OperationHolder::isRunning() const diff --git a/apps/opencs/model/doc/stage.cpp b/apps/opencs/model/doc/stage.cpp index 1a2c5c721..78aa14574 100644 --- a/apps/opencs/model/doc/stage.cpp +++ b/apps/opencs/model/doc/stage.cpp @@ -2,3 +2,5 @@ #include "stage.hpp" CSMDoc::Stage::~Stage() {} + +void CSMDoc::Stage::updateUserSetting (const QString& name, const QStringList& value) {} diff --git a/apps/opencs/model/doc/stage.hpp b/apps/opencs/model/doc/stage.hpp index 126823ae9..e0328a91a 100644 --- a/apps/opencs/model/doc/stage.hpp +++ b/apps/opencs/model/doc/stage.hpp @@ -8,6 +8,8 @@ #include "messages.hpp" +class QString; + namespace CSMDoc { class Stage @@ -21,6 +23,9 @@ namespace CSMDoc virtual void perform (int stage, Messages& messages) = 0; ///< Messages resulting from this stage will be appended to \a messages. + + /// Default-implementation: ignore + virtual void updateUserSetting (const QString& name, const QStringList& value); }; } From 9a102f81c8e7956e85c8f7599c2293c76f579a32 Mon Sep 17 00:00:00 2001 From: Marc Zinnschlag Date: Sat, 20 Jun 2015 16:21:04 +0200 Subject: [PATCH 20/30] added setting for controlling script compiler warnings --- apps/opencs/model/settings/usersettings.cpp | 16 +++++++++++++++- apps/opencs/model/tools/scriptcheck.cpp | 20 +++++++++++++++++++- apps/opencs/model/tools/scriptcheck.hpp | 10 ++++++++++ apps/opencs/model/tools/tools.cpp | 5 +++++ 4 files changed, 49 insertions(+), 2 deletions(-) diff --git a/apps/opencs/model/settings/usersettings.cpp b/apps/opencs/model/settings/usersettings.cpp index d1dddf8ba..78db5313b 100644 --- a/apps/opencs/model/settings/usersettings.cpp +++ b/apps/opencs/model/settings/usersettings.cpp @@ -293,7 +293,7 @@ void CSMSettings::UserSettings::buildSettingModelDefaults() autoDelete->setDefaultValue ("true"); } - declareSection ("script-editor", "Script Editor"); + declareSection ("script-editor", "Scripts"); { Setting *lineNum = createSetting (Type_CheckBox, "show-linenum", "Show Line Numbers"); lineNum->setDefaultValue ("true"); @@ -312,6 +312,20 @@ void CSMSettings::UserSettings::buildSettingModelDefaults() "\nA name from the list of colors defined in the list of SVG color keyword names." "\nX11 color names may also work."; + QString modeIgnore ("Ignore"); + + QStringList modes; + modes << modeIgnore << "Strict"; + + Setting *warnings = createSetting (Type_ComboBox, "warnings", + "Warning Mode"); + warnings->setDeclaredValues (modes); + warnings->setDefaultValue (modeIgnore); + warnings->setToolTip ("

    How to handle warning messages during compilation:

    " + "

  • Ignore: Do not report warning
  • " + "
  • Strict: Promote warning to an error
  • " + "
"); + Setting *formatInt = createSetting (Type_LineEdit, "colour-int", "Highlight Colour: Int"); formatInt->setDefaultValues (QStringList() << "Dark magenta"); formatInt->setToolTip ("(Default: Green) Use one of the following formats:" + tooltip); diff --git a/apps/opencs/model/tools/scriptcheck.cpp b/apps/opencs/model/tools/scriptcheck.cpp index a70ee2ae4..33922e9cf 100644 --- a/apps/opencs/model/tools/scriptcheck.cpp +++ b/apps/opencs/model/tools/scriptcheck.cpp @@ -44,7 +44,7 @@ void CSMTools::ScriptCheckStage::report (const std::string& message, Type type) } CSMTools::ScriptCheckStage::ScriptCheckStage (const CSMDoc::Document& document) -: mDocument (document), mContext (document.getData()), mMessages (0) +: mDocument (document), mContext (document.getData()), mMessages (0), mWarningMode (Mode_Ignore) { /// \todo add an option to configure warning mode setWarningsMode (0); @@ -58,6 +58,7 @@ int CSMTools::ScriptCheckStage::setup() mContext.clear(); mMessages = 0; mId.clear(); + Compiler::ErrorHandler::reset(); return mDocument.getData().getScripts().getSize(); } @@ -72,6 +73,12 @@ void CSMTools::ScriptCheckStage::perform (int stage, CSMDoc::Messages& messages) mMessages = &messages; + switch (mWarningMode) + { + case Mode_Ignore: setWarningsMode (0); break; + case Mode_Strict: setWarningsMode (1); break; + } + try { const CSMWorld::Data& data = mDocument.getData(); @@ -99,3 +106,14 @@ void CSMTools::ScriptCheckStage::perform (int stage, CSMDoc::Messages& messages) mMessages = 0; } + +void CSMTools::ScriptCheckStage::updateUserSetting (const QString& name, const QStringList& value) +{ + if (name=="script-editor/warnings") + { + if (value.at (0)=="Ignore") + mWarningMode = Mode_Ignore; + else if (value.at (0)=="Strict") + mWarningMode = Mode_Strict; + } +} diff --git a/apps/opencs/model/tools/scriptcheck.hpp b/apps/opencs/model/tools/scriptcheck.hpp index 3fe12fc9a..0d42b275c 100644 --- a/apps/opencs/model/tools/scriptcheck.hpp +++ b/apps/opencs/model/tools/scriptcheck.hpp @@ -18,13 +18,21 @@ namespace CSMTools /// \brief VerifyStage: make sure that scripts compile class ScriptCheckStage : public CSMDoc::Stage, private Compiler::ErrorHandler { + enum WarningMode + { + Mode_Ignore, + Mode_Strict + }; + const CSMDoc::Document& mDocument; Compiler::Extensions mExtensions; CSMWorld::ScriptContext mContext; std::string mId; std::string mFile; CSMDoc::Messages *mMessages; + WarningMode mWarningMode; + virtual void report (const std::string& message, const Compiler::TokenLoc& loc, Type type); ///< Report error to the user. @@ -40,6 +48,8 @@ namespace CSMTools virtual void perform (int stage, CSMDoc::Messages& messages); ///< Messages resulting from this tage will be appended to \a messages. + + virtual void updateUserSetting (const QString& name, const QStringList& value); }; } diff --git a/apps/opencs/model/tools/tools.cpp b/apps/opencs/model/tools/tools.cpp index 7d70abae5..fda373bcf 100644 --- a/apps/opencs/model/tools/tools.cpp +++ b/apps/opencs/model/tools/tools.cpp @@ -51,6 +51,11 @@ CSMDoc::OperationHolder *CSMTools::Tools::getVerifier() { mVerifierOperation = new CSMDoc::Operation (CSMDoc::State_Verifying, false); + std::vector settings; + settings.push_back ("script-editor/warnings"); + + mVerifierOperation->configureSettings (settings); + connect (&mVerifier, SIGNAL (progress (int, int, int)), this, SIGNAL (progress (int, int, int))); connect (&mVerifier, SIGNAL (done (int, bool)), this, SIGNAL (done (int, bool))); connect (&mVerifier, From 0e21c61297d8775740386634e28f60f51ee7dbe2 Mon Sep 17 00:00:00 2001 From: Marc Zinnschlag Date: Sat, 20 Jun 2015 16:55:34 +0200 Subject: [PATCH 21/30] replaced redundant CSMTools::ReportModel::Line struct with CSMDoc::Message struct --- apps/opencs/model/doc/messages.cpp | 13 +++++++------ apps/opencs/model/doc/messages.hpp | 18 ++++++++++++------ apps/opencs/model/tools/reportmodel.cpp | 9 ++------- apps/opencs/model/tools/reportmodel.hpp | 14 +++----------- 4 files changed, 24 insertions(+), 30 deletions(-) diff --git a/apps/opencs/model/doc/messages.cpp b/apps/opencs/model/doc/messages.cpp index 9b295fb28..3c709683e 100644 --- a/apps/opencs/model/doc/messages.cpp +++ b/apps/opencs/model/doc/messages.cpp @@ -1,15 +1,16 @@ #include "messages.hpp" +CSMDoc::Message::Message (const CSMWorld::UniversalId& id, const std::string& message, + const std::string& hint) +: mId (id), mMessage (message), mHint (hint) +{} + + void CSMDoc::Messages::add (const CSMWorld::UniversalId& id, const std::string& message, const std::string& hint) { - Message data; - data.mId = id; - data.mMessage = message; - data.mHint = hint; - - mMessages.push_back (data); + mMessages.push_back (Message (id, message, hint)); } void CSMDoc::Messages::push_back (const std::pair& data) diff --git a/apps/opencs/model/doc/messages.hpp b/apps/opencs/model/doc/messages.hpp index 0f36c73a7..4e143d869 100644 --- a/apps/opencs/model/doc/messages.hpp +++ b/apps/opencs/model/doc/messages.hpp @@ -8,16 +8,22 @@ namespace CSMDoc { + struct Message + { + CSMWorld::UniversalId mId; + std::string mMessage; + std::string mHint; + + Message (const CSMWorld::UniversalId& id, const std::string& message, + const std::string& hint); + }; + class Messages { public: - struct Message - { - CSMWorld::UniversalId mId; - std::string mMessage; - std::string mHint; - }; + // \deprecated Use CSMDoc::Message directly instead. + typedef CSMDoc::Message Message; typedef std::vector Collection; diff --git a/apps/opencs/model/tools/reportmodel.cpp b/apps/opencs/model/tools/reportmodel.cpp index 1248e202b..e661e9eac 100644 --- a/apps/opencs/model/tools/reportmodel.cpp +++ b/apps/opencs/model/tools/reportmodel.cpp @@ -6,11 +6,6 @@ #include "../world/columns.hpp" -CSMTools::ReportModel::Line::Line (const CSMWorld::UniversalId& id, const std::string& message, - const std::string& hint) -: mId (id), mMessage (message), mHint (hint) -{} - CSMTools::ReportModel::ReportModel (bool fieldColumn) { if (fieldColumn) @@ -137,14 +132,14 @@ void CSMTools::ReportModel::add (const CSMWorld::UniversalId& id, const std::str { beginInsertRows (QModelIndex(), mRows.size(), mRows.size()); - mRows.push_back (Line (id, message, hint)); + mRows.push_back (CSMDoc::Message (id, message, hint)); endInsertRows(); } void CSMTools::ReportModel::flagAsReplaced (int index) { - Line& line = mRows.at (index); + CSMDoc::Message& line = mRows.at (index); std::string hint = line.mHint; if (hint.empty() || hint[0]!='R') diff --git a/apps/opencs/model/tools/reportmodel.hpp b/apps/opencs/model/tools/reportmodel.hpp index 4d2d0542f..ff20f74a5 100644 --- a/apps/opencs/model/tools/reportmodel.hpp +++ b/apps/opencs/model/tools/reportmodel.hpp @@ -6,6 +6,8 @@ #include +#include "../doc/messages.hpp" + #include "../world/universalid.hpp" namespace CSMTools @@ -14,17 +16,7 @@ namespace CSMTools { Q_OBJECT - struct Line - { - Line (const CSMWorld::UniversalId& id, const std::string& message, - const std::string& hint); - - CSMWorld::UniversalId mId; - std::string mMessage; - std::string mHint; - }; - - std::vector mRows; + std::vector mRows; // Fixed columns enum Columns From 8791832c865b01f1d32f6b49d76febdb99caf8e2 Mon Sep 17 00:00:00 2001 From: Marc Zinnschlag Date: Sat, 20 Jun 2015 17:56:42 +0200 Subject: [PATCH 22/30] standarised on the use of the Message struct when passing operations messages around --- apps/opencs/main.cpp | 3 +++ apps/opencs/model/doc/document.cpp | 9 ++++----- apps/opencs/model/doc/document.hpp | 3 +-- apps/opencs/model/doc/loader.cpp | 3 ++- apps/opencs/model/doc/messages.cpp | 2 ++ apps/opencs/model/doc/messages.hpp | 6 ++++++ apps/opencs/model/doc/operation.cpp | 4 ++-- apps/opencs/model/doc/operation.hpp | 5 +++-- apps/opencs/model/doc/operationholder.cpp | 4 ++-- apps/opencs/model/doc/operationholder.hpp | 5 +++-- apps/opencs/model/tools/reportmodel.cpp | 5 ++--- apps/opencs/model/tools/reportmodel.hpp | 3 +-- apps/opencs/model/tools/tools.cpp | 15 ++++++--------- apps/opencs/model/tools/tools.hpp | 3 +-- 14 files changed, 38 insertions(+), 32 deletions(-) diff --git a/apps/opencs/main.cpp b/apps/opencs/main.cpp index b11561c13..ce434fc43 100644 --- a/apps/opencs/main.cpp +++ b/apps/opencs/main.cpp @@ -13,6 +13,8 @@ #include +#include "model/doc/messages.hpp" + #include "model/world/universalid.hpp" #ifdef Q_OS_MAC @@ -52,6 +54,7 @@ int main(int argc, char *argv[]) qRegisterMetaType ("std::string"); qRegisterMetaType ("CSMWorld::UniversalId"); + qRegisterMetaType ("CSMDoc::Message"); OgreInit::OgreInit ogreInit; diff --git a/apps/opencs/model/doc/document.cpp b/apps/opencs/model/doc/document.cpp index b833b527f..1e6ae5455 100644 --- a/apps/opencs/model/doc/document.cpp +++ b/apps/opencs/model/doc/document.cpp @@ -2304,8 +2304,8 @@ CSMDoc::Document::Document (const Files::ConfigurationManager& configuration, connect (&mSaving, SIGNAL (done (int, bool)), this, SLOT (operationDone (int, bool))); connect ( - &mSaving, SIGNAL (reportMessage (const CSMWorld::UniversalId&, const std::string&, const std::string&, int)), - this, SLOT (reportMessage (const CSMWorld::UniversalId&, const std::string&, const std::string&, int))); + &mSaving, SIGNAL (reportMessage (const CSMDoc::Message&, int)), + this, SLOT (reportMessage (const CSMDoc::Message&, int))); connect (&mRunner, SIGNAL (runStateChanged()), this, SLOT (runStateChanged())); } @@ -2401,11 +2401,10 @@ void CSMDoc::Document::modificationStateChanged (bool clean) emit stateChanged (getState(), this); } -void CSMDoc::Document::reportMessage (const CSMWorld::UniversalId& id, const std::string& message, - const std::string& hint, int type) +void CSMDoc::Document::reportMessage (const CSMDoc::Message& message, int type) { /// \todo find a better way to get these messages to the user. - std::cout << message << std::endl; + std::cout << message.mMessage << std::endl; } void CSMDoc::Document::operationDone (int type, bool failed) diff --git a/apps/opencs/model/doc/document.hpp b/apps/opencs/model/doc/document.hpp index 14daeeb75..4aaaf40b0 100644 --- a/apps/opencs/model/doc/document.hpp +++ b/apps/opencs/model/doc/document.hpp @@ -158,8 +158,7 @@ namespace CSMDoc void modificationStateChanged (bool clean); - void reportMessage (const CSMWorld::UniversalId& id, const std::string& message, - const std::string& hint, int type); + void reportMessage (const CSMDoc::Message& message, int type); void operationDone (int type, bool failed); diff --git a/apps/opencs/model/doc/loader.cpp b/apps/opencs/model/doc/loader.cpp index 43f3b850e..5cdade37e 100644 --- a/apps/opencs/model/doc/loader.cpp +++ b/apps/opencs/model/doc/loader.cpp @@ -68,7 +68,8 @@ void CSMDoc::Loader::load() for (CSMDoc::Messages::Iterator iter (messages.begin()); iter!=messages.end(); ++iter) { - document->getReport (log)->add (iter->mId, iter->mMessage); + document->getReport (log)->add ( + CSMDoc::Message (iter->mId, iter->mMessage, "")); emit loadMessage (document, iter->mMessage); } } diff --git a/apps/opencs/model/doc/messages.cpp b/apps/opencs/model/doc/messages.cpp index 3c709683e..07604cd85 100644 --- a/apps/opencs/model/doc/messages.cpp +++ b/apps/opencs/model/doc/messages.cpp @@ -1,6 +1,8 @@ #include "messages.hpp" +CSMDoc::Message::Message() {} + CSMDoc::Message::Message (const CSMWorld::UniversalId& id, const std::string& message, const std::string& hint) : mId (id), mMessage (message), mHint (hint) diff --git a/apps/opencs/model/doc/messages.hpp b/apps/opencs/model/doc/messages.hpp index 4e143d869..ecdb7e243 100644 --- a/apps/opencs/model/doc/messages.hpp +++ b/apps/opencs/model/doc/messages.hpp @@ -4,6 +4,8 @@ #include #include +#include + #include "../world/universalid.hpp" namespace CSMDoc @@ -14,6 +16,8 @@ namespace CSMDoc std::string mMessage; std::string mHint; + Message(); + Message (const CSMWorld::UniversalId& id, const std::string& message, const std::string& hint); }; @@ -47,4 +51,6 @@ namespace CSMDoc }; } +Q_DECLARE_METATYPE (CSMDoc::Message) + #endif diff --git a/apps/opencs/model/doc/operation.cpp b/apps/opencs/model/doc/operation.cpp index 4a39d2911..99d581a95 100644 --- a/apps/opencs/model/doc/operation.cpp +++ b/apps/opencs/model/doc/operation.cpp @@ -129,7 +129,7 @@ void CSMDoc::Operation::executeStage() } catch (const std::exception& e) { - emit reportMessage (CSMWorld::UniversalId(), e.what(), "", mType); + emit reportMessage (Message (CSMWorld::UniversalId(), e.what(), ""), mType); abort(); } @@ -141,7 +141,7 @@ void CSMDoc::Operation::executeStage() emit progress (mCurrentStepTotal, mTotalSteps ? mTotalSteps : 1, mType); for (Messages::Iterator iter (messages.begin()); iter!=messages.end(); ++iter) - emit reportMessage (iter->mId, iter->mMessage, iter->mHint, mType); + emit reportMessage (*iter, mType); if (mCurrentStage==mStages.end()) operationDone(); diff --git a/apps/opencs/model/doc/operation.hpp b/apps/opencs/model/doc/operation.hpp index 6d6ed112b..d90a1bf4f 100644 --- a/apps/opencs/model/doc/operation.hpp +++ b/apps/opencs/model/doc/operation.hpp @@ -8,6 +8,8 @@ #include #include +#include "messages.hpp" + namespace CSMWorld { class UniversalId; @@ -61,8 +63,7 @@ namespace CSMDoc void progress (int current, int max, int type); - void reportMessage (const CSMWorld::UniversalId& id, const std::string& message, - const std::string& hint, int type); + void reportMessage (const CSMDoc::Message& message, int type); void done (int type, bool failed); diff --git a/apps/opencs/model/doc/operationholder.cpp b/apps/opencs/model/doc/operationholder.cpp index 5157fd80c..25fc6fc26 100644 --- a/apps/opencs/model/doc/operationholder.cpp +++ b/apps/opencs/model/doc/operationholder.cpp @@ -21,8 +21,8 @@ void CSMDoc::OperationHolder::setOperation (Operation *operation) this, SIGNAL (progress (int, int, int))); connect ( - mOperation, SIGNAL (reportMessage (const CSMWorld::UniversalId&, const std::string&, const std::string&, int)), - this, SIGNAL (reportMessage (const CSMWorld::UniversalId&, const std::string&, const std::string&, int))); + mOperation, SIGNAL (reportMessage (const CSMDoc::Message&, int)), + this, SIGNAL (reportMessage (const CSMDoc::Message&, int))); connect ( mOperation, SIGNAL (done (int, bool)), diff --git a/apps/opencs/model/doc/operationholder.hpp b/apps/opencs/model/doc/operationholder.hpp index 6fe6df053..b73d61dab 100644 --- a/apps/opencs/model/doc/operationholder.hpp +++ b/apps/opencs/model/doc/operationholder.hpp @@ -4,6 +4,8 @@ #include #include +#include "messages.hpp" + namespace CSMWorld { class UniversalId; @@ -44,8 +46,7 @@ namespace CSMDoc void progress (int current, int max, int type); - void reportMessage (const CSMWorld::UniversalId& id, const std::string& message, - const std::string& hint, int type); + void reportMessage (const CSMDoc::Message& message, int type); void done (int type, bool failed); diff --git a/apps/opencs/model/tools/reportmodel.cpp b/apps/opencs/model/tools/reportmodel.cpp index e661e9eac..b44ad7b60 100644 --- a/apps/opencs/model/tools/reportmodel.cpp +++ b/apps/opencs/model/tools/reportmodel.cpp @@ -127,12 +127,11 @@ bool CSMTools::ReportModel::removeRows (int row, int count, const QModelIndex& p return true; } -void CSMTools::ReportModel::add (const CSMWorld::UniversalId& id, const std::string& message, - const std::string& hint) +void CSMTools::ReportModel::add (const CSMDoc::Message& message) { beginInsertRows (QModelIndex(), mRows.size(), mRows.size()); - mRows.push_back (CSMDoc::Message (id, message, hint)); + mRows.push_back (message); endInsertRows(); } diff --git a/apps/opencs/model/tools/reportmodel.hpp b/apps/opencs/model/tools/reportmodel.hpp index ff20f74a5..e9b6124b3 100644 --- a/apps/opencs/model/tools/reportmodel.hpp +++ b/apps/opencs/model/tools/reportmodel.hpp @@ -42,8 +42,7 @@ namespace CSMTools virtual bool removeRows (int row, int count, const QModelIndex& parent = QModelIndex()); - void add (const CSMWorld::UniversalId& id, const std::string& message, - const std::string& hint = ""); + void add (const CSMDoc::Message& message); void flagAsReplaced (int index); diff --git a/apps/opencs/model/tools/tools.cpp b/apps/opencs/model/tools/tools.cpp index fda373bcf..f46dbe6d3 100644 --- a/apps/opencs/model/tools/tools.cpp +++ b/apps/opencs/model/tools/tools.cpp @@ -58,9 +58,8 @@ CSMDoc::OperationHolder *CSMTools::Tools::getVerifier() connect (&mVerifier, SIGNAL (progress (int, int, int)), this, SIGNAL (progress (int, int, int))); connect (&mVerifier, SIGNAL (done (int, bool)), this, SIGNAL (done (int, bool))); - connect (&mVerifier, - SIGNAL (reportMessage (const CSMWorld::UniversalId&, const std::string&, const std::string&, int)), - this, SLOT (verifierMessage (const CSMWorld::UniversalId&, const std::string&, const std::string&, int))); + connect (&mVerifier, SIGNAL (reportMessage (const CSMDoc::Message&, int)), + this, SLOT (verifierMessage (const CSMDoc::Message&, int))); std::vector mandatoryIds; // I want C++11, damn it! mandatoryIds.push_back ("Day"); @@ -125,9 +124,8 @@ CSMTools::Tools::Tools (CSMDoc::Document& document) connect (&mSearch, SIGNAL (progress (int, int, int)), this, SIGNAL (progress (int, int, int))); connect (&mSearch, SIGNAL (done (int, bool)), this, SIGNAL (done (int, bool))); - connect (&mSearch, - SIGNAL (reportMessage (const CSMWorld::UniversalId&, const std::string&, const std::string&, int)), - this, SLOT (verifierMessage (const CSMWorld::UniversalId&, const std::string&, const std::string&, int))); + connect (&mSearch, SIGNAL (reportMessage (const CSMDoc::Message&, int)), + this, SLOT (verifierMessage (const CSMDoc::Message&, int))); } CSMTools::Tools::~Tools() @@ -215,12 +213,11 @@ CSMTools::ReportModel *CSMTools::Tools::getReport (const CSMWorld::UniversalId& return mReports.at (id.getIndex()); } -void CSMTools::Tools::verifierMessage (const CSMWorld::UniversalId& id, const std::string& message, - const std::string& hint, int type) +void CSMTools::Tools::verifierMessage (const CSMDoc::Message& message, int type) { std::map::iterator iter = mActiveReports.find (type); if (iter!=mActiveReports.end()) - mReports[iter->second]->add (id, message, hint); + mReports[iter->second]->add (message); } diff --git a/apps/opencs/model/tools/tools.hpp b/apps/opencs/model/tools/tools.hpp index 0f9e57044..2912fc471 100644 --- a/apps/opencs/model/tools/tools.hpp +++ b/apps/opencs/model/tools/tools.hpp @@ -75,8 +75,7 @@ namespace CSMTools private slots: - void verifierMessage (const CSMWorld::UniversalId& id, const std::string& message, - const std::string& hint, int type); + void verifierMessage (const CSMDoc::Message& message, int type); signals: From 197b8ec731671002b42976d9a2057ffae5c797a7 Mon Sep 17 00:00:00 2001 From: Marc Zinnschlag Date: Sat, 20 Jun 2015 19:04:19 +0200 Subject: [PATCH 23/30] added severity attribute for operation messages (Fixes #2717) --- apps/opencs/model/doc/loader.cpp | 5 +-- apps/opencs/model/doc/messages.cpp | 15 +++++-- apps/opencs/model/doc/messages.hpp | 19 ++++++++- apps/opencs/model/doc/operation.cpp | 12 ++++-- apps/opencs/model/doc/operation.hpp | 4 ++ apps/opencs/model/tools/reportmodel.cpp | 47 ++++++++++++++++----- apps/opencs/model/tools/reportmodel.hpp | 6 ++- apps/opencs/model/tools/scriptcheck.cpp | 30 ++++++++----- apps/opencs/model/tools/scriptcheck.hpp | 1 + apps/opencs/model/tools/search.cpp | 2 +- apps/opencs/model/tools/searchoperation.cpp | 2 + apps/opencs/model/tools/tools.cpp | 2 +- apps/opencs/model/world/data.cpp | 10 +++-- 13 files changed, 116 insertions(+), 39 deletions(-) diff --git a/apps/opencs/model/doc/loader.cpp b/apps/opencs/model/doc/loader.cpp index 5cdade37e..33725a6f9 100644 --- a/apps/opencs/model/doc/loader.cpp +++ b/apps/opencs/model/doc/loader.cpp @@ -52,7 +52,7 @@ void CSMDoc::Loader::load() { if (iter->second.mRecordsLeft) { - CSMDoc::Messages messages; + Messages messages (Message::Severity_Error); for (int i=0; igetData().continueLoading (messages)) { @@ -68,8 +68,7 @@ void CSMDoc::Loader::load() for (CSMDoc::Messages::Iterator iter (messages.begin()); iter!=messages.end(); ++iter) { - document->getReport (log)->add ( - CSMDoc::Message (iter->mId, iter->mMessage, "")); + document->getReport (log)->add (*iter); emit loadMessage (document, iter->mMessage); } } diff --git a/apps/opencs/model/doc/messages.cpp b/apps/opencs/model/doc/messages.cpp index 07604cd85..34157a05f 100644 --- a/apps/opencs/model/doc/messages.cpp +++ b/apps/opencs/model/doc/messages.cpp @@ -4,15 +4,22 @@ CSMDoc::Message::Message() {} CSMDoc::Message::Message (const CSMWorld::UniversalId& id, const std::string& message, - const std::string& hint) -: mId (id), mMessage (message), mHint (hint) + const std::string& hint, Severity severity) +: mId (id), mMessage (message), mHint (hint), mSeverity (severity) {} +CSMDoc::Messages::Messages (Message::Severity default_ = Message::Severity_Error) +: mDefault (default_) +{} + void CSMDoc::Messages::add (const CSMWorld::UniversalId& id, const std::string& message, - const std::string& hint) + const std::string& hint, Message::Severity severity) { - mMessages.push_back (Message (id, message, hint)); + if (severity==Message::Severity_Default) + severity = mDefault; + + mMessages.push_back (Message (id, message, hint, severity)); } void CSMDoc::Messages::push_back (const std::pair& data) diff --git a/apps/opencs/model/doc/messages.hpp b/apps/opencs/model/doc/messages.hpp index ecdb7e243..86f5feb15 100644 --- a/apps/opencs/model/doc/messages.hpp +++ b/apps/opencs/model/doc/messages.hpp @@ -12,14 +12,25 @@ namespace CSMDoc { struct Message { + enum Severity + { + Severity_Info = 0, // no problem + Severity_Warning = 1, // a potential problem, but we are probably fine + Severity_Error = 2, // an error; we are not fine + Severity_SeriousError = 3, // an error so bad we can't even be sure if we are + // reporting it correctly + Severity_Default = 4 + }; + CSMWorld::UniversalId mId; std::string mMessage; std::string mHint; + Severity mSeverity; Message(); Message (const CSMWorld::UniversalId& id, const std::string& message, - const std::string& hint); + const std::string& hint, Severity severity); }; class Messages @@ -36,11 +47,15 @@ namespace CSMDoc private: Collection mMessages; + Message::Severity mDefault; public: + Messages (Message::Severity default_); + void add (const CSMWorld::UniversalId& id, const std::string& message, - const std::string& hint = ""); + const std::string& hint = "", + Message::Severity severity = Message::Severity_Default); /// \deprecated Use add instead. void push_back (const std::pair& data); diff --git a/apps/opencs/model/doc/operation.cpp b/apps/opencs/model/doc/operation.cpp index 99d581a95..8b2717086 100644 --- a/apps/opencs/model/doc/operation.cpp +++ b/apps/opencs/model/doc/operation.cpp @@ -33,7 +33,8 @@ void CSMDoc::Operation::prepareStages() CSMDoc::Operation::Operation (int type, bool ordered, bool finalAlways) : mType (type), mStages(std::vector >()), mCurrentStage(mStages.begin()), mCurrentStep(0), mCurrentStepTotal(0), mTotalSteps(0), mOrdered (ordered), - mFinalAlways (finalAlways), mError(false), mConnected (false), mPrepared (false) + mFinalAlways (finalAlways), mError(false), mConnected (false), mPrepared (false), + mDefaultSeverity (Message::Severity_Error) { mTimer = new QTimer (this); } @@ -72,6 +73,11 @@ void CSMDoc::Operation::configureSettings (const std::vector& settings) } } +void CSMDoc::Operation::setDefaultSeverity (Message::Severity severity) +{ + mDefaultSeverity = severity; +} + bool CSMDoc::Operation::hasError() const { return mError; @@ -112,7 +118,7 @@ void CSMDoc::Operation::executeStage() mPrepared = true; } - Messages messages; + Messages messages (mDefaultSeverity); while (mCurrentStage!=mStages.end()) { @@ -129,7 +135,7 @@ void CSMDoc::Operation::executeStage() } catch (const std::exception& e) { - emit reportMessage (Message (CSMWorld::UniversalId(), e.what(), ""), mType); + emit reportMessage (Message (CSMWorld::UniversalId(), e.what(), "", Message::Severity_SeriousError), mType); abort(); } diff --git a/apps/opencs/model/doc/operation.hpp b/apps/opencs/model/doc/operation.hpp index d90a1bf4f..703f9d44b 100644 --- a/apps/opencs/model/doc/operation.hpp +++ b/apps/opencs/model/doc/operation.hpp @@ -36,6 +36,7 @@ namespace CSMDoc QTimer *mTimer; std::map mSettings; bool mPrepared; + Message::Severity mDefaultSeverity; void prepareStages(); @@ -57,6 +58,9 @@ namespace CSMDoc /// \attention Do no call this function while this Operation is running. void configureSettings (const std::vector& settings); + /// \attention Do no call this function while this Operation is running. + void setDefaultSeverity (Message::Severity severity); + bool hasError() const; signals: diff --git a/apps/opencs/model/tools/reportmodel.cpp b/apps/opencs/model/tools/reportmodel.cpp index b44ad7b60..480691710 100644 --- a/apps/opencs/model/tools/reportmodel.cpp +++ b/apps/opencs/model/tools/reportmodel.cpp @@ -6,19 +6,18 @@ #include "../world/columns.hpp" -CSMTools::ReportModel::ReportModel (bool fieldColumn) +CSMTools::ReportModel::ReportModel (bool fieldColumn, bool severityColumn) +: mColumnField (-1), mColumnSeverity (-1) { + int index = 3; + + if (severityColumn) + mColumnSeverity = index++; + if (fieldColumn) - { - mColumnField = 3; - mColumnDescription = 4; - } - else - { - mColumnDescription = 3; + mColumnField = index++; - mColumnField = -1; - } + mColumnDescription = index; } int CSMTools::ReportModel::rowCount (const QModelIndex & parent) const @@ -83,6 +82,18 @@ QVariant CSMTools::ReportModel::data (const QModelIndex & index, int role) const return QString::fromUtf8 (field.c_str()); } + + if (index.column()==mColumnSeverity) + { + switch (mRows.at (index.row()).mSeverity) + { + case CSMDoc::Message::Severity_Info: return "Information"; + case CSMDoc::Message::Severity_Warning: return "Warning"; + case CSMDoc::Message::Severity_Error: return "Error"; + case CSMDoc::Message::Severity_SeriousError: return "Serious Error"; + case CSMDoc::Message::Severity_Default: break; + } + } return QVariant(); } @@ -107,6 +118,9 @@ QVariant CSMTools::ReportModel::headerData (int section, Qt::Orientation orienta if (section==mColumnField) return "Field"; + if (section==mColumnSeverity) + return "Severity"; + return "-"; } @@ -170,3 +184,16 @@ void CSMTools::ReportModel::clear() endRemoveRows(); } } + +int CSMTools::ReportModel::countErrors() const +{ + int count = 0; + + for (std::vector::const_iterator iter (mRows.begin()); + iter!=mRows.end(); ++iter) + if (iter->mSeverity==CSMDoc::Message::Severity_Error || + iter->mSeverity==CSMDoc::Message::Severity_SeriousError) + ++count; + + return count; +} diff --git a/apps/opencs/model/tools/reportmodel.hpp b/apps/opencs/model/tools/reportmodel.hpp index e9b6124b3..5704970f5 100644 --- a/apps/opencs/model/tools/reportmodel.hpp +++ b/apps/opencs/model/tools/reportmodel.hpp @@ -27,10 +27,11 @@ namespace CSMTools // Configurable columns int mColumnDescription; int mColumnField; + int mColumnSeverity; public: - ReportModel (bool fieldColumn = false); + ReportModel (bool fieldColumn = false, bool severityColumn = true); virtual int rowCount (const QModelIndex & parent = QModelIndex()) const; @@ -51,6 +52,9 @@ namespace CSMTools std::string getHint (int row) const; void clear(); + + // Return number of messages with Error or SeriousError severity. + int countErrors() const; }; } diff --git a/apps/opencs/model/tools/scriptcheck.cpp b/apps/opencs/model/tools/scriptcheck.cpp index 33922e9cf..190b146c9 100644 --- a/apps/opencs/model/tools/scriptcheck.cpp +++ b/apps/opencs/model/tools/scriptcheck.cpp @@ -11,6 +11,17 @@ #include "../world/data.hpp" +CSMDoc::Message::Severity CSMTools::ScriptCheckStage::getSeverity (Type type) +{ + switch (type) + { + case WarningMessage: return CSMDoc::Message::Severity_Warning; + case ErrorMessage: return CSMDoc::Message::Severity_Error; + } + + return CSMDoc::Message::Severity_SeriousError; +} + void CSMTools::ScriptCheckStage::report (const std::string& message, const Compiler::TokenLoc& loc, Type type) { @@ -18,11 +29,6 @@ void CSMTools::ScriptCheckStage::report (const std::string& message, const Compi CSMWorld::UniversalId id (CSMWorld::UniversalId::Type_Script, mId); - if (type==ErrorMessage) - stream << "error "; - else - stream << "warning "; - stream << "script " << mFile << ", line " << loc.mLine << ", column " << loc.mColumn @@ -32,15 +38,17 @@ void CSMTools::ScriptCheckStage::report (const std::string& message, const Compi hintStream << "l:" << loc.mLine << " " << loc.mColumn; - mMessages->add (id, stream.str(), hintStream.str()); + mMessages->add (id, stream.str(), hintStream.str(), getSeverity (type)); } void CSMTools::ScriptCheckStage::report (const std::string& message, Type type) { CSMWorld::UniversalId id (CSMWorld::UniversalId::Type_Script, mId); - mMessages->push_back (std::make_pair (id, - (type==ErrorMessage ? "error: " : "warning: ") + message)); + std::ostringstream stream; + stream << "script " << mFile << ": " << message; + + mMessages->add (id, stream.str(), "", getSeverity (type)); } CSMTools::ScriptCheckStage::ScriptCheckStage (const CSMDoc::Document& document) @@ -100,8 +108,10 @@ void CSMTools::ScriptCheckStage::perform (int stage, CSMDoc::Messages& messages) { CSMWorld::UniversalId id (CSMWorld::UniversalId::Type_Script, mId); - messages.push_back (std::make_pair (id, - std::string ("Critical compile error: ") + error.what())); + std::ostringstream stream; + stream << "script " << mFile << ": " << error.what(); + + messages.add (id, stream.str(), "", CSMDoc::Message::Severity_SeriousError); } mMessages = 0; diff --git a/apps/opencs/model/tools/scriptcheck.hpp b/apps/opencs/model/tools/scriptcheck.hpp index 0d42b275c..97c50a1eb 100644 --- a/apps/opencs/model/tools/scriptcheck.hpp +++ b/apps/opencs/model/tools/scriptcheck.hpp @@ -32,6 +32,7 @@ namespace CSMTools CSMDoc::Messages *mMessages; WarningMode mWarningMode; + CSMDoc::Message::Severity getSeverity (Type type); virtual void report (const std::string& message, const Compiler::TokenLoc& loc, Type type); ///< Report error to the user. diff --git a/apps/opencs/model/tools/search.cpp b/apps/opencs/model/tools/search.cpp index 7eb531161..449df2c63 100644 --- a/apps/opencs/model/tools/search.cpp +++ b/apps/opencs/model/tools/search.cpp @@ -280,7 +280,7 @@ void CSMTools::Search::replace (CSMDoc::Document& document, CSMWorld::IdTableBas bool CSMTools::Search::verify (CSMDoc::Document& document, CSMWorld::IdTableBase *model, const CSMWorld::UniversalId& id, const std::string& messageHint) const { - CSMDoc::Messages messages; + CSMDoc::Messages messages (CSMDoc::Message::Severity_Info); int row = model->getModelIndex (id.getId(), model->findColumnIndex (CSMWorld::Columns::ColumnId_Id)).row(); diff --git a/apps/opencs/model/tools/searchoperation.cpp b/apps/opencs/model/tools/searchoperation.cpp index 4512de582..8cbc5dc8e 100644 --- a/apps/opencs/model/tools/searchoperation.cpp +++ b/apps/opencs/model/tools/searchoperation.cpp @@ -21,6 +21,8 @@ CSMTools::SearchOperation::SearchOperation (CSMDoc::Document& document) iter!=types.end(); ++iter) appendStage (new SearchStage (&dynamic_cast ( *document.getData().getTableModel (*iter)))); + + setDefaultSeverity (CSMDoc::Message::Severity_Info); } void CSMTools::SearchOperation::configure (const Search& search) diff --git a/apps/opencs/model/tools/tools.cpp b/apps/opencs/model/tools/tools.cpp index f46dbe6d3..f0d649f38 100644 --- a/apps/opencs/model/tools/tools.cpp +++ b/apps/opencs/model/tools/tools.cpp @@ -158,7 +158,7 @@ CSMWorld::UniversalId CSMTools::Tools::runVerifier() CSMWorld::UniversalId CSMTools::Tools::newSearch() { - mReports.insert (std::make_pair (mNextReportNumber++, new ReportModel (true))); + mReports.insert (std::make_pair (mNextReportNumber++, new ReportModel (true, false))); return CSMWorld::UniversalId (CSMWorld::UniversalId::Type_Search, mNextReportNumber-1); } diff --git a/apps/opencs/model/world/data.cpp b/apps/opencs/model/world/data.cpp index 529c8f88f..5acd80339 100644 --- a/apps/opencs/model/world/data.cpp +++ b/apps/opencs/model/world/data.cpp @@ -923,7 +923,7 @@ bool CSMWorld::Data::continueLoading (CSMDoc::Messages& messages) { // log an error and continue loading the refs to the last loaded cell CSMWorld::UniversalId id (CSMWorld::UniversalId::Type_None); - messages.add (id, "Logic error: cell index out of bounds"); + messages.add (id, "Logic error: cell index out of bounds", "", CSMDoc::Message::Severity_Error); index = mCells.getSize()-1; } std::string cellId = Misc::StringUtils::lowerCase (mCells.getId (index)); @@ -984,7 +984,8 @@ bool CSMWorld::Data::continueLoading (CSMDoc::Messages& messages) else { messages.add (UniversalId::Type_None, - "Trying to delete dialogue record " + id + " which does not exist"); + "Trying to delete dialogue record " + id + " which does not exist", + "", CSMDoc::Message::Severity_Warning); } } else @@ -1001,7 +1002,7 @@ bool CSMWorld::Data::continueLoading (CSMDoc::Messages& messages) if (!mDialogue) { messages.add (UniversalId::Type_None, - "Found info record not following a dialogue record"); + "Found info record not following a dialogue record", "", CSMDoc::Message::Severity_Error); mReader->skipRecord(); break; @@ -1044,7 +1045,8 @@ bool CSMWorld::Data::continueLoading (CSMDoc::Messages& messages) if (unhandledRecord) { - messages.add (UniversalId::Type_None, "Unsupported record type: " + n.toString()); + messages.add (UniversalId::Type_None, "Unsupported record type: " + n.toString(), "", + CSMDoc::Message::Severity_Error); mReader->skipRecord(); } From b9f6baf317bfc3f1cbabafe1d79749a5d83ca523 Mon Sep 17 00:00:00 2001 From: Marc Zinnschlag Date: Sat, 20 Jun 2015 19:16:15 +0200 Subject: [PATCH 24/30] add normal script warnings mode (Fixes #2642) --- apps/opencs/model/settings/usersettings.cpp | 7 ++++--- apps/opencs/model/tools/scriptcheck.cpp | 5 ++++- apps/opencs/model/tools/scriptcheck.hpp | 1 + 3 files changed, 9 insertions(+), 4 deletions(-) diff --git a/apps/opencs/model/settings/usersettings.cpp b/apps/opencs/model/settings/usersettings.cpp index 78db5313b..3e59d0582 100644 --- a/apps/opencs/model/settings/usersettings.cpp +++ b/apps/opencs/model/settings/usersettings.cpp @@ -312,17 +312,18 @@ void CSMSettings::UserSettings::buildSettingModelDefaults() "\nA name from the list of colors defined in the list of SVG color keyword names." "\nX11 color names may also work."; - QString modeIgnore ("Ignore"); + QString modeNormal ("Normal"); QStringList modes; - modes << modeIgnore << "Strict"; + modes << "Ignore" << modeNormal << "Strict"; Setting *warnings = createSetting (Type_ComboBox, "warnings", "Warning Mode"); warnings->setDeclaredValues (modes); - warnings->setDefaultValue (modeIgnore); + warnings->setDefaultValue (modeNormal); warnings->setToolTip ("
    How to handle warning messages during compilation:

    " "

  • Ignore: Do not report warning
  • " + "
  • Normal: Report warning as a warning
  • " "
  • Strict: Promote warning to an error
  • " "
"); diff --git a/apps/opencs/model/tools/scriptcheck.cpp b/apps/opencs/model/tools/scriptcheck.cpp index 190b146c9..928ae156f 100644 --- a/apps/opencs/model/tools/scriptcheck.cpp +++ b/apps/opencs/model/tools/scriptcheck.cpp @@ -84,7 +84,8 @@ void CSMTools::ScriptCheckStage::perform (int stage, CSMDoc::Messages& messages) switch (mWarningMode) { case Mode_Ignore: setWarningsMode (0); break; - case Mode_Strict: setWarningsMode (1); break; + case Mode_Normal: setWarningsMode (1); break; + case Mode_Strict: setWarningsMode (2); break; } try @@ -123,6 +124,8 @@ void CSMTools::ScriptCheckStage::updateUserSetting (const QString& name, const Q { if (value.at (0)=="Ignore") mWarningMode = Mode_Ignore; + else if (value.at (0)=="Normal") + mWarningMode = Mode_Normal; else if (value.at (0)=="Strict") mWarningMode = Mode_Strict; } diff --git a/apps/opencs/model/tools/scriptcheck.hpp b/apps/opencs/model/tools/scriptcheck.hpp index 97c50a1eb..3f0276652 100644 --- a/apps/opencs/model/tools/scriptcheck.hpp +++ b/apps/opencs/model/tools/scriptcheck.hpp @@ -21,6 +21,7 @@ namespace CSMTools enum WarningMode { Mode_Ignore, + Mode_Normal, Mode_Strict }; From c644f15167b777323b165375c4728fcb877ea10a Mon Sep 17 00:00:00 2001 From: Marc Zinnschlag Date: Sat, 20 Jun 2015 19:46:38 +0200 Subject: [PATCH 25/30] calm down travis --- apps/opencs/model/doc/messages.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/opencs/model/doc/messages.cpp b/apps/opencs/model/doc/messages.cpp index 34157a05f..bd6e808c8 100644 --- a/apps/opencs/model/doc/messages.cpp +++ b/apps/opencs/model/doc/messages.cpp @@ -9,7 +9,7 @@ CSMDoc::Message::Message (const CSMWorld::UniversalId& id, const std::string& me {} -CSMDoc::Messages::Messages (Message::Severity default_ = Message::Severity_Error) +CSMDoc::Messages::Messages (Message::Severity default_) : mDefault (default_) {} From c65e7a31e7272ac450fc792ecfe690075e7e643e Mon Sep 17 00:00:00 2001 From: dteviot Date: Sun, 21 Jun 2015 16:23:40 +1200 Subject: [PATCH 26/30] Aquatic creatures no longer try to get onto land. AiWander for aquatic creatures no longer uses path grid points as they're usually on land. --- apps/openmw/mwmechanics/aiwander.cpp | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/apps/openmw/mwmechanics/aiwander.cpp b/apps/openmw/mwmechanics/aiwander.cpp index 1f4133c0a..d89a29e1d 100644 --- a/apps/openmw/mwmechanics/aiwander.cpp +++ b/apps/openmw/mwmechanics/aiwander.cpp @@ -651,9 +651,6 @@ namespace MWMechanics if (mAllowedNodes.empty()) return; - if (actor.getClass().isPureWaterCreature(actor)) - return; - state.moveIn(new AiWanderStorage()); int index = OEngine::Misc::Rng::rollDice(mAllowedNodes.size()); @@ -700,7 +697,8 @@ namespace MWMechanics // actor can wander from the spawn position. AiWander assumes that // pathgrid points are available, and uses them to randomly select wander // destinations within the allowed set of pathgrid points (nodes). - if(mDistance) + // ... pathgrids don't usually include water, so swimmers ignore them + if (mDistance && !actor.getClass().isPureWaterCreature(actor)) { float cellXOffset = 0; float cellYOffset = 0; From 44582fe3b329d928934015cb2924daf52c964503 Mon Sep 17 00:00:00 2001 From: scrawl Date: Sun, 21 Jun 2015 17:27:52 +0200 Subject: [PATCH 27/30] Don't use separate werewolf skills/attributes for non-player werewolves Still need to deal with save files. --- apps/openmw/mwmechanics/creaturestats.cpp | 11 ++--- apps/openmw/mwmechanics/creaturestats.hpp | 4 -- apps/openmw/mwmechanics/npcstats.cpp | 53 +++++++++-------------- apps/openmw/mwmechanics/npcstats.hpp | 5 ++- apps/openmw/mwworld/player.cpp | 49 +++++++++++++++++++++ apps/openmw/mwworld/player.hpp | 13 ++++++ apps/openmw/mwworld/worldimp.cpp | 11 +++++ components/esm/npcstats.cpp | 4 -- 8 files changed, 101 insertions(+), 49 deletions(-) diff --git a/apps/openmw/mwmechanics/creaturestats.cpp b/apps/openmw/mwmechanics/creaturestats.cpp index 308e72027..e5cb561bf 100644 --- a/apps/openmw/mwmechanics/creaturestats.cpp +++ b/apps/openmw/mwmechanics/creaturestats.cpp @@ -20,7 +20,7 @@ namespace MWMechanics mKnockdown(false), mKnockdownOneFrame(false), mKnockdownOverOneFrame(false), mHitRecovery(false), mBlock(false), mMovementFlags(0), mAttackStrength(0.f), mFallHeight(0), mRecalcMagicka(false), mLastRestock(0,0), mGoldPool(0), mActorId(-1), - mDeathAnimation(0), mIsWerewolf(false), mLevel (0) + mDeathAnimation(0), mLevel (0) { for (int i=0; i<4; ++i) mAiSettings[i] = 0; @@ -55,7 +55,7 @@ namespace MWMechanics if (index < 0 || index > 7) { throw std::runtime_error("attribute index is out of range"); } - return (!mIsWerewolf ? mAttributes[index] : mWerewolfAttributes[index]); + return mAttributes[index]; } const DynamicStat &CreatureStats::getHealth() const @@ -139,14 +139,11 @@ namespace MWMechanics throw std::runtime_error("attribute index is out of range"); } - const AttributeValue& currentValue = !mIsWerewolf ? mAttributes[index] : mWerewolfAttributes[index]; + const AttributeValue& currentValue = mAttributes[index]; if (value != currentValue) { - if(!mIsWerewolf) - mAttributes[index] = value; - else - mWerewolfAttributes[index] = value; + mAttributes[index] = value; if (index == ESM::Attribute::Intelligence) mRecalcMagicka = true; diff --git a/apps/openmw/mwmechanics/creaturestats.hpp b/apps/openmw/mwmechanics/creaturestats.hpp index 145eb8a5b..146d9fb1e 100644 --- a/apps/openmw/mwmechanics/creaturestats.hpp +++ b/apps/openmw/mwmechanics/creaturestats.hpp @@ -77,10 +77,6 @@ namespace MWMechanics std::vector mSummonGraveyard; protected: - // These two are only set by NpcStats, but they are declared in CreatureStats to prevent using virtual methods. - bool mIsWerewolf; - AttributeValue mWerewolfAttributes[8]; - int mLevel; public: diff --git a/apps/openmw/mwmechanics/npcstats.cpp b/apps/openmw/mwmechanics/npcstats.cpp index 94819e626..577c76c97 100644 --- a/apps/openmw/mwmechanics/npcstats.cpp +++ b/apps/openmw/mwmechanics/npcstats.cpp @@ -32,6 +32,7 @@ MWMechanics::NpcStats::NpcStats() , mWerewolfKills (0) , mLevelProgress(0) , mTimeToStartDrowning(20.0) + , mIsWerewolf(false) { mSkillIncreases.resize (ESM::Attribute::Length, 0); } @@ -51,7 +52,7 @@ const MWMechanics::SkillValue& MWMechanics::NpcStats::getSkill (int index) const if (index<0 || index>=ESM::Skill::Length) throw std::runtime_error ("skill index out of range"); - return (!mIsWerewolf ? mSkill[index] : mWerewolfSkill[index]); + return mSkill[index]; } MWMechanics::SkillValue& MWMechanics::NpcStats::getSkill (int index) @@ -59,7 +60,15 @@ MWMechanics::SkillValue& MWMechanics::NpcStats::getSkill (int index) if (index<0 || index>=ESM::Skill::Length) throw std::runtime_error ("skill index out of range"); - return (!mIsWerewolf ? mSkill[index] : mWerewolfSkill[index]); + return mSkill[index]; +} + +void MWMechanics::NpcStats::setSkill(int index, const MWMechanics::SkillValue &value) +{ + if (index<0 || index>=ESM::Skill::Length) + throw std::runtime_error ("skill index out of range"); + + mSkill[index] = value; } const std::map& MWMechanics::NpcStats::getFactionRanks() const @@ -188,10 +197,6 @@ float MWMechanics::NpcStats::getSkillProgressRequirement (int skillIndex, const void MWMechanics::NpcStats::useSkill (int skillIndex, const ESM::Class& class_, int usageType, float extraFactor) { - // Don't increase skills as a werewolf - if(mIsWerewolf) - return; - const ESM::Skill *skill = MWBase::Environment::get().getWorld()->getStore().get().find (skillIndex); float skillGain = 1; @@ -403,34 +408,12 @@ bool MWMechanics::NpcStats::isWerewolf() const void MWMechanics::NpcStats::setWerewolf (bool set) { + if (mIsWerewolf == set) + return; + if(set != false) { - const MWWorld::Store &gmst = MWBase::Environment::get().getWorld()->getStore().get(); - mWerewolfKills = 0; - - for(size_t i = 0;i < ESM::Attribute::Length;i++) - { - mWerewolfAttributes[i] = getAttribute(i); - // Oh, Bethesda. It's "Intelligence". - std::string name = "fWerewolf"+((i==ESM::Attribute::Intelligence) ? std::string("Intellegence") : - ESM::Attribute::sAttributeNames[i]); - mWerewolfAttributes[i].setBase(int(gmst.find(name)->getFloat())); - } - - for(size_t i = 0;i < ESM::Skill::Length;i++) - { - mWerewolfSkill[i] = getSkill(i); - - // Acrobatics is set separately for some reason. - if(i == ESM::Skill::Acrobatics) - continue; - - // "Mercantile"! >_< - std::string name = "fWerewolf"+((i==ESM::Skill::Mercantile) ? std::string("Merchantile") : - ESM::Skill::sSkillNames[i]); - mWerewolfSkill[i].setBase(int(gmst.find(name)->getFloat())); - } } mIsWerewolf = set; } @@ -466,12 +449,14 @@ void MWMechanics::NpcStats::writeState (ESM::NpcStats& state) const for (int i=0; i& getFactionRanks() const; /// Increase the rank in this faction by 1, if such a rank exists. diff --git a/apps/openmw/mwworld/player.cpp b/apps/openmw/mwworld/player.cpp index 0b81532e1..d0d99bfcf 100644 --- a/apps/openmw/mwworld/player.cpp +++ b/apps/openmw/mwworld/player.cpp @@ -49,6 +49,55 @@ namespace MWWorld mPlayer.mData.setPosition(playerPos); } + void Player::saveSkillsAttributes() + { + MWMechanics::NpcStats& stats = getPlayer().getClass().getNpcStats(getPlayer()); + for (int i=0; i& gmst = MWBase::Environment::get().getWorld()->getStore().get(); + MWMechanics::NpcStats& stats = getPlayer().getClass().getNpcStats(getPlayer()); + for(size_t i = 0;i < ESM::Attribute::Length;++i) + { + // Oh, Bethesda. It's "Intelligence". + std::string name = "fWerewolf"+((i==ESM::Attribute::Intelligence) ? std::string("Intellegence") : + ESM::Attribute::sAttributeNames[i]); + + MWMechanics::AttributeValue value = stats.getAttribute(i); + value.setBase(int(gmst.find(name)->getFloat())); + stats.setAttribute(i, value); + } + + for(size_t i = 0;i < ESM::Skill::Length;i++) + { + // Acrobatics is set separately for some reason. + if(i == ESM::Skill::Acrobatics) + continue; + + // "Mercantile"! >_< + std::string name = "fWerewolf"+((i==ESM::Skill::Mercantile) ? std::string("Merchantile") : + ESM::Skill::sSkillNames[i]); + + MWMechanics::SkillValue value = stats.getSkill(i); + value.setBase(int(gmst.find(name)->getFloat())); + stats.setSkill(i, value); + } + } + void Player::set(const ESM::NPC *player) { mPlayer.mBase = player; diff --git a/apps/openmw/mwworld/player.hpp b/apps/openmw/mwworld/player.hpp index 25d8981cd..2845c5822 100644 --- a/apps/openmw/mwworld/player.hpp +++ b/apps/openmw/mwworld/player.hpp @@ -6,6 +6,11 @@ #include "../mwmechanics/drawstate.hpp" +#include "../mwmechanics/stat.hpp" + +#include +#include + #include namespace ESM @@ -50,10 +55,18 @@ namespace MWWorld int mCurrentCrimeId; // the id assigned witnesses int mPaidCrimeId; // the last id paid off (0 bounty) + // Saved skills and attributes prior to becoming a werewolf + MWMechanics::SkillValue mSaveSkills[ESM::Skill::Length]; + MWMechanics::AttributeValue mSaveAttributes[ESM::Attribute::Length]; + public: Player(const ESM::NPC *player, const MWBase::World& world); + void saveSkillsAttributes(); + void restoreSkillsAttributes(); + void setWerewolfSkillsAttributes(); + // For mark/recall magic effects void markPosition (CellStore* markedCell, ESM::Position markedPosition); void getMarkedPosition (CellStore*& markedCell, ESM::Position& markedPosition) const; diff --git a/apps/openmw/mwworld/worldimp.cpp b/apps/openmw/mwworld/worldimp.cpp index 0f33f3d59..f8de9f65b 100644 --- a/apps/openmw/mwworld/worldimp.cpp +++ b/apps/openmw/mwworld/worldimp.cpp @@ -2485,6 +2485,17 @@ namespace MWWorld if (npcStats.isWerewolf() == werewolf) return; + if (actor == getPlayerPtr()) + { + if (werewolf) + { + mPlayer->saveSkillsAttributes(); + mPlayer->setWerewolfSkillsAttributes(); + } + else + mPlayer->restoreSkillsAttributes(); + } + npcStats.setWerewolf(werewolf); // This is a bit dangerous. Equipped items other than WerewolfRobe may reference diff --git a/components/esm/npcstats.cpp b/components/esm/npcstats.cpp index cc1d6b3dd..fa808b72f 100644 --- a/components/esm/npcstats.cpp +++ b/components/esm/npcstats.cpp @@ -117,10 +117,6 @@ void ESM::NpcStats::save (ESMWriter &esm) const mSkills[i].mWerewolf.save (esm); } - esm.writeHNT ("HWAT", true); - for (int i=0; i<8; ++i) - mWerewolfAttributes[i].save (esm); - if (mIsWerewolf) esm.writeHNT ("WOLF", mIsWerewolf); From d6a7255391425d34512b8b05ac27db1c6fdbf30f Mon Sep 17 00:00:00 2001 From: scrawl Date: Sun, 21 Jun 2015 17:36:11 +0200 Subject: [PATCH 28/30] Loading/saving for player's original skills/attributes (prior to becoming a werewolf) --- apps/openmw/mwworld/player.cpp | 10 ++++++++++ components/esm/player.cpp | 13 +++++++++++++ components/esm/player.hpp | 6 ++++++ 3 files changed, 29 insertions(+) diff --git a/apps/openmw/mwworld/player.cpp b/apps/openmw/mwworld/player.cpp index d0d99bfcf..e681bd7c5 100644 --- a/apps/openmw/mwworld/player.cpp +++ b/apps/openmw/mwworld/player.cpp @@ -271,6 +271,11 @@ namespace MWWorld player.mAutoMove = mAutoMove ? 1 : 0; + for (int i=0; i mSaveAttributes[ESM::Attribute::Length]; + StatState mSaveSkills[ESM::Skill::Length]; + void load (ESMReader &esm); void save (ESMWriter &esm) const; }; From 2ce269c0fc2eff88d0dc0e2f7ce971255e842f1e Mon Sep 17 00:00:00 2001 From: scrawl Date: Sun, 21 Jun 2015 18:18:24 +0200 Subject: [PATCH 29/30] Werewolf stats compatibility with old save files --- apps/openmw/mwmechanics/npcstats.cpp | 23 +++------------- apps/openmw/mwworld/player.cpp | 6 +++++ components/esm/esmreader.cpp | 11 ++++++++ components/esm/esmreader.hpp | 2 ++ components/esm/npcstats.cpp | 40 +++++++++++++++++++++------- components/esm/npcstats.hpp | 11 +++----- 6 files changed, 56 insertions(+), 37 deletions(-) diff --git a/apps/openmw/mwmechanics/npcstats.cpp b/apps/openmw/mwmechanics/npcstats.cpp index 577c76c97..b9aa8b301 100644 --- a/apps/openmw/mwmechanics/npcstats.cpp +++ b/apps/openmw/mwmechanics/npcstats.cpp @@ -447,16 +447,8 @@ void MWMechanics::NpcStats::writeState (ESM::NpcStats& state) const state.mDisposition = mDisposition; for (int i=0; i > skills(mSkills, mSkills + sizeof(mSkills)/sizeof(mSkills[0])); + + for (int i=0; i<27; ++i) + { + ESM::StatState skill; + skill.load(esm); + skills.push_back(skill); + } + + int i=0; + for (std::vector >::iterator it = skills.begin(); it != skills.end(); ++i) + { + if (i%2 == 1) + it = skills.erase(it); + else + ++it; + } + assert(skills.size() == 27); + std::copy(skills.begin(), skills.end(), mSkills); } + // No longer used bool hasWerewolfAttributes = false; esm.getHNOT (hasWerewolfAttributes, "HWAT"); - if (hasWerewolfAttributes) { + ESM::StatState dummy; for (int i=0; i<8; ++i) - mWerewolfAttributes[i].load (esm); + dummy.load(esm); + mWerewolfDeprecatedData = true; } mIsWerewolf = false; @@ -112,10 +136,7 @@ void ESM::NpcStats::save (ESMWriter &esm) const esm.writeHNT ("DISP", mDisposition); for (int i=0; i<27; ++i) - { - mSkills[i].mRegular.save (esm); - mSkills[i].mWerewolf.save (esm); - } + mSkills[i].save (esm); if (mIsWerewolf) esm.writeHNT ("WOLF", mIsWerewolf); @@ -147,6 +168,7 @@ void ESM::NpcStats::save (ESMWriter &esm) const void ESM::NpcStats::blank() { + mWerewolfDeprecatedData = false; mIsWerewolf = false; mDisposition = 0; mBounty = 0; diff --git a/components/esm/npcstats.hpp b/components/esm/npcstats.hpp index 0138ab209..9b27f587c 100644 --- a/components/esm/npcstats.hpp +++ b/components/esm/npcstats.hpp @@ -16,12 +16,6 @@ namespace ESM struct NpcStats { - struct Skill - { - StatState mRegular; - StatState mWerewolf; - }; - struct Faction { bool mExpelled; @@ -31,12 +25,13 @@ namespace ESM Faction(); }; - StatState mWerewolfAttributes[8]; bool mIsWerewolf; + bool mWerewolfDeprecatedData; + std::map mFactions; // lower case IDs int mDisposition; - Skill mSkills[27]; + StatState mSkills[27]; int mBounty; int mReputation; int mWerewolfKills; From 3f54f77647923571a42b4ceb5c18295ce25496c0 Mon Sep 17 00:00:00 2001 From: scrawl Date: Sun, 21 Jun 2015 22:15:35 +0200 Subject: [PATCH 30/30] essimporter build fix --- apps/essimporter/convertacdt.cpp | 6 +++--- apps/essimporter/convertplayer.cpp | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/apps/essimporter/convertacdt.cpp b/apps/essimporter/convertacdt.cpp index 55a20ec3d..8f090b3fc 100644 --- a/apps/essimporter/convertacdt.cpp +++ b/apps/essimporter/convertacdt.cpp @@ -41,9 +41,9 @@ namespace ESSImport { for (int i=0; i