From 170692b48004a7ee7ed3a96027d34ef78d110a8f Mon Sep 17 00:00:00 2001 From: Stanislav Bas Date: Fri, 19 Jun 2015 19:24:06 +0300 Subject: [PATCH 01/45] InfoTableProxyModel: invalidate first row cache after row insertion/deletion --- .../model/world/infotableproxymodel.cpp | 19 +++++++++++++------ .../model/world/infotableproxymodel.hpp | 2 +- 2 files changed, 14 insertions(+), 7 deletions(-) diff --git a/apps/opencs/model/world/infotableproxymodel.cpp b/apps/opencs/model/world/infotableproxymodel.cpp index 7522e492b..5192dfec0 100644 --- a/apps/opencs/model/world/infotableproxymodel.cpp +++ b/apps/opencs/model/world/infotableproxymodel.cpp @@ -15,11 +15,18 @@ void CSMWorld::InfoTableProxyModel::setSourceModel(QAbstractItemModel *sourceMod { IdTableProxyModel::setSourceModel(sourceModel); mSourceModel = dynamic_cast(sourceModel); - connect(mSourceModel, - SIGNAL(dataChanged(const QModelIndex &, const QModelIndex &)), - this, - SLOT(modelDataChanged(const QModelIndex &, const QModelIndex &))); - mFirstRowCache.clear(); + if (mSourceModel != NULL) + { + connect(mSourceModel, + SIGNAL(rowsInserted(const QModelIndex &, int, int)), + this, + SLOT(modelRowsChanged(const QModelIndex &, int, int))); + connect(mSourceModel, + SIGNAL(rowsRemoved(const QModelIndex &, int, int)), + this, + SLOT(modelRowsChanged(const QModelIndex &, int, int))); + mFirstRowCache.clear(); + } } bool CSMWorld::InfoTableProxyModel::lessThan(const QModelIndex &left, const QModelIndex &right) const @@ -52,7 +59,7 @@ int CSMWorld::InfoTableProxyModel::getFirstInfoRow(int currentRow) const return currentRow + 1; } -void CSMWorld::InfoTableProxyModel::modelDataChanged(const QModelIndex &/*topLeft*/, const QModelIndex &/*bottomRight*/) +void CSMWorld::InfoTableProxyModel::modelRowsChanged(const QModelIndex &/*parent*/, int /*start*/, int /*end*/) { mFirstRowCache.clear(); } diff --git a/apps/opencs/model/world/infotableproxymodel.hpp b/apps/opencs/model/world/infotableproxymodel.hpp index 322831626..7b0cd8ede 100644 --- a/apps/opencs/model/world/infotableproxymodel.hpp +++ b/apps/opencs/model/world/infotableproxymodel.hpp @@ -31,7 +31,7 @@ namespace CSMWorld virtual bool lessThan(const QModelIndex &left, const QModelIndex &right) const; private slots: - void modelDataChanged(const QModelIndex &topLeft, const QModelIndex &bottomRight); + void modelRowsChanged(const QModelIndex &parent, int start, int end); }; } From f1a38ffe930cb2ae13554543095ab0746edaf637 Mon Sep 17 00:00:00 2001 From: Stanislav Bas Date: Sat, 20 Jun 2015 11:29:15 +0300 Subject: [PATCH 02/45] InfoTableProxyModel: ignore the letter case in the search of the first Topic/Journal row --- .../model/world/infotableproxymodel.cpp | 19 +++++++++++++++---- 1 file changed, 15 insertions(+), 4 deletions(-) diff --git a/apps/opencs/model/world/infotableproxymodel.cpp b/apps/opencs/model/world/infotableproxymodel.cpp index 5192dfec0..2812bae60 100644 --- a/apps/opencs/model/world/infotableproxymodel.cpp +++ b/apps/opencs/model/world/infotableproxymodel.cpp @@ -1,8 +1,18 @@ #include "infotableproxymodel.hpp" +#include + #include "idtablebase.hpp" #include "columns.hpp" +namespace +{ + QString toLower(const QString &str) + { + return Misc::StringUtils::lowerCase(str.toStdString()).c_str(); + } +} + CSMWorld::InfoTableProxyModel::InfoTableProxyModel(CSMWorld::UniversalId::Type type, QObject *parent) : IdTableProxyModel(parent), mType(type), @@ -45,7 +55,7 @@ int CSMWorld::InfoTableProxyModel::getFirstInfoRow(int currentRow) const } int column = mSourceModel->findColumnIndex(columnId); - QString info = mSourceModel->data(mSourceModel->index(currentRow, column)).toString(); + QString info = toLower(mSourceModel->data(mSourceModel->index(currentRow, column)).toString()); if (mFirstRowCache.contains(info)) { @@ -53,10 +63,11 @@ int CSMWorld::InfoTableProxyModel::getFirstInfoRow(int currentRow) const } while (--currentRow >= 0 && - mSourceModel->data(mSourceModel->index(currentRow, column)) == info); + toLower(mSourceModel->data(mSourceModel->index(currentRow, column)).toString()) == info); + ++currentRow; - mFirstRowCache[info] = currentRow + 1; - return currentRow + 1; + mFirstRowCache[info] = currentRow; + return currentRow; } void CSMWorld::InfoTableProxyModel::modelRowsChanged(const QModelIndex &/*parent*/, int /*start*/, int /*end*/) From ced4e237a8e3c7069ebe769c0fea3fe2585d7e30 Mon Sep 17 00:00:00 2001 From: Stanislav Bas Date: Sat, 20 Jun 2015 12:43:53 +0300 Subject: [PATCH 03/45] Fix the sorting of Info tables when new row are added --- apps/opencs/model/world/infotableproxymodel.cpp | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/apps/opencs/model/world/infotableproxymodel.cpp b/apps/opencs/model/world/infotableproxymodel.cpp index 2812bae60..3e564506c 100644 --- a/apps/opencs/model/world/infotableproxymodel.cpp +++ b/apps/opencs/model/world/infotableproxymodel.cpp @@ -43,6 +43,12 @@ bool CSMWorld::InfoTableProxyModel::lessThan(const QModelIndex &left, const QMod { QModelIndex first = mSourceModel->index(getFirstInfoRow(left.row()), left.column()); QModelIndex second = mSourceModel->index(getFirstInfoRow(right.row()), right.column()); + + // If both indexes are belonged to the same Topic/Journal, compare their original rows only + if (first.row() == second.row()) + { + return sortOrder() == Qt::AscendingOrder ? left.row() < right.row() : right.row() < left.row(); + } return IdTableProxyModel::lessThan(first, second); } From 27ece7f36aec12f14987227b37a3af45b1f7e81b Mon Sep 17 00:00:00 2001 From: Stanislav Bas Date: Sat, 20 Jun 2015 17:33:36 +0300 Subject: [PATCH 04/45] Rework DropLineEdit. Make it type-sensitive --- apps/opencs/CMakeLists.txt | 2 +- apps/opencs/view/widget/droplineedit.cpp | 82 +++++++++++++++++++ apps/opencs/view/widget/droplineedit.hpp | 50 +++++++++++ apps/opencs/view/world/dialoguesubview.cpp | 5 +- .../view/world/idcompletiondelegate.cpp | 4 +- apps/opencs/view/world/util.cpp | 31 +------ apps/opencs/view/world/util.hpp | 19 ----- 7 files changed, 143 insertions(+), 50 deletions(-) create mode 100644 apps/opencs/view/widget/droplineedit.cpp create mode 100644 apps/opencs/view/widget/droplineedit.hpp diff --git a/apps/opencs/CMakeLists.txt b/apps/opencs/CMakeLists.txt index d86798af9..fa703e497 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 coloreditor colorpickerpopup + scenetooltoggle2 completerpopup coloreditor colorpickerpopup droplineedit ) opencs_units (view/render diff --git a/apps/opencs/view/widget/droplineedit.cpp b/apps/opencs/view/widget/droplineedit.cpp new file mode 100644 index 000000000..0b2ac6381 --- /dev/null +++ b/apps/opencs/view/widget/droplineedit.cpp @@ -0,0 +1,82 @@ +#include "droplineedit.hpp" + +#include + +#include "../../model/world/tablemimedata.hpp" + +namespace +{ + const CSMWorld::TableMimeData *getEventMimeData(QDropEvent *event) + { + Q_ASSERT(event != NULL); + return dynamic_cast(event->mimeData()); + } +} + +CSVWidget::DropLineEdit::DropLineEdit(QWidget *parent, CSMWorld::UniversalId::Type type) + : QLineEdit(parent), + mDropType(type) +{ + setAcceptDrops(true); +} + +void CSVWidget::DropLineEdit::dragEnterEvent(QDragEnterEvent *event) +{ + if (canAcceptEventData(event)) + { + event->acceptProposedAction(); + } +} + +void CSVWidget::DropLineEdit::dragMoveEvent(QDragMoveEvent *event) +{ + if (canAcceptEventData(event)) + { + event->accept(); + } +} + +void CSVWidget::DropLineEdit::dropEvent(QDropEvent *event) +{ + const CSMWorld::TableMimeData *data = getEventMimeData(event); + if (data == NULL) // May happen when non-records (e.g. plain text) are dragged and dropped + { + return; + } + + int dataIndex = getAcceptedDataIndex(*data); + if (dataIndex != -1) + { + setText(data->getData()[dataIndex].getId().c_str()); + emit tableMimeDataDropped(data->getData(), data->getDocumentPtr()); + } +} + +bool CSVWidget::DropLineEdit::canAcceptEventData(QDropEvent *event) const +{ + const CSMWorld::TableMimeData *data = getEventMimeData(event); + if (data == NULL) // May happen when non-records (e.g. plain text) are dragged and dropped + { + return false; + } + return getAcceptedDataIndex(*data) != -1; +} + +int CSVWidget::DropLineEdit::getAcceptedDataIndex(const CSMWorld::TableMimeData &data) const +{ + if (mDropType == CSMWorld::UniversalId::Type_None) + { + return 0; + } + + std::vector idData = data.getData(); + int size = static_cast(idData.size()); + for (int i = 0; i < size; ++i) + { + if (idData[i].getType() == mDropType) + { + return i; + } + } + return -1; +} diff --git a/apps/opencs/view/widget/droplineedit.hpp b/apps/opencs/view/widget/droplineedit.hpp new file mode 100644 index 000000000..e49c947b4 --- /dev/null +++ b/apps/opencs/view/widget/droplineedit.hpp @@ -0,0 +1,50 @@ +#ifndef CSV_WIDGET_DROPLINEEDIT_HPP +#define CSV_WIDGET_DROPLINEEDIT_HPP + +#include + +#include "../../model/world/universalid.hpp" + +namespace CSMDoc +{ + class Document; +} + +namespace CSMWorld +{ + class TableMimeData; +} + +namespace CSVWidget +{ + class DropLineEdit : public QLineEdit + { + Q_OBJECT + + CSMWorld::UniversalId::Type mDropType; + ///< The accepted ID type for this LineEdit. + ///< If \a mDropType has Type_None type, this LineEdit accepts all ID types + + bool canAcceptEventData(QDropEvent *event) const; + ///< Checks whether the \a event contains CSMWorld::TableMimeData with a proper ID type + + int getAcceptedDataIndex(const CSMWorld::TableMimeData &data) const; + ///< Checks whether the \a data has a proper type + ///< \return -1 if there is no suitable data (ID type) + + public: + DropLineEdit(QWidget *parent = 0, + CSMWorld::UniversalId::Type type = CSMWorld::UniversalId::Type_None); + + protected: + void dragEnterEvent(QDragEnterEvent *event); + void dragMoveEvent(QDragMoveEvent *event); + void dropEvent(QDropEvent *event); + + signals: + void tableMimeDataDropped(const std::vector &data, + const CSMDoc::Document *document); + }; +} + +#endif diff --git a/apps/opencs/view/world/dialoguesubview.cpp b/apps/opencs/view/world/dialoguesubview.cpp index 5d9eda3f2..a1dbc902e 100644 --- a/apps/opencs/view/world/dialoguesubview.cpp +++ b/apps/opencs/view/world/dialoguesubview.cpp @@ -34,6 +34,7 @@ #include "../../model/doc/document.hpp" #include "../widget/coloreditor.hpp" +#include "../widget/droplineedit.hpp" #include "recordstatusdelegate.hpp" #include "util.hpp" @@ -306,7 +307,7 @@ QWidget* CSVWorld::DialogueDelegateDispatcher::makeEditor(CSMWorld::ColumnBase:: // NOTE: For each entry in CSVWorld::CommandDelegate::createEditor() a corresponding entry // is required here - if (qobject_cast(editor)) + if (qobject_cast(editor)) { connect(editor, SIGNAL(editingFinished()), proxy, SLOT(editorDataCommited())); @@ -850,7 +851,7 @@ void CSVWorld::DialogueSubView::tableMimeDataDropped (QWidget* editor, { if (document == &mDocument) { - qobject_cast(editor)->setText(id.getId().c_str()); + qobject_cast(editor)->setText(id.getId().c_str()); } } diff --git a/apps/opencs/view/world/idcompletiondelegate.cpp b/apps/opencs/view/world/idcompletiondelegate.cpp index 056026471..5c92e6576 100644 --- a/apps/opencs/view/world/idcompletiondelegate.cpp +++ b/apps/opencs/view/world/idcompletiondelegate.cpp @@ -2,6 +2,8 @@ #include "../../model/world/idcompletionmanager.hpp" +#include "../widget/droplineedit.hpp" + CSVWorld::IdCompletionDelegate::IdCompletionDelegate(CSMWorld::CommandDispatcher *dispatcher, CSMDoc::Document& document, QObject *parent) @@ -26,7 +28,7 @@ QWidget *CSVWorld::IdCompletionDelegate::createEditor(QWidget *parent, } CSMWorld::IdCompletionManager &completionManager = getDocument().getIdCompletionManager(); - DropLineEdit *editor = new DropLineEdit(parent); + CSVWidget::DropLineEdit *editor = new CSVWidget::DropLineEdit(parent); editor->setCompleter(completionManager.getCompleter(display).get()); return editor; } diff --git a/apps/opencs/view/world/util.cpp b/apps/opencs/view/world/util.cpp index 5974987c0..684327fc2 100644 --- a/apps/opencs/view/world/util.cpp +++ b/apps/opencs/view/world/util.cpp @@ -17,7 +17,10 @@ #include "../../model/world/commands.hpp" #include "../../model/world/tablemimedata.hpp" #include "../../model/world/commanddispatcher.hpp" + #include "../widget/coloreditor.hpp" +#include "../widget/droplineedit.hpp" + #include "dialoguespinbox.hpp" #include "scriptedit.hpp" @@ -250,7 +253,7 @@ QWidget *CSVWorld::CommandDelegate::createEditor (QWidget *parent, const QStyleO case CSMWorld::ColumnBase::Display_Video: case CSMWorld::ColumnBase::Display_GlobalVariable: - return new DropLineEdit(parent); + return new CSVWidget::DropLineEdit(parent); case CSMWorld::ColumnBase::Display_ScriptLines: @@ -324,29 +327,3 @@ void CSVWorld::CommandDelegate::setEditorData (QWidget *editor, const QModelInde } } - -CSVWorld::DropLineEdit::DropLineEdit(QWidget* parent) : -QLineEdit(parent) -{ - setAcceptDrops(true); -} - -void CSVWorld::DropLineEdit::dragEnterEvent(QDragEnterEvent *event) -{ - event->acceptProposedAction(); -} - -void CSVWorld::DropLineEdit::dragMoveEvent(QDragMoveEvent *event) -{ - event->accept(); -} - -void CSVWorld::DropLineEdit::dropEvent(QDropEvent *event) -{ - const CSMWorld::TableMimeData* data(dynamic_cast(event->mimeData())); - if (!data) // May happen when non-records (e.g. plain text) are dragged and dropped - return; - - emit tableMimeDataDropped(data->getData(), data->getDocumentPtr()); - //WIP -} diff --git a/apps/opencs/view/world/util.hpp b/apps/opencs/view/world/util.hpp index 8355e971c..d695be0d7 100644 --- a/apps/opencs/view/world/util.hpp +++ b/apps/opencs/view/world/util.hpp @@ -5,7 +5,6 @@ #include #include -#include #include "../../model/world/columnbase.hpp" #include "../../model/doc/document.hpp" @@ -91,24 +90,6 @@ namespace CSVWorld }; - class DropLineEdit : public QLineEdit - { - Q_OBJECT - - public: - DropLineEdit(QWidget *parent); - - private: - void dragEnterEvent(QDragEnterEvent *event); - - void dragMoveEvent(QDragMoveEvent *event); - - void dropEvent(QDropEvent *event); - - signals: - void tableMimeDataDropped(const std::vector& data, const CSMDoc::Document* document); - }; - ///< \brief Use commands instead of manipulating the model directly class CommandDelegate : public QStyledItemDelegate { From 64701b273d041411bc75caaf9527ea2183ee6679 Mon Sep 17 00:00:00 2001 From: Stanislav Bas Date: Sat, 20 Jun 2015 18:29:31 +0300 Subject: [PATCH 05/45] LineEdits for ID values accept drops with a proper type --- apps/opencs/view/widget/droplineedit.cpp | 9 ++++++++- apps/opencs/view/widget/droplineedit.hpp | 5 +++-- apps/opencs/view/world/idcompletiondelegate.cpp | 2 +- apps/opencs/view/world/util.cpp | 2 +- 4 files changed, 13 insertions(+), 5 deletions(-) diff --git a/apps/opencs/view/widget/droplineedit.cpp b/apps/opencs/view/widget/droplineedit.cpp index 0b2ac6381..f3500dcd2 100644 --- a/apps/opencs/view/widget/droplineedit.cpp +++ b/apps/opencs/view/widget/droplineedit.cpp @@ -13,13 +13,20 @@ namespace } } -CSVWidget::DropLineEdit::DropLineEdit(QWidget *parent, CSMWorld::UniversalId::Type type) +CSVWidget::DropLineEdit::DropLineEdit(CSMWorld::UniversalId::Type type, QWidget *parent) : QLineEdit(parent), mDropType(type) { setAcceptDrops(true); } +CSVWidget::DropLineEdit::DropLineEdit(CSMWorld::ColumnBase::Display display, QWidget *parent) + : QLineEdit(parent), + mDropType(CSMWorld::TableMimeData::convertEnums(display)) +{ + setAcceptDrops(true); +} + void CSVWidget::DropLineEdit::dragEnterEvent(QDragEnterEvent *event) { if (canAcceptEventData(event)) diff --git a/apps/opencs/view/widget/droplineedit.hpp b/apps/opencs/view/widget/droplineedit.hpp index e49c947b4..7ba0513cc 100644 --- a/apps/opencs/view/widget/droplineedit.hpp +++ b/apps/opencs/view/widget/droplineedit.hpp @@ -3,6 +3,7 @@ #include +#include "../../model/world/columnbase.hpp" #include "../../model/world/universalid.hpp" namespace CSMDoc @@ -33,8 +34,8 @@ namespace CSVWidget ///< \return -1 if there is no suitable data (ID type) public: - DropLineEdit(QWidget *parent = 0, - CSMWorld::UniversalId::Type type = CSMWorld::UniversalId::Type_None); + DropLineEdit(CSMWorld::UniversalId::Type type, QWidget *parent = 0); + DropLineEdit(CSMWorld::ColumnBase::Display display, QWidget *parent = 0); protected: void dragEnterEvent(QDragEnterEvent *event); diff --git a/apps/opencs/view/world/idcompletiondelegate.cpp b/apps/opencs/view/world/idcompletiondelegate.cpp index 5c92e6576..970490828 100644 --- a/apps/opencs/view/world/idcompletiondelegate.cpp +++ b/apps/opencs/view/world/idcompletiondelegate.cpp @@ -28,7 +28,7 @@ QWidget *CSVWorld::IdCompletionDelegate::createEditor(QWidget *parent, } CSMWorld::IdCompletionManager &completionManager = getDocument().getIdCompletionManager(); - CSVWidget::DropLineEdit *editor = new CSVWidget::DropLineEdit(parent); + CSVWidget::DropLineEdit *editor = new CSVWidget::DropLineEdit(display, parent); editor->setCompleter(completionManager.getCompleter(display).get()); return editor; } diff --git a/apps/opencs/view/world/util.cpp b/apps/opencs/view/world/util.cpp index 684327fc2..d3969dad4 100644 --- a/apps/opencs/view/world/util.cpp +++ b/apps/opencs/view/world/util.cpp @@ -253,7 +253,7 @@ QWidget *CSVWorld::CommandDelegate::createEditor (QWidget *parent, const QStyleO case CSMWorld::ColumnBase::Display_Video: case CSMWorld::ColumnBase::Display_GlobalVariable: - return new CSVWidget::DropLineEdit(parent); + return new CSVWidget::DropLineEdit(CSMWorld::UniversalId::Type_None, parent); case CSMWorld::ColumnBase::Display_ScriptLines: From 7dcdd130bb65be9fa79d8240946458420c2248d4 Mon Sep 17 00:00:00 2001 From: Stanislav Bas Date: Sat, 20 Jun 2015 20:52:47 +0300 Subject: [PATCH 06/45] Rework Dialogue subview code according to DropLineEdit changes --- apps/opencs/view/widget/droplineedit.cpp | 9 ++- apps/opencs/view/widget/droplineedit.hpp | 3 +- apps/opencs/view/world/dialoguesubview.cpp | 70 +--------------------- apps/opencs/view/world/dialoguesubview.hpp | 20 ------- apps/opencs/view/world/util.cpp | 24 ++------ 5 files changed, 14 insertions(+), 112 deletions(-) diff --git a/apps/opencs/view/widget/droplineedit.cpp b/apps/opencs/view/widget/droplineedit.cpp index f3500dcd2..6dae15746 100644 --- a/apps/opencs/view/widget/droplineedit.cpp +++ b/apps/opencs/view/widget/droplineedit.cpp @@ -54,8 +54,9 @@ void CSVWidget::DropLineEdit::dropEvent(QDropEvent *event) int dataIndex = getAcceptedDataIndex(*data); if (dataIndex != -1) { - setText(data->getData()[dataIndex].getId().c_str()); - emit tableMimeDataDropped(data->getData(), data->getDocumentPtr()); + std::vector idData = data->getData(); + setText(idData[dataIndex].getId().c_str()); + emit tableMimeDataDropped(idData[dataIndex], data->getDocumentPtr()); } } @@ -76,11 +77,13 @@ int CSVWidget::DropLineEdit::getAcceptedDataIndex(const CSMWorld::TableMimeData return 0; } + bool isReferenceable = mDropType == CSMWorld::UniversalId::Type_Referenceable; std::vector idData = data.getData(); int size = static_cast(idData.size()); for (int i = 0; i < size; ++i) { - if (idData[i].getType() == mDropType) + CSMWorld::UniversalId::Type type = idData[i].getType(); + if (type == mDropType || isReferenceable && CSMWorld::TableMimeData::isReferencable(type)) { return i; } diff --git a/apps/opencs/view/widget/droplineedit.hpp b/apps/opencs/view/widget/droplineedit.hpp index 7ba0513cc..ce086b7dc 100644 --- a/apps/opencs/view/widget/droplineedit.hpp +++ b/apps/opencs/view/widget/droplineedit.hpp @@ -43,8 +43,7 @@ namespace CSVWidget void dropEvent(QDropEvent *event); signals: - void tableMimeDataDropped(const std::vector &data, - const CSMDoc::Document *document); + void tableMimeDataDropped(const CSMWorld::UniversalId &id, const CSMDoc::Document *document); }; } diff --git a/apps/opencs/view/world/dialoguesubview.cpp b/apps/opencs/view/world/dialoguesubview.cpp index a1dbc902e..284c5928b 100644 --- a/apps/opencs/view/world/dialoguesubview.cpp +++ b/apps/opencs/view/world/dialoguesubview.cpp @@ -130,52 +130,6 @@ QWidget* CSVWorld::DialogueDelegateDispatcherProxy::getEditor() const return mEditor; } -void CSVWorld::DialogueDelegateDispatcherProxy::tableMimeDataDropped(const std::vector& data, const CSMDoc::Document* document) -{ - QLineEdit* lineEdit = qobject_cast(mEditor); - { - if (!lineEdit || !mIndexWrapper.get()) - { - return; - } - } - for (unsigned i = 0; i < data.size(); ++i) - { - CSMWorld::UniversalId::Type type = data[i].getType(); - if (mDisplay == CSMWorld::ColumnBase::Display_Referenceable) - { - if (type == CSMWorld::UniversalId::Type_Activator - || type == CSMWorld::UniversalId::Type_Potion - || type == CSMWorld::UniversalId::Type_Apparatus - || type == CSMWorld::UniversalId::Type_Armor - || type == CSMWorld::UniversalId::Type_Book - || type == CSMWorld::UniversalId::Type_Clothing - || type == CSMWorld::UniversalId::Type_Container - || type == CSMWorld::UniversalId::Type_Creature - || type == CSMWorld::UniversalId::Type_Door - || type == CSMWorld::UniversalId::Type_Ingredient - || type == CSMWorld::UniversalId::Type_CreatureLevelledList - || type == CSMWorld::UniversalId::Type_ItemLevelledList - || type == CSMWorld::UniversalId::Type_Light - || type == CSMWorld::UniversalId::Type_Lockpick - || type == CSMWorld::UniversalId::Type_Miscellaneous - || type == CSMWorld::UniversalId::Type_Npc - || type == CSMWorld::UniversalId::Type_Probe - || type == CSMWorld::UniversalId::Type_Repair - || type == CSMWorld::UniversalId::Type_Static - || type == CSMWorld::UniversalId::Type_Weapon) - { - type = CSMWorld::UniversalId::Type_Referenceable; - } - } - if (mDisplay == CSMWorld::TableMimeData::convertEnums(type)) - { - emit tableMimeDataDropped(mEditor, mIndexWrapper->mIndex, data[i], document); - emit editorDataCommited(mEditor, mIndexWrapper->mIndex, mDisplay); - break; - } - } -} /* ==============================DialogueDelegateDispatcher========================================== */ @@ -311,12 +265,8 @@ QWidget* CSVWorld::DialogueDelegateDispatcher::makeEditor(CSMWorld::ColumnBase:: { connect(editor, SIGNAL(editingFinished()), proxy, SLOT(editorDataCommited())); - connect(editor, SIGNAL(tableMimeDataDropped(const std::vector&, const CSMDoc::Document*)), - proxy, SLOT(tableMimeDataDropped(const std::vector&, const CSMDoc::Document*))); - - connect(proxy, SIGNAL(tableMimeDataDropped(QWidget*, const QModelIndex&, const CSMWorld::UniversalId&, const CSMDoc::Document*)), - this, SIGNAL(tableMimeDataDropped(QWidget*, const QModelIndex&, const CSMWorld::UniversalId&, const CSMDoc::Document*))); - + connect(editor, SIGNAL(tableMimeDataDropped(const CSMWorld::UniversalId&, const CSMDoc::Document*)), + proxy, SLOT(editorDataCommited())); } else if (qobject_cast(editor)) { @@ -387,9 +337,6 @@ mCommandDispatcher (commandDispatcher), mDocument (document) { remake (row); - - connect(mDispatcher, SIGNAL(tableMimeDataDropped(QWidget*, const QModelIndex&, const CSMWorld::UniversalId&, const CSMDoc::Document*)), - this, SIGNAL(tableMimeDataDropped(QWidget*, const QModelIndex&, const CSMWorld::UniversalId&, const CSMDoc::Document*))); } void CSVWorld::EditWidget::remake(int row) @@ -680,8 +627,6 @@ CSVWorld::DialogueSubView::DialogueSubView (const CSMWorld::UniversalId& id, CSM mEditWidget = new EditWidget(mainWidget, mTable->getModelIndex(mCurrentId, 0).row(), mTable, mCommandDispatcher, document, false); - connect(mEditWidget, SIGNAL(tableMimeDataDropped(QWidget*, const QModelIndex&, const CSMWorld::UniversalId&, const CSMDoc::Document*)), - this, SLOT(tableMimeDataDropped(QWidget*, const QModelIndex&, const CSMWorld::UniversalId&, const CSMDoc::Document*))); mMainLayout->addWidget(mEditWidget); mEditWidget->setSizePolicy(QSizePolicy::MinimumExpanding, QSizePolicy::MinimumExpanding); @@ -844,17 +789,6 @@ void CSVWorld::DialogueSubView::rowsAboutToBeRemoved(const QModelIndex &parent, } } -void CSVWorld::DialogueSubView::tableMimeDataDropped (QWidget* editor, - const QModelIndex& index, - const CSMWorld::UniversalId& id, - const CSMDoc::Document* document) -{ - if (document == &mDocument) - { - qobject_cast(editor)->setText(id.getId().c_str()); - } -} - void CSVWorld::DialogueSubView::requestFocus (const std::string& id) { changeCurrentId(id); diff --git a/apps/opencs/view/world/dialoguesubview.hpp b/apps/opencs/view/world/dialoguesubview.hpp index 6cbd8ad77..69e0dc864 100644 --- a/apps/opencs/view/world/dialoguesubview.hpp +++ b/apps/opencs/view/world/dialoguesubview.hpp @@ -86,18 +86,12 @@ namespace CSVWorld public slots: void editorDataCommited(); void setIndex(const QModelIndex& index); - void tableMimeDataDropped(const std::vector& data, - const CSMDoc::Document* document); signals: void editorDataCommited(QWidget* editor, const QModelIndex& index, CSMWorld::ColumnBase::Display display); - void tableMimeDataDropped(QWidget* editor, const QModelIndex& index, - const CSMWorld::UniversalId& id, - const CSMDoc::Document* document); - }; class DialogueDelegateDispatcher : public QAbstractItemDelegate @@ -153,11 +147,6 @@ namespace CSVWorld private slots: void editorDataCommited(QWidget* editor, const QModelIndex& index, CSMWorld::ColumnBase::Display display); - - signals: - void tableMimeDataDropped(QWidget* editor, const QModelIndex& index, - const CSMWorld::UniversalId& id, - const CSMDoc::Document* document); }; class EditWidget : public QScrollArea @@ -182,11 +171,6 @@ namespace CSVWorld virtual ~EditWidget(); void remake(int row); - - signals: - void tableMimeDataDropped(QWidget* editor, const QModelIndex& index, - const CSMWorld::UniversalId& id, - const CSMDoc::Document* document); }; class DialogueSubView : public CSVDoc::SubView @@ -230,10 +214,6 @@ namespace CSVWorld void dataChanged(const QModelIndex & index); ///\brief we need to care for deleting currently edited record - void tableMimeDataDropped(QWidget* editor, const QModelIndex& index, - const CSMWorld::UniversalId& id, - const CSMDoc::Document* document); - void requestFocus (const std::string& id); void rowsAboutToBeRemoved(const QModelIndex &parent, int start, int end); diff --git a/apps/opencs/view/world/util.cpp b/apps/opencs/view/world/util.cpp index d3969dad4..815505589 100644 --- a/apps/opencs/view/world/util.cpp +++ b/apps/opencs/view/world/util.cpp @@ -236,29 +236,15 @@ QWidget *CSVWorld::CommandDelegate::createEditor (QWidget *parent, const QStyleO return new QCheckBox(parent); - case CSMWorld::ColumnBase::Display_String: - case CSMWorld::ColumnBase::Display_Skill: - case CSMWorld::ColumnBase::Display_Script: - case CSMWorld::ColumnBase::Display_Race: - case CSMWorld::ColumnBase::Display_Region: - case CSMWorld::ColumnBase::Display_Class: - case CSMWorld::ColumnBase::Display_Faction: - case CSMWorld::ColumnBase::Display_Miscellaneous: - case CSMWorld::ColumnBase::Display_Sound: - case CSMWorld::ColumnBase::Display_Mesh: - case CSMWorld::ColumnBase::Display_Icon: - case CSMWorld::ColumnBase::Display_Music: - case CSMWorld::ColumnBase::Display_SoundRes: - case CSMWorld::ColumnBase::Display_Texture: - case CSMWorld::ColumnBase::Display_Video: - case CSMWorld::ColumnBase::Display_GlobalVariable: - - return new CSVWidget::DropLineEdit(CSMWorld::UniversalId::Type_None, parent); - case CSMWorld::ColumnBase::Display_ScriptLines: return new ScriptEdit (mDocument, ScriptHighlighter::Mode_Console, parent); + case CSMWorld::ColumnBase::Display_String: + // For other Display types (that represent record IDs) with drop support IdCompletionDelegate is used + + return new CSVWidget::DropLineEdit(CSMWorld::UniversalId::Type_None, parent); + default: return QStyledItemDelegate::createEditor (parent, option, index); From dc37aea8ebd678b9824f0558b48085b30c61fe0a Mon Sep 17 00:00:00 2001 From: Stanislav Bas Date: Sat, 20 Jun 2015 21:00:15 +0300 Subject: [PATCH 07/45] Add missing mappings to TableMimeData --- apps/opencs/model/world/tablemimedata.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/apps/opencs/model/world/tablemimedata.cpp b/apps/opencs/model/world/tablemimedata.cpp index d40e0c217..101bbf9ba 100644 --- a/apps/opencs/model/world/tablemimedata.cpp +++ b/apps/opencs/model/world/tablemimedata.cpp @@ -264,6 +264,8 @@ namespace { CSMWorld::UniversalId::Type_Texture, CSMWorld::ColumnBase::Display_Texture }, { CSMWorld::UniversalId::Type_Video, CSMWorld::ColumnBase::Display_Video }, { CSMWorld::UniversalId::Type_Global, CSMWorld::ColumnBase::Display_GlobalVariable }, + { CSMWorld::UniversalId::Type_BodyPart, CSMWorld::ColumnBase::Display_BodyPart }, + { CSMWorld::UniversalId::Type_Enchantment, CSMWorld::ColumnBase::Display_Enchantment }, { CSMWorld::UniversalId::Type_None, CSMWorld::ColumnBase::Display_None } // end marker }; From 256545205226c44320eb813397bd23021f0e8a31 Mon Sep 17 00:00:00 2001 From: Stanislav Bas Date: Sun, 21 Jun 2015 17:08:10 +0300 Subject: [PATCH 08/45] Add some drag'n'drop utils to work with TableMimeData --- apps/opencs/CMakeLists.txt | 2 +- apps/opencs/view/world/dragdroputils.cpp | 26 ++++++++++++++++++++ apps/opencs/view/world/dragdroputils.hpp | 30 ++++++++++++++++++++++++ 3 files changed, 57 insertions(+), 1 deletion(-) create mode 100644 apps/opencs/view/world/dragdroputils.cpp create mode 100644 apps/opencs/view/world/dragdroputils.hpp diff --git a/apps/opencs/CMakeLists.txt b/apps/opencs/CMakeLists.txt index fa703e497..5386da707 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 - colordelegate + colordelegate dragdroputils ) opencs_units (view/widget diff --git a/apps/opencs/view/world/dragdroputils.cpp b/apps/opencs/view/world/dragdroputils.cpp new file mode 100644 index 000000000..7f3974e53 --- /dev/null +++ b/apps/opencs/view/world/dragdroputils.cpp @@ -0,0 +1,26 @@ +#include "dragdroputils.hpp" + +#include + +#include "../../model/world/tablemimedata.hpp" + +const CSMWorld::TableMimeData *CSVWorld::DragDropUtils::getTableMimeData(const QDropEvent &event) +{ + return dynamic_cast(event.mimeData()); +} + +bool CSVWorld::DragDropUtils::canAcceptData(const QDropEvent &event, CSMWorld::ColumnBase::Display type) +{ + const CSMWorld::TableMimeData *data = getTableMimeData(event); + return data != NULL && data->holdsType(type); +} + +CSMWorld::UniversalId CSVWorld::DragDropUtils::getAcceptedData(const QDropEvent &event, + CSMWorld::ColumnBase::Display type) +{ + if (canAcceptData(event, type)) + { + return getTableMimeData(event)->returnMatching(type); + } + return CSMWorld::UniversalId::Type_None; +} diff --git a/apps/opencs/view/world/dragdroputils.hpp b/apps/opencs/view/world/dragdroputils.hpp new file mode 100644 index 000000000..88e2958a5 --- /dev/null +++ b/apps/opencs/view/world/dragdroputils.hpp @@ -0,0 +1,30 @@ +#ifndef CSV_WORLD_DRAGDROPUTILS_HPP +#define CSV_WORLD_DRAGDROPUTILS_HPP + +#include "../../model/world/columnbase.hpp" + +class QDropEvent; + +namespace CSMWorld +{ + class TableMimeData; + class UniversalId; +} + +namespace CSVWorld +{ + class DragDropUtils + { + public: + static const CSMWorld::TableMimeData *getTableMimeData(const QDropEvent &event); + + static bool canAcceptData(const QDropEvent &event, CSMWorld::ColumnBase::Display type); + ///< Checks whether the \a event contains a valid CSMWorld::TableMimeData that holds the \a type + + static CSMWorld::UniversalId getAcceptedData(const QDropEvent &event, CSMWorld::ColumnBase::Display type); + ///< Gets the accepted data from the \a event using the \a type + ///< \return Type_None if the \a event data doesn't holds the \a type + }; +} + +#endif From a23de394f8ef2dd4c5fdb28b03cf8527cd42e3e0 Mon Sep 17 00:00:00 2001 From: Stanislav Bas Date: Sun, 21 Jun 2015 17:16:13 +0300 Subject: [PATCH 09/45] Refine DropLineEdit code --- apps/opencs/view/widget/droplineedit.cpp | 69 ++++-------------------- apps/opencs/view/widget/droplineedit.hpp | 17 ++---- apps/opencs/view/world/util.cpp | 2 +- 3 files changed, 14 insertions(+), 74 deletions(-) diff --git a/apps/opencs/view/widget/droplineedit.cpp b/apps/opencs/view/widget/droplineedit.cpp index 6dae15746..98f1d81c3 100644 --- a/apps/opencs/view/widget/droplineedit.cpp +++ b/apps/opencs/view/widget/droplineedit.cpp @@ -3,33 +3,20 @@ #include #include "../../model/world/tablemimedata.hpp" +#include "../../model/world/universalid.hpp" -namespace -{ - const CSMWorld::TableMimeData *getEventMimeData(QDropEvent *event) - { - Q_ASSERT(event != NULL); - return dynamic_cast(event->mimeData()); - } -} +#include "../world/dragdroputils.hpp" -CSVWidget::DropLineEdit::DropLineEdit(CSMWorld::UniversalId::Type type, QWidget *parent) +CSVWidget::DropLineEdit::DropLineEdit(CSMWorld::ColumnBase::Display type, QWidget *parent) : QLineEdit(parent), mDropType(type) { setAcceptDrops(true); } -CSVWidget::DropLineEdit::DropLineEdit(CSMWorld::ColumnBase::Display display, QWidget *parent) - : QLineEdit(parent), - mDropType(CSMWorld::TableMimeData::convertEnums(display)) -{ - setAcceptDrops(true); -} - void CSVWidget::DropLineEdit::dragEnterEvent(QDragEnterEvent *event) { - if (canAcceptEventData(event)) + if (CSVWorld::DragDropUtils::canAcceptData(*event, mDropType)) { event->acceptProposedAction(); } @@ -37,7 +24,7 @@ void CSVWidget::DropLineEdit::dragEnterEvent(QDragEnterEvent *event) void CSVWidget::DropLineEdit::dragMoveEvent(QDragMoveEvent *event) { - if (canAcceptEventData(event)) + if (CSVWorld::DragDropUtils::canAcceptData(*event, mDropType)) { event->accept(); } @@ -45,48 +32,10 @@ void CSVWidget::DropLineEdit::dragMoveEvent(QDragMoveEvent *event) void CSVWidget::DropLineEdit::dropEvent(QDropEvent *event) { - const CSMWorld::TableMimeData *data = getEventMimeData(event); - if (data == NULL) // May happen when non-records (e.g. plain text) are dragged and dropped - { - return; - } - - int dataIndex = getAcceptedDataIndex(*data); - if (dataIndex != -1) - { - std::vector idData = data->getData(); - setText(idData[dataIndex].getId().c_str()); - emit tableMimeDataDropped(idData[dataIndex], data->getDocumentPtr()); - } -} - -bool CSVWidget::DropLineEdit::canAcceptEventData(QDropEvent *event) const -{ - const CSMWorld::TableMimeData *data = getEventMimeData(event); - if (data == NULL) // May happen when non-records (e.g. plain text) are dragged and dropped - { - return false; - } - return getAcceptedDataIndex(*data) != -1; -} - -int CSVWidget::DropLineEdit::getAcceptedDataIndex(const CSMWorld::TableMimeData &data) const -{ - if (mDropType == CSMWorld::UniversalId::Type_None) - { - return 0; - } - - bool isReferenceable = mDropType == CSMWorld::UniversalId::Type_Referenceable; - std::vector idData = data.getData(); - int size = static_cast(idData.size()); - for (int i = 0; i < size; ++i) + if (CSVWorld::DragDropUtils::canAcceptData(*event, mDropType)) { - CSMWorld::UniversalId::Type type = idData[i].getType(); - if (type == mDropType || isReferenceable && CSMWorld::TableMimeData::isReferencable(type)) - { - return i; - } + CSMWorld::UniversalId id = CSVWorld::DragDropUtils::getAcceptedData(*event, mDropType); + setText(id.getId().c_str()); + emit tableMimeDataDropped(id, CSVWorld::DragDropUtils::getTableMimeData(*event)->getDocumentPtr()); } - return -1; } diff --git a/apps/opencs/view/widget/droplineedit.hpp b/apps/opencs/view/widget/droplineedit.hpp index ce086b7dc..60832e71b 100644 --- a/apps/opencs/view/widget/droplineedit.hpp +++ b/apps/opencs/view/widget/droplineedit.hpp @@ -4,7 +4,6 @@ #include #include "../../model/world/columnbase.hpp" -#include "../../model/world/universalid.hpp" namespace CSMDoc { @@ -14,6 +13,7 @@ namespace CSMDoc namespace CSMWorld { class TableMimeData; + class UniversalId; } namespace CSVWidget @@ -22,20 +22,11 @@ namespace CSVWidget { Q_OBJECT - CSMWorld::UniversalId::Type mDropType; - ///< The accepted ID type for this LineEdit. - ///< If \a mDropType has Type_None type, this LineEdit accepts all ID types - - bool canAcceptEventData(QDropEvent *event) const; - ///< Checks whether the \a event contains CSMWorld::TableMimeData with a proper ID type - - int getAcceptedDataIndex(const CSMWorld::TableMimeData &data) const; - ///< Checks whether the \a data has a proper type - ///< \return -1 if there is no suitable data (ID type) + CSMWorld::ColumnBase::Display mDropType; + ///< The accepted Display type for this LineEdit. public: - DropLineEdit(CSMWorld::UniversalId::Type type, QWidget *parent = 0); - DropLineEdit(CSMWorld::ColumnBase::Display display, QWidget *parent = 0); + DropLineEdit(CSMWorld::ColumnBase::Display type, QWidget *parent = 0); protected: void dragEnterEvent(QDragEnterEvent *event); diff --git a/apps/opencs/view/world/util.cpp b/apps/opencs/view/world/util.cpp index 815505589..62cde4608 100644 --- a/apps/opencs/view/world/util.cpp +++ b/apps/opencs/view/world/util.cpp @@ -243,7 +243,7 @@ QWidget *CSVWorld::CommandDelegate::createEditor (QWidget *parent, const QStyleO case CSMWorld::ColumnBase::Display_String: // For other Display types (that represent record IDs) with drop support IdCompletionDelegate is used - return new CSVWidget::DropLineEdit(CSMWorld::UniversalId::Type_None, parent); + return new CSVWidget::DropLineEdit(display, parent); default: From b9882eb59ab0c8a13d64b9ed7ffa7b1bdff0f12a Mon Sep 17 00:00:00 2001 From: Stanislav Bas Date: Sun, 21 Jun 2015 18:40:13 +0300 Subject: [PATCH 10/45] DragRecordTable checks drag type before accepting it --- apps/opencs/view/world/dragrecordtable.cpp | 53 +++++++++++++++++++++- apps/opencs/view/world/dragrecordtable.hpp | 7 +++ apps/opencs/view/world/table.cpp | 30 ------------ apps/opencs/view/world/table.hpp | 2 - 4 files changed, 58 insertions(+), 34 deletions(-) diff --git a/apps/opencs/view/world/dragrecordtable.cpp b/apps/opencs/view/world/dragrecordtable.cpp index 2a1ae1f40..3712348e2 100644 --- a/apps/opencs/view/world/dragrecordtable.cpp +++ b/apps/opencs/view/world/dragrecordtable.cpp @@ -1,8 +1,14 @@ +#include "dragrecordtable.hpp" + #include #include +#include "../../model/doc/document.hpp" + #include "../../model/world/tablemimedata.hpp" -#include "dragrecordtable.hpp" +#include "../../model/world/commands.hpp" + +#include "dragdroputils.hpp" void CSVWorld::DragRecordTable::startDragFromTable (const CSVWorld::DragRecordTable& table) { @@ -35,5 +41,48 @@ void CSVWorld::DragRecordTable::dragEnterEvent(QDragEnterEvent *event) void CSVWorld::DragRecordTable::dragMoveEvent(QDragMoveEvent *event) { - event->accept(); + QModelIndex index = indexAt(event->pos()); + if (CSVWorld::DragDropUtils::canAcceptData(*event, getIndexDisplayType(index))) + { + event->accept(); + } + else + { + event->ignore(); + } +} + +void CSVWorld::DragRecordTable::dropEvent(QDropEvent *event) +{ + QModelIndex index = indexAt(event->pos()); + CSMWorld::ColumnBase::Display display = getIndexDisplayType(index); + if (CSVWorld::DragDropUtils::canAcceptData(*event, display)) + { + const CSMWorld::TableMimeData *data = CSVWorld::DragDropUtils::getTableMimeData(*event); + if (data->fromDocument(mDocument)) + { + CSMWorld::UniversalId id = CSVWorld::DragDropUtils::getAcceptedData(*event, display); + QVariant newIndexData = QString::fromUtf8(id.getId().c_str()); + QVariant oldIndexData = index.data(Qt::EditRole); + if (newIndexData != oldIndexData) + { + mDocument.getUndoStack().push(new CSMWorld::ModifyCommand(*model(), index, newIndexData)); + } + } + } +} + +CSMWorld::ColumnBase::Display CSVWorld::DragRecordTable::getIndexDisplayType(const QModelIndex &index) const +{ + Q_ASSERT(model() != NULL); + + if (index.isValid()) + { + QVariant display = model()->headerData(index.column(), Qt::Horizontal, CSMWorld::ColumnBase::Role_Display); + if (display.isValid()) + { + return static_cast(display.toInt()); + } + } + return CSMWorld::ColumnBase::Display_None; } diff --git a/apps/opencs/view/world/dragrecordtable.hpp b/apps/opencs/view/world/dragrecordtable.hpp index 48f9e2528..560864ba5 100644 --- a/apps/opencs/view/world/dragrecordtable.hpp +++ b/apps/opencs/view/world/dragrecordtable.hpp @@ -4,6 +4,8 @@ #include #include +#include "../../model/world/columnbase.hpp" + class QWidget; class QAction; @@ -38,6 +40,11 @@ namespace CSVWorld void dragEnterEvent(QDragEnterEvent *event); void dragMoveEvent(QDragMoveEvent *event); + + void dropEvent(QDropEvent *event); + + private: + CSMWorld::ColumnBase::Display getIndexDisplayType(const QModelIndex &index) const; }; } diff --git a/apps/opencs/view/world/table.cpp b/apps/opencs/view/world/table.cpp index 072b645c4..0ec701a65 100644 --- a/apps/opencs/view/world/table.cpp +++ b/apps/opencs/view/world/table.cpp @@ -697,36 +697,6 @@ void CSVWorld::Table::mouseMoveEvent (QMouseEvent* event) } } -void CSVWorld::Table::dropEvent(QDropEvent *event) -{ - QModelIndex index = indexAt (event->pos()); - - if (!index.isValid()) - { - return; - } - - const CSMWorld::TableMimeData* mime = dynamic_cast (event->mimeData()); - if (!mime) // May happen when non-records (e.g. plain text) are dragged and dropped - return; - - if (mime->fromDocument (mDocument)) - { - CSMWorld::ColumnBase::Display display = static_cast - (mModel->headerData (index.column(), Qt::Horizontal, CSMWorld::ColumnBase::Role_Display).toInt()); - - if (mime->holdsType (display)) - { - CSMWorld::UniversalId record (mime->returnMatching (display)); - - std::auto_ptr command (new CSMWorld::ModifyCommand - (*mProxyModel, index, QVariant (QString::fromUtf8 (record.getId().c_str())))); - - mDocument.getUndoStack().push (command.release()); - } - } //TODO handle drops from different document -} - std::vector CSVWorld::Table::getColumnsWithDisplay(CSMWorld::ColumnBase::Display display) const { const int count = mModel->columnCount(); diff --git a/apps/opencs/view/world/table.hpp b/apps/opencs/view/world/table.hpp index 67bf3fe85..38fcd83bd 100644 --- a/apps/opencs/view/world/table.hpp +++ b/apps/opencs/view/world/table.hpp @@ -76,8 +76,6 @@ namespace CSVWorld void mouseMoveEvent(QMouseEvent *event); - void dropEvent(QDropEvent *event); - protected: virtual void mouseDoubleClickEvent (QMouseEvent *event); From d606b62688e14ea214d0939fec908c6996cf6b82 Mon Sep 17 00:00:00 2001 From: Stanislav Bas Date: Sun, 21 Jun 2015 21:35:00 +0300 Subject: [PATCH 11/45] Nested tables accept drops --- apps/opencs/view/world/dragrecordtable.cpp | 12 +++++++-- apps/opencs/view/world/nestedtable.cpp | 29 +++++++++------------- apps/opencs/view/world/nestedtable.hpp | 12 +++------ 3 files changed, 26 insertions(+), 27 deletions(-) diff --git a/apps/opencs/view/world/dragrecordtable.cpp b/apps/opencs/view/world/dragrecordtable.cpp index 3712348e2..8d01cff3e 100644 --- a/apps/opencs/view/world/dragrecordtable.cpp +++ b/apps/opencs/view/world/dragrecordtable.cpp @@ -12,7 +12,13 @@ void CSVWorld::DragRecordTable::startDragFromTable (const CSVWorld::DragRecordTable& table) { - CSMWorld::TableMimeData* mime = new CSMWorld::TableMimeData (table.getDraggedRecords(), mDocument); + std::vector records = table.getDraggedRecords(); + if (records.empty()) + { + return; + } + + CSMWorld::TableMimeData* mime = new CSMWorld::TableMimeData (records, mDocument); if (mime) { @@ -27,7 +33,9 @@ CSVWorld::DragRecordTable::DragRecordTable (CSMDoc::Document& document, QWidget* QTableView(parent), mDocument(document), mEditLock(false) -{} +{ + setAcceptDrops(true); +} void CSVWorld::DragRecordTable::setEditLock (bool locked) { diff --git a/apps/opencs/view/world/nestedtable.cpp b/apps/opencs/view/world/nestedtable.cpp index 112873cb9..92df59a5f 100644 --- a/apps/opencs/view/world/nestedtable.cpp +++ b/apps/opencs/view/world/nestedtable.cpp @@ -14,8 +14,7 @@ CSVWorld::NestedTable::NestedTable(CSMDoc::Document& document, CSMWorld::UniversalId id, CSMWorld::NestedTableProxyModel* model, QWidget* parent) - : QTableView(parent), - mUndoStack(document.getUndoStack()), + : DragRecordTable(document, parent), mModel(model) { mDispatcher = new CSMWorld::CommandDispatcher (document, id, this); @@ -47,8 +46,6 @@ CSVWorld::NestedTable::NestedTable(CSMDoc::Document& document, setModel(model); - setAcceptDrops(true); - mAddNewRowAction = new QAction (tr ("Add new row"), this); connect(mAddNewRowAction, SIGNAL(triggered()), @@ -60,12 +57,10 @@ CSVWorld::NestedTable::NestedTable(CSMDoc::Document& document, this, SLOT(removeRowActionTriggered())); } -void CSVWorld::NestedTable::dragEnterEvent(QDragEnterEvent *event) -{ -} - -void CSVWorld::NestedTable::dragMoveEvent(QDragMoveEvent *event) +std::vector CSVWorld::NestedTable::getDraggedRecords() const { + // No drag support for nested tables + return std::vector(); } void CSVWorld::NestedTable::contextMenuEvent (QContextMenuEvent *event) @@ -84,16 +79,16 @@ void CSVWorld::NestedTable::contextMenuEvent (QContextMenuEvent *event) void CSVWorld::NestedTable::removeRowActionTriggered() { - mUndoStack.push(new CSMWorld::DeleteNestedCommand(*(mModel->model()), - mModel->getParentId(), - selectionModel()->selectedRows().begin()->row(), - mModel->getParentColumn())); + mDocument.getUndoStack().push(new CSMWorld::DeleteNestedCommand(*(mModel->model()), + mModel->getParentId(), + selectionModel()->selectedRows().begin()->row(), + mModel->getParentColumn())); } void CSVWorld::NestedTable::addNewRowActionTriggered() { - mUndoStack.push(new CSMWorld::AddNestedCommand(*(mModel->model()), - mModel->getParentId(), - selectionModel()->selectedRows().size(), - mModel->getParentColumn())); + mDocument.getUndoStack().push(new CSMWorld::AddNestedCommand(*(mModel->model()), + mModel->getParentId(), + selectionModel()->selectedRows().size(), + mModel->getParentColumn())); } diff --git a/apps/opencs/view/world/nestedtable.hpp b/apps/opencs/view/world/nestedtable.hpp index 5db977942..112920401 100644 --- a/apps/opencs/view/world/nestedtable.hpp +++ b/apps/opencs/view/world/nestedtable.hpp @@ -1,10 +1,10 @@ #ifndef CSV_WORLD_NESTEDTABLE_H #define CSV_WORLD_NESTEDTABLE_H -#include #include -class QUndoStack; +#include "dragrecordtable.hpp" + class QAction; class QContextMenuEvent; @@ -22,13 +22,12 @@ namespace CSMDoc namespace CSVWorld { - class NestedTable : public QTableView + class NestedTable : public DragRecordTable { Q_OBJECT QAction *mAddNewRowAction; QAction *mRemoveRowAction; - QUndoStack& mUndoStack; CSMWorld::NestedTableProxyModel* mModel; CSMWorld::CommandDispatcher *mDispatcher; @@ -38,10 +37,7 @@ namespace CSVWorld CSMWorld::NestedTableProxyModel* model, QWidget* parent = NULL); - protected: - void dragEnterEvent(QDragEnterEvent *event); - - void dragMoveEvent(QDragMoveEvent *event); + virtual std::vector getDraggedRecords() const; private: void contextMenuEvent (QContextMenuEvent *event); From 33a3dabc313665a83384b373a5f5decba8974e54 Mon Sep 17 00:00:00 2001 From: scrawl Date: Wed, 24 Jun 2015 03:50:36 +0200 Subject: [PATCH 12/45] An alchemy effect listed more than once in the same ingredient should not automatically create a potion of that effect (Bug #2722) --- apps/openmw/mwmechanics/alchemy.cpp | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/apps/openmw/mwmechanics/alchemy.cpp b/apps/openmw/mwmechanics/alchemy.cpp index 58c42ddb8..1d43c71ff 100644 --- a/apps/openmw/mwmechanics/alchemy.cpp +++ b/apps/openmw/mwmechanics/alchemy.cpp @@ -44,6 +44,8 @@ std::set MWMechanics::Alchemy::listEffects() const { const MWWorld::LiveCellRef *ingredient = iter->get(); + std::set seenEffects; + for (int i=0; i<4; ++i) if (ingredient->mBase->mData.mEffectID[i]!=-1) { @@ -51,7 +53,8 @@ std::set MWMechanics::Alchemy::listEffects() const ingredient->mBase->mData.mEffectID[i], ingredient->mBase->mData.mSkills[i]!=-1 ? ingredient->mBase->mData.mSkills[i] : ingredient->mBase->mData.mAttributes[i]); - ++effects[key]; + if (seenEffects.insert(key).second) + ++effects[key]; } } } From 6f34a0501a0d8a2562716fd009983644e9d4ca5b Mon Sep 17 00:00:00 2001 From: scrawl Date: Wed, 24 Jun 2015 03:52:27 +0200 Subject: [PATCH 13/45] Attempting to make a potion with no effects removes the ingredients (Fixes #2722) --- apps/openmw/mwmechanics/alchemy.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/apps/openmw/mwmechanics/alchemy.cpp b/apps/openmw/mwmechanics/alchemy.cpp index 1d43c71ff..2fc9fe42f 100644 --- a/apps/openmw/mwmechanics/alchemy.cpp +++ b/apps/openmw/mwmechanics/alchemy.cpp @@ -463,7 +463,10 @@ MWMechanics::Alchemy::Result MWMechanics::Alchemy::create (const std::string& na return Result_NoName; if (listEffects().empty()) + { + removeIngredients(); return Result_NoEffects; + } if (beginEffects() == endEffects()) { From d1339a643afced0d1e502eebe79c947b2c4ad953 Mon Sep 17 00:00:00 2001 From: Stanislav Bas Date: Wed, 24 Jun 2015 15:07:09 +0300 Subject: [PATCH 14/45] Fix for NestedTableProxyModel::forwardDataChanged() --- apps/opencs/model/world/nestedtableproxymodel.cpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/apps/opencs/model/world/nestedtableproxymodel.cpp b/apps/opencs/model/world/nestedtableproxymodel.cpp index acf197716..052e629aa 100644 --- a/apps/opencs/model/world/nestedtableproxymodel.cpp +++ b/apps/opencs/model/world/nestedtableproxymodel.cpp @@ -192,4 +192,8 @@ void CSMWorld::NestedTableProxyModel::forwardDataChanged (const QModelIndex& top emit dataChanged(index(0,0), index(mMainModel->rowCount(parent)-1, mMainModel->columnCount(parent)-1)); } + else if (topLeft.parent() == parent && bottomRight.parent() == parent) + { + emit dataChanged(index(topLeft.row(), topLeft.column()), index(bottomRight.row(), bottomRight.column())); + } } From 270c17faa786917ac03f44906c055eec70da577d Mon Sep 17 00:00:00 2001 From: Stanislav Bas Date: Wed, 24 Jun 2015 16:36:09 +0300 Subject: [PATCH 15/45] Prevent drops on non-editable table cells --- apps/opencs/view/world/dragrecordtable.cpp | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/apps/opencs/view/world/dragrecordtable.cpp b/apps/opencs/view/world/dragrecordtable.cpp index 8d01cff3e..5e8ddae26 100644 --- a/apps/opencs/view/world/dragrecordtable.cpp +++ b/apps/opencs/view/world/dragrecordtable.cpp @@ -52,7 +52,10 @@ void CSVWorld::DragRecordTable::dragMoveEvent(QDragMoveEvent *event) QModelIndex index = indexAt(event->pos()); if (CSVWorld::DragDropUtils::canAcceptData(*event, getIndexDisplayType(index))) { - event->accept(); + if (index.flags() & Qt::ItemIsEditable) + { + event->accept(); + } } else { From e29d9bcc8eac923ecf90c73733302033e01c2700 Mon Sep 17 00:00:00 2001 From: Marc Zinnschlag Date: Wed, 24 Jun 2015 17:29:47 +0200 Subject: [PATCH 16/45] use a namespace instead of a class with only static functions --- apps/opencs/view/world/dragdroputils.hpp | 17 ++++++++--------- 1 file changed, 8 insertions(+), 9 deletions(-) diff --git a/apps/opencs/view/world/dragdroputils.hpp b/apps/opencs/view/world/dragdroputils.hpp index 88e2958a5..d1d780708 100644 --- a/apps/opencs/view/world/dragdroputils.hpp +++ b/apps/opencs/view/world/dragdroputils.hpp @@ -13,18 +13,17 @@ namespace CSMWorld namespace CSVWorld { - class DragDropUtils + namespace DragDropUtils { - public: - static const CSMWorld::TableMimeData *getTableMimeData(const QDropEvent &event); + const CSMWorld::TableMimeData *getTableMimeData(const QDropEvent &event); - static bool canAcceptData(const QDropEvent &event, CSMWorld::ColumnBase::Display type); - ///< Checks whether the \a event contains a valid CSMWorld::TableMimeData that holds the \a type + bool canAcceptData(const QDropEvent &event, CSMWorld::ColumnBase::Display type); + ///< Checks whether the \a event contains a valid CSMWorld::TableMimeData that holds the \a type - static CSMWorld::UniversalId getAcceptedData(const QDropEvent &event, CSMWorld::ColumnBase::Display type); - ///< Gets the accepted data from the \a event using the \a type - ///< \return Type_None if the \a event data doesn't holds the \a type - }; + CSMWorld::UniversalId getAcceptedData(const QDropEvent &event, CSMWorld::ColumnBase::Display type); + ///< Gets the accepted data from the \a event using the \a type + ///< \return Type_None if the \a event data doesn't holds the \a type + } } #endif From 21f0b586ec1d09828cf75117804b09df3c480f64 Mon Sep 17 00:00:00 2001 From: Stanislav Bas Date: Wed, 24 Jun 2015 20:01:29 +0300 Subject: [PATCH 17/45] Rows with the same topic but in different letter case can be reordered --- apps/opencs/model/world/infocollection.cpp | 3 ++- apps/opencs/view/world/table.cpp | 21 +++++++++++++++------ 2 files changed, 17 insertions(+), 7 deletions(-) diff --git a/apps/opencs/model/world/infocollection.cpp b/apps/opencs/model/world/infocollection.cpp index a508d28f3..560be8131 100644 --- a/apps/opencs/model/world/infocollection.cpp +++ b/apps/opencs/model/world/infocollection.cpp @@ -97,7 +97,8 @@ bool CSMWorld::InfoCollection::reorderRows (int baseIndex, const std::vector #include +#include + #include "../../model/doc/document.hpp" #include "../../model/world/data.hpp" @@ -128,17 +130,24 @@ void CSVWorld::Table::contextMenuEvent (QContextMenuEvent *event) { int row = mProxyModel->mapToSource ( mProxyModel->index (selectedRows.begin()->row(), 0)).row(); + QString curData = mModel->data(mModel->index(row, column)).toString(); - if (row>0 && mModel->data (mModel->index (row, column))== - mModel->data (mModel->index (row-1, column))) + if (row > 0) { - menu.addAction (mMoveUpAction); + QString prevData = mModel->data(mModel->index(row - 1, column)).toString(); + if (Misc::StringUtils::ciEqual(curData.toStdString(), prevData.toStdString())) + { + menu.addAction(mMoveUpAction); + } } - if (rowrowCount()-1 && mModel->data (mModel->index (row, column))== - mModel->data (mModel->index (row+1, column))) + if (row < mModel->rowCount() - 1) { - menu.addAction (mMoveDownAction); + QString nextData = mModel->data(mModel->index(row + 1, column)).toString(); + if (Misc::StringUtils::ciEqual(curData.toStdString(), nextData.toStdString())) + { + menu.addAction(mMoveDownAction); + } } } } From 5b82b9d9d0efc0a395c289e546bd87cae00dcea3 Mon Sep 17 00:00:00 2001 From: Stanislav Bas Date: Thu, 25 Jun 2015 11:20:35 +0300 Subject: [PATCH 18/45] ReferenceCreator accepts drops of Cell ID --- apps/opencs/view/world/referencecreator.cpp | 5 +++-- apps/opencs/view/world/referencecreator.hpp | 9 ++++++--- 2 files changed, 9 insertions(+), 5 deletions(-) diff --git a/apps/opencs/view/world/referencecreator.cpp b/apps/opencs/view/world/referencecreator.cpp index 81efb17ab..2b0d44df0 100644 --- a/apps/opencs/view/world/referencecreator.cpp +++ b/apps/opencs/view/world/referencecreator.cpp @@ -2,7 +2,6 @@ #include "referencecreator.hpp" #include -#include #include "../../model/doc/document.hpp" @@ -12,6 +11,8 @@ #include "../../model/world/idtable.hpp" #include "../../model/world/idcompletionmanager.hpp" +#include "../widget/droplineedit.hpp" + std::string CSVWorld::ReferenceCreator::getId() const { return mId; @@ -80,7 +81,7 @@ CSVWorld::ReferenceCreator::ReferenceCreator (CSMWorld::Data& data, QUndoStack& QLabel *label = new QLabel ("Cell", this); insertBeforeButtons (label, false); - mCell = new QLineEdit (this); + mCell = new CSVWidget::DropLineEdit(CSMWorld::ColumnBase::Display_Cell, this); mCell->setCompleter(completionManager.getCompleter(CSMWorld::ColumnBase::Display_Cell).get()); insertBeforeButtons (mCell, true); diff --git a/apps/opencs/view/world/referencecreator.hpp b/apps/opencs/view/world/referencecreator.hpp index 7f56143c9..c230d0126 100644 --- a/apps/opencs/view/world/referencecreator.hpp +++ b/apps/opencs/view/world/referencecreator.hpp @@ -3,13 +3,16 @@ #include "genericcreator.hpp" -class QLineEdit; - namespace CSMWorld { class IdCompletionManager; } +namespace CSVWidget +{ + class DropLineEdit; +} + namespace CSVWorld { @@ -17,7 +20,7 @@ namespace CSVWorld { Q_OBJECT - QLineEdit *mCell; + CSVWidget::DropLineEdit *mCell; std::string mId; private: From d282bead236fe73611dba32f15220e6b73a1ca10 Mon Sep 17 00:00:00 2001 From: Stanislav Bas Date: Thu, 25 Jun 2015 11:24:19 +0300 Subject: [PATCH 19/45] InfoCreator accepts drops of Topic/Journal ID --- apps/opencs/view/world/infocreator.cpp | 5 +++-- apps/opencs/view/world/infocreator.hpp | 9 ++++++--- 2 files changed, 9 insertions(+), 5 deletions(-) diff --git a/apps/opencs/view/world/infocreator.cpp b/apps/opencs/view/world/infocreator.cpp index 916427fc2..268a82a28 100644 --- a/apps/opencs/view/world/infocreator.cpp +++ b/apps/opencs/view/world/infocreator.cpp @@ -4,7 +4,6 @@ #include #include -#include #include #include @@ -17,6 +16,8 @@ #include "../../model/world/idtable.hpp" #include "../../model/world/idcompletionmanager.hpp" +#include "../widget/droplineedit.hpp" + std::string CSVWorld::InfoCreator::getId() const { std::string id = Misc::StringUtils::lowerCase (mTopic->text().toUtf8().constData()); @@ -48,12 +49,12 @@ CSVWorld::InfoCreator::InfoCreator (CSMWorld::Data& data, QUndoStack& undoStack, QLabel *label = new QLabel ("Topic", this); insertBeforeButtons (label, false); - mTopic = new QLineEdit (this); CSMWorld::ColumnBase::Display displayType = CSMWorld::ColumnBase::Display_Topic; if (getCollectionId().getType() == CSMWorld::UniversalId::Type_JournalInfos) { displayType = CSMWorld::ColumnBase::Display_Journal; } + mTopic = new CSVWidget::DropLineEdit(displayType, this); mTopic->setCompleter(completionManager.getCompleter(displayType).get()); insertBeforeButtons (mTopic, true); diff --git a/apps/opencs/view/world/infocreator.hpp b/apps/opencs/view/world/infocreator.hpp index 1928004bb..d131e3fac 100644 --- a/apps/opencs/view/world/infocreator.hpp +++ b/apps/opencs/view/world/infocreator.hpp @@ -3,21 +3,24 @@ #include "genericcreator.hpp" -class QLineEdit; - namespace CSMWorld { class InfoCollection; class IdCompletionManager; } +namespace CSVWidget +{ + class DropLineEdit; +} + namespace CSVWorld { class InfoCreator : public GenericCreator { Q_OBJECT - QLineEdit *mTopic; + CSVWidget::DropLineEdit *mTopic; virtual std::string getId() const; From 6fbdbb11d5c332913aa20d57707063245fb36d92 Mon Sep 17 00:00:00 2001 From: Marc Zinnschlag Date: Thu, 25 Jun 2015 12:03:40 +0200 Subject: [PATCH 20/45] added refrash menu item to report table (Fixes #2620) --- apps/opencs/model/doc/document.cpp | 4 ++-- apps/opencs/model/doc/document.hpp | 2 +- apps/opencs/model/tools/tools.cpp | 13 +++++++++---- apps/opencs/model/tools/tools.hpp | 7 +++++-- apps/opencs/view/tools/reportsubview.cpp | 22 ++++++++++++++++++++-- apps/opencs/view/tools/reportsubview.hpp | 6 ++++++ apps/opencs/view/tools/reporttable.cpp | 18 ++++++++++++++++-- apps/opencs/view/tools/reporttable.hpp | 9 ++++++++- 8 files changed, 67 insertions(+), 14 deletions(-) diff --git a/apps/opencs/model/doc/document.cpp b/apps/opencs/model/doc/document.cpp index 1e6ae5455..cb349d8be 100644 --- a/apps/opencs/model/doc/document.cpp +++ b/apps/opencs/model/doc/document.cpp @@ -2369,9 +2369,9 @@ void CSMDoc::Document::save() emit stateChanged (getState(), this); } -CSMWorld::UniversalId CSMDoc::Document::verify() +CSMWorld::UniversalId CSMDoc::Document::verify (const CSMWorld::UniversalId& reportId) { - CSMWorld::UniversalId id = mTools.runVerifier(); + CSMWorld::UniversalId id = mTools.runVerifier (reportId); emit stateChanged (getState(), this); return id; } diff --git a/apps/opencs/model/doc/document.hpp b/apps/opencs/model/doc/document.hpp index 4aaaf40b0..557f3cb23 100644 --- a/apps/opencs/model/doc/document.hpp +++ b/apps/opencs/model/doc/document.hpp @@ -120,7 +120,7 @@ namespace CSMDoc void save(); - CSMWorld::UniversalId verify(); + CSMWorld::UniversalId verify (const CSMWorld::UniversalId& reportId = CSMWorld::UniversalId()); CSMWorld::UniversalId newSearch(); diff --git a/apps/opencs/model/tools/tools.cpp b/apps/opencs/model/tools/tools.cpp index f0d649f38..c9c116091 100644 --- a/apps/opencs/model/tools/tools.cpp +++ b/apps/opencs/model/tools/tools.cpp @@ -146,14 +146,19 @@ CSMTools::Tools::~Tools() delete iter->second; } -CSMWorld::UniversalId CSMTools::Tools::runVerifier() +CSMWorld::UniversalId CSMTools::Tools::runVerifier (const CSMWorld::UniversalId& reportId) { - mReports.insert (std::make_pair (mNextReportNumber++, new ReportModel)); - mActiveReports[CSMDoc::State_Verifying] = mNextReportNumber-1; + int reportNumber = reportId.getType()==CSMWorld::UniversalId::Type_VerificationResults ? + reportId.getIndex() : mNextReportNumber++; + + if (mReports.find (reportNumber)==mReports.end()) + mReports.insert (std::make_pair (reportNumber, new ReportModel)); + + mActiveReports[CSMDoc::State_Verifying] = reportNumber; getVerifier()->start(); - return CSMWorld::UniversalId (CSMWorld::UniversalId::Type_VerificationResults, mNextReportNumber-1); + return CSMWorld::UniversalId (CSMWorld::UniversalId::Type_VerificationResults, reportNumber); } CSMWorld::UniversalId CSMTools::Tools::newSearch() diff --git a/apps/opencs/model/tools/tools.hpp b/apps/opencs/model/tools/tools.hpp index 2912fc471..78484d15d 100644 --- a/apps/opencs/model/tools/tools.hpp +++ b/apps/opencs/model/tools/tools.hpp @@ -57,8 +57,11 @@ namespace CSMTools virtual ~Tools(); - CSMWorld::UniversalId runVerifier(); - ///< \return ID of the report for this verification run + /// \param reportId If a valid VerificationResults ID, run verifier for the + /// specified report instead of creating a new one. + /// + /// \return ID of the report for this verification run + CSMWorld::UniversalId runVerifier (const CSMWorld::UniversalId& reportId = CSMWorld::UniversalId()); /// Return ID of the report for this search. CSMWorld::UniversalId newSearch(); diff --git a/apps/opencs/view/tools/reportsubview.cpp b/apps/opencs/view/tools/reportsubview.cpp index 492874c01..42c4d40da 100644 --- a/apps/opencs/view/tools/reportsubview.cpp +++ b/apps/opencs/view/tools/reportsubview.cpp @@ -4,12 +4,18 @@ #include "reporttable.hpp" CSVTools::ReportSubView::ReportSubView (const CSMWorld::UniversalId& id, CSMDoc::Document& document) -: CSVDoc::SubView (id) +: CSVDoc::SubView (id), mDocument (document), mRefreshState (0) { - setWidget (mTable = new ReportTable (document, id, false, this)); + if (id.getType()==CSMWorld::UniversalId::Type_VerificationResults) + mRefreshState = CSMDoc::State_Verifying; + + setWidget (mTable = new ReportTable (document, id, false, mRefreshState, this)); connect (mTable, SIGNAL (editRequest (const CSMWorld::UniversalId&, const std::string&)), SIGNAL (focusId (const CSMWorld::UniversalId&, const std::string&))); + + if (mRefreshState==CSMDoc::State_Verifying) + connect (mTable, SIGNAL (refreshRequest()), this, SLOT (refreshRequest())); } void CSVTools::ReportSubView::setEditLock (bool locked) @@ -21,3 +27,15 @@ void CSVTools::ReportSubView::updateUserSetting (const QString &name, const QStr { mTable->updateUserSetting (name, list); } + +void CSVTools::ReportSubView::refreshRequest() +{ + if (!(mDocument.getState() & mRefreshState)) + { + if (mRefreshState==CSMDoc::State_Verifying) + { + mTable->clear(); + mDocument.verify (getUniversalId()); + } + } +} diff --git a/apps/opencs/view/tools/reportsubview.hpp b/apps/opencs/view/tools/reportsubview.hpp index 7e8a08e3c..b8eb2690a 100644 --- a/apps/opencs/view/tools/reportsubview.hpp +++ b/apps/opencs/view/tools/reportsubview.hpp @@ -20,6 +20,8 @@ namespace CSVTools Q_OBJECT ReportTable *mTable; + CSMDoc::Document& mDocument; + int mRefreshState; public: @@ -28,6 +30,10 @@ namespace CSVTools virtual void setEditLock (bool locked); virtual void updateUserSetting (const QString &, const QStringList &); + + private slots: + + void refreshRequest(); }; } diff --git a/apps/opencs/view/tools/reporttable.cpp b/apps/opencs/view/tools/reporttable.cpp index e530e1159..6ef88bfdd 100644 --- a/apps/opencs/view/tools/reporttable.cpp +++ b/apps/opencs/view/tools/reporttable.cpp @@ -74,7 +74,12 @@ void CSVTools::ReportTable::contextMenuEvent (QContextMenuEvent *event) if (found) menu.addAction (mReplaceAction); + } + if (mRefreshAction) + { + mRefreshAction->setEnabled ((mDocument.getState() & mRefreshState)==0); + menu.addAction (mRefreshAction); } menu.exec (event->globalPos()); @@ -134,8 +139,10 @@ void CSVTools::ReportTable::mouseDoubleClickEvent (QMouseEvent *event) } CSVTools::ReportTable::ReportTable (CSMDoc::Document& document, - const CSMWorld::UniversalId& id, bool richTextDescription, QWidget *parent) -: CSVWorld::DragRecordTable (document, parent), mModel (document.getReport (id)) + const CSMWorld::UniversalId& id, bool richTextDescription, int refreshState, + QWidget *parent) +: CSVWorld::DragRecordTable (document, parent), mModel (document.getReport (id)), + mRefreshAction (0), mRefreshState (refreshState) { #if QT_VERSION >= QT_VERSION_CHECK(5,0,0) horizontalHeader()->setSectionResizeMode (QHeaderView::Interactive); @@ -171,6 +178,13 @@ CSVTools::ReportTable::ReportTable (CSMDoc::Document& document, connect (mReplaceAction, SIGNAL (triggered()), this, SIGNAL (replaceRequest())); addAction (mReplaceAction); + if (mRefreshState) + { + mRefreshAction = new QAction (tr ("Refresh"), this); + connect (mRefreshAction, SIGNAL (triggered()), this, SIGNAL (refreshRequest())); + addAction (mRefreshAction); + } + 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)); diff --git a/apps/opencs/view/tools/reporttable.hpp b/apps/opencs/view/tools/reporttable.hpp index 95ab07cbb..4f77a57c4 100644 --- a/apps/opencs/view/tools/reporttable.hpp +++ b/apps/opencs/view/tools/reporttable.hpp @@ -36,7 +36,9 @@ namespace CSVTools QAction *mShowAction; QAction *mRemoveAction; QAction *mReplaceAction; + QAction *mRefreshAction; std::map mDoubleClickActions; + int mRefreshState; private: @@ -49,8 +51,11 @@ namespace CSVTools public: /// \param richTextDescription Use rich text in the description column. + /// \param refreshState Document state to check for refresh function. If value is + /// 0 no refresh function exists. If the document current has the specified state + /// the refresh function is disabled. ReportTable (CSMDoc::Document& document, const CSMWorld::UniversalId& id, - bool richTextDescription, QWidget *parent = 0); + bool richTextDescription, int refreshState = 0, QWidget *parent = 0); virtual std::vector getDraggedRecords() const; @@ -76,6 +81,8 @@ namespace CSVTools void editRequest (const CSMWorld::UniversalId& id, const std::string& hint); void replaceRequest(); + + void refreshRequest(); }; } From 71f3b7ed4f6ab80592dfbf4ef03669e5909535b7 Mon Sep 17 00:00:00 2001 From: cc9cii Date: Thu, 25 Jun 2015 20:21:51 +1000 Subject: [PATCH 21/45] Fix crash when user preference is missing. --- apps/opencs/model/tools/scriptcheck.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/opencs/model/tools/scriptcheck.cpp b/apps/opencs/model/tools/scriptcheck.cpp index 928ae156f..665edd7a3 100644 --- a/apps/opencs/model/tools/scriptcheck.cpp +++ b/apps/opencs/model/tools/scriptcheck.cpp @@ -120,7 +120,7 @@ void CSMTools::ScriptCheckStage::perform (int stage, CSMDoc::Messages& messages) void CSMTools::ScriptCheckStage::updateUserSetting (const QString& name, const QStringList& value) { - if (name=="script-editor/warnings") + if (name=="script-editor/warnings" && !value.isEmpty()) { if (value.at (0)=="Ignore") mWarningMode = Mode_Ignore; From c0f3d70f0662b79c2a8fd66fdef0f8ec61e61f50 Mon Sep 17 00:00:00 2001 From: cc9cii Date: Thu, 25 Jun 2015 20:23:43 +1000 Subject: [PATCH 22/45] Use the new severity message attribute. --- apps/opencs/model/tools/pathgridcheck.cpp | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/apps/opencs/model/tools/pathgridcheck.cpp b/apps/opencs/model/tools/pathgridcheck.cpp index 76edeb573..69ee5a809 100644 --- a/apps/opencs/model/tools/pathgridcheck.cpp +++ b/apps/opencs/model/tools/pathgridcheck.cpp @@ -30,9 +30,9 @@ void CSMTools::PathgridCheckStage::perform (int stage, CSMDoc::Messages& message // check the number of pathgrid points if (pathgrid.mData.mS2 > static_cast(pathgrid.mPoints.size())) - messages.push_back (std::make_pair (id, pathgrid.mId + " has less points than expected")); + messages.add (id, pathgrid.mId + " has less points than expected", "", CSMDoc::Message::Severity_Error); else if (pathgrid.mData.mS2 > static_cast(pathgrid.mPoints.size())) - messages.push_back (std::make_pair (id, pathgrid.mId + " has more points than expected")); + messages.add (id, pathgrid.mId + " has more points than expected", "", CSMDoc::Message::Severity_Error); std::vector pointList(pathgrid.mPoints.size()); std::vector duplList; @@ -51,7 +51,7 @@ void CSMTools::PathgridCheckStage::perform (int stage, CSMDoc::Messages& message std::ostringstream ss; ss << "has a duplicate edge between points" << pathgrid.mEdges[i].mV0 << " and " << pathgrid.mEdges[i].mV1; - messages.push_back (std::make_pair (id, pathgrid.mId + ss.str())); + messages.add (id, pathgrid.mId + ss.str(), "", CSMDoc::Message::Severity_Error); break; } } @@ -64,7 +64,7 @@ void CSMTools::PathgridCheckStage::perform (int stage, CSMDoc::Messages& message { std::ostringstream ss; ss << " has an edge connecting a non-existent point " << pathgrid.mEdges[i].mV0; - messages.push_back (std::make_pair (id, pathgrid.mId + ss.str())); + messages.add (id, pathgrid.mId + ss.str(), "", CSMDoc::Message::Severity_Error); } } @@ -75,13 +75,13 @@ void CSMTools::PathgridCheckStage::perform (int stage, CSMDoc::Messages& message { std::ostringstream ss; ss << " has has less edges than expected for point " << i; - messages.push_back (std::make_pair (id, pathgrid.mId + ss.str())); + messages.add (id, pathgrid.mId + ss.str(), "", CSMDoc::Message::Severity_Error); } else if (pathgrid.mPoints[i].mConnectionNum < pointList[i].mConnectionNum) { std::ostringstream ss; ss << " has has more edges than expected for point " << i; - messages.push_back (std::make_pair (id, pathgrid.mId + ss.str())); + messages.add (id, pathgrid.mId + ss.str(), "", CSMDoc::Message::Severity_Error); } // check that edges are bidirectional @@ -101,7 +101,7 @@ void CSMTools::PathgridCheckStage::perform (int stage, CSMDoc::Messages& message { std::ostringstream ss; ss << " has a missing edge between points " << i << " and " << pointList[i].mOtherIndex[j]; - messages.push_back (std::make_pair (id, pathgrid.mId + ss.str())); + messages.add (id, pathgrid.mId + ss.str(), "", CSMDoc::Message::Severity_Error); } } @@ -124,7 +124,7 @@ void CSMTools::PathgridCheckStage::perform (int stage, CSMDoc::Messages& message << ") x=" << pathgrid.mPoints[i].mX << ", y=" << pathgrid.mPoints[i].mY << ", z=" << pathgrid.mPoints[i].mZ; - messages.push_back (std::make_pair (id, pathgrid.mId + ss.str())); + messages.add (id, pathgrid.mId + ss.str(), "", CSMDoc::Message::Severity_Warning); duplList.push_back(i); break; @@ -143,7 +143,7 @@ void CSMTools::PathgridCheckStage::perform (int stage, CSMDoc::Messages& message << ") x=" << pathgrid.mPoints[i].mX << ", y=" << pathgrid.mPoints[i].mY << ", z=" << pathgrid.mPoints[i].mZ; - messages.push_back (std::make_pair (id, pathgrid.mId + ss.str())); + messages.add (id, pathgrid.mId + ss.str(), "", CSMDoc::Message::Severity_Warning); } } From 69db0179ca104699d70142286a5a1d226177644f Mon Sep 17 00:00:00 2001 From: Marc Zinnschlag Date: Thu, 25 Jun 2015 13:05:57 +0200 Subject: [PATCH 23/45] update refresh menu item on stateChanged signal instead of when opening the menu --- apps/opencs/view/tools/reportsubview.cpp | 5 +++++ apps/opencs/view/tools/reporttable.cpp | 10 +++++++--- apps/opencs/view/tools/reporttable.hpp | 4 ++++ 3 files changed, 16 insertions(+), 3 deletions(-) diff --git a/apps/opencs/view/tools/reportsubview.cpp b/apps/opencs/view/tools/reportsubview.cpp index 42c4d40da..e29447f25 100644 --- a/apps/opencs/view/tools/reportsubview.cpp +++ b/apps/opencs/view/tools/reportsubview.cpp @@ -15,7 +15,12 @@ CSVTools::ReportSubView::ReportSubView (const CSMWorld::UniversalId& id, CSMDoc: SIGNAL (focusId (const CSMWorld::UniversalId&, const std::string&))); if (mRefreshState==CSMDoc::State_Verifying) + { connect (mTable, SIGNAL (refreshRequest()), this, SLOT (refreshRequest())); + + connect (&document, SIGNAL (stateChanged (int, CSMDoc::Document *)), + mTable, SLOT (stateChanged (int, CSMDoc::Document *))); + } } void CSVTools::ReportSubView::setEditLock (bool locked) diff --git a/apps/opencs/view/tools/reporttable.cpp b/apps/opencs/view/tools/reporttable.cpp index 6ef88bfdd..ca6b0dabf 100644 --- a/apps/opencs/view/tools/reporttable.cpp +++ b/apps/opencs/view/tools/reporttable.cpp @@ -77,10 +77,7 @@ void CSVTools::ReportTable::contextMenuEvent (QContextMenuEvent *event) } if (mRefreshAction) - { - mRefreshAction->setEnabled ((mDocument.getState() & mRefreshState)==0); menu.addAction (mRefreshAction); - } menu.exec (event->globalPos()); } @@ -181,6 +178,7 @@ CSVTools::ReportTable::ReportTable (CSMDoc::Document& document, if (mRefreshState) { mRefreshAction = new QAction (tr ("Refresh"), this); + mRefreshAction->setEnabled (!(mDocument.getState() & mRefreshState)); connect (mRefreshAction, SIGNAL (triggered()), this, SIGNAL (refreshRequest())); addAction (mRefreshAction); } @@ -301,3 +299,9 @@ void CSVTools::ReportTable::clear() { mModel->clear(); } + +void CSVTools::ReportTable::stateChanged (int state, CSMDoc::Document *document) +{ + if (mRefreshAction) + mRefreshAction->setEnabled (!(state & mRefreshState)); +} diff --git a/apps/opencs/view/tools/reporttable.hpp b/apps/opencs/view/tools/reporttable.hpp index 4f77a57c4..e19b327e4 100644 --- a/apps/opencs/view/tools/reporttable.hpp +++ b/apps/opencs/view/tools/reporttable.hpp @@ -76,6 +76,10 @@ namespace CSVTools void removeSelection(); + public slots: + + void stateChanged (int state, CSMDoc::Document *document); + signals: void editRequest (const CSMWorld::UniversalId& id, const std::string& hint); From 867ce686ae3bbd4b571c467502d035334f63304c Mon Sep 17 00:00:00 2001 From: Stanislav Bas Date: Thu, 25 Jun 2015 19:30:53 +0300 Subject: [PATCH 24/45] Proper conversion to QString for DropLineEdit::dropEvent() --- apps/opencs/view/widget/droplineedit.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/opencs/view/widget/droplineedit.cpp b/apps/opencs/view/widget/droplineedit.cpp index 98f1d81c3..1df598cb8 100644 --- a/apps/opencs/view/widget/droplineedit.cpp +++ b/apps/opencs/view/widget/droplineedit.cpp @@ -35,7 +35,7 @@ void CSVWidget::DropLineEdit::dropEvent(QDropEvent *event) if (CSVWorld::DragDropUtils::canAcceptData(*event, mDropType)) { CSMWorld::UniversalId id = CSVWorld::DragDropUtils::getAcceptedData(*event, mDropType); - setText(id.getId().c_str()); + setText(QString::fromUtf8(id.getId().c_str())); emit tableMimeDataDropped(id, CSVWorld::DragDropUtils::getTableMimeData(*event)->getDocumentPtr()); } } From 844e5c504d6d9f00d93e083274243fb1730c5112 Mon Sep 17 00:00:00 2001 From: Stanislav Bas Date: Thu, 25 Jun 2015 19:41:26 +0300 Subject: [PATCH 25/45] Fix conversion to QString --- apps/opencs/model/world/infotableproxymodel.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/opencs/model/world/infotableproxymodel.cpp b/apps/opencs/model/world/infotableproxymodel.cpp index 3e564506c..4ee9fa60c 100644 --- a/apps/opencs/model/world/infotableproxymodel.cpp +++ b/apps/opencs/model/world/infotableproxymodel.cpp @@ -9,7 +9,7 @@ namespace { QString toLower(const QString &str) { - return Misc::StringUtils::lowerCase(str.toStdString()).c_str(); + return QString::fromUtf8(Misc::StringUtils::lowerCase(str.toStdString()).c_str()); } } From ea97b0a20c3556f5f76d885677df2322ffe8cf04 Mon Sep 17 00:00:00 2001 From: Stanislav Bas Date: Thu, 25 Jun 2015 20:08:42 +0300 Subject: [PATCH 26/45] Refine InfoTableProxyModel::getFirstInfoRow() code --- .../model/world/infotableproxymodel.cpp | 25 ++++++++----------- .../model/world/infotableproxymodel.hpp | 3 +++ 2 files changed, 14 insertions(+), 14 deletions(-) diff --git a/apps/opencs/model/world/infotableproxymodel.cpp b/apps/opencs/model/world/infotableproxymodel.cpp index 4ee9fa60c..e34c50566 100644 --- a/apps/opencs/model/world/infotableproxymodel.cpp +++ b/apps/opencs/model/world/infotableproxymodel.cpp @@ -16,7 +16,9 @@ namespace CSMWorld::InfoTableProxyModel::InfoTableProxyModel(CSMWorld::UniversalId::Type type, QObject *parent) : IdTableProxyModel(parent), mType(type), - mSourceModel(NULL) + mSourceModel(NULL), + mInfoColumnId(type == UniversalId::Type_TopicInfos ? Columns::ColumnId_Topic : + Columns::ColumnId_Journal) { Q_ASSERT(type == UniversalId::Type_TopicInfos || type == UniversalId::Type_JournalInfos); } @@ -54,26 +56,21 @@ bool CSMWorld::InfoTableProxyModel::lessThan(const QModelIndex &left, const QMod int CSMWorld::InfoTableProxyModel::getFirstInfoRow(int currentRow) const { - Columns::ColumnId columnId = Columns::ColumnId_Topic; - if (mType == UniversalId::Type_JournalInfos) - { - columnId = Columns::ColumnId_Journal; - } - - int column = mSourceModel->findColumnIndex(columnId); - QString info = toLower(mSourceModel->data(mSourceModel->index(currentRow, column)).toString()); + int row = currentRow; + int column = mSourceModel->findColumnIndex(mInfoColumnId); + QString info = toLower(mSourceModel->data(mSourceModel->index(row, column)).toString()); if (mFirstRowCache.contains(info)) { return mFirstRowCache[info]; } - while (--currentRow >= 0 && - toLower(mSourceModel->data(mSourceModel->index(currentRow, column)).toString()) == info); - ++currentRow; + while (--row >= 0 && + toLower(mSourceModel->data(mSourceModel->index(row, column)).toString()) == info); + ++row; - mFirstRowCache[info] = currentRow; - return currentRow; + mFirstRowCache[info] = row; + return row; } void CSMWorld::InfoTableProxyModel::modelRowsChanged(const QModelIndex &/*parent*/, int /*start*/, int /*end*/) diff --git a/apps/opencs/model/world/infotableproxymodel.hpp b/apps/opencs/model/world/infotableproxymodel.hpp index 7b0cd8ede..28d6017b3 100644 --- a/apps/opencs/model/world/infotableproxymodel.hpp +++ b/apps/opencs/model/world/infotableproxymodel.hpp @@ -4,6 +4,7 @@ #include #include "idtableproxymodel.hpp" +#include "columns.hpp" #include "universalid.hpp" namespace CSMWorld @@ -16,6 +17,8 @@ namespace CSMWorld UniversalId::Type mType; IdTableBase *mSourceModel; + Columns::ColumnId mInfoColumnId; + ///< Contains ID for Topic or Journal ID mutable QHash mFirstRowCache; From f3ff90e1fde2f46d980a3f2525b79f34edcc151d Mon Sep 17 00:00:00 2001 From: Marc Zinnschlag Date: Fri, 26 Jun 2015 13:01:25 +0200 Subject: [PATCH 27/45] moved meta data into a new single-row table --- apps/opencs/CMakeLists.txt | 2 +- apps/opencs/model/doc/document.cpp | 3 --- apps/opencs/model/world/data.cpp | 29 +++++++++++++------------ apps/opencs/model/world/data.hpp | 10 ++++----- apps/opencs/model/world/metadata.cpp | 27 +++++++++++++++++++++++ apps/opencs/model/world/metadata.hpp | 29 +++++++++++++++++++++++++ apps/opencs/model/world/universalid.cpp | 1 + apps/opencs/model/world/universalid.hpp | 1 + 8 files changed, 78 insertions(+), 24 deletions(-) create mode 100644 apps/opencs/model/world/metadata.cpp create mode 100644 apps/opencs/model/world/metadata.hpp diff --git a/apps/opencs/CMakeLists.txt b/apps/opencs/CMakeLists.txt index 5386da707..3399b9ddd 100644 --- a/apps/opencs/CMakeLists.txt +++ b/apps/opencs/CMakeLists.txt @@ -26,7 +26,7 @@ opencs_units_noqt (model/world universalid record commands columnbase scriptcontext cell refidcollection refidadapter refiddata refidadapterimp ref collectionbase refcollection columns infocollection tablemimedata cellcoordinates cellselection resources resourcesmanager scope pathgrid landtexture land nestedtablewrapper nestedcollection nestedcoladapterimp nestedinfocollection - idcompletionmanager + idcompletionmanager metadata ) opencs_hdrs_noqt (model/world diff --git a/apps/opencs/model/doc/document.cpp b/apps/opencs/model/doc/document.cpp index 1e6ae5455..34ae3dd8a 100644 --- a/apps/opencs/model/doc/document.cpp +++ b/apps/opencs/model/doc/document.cpp @@ -2282,9 +2282,6 @@ CSMDoc::Document::Document (const Files::ConfigurationManager& configuration, if (mNew) { - mData.setDescription (""); - mData.setAuthor (""); - if (mContentFiles.size()==1) createBase(); } diff --git a/apps/opencs/model/world/data.cpp b/apps/opencs/model/world/data.cpp index 5acd80339..3bd892618 100644 --- a/apps/opencs/model/world/data.cpp +++ b/apps/opencs/model/world/data.cpp @@ -475,6 +475,8 @@ CSMWorld::Data::Data (ToUTF8::FromType encoding, const ResourcesManager& resourc mDebugProfiles.addColumn (new ScriptColumn ( ScriptColumn::Type_Lines)); + mMetaData.appendBlankRecord ("sys::meta"); + addModel (new IdTable (&mGlobals), UniversalId::Type_Global); addModel (new IdTable (&mGmsts), UniversalId::Type_Gmst); addModel (new IdTable (&mSkills), UniversalId::Type_Skill); @@ -515,6 +517,7 @@ CSMWorld::Data::Data (ToUTF8::FromType encoding, const ResourcesManager& resourc UniversalId::Type_Texture); addModel (new ResourceTable (&mResourcesManager.get (UniversalId::Type_Videos)), UniversalId::Type_Video); + addModel (new IdTable (&mMetaData), UniversalId::Type_MetaData); mRefLoadCache.clear(); // clear here rather than startLoading() and continueLoading() for multiple content files } @@ -803,6 +806,11 @@ const CSMWorld::Resources& CSMWorld::Data::getResources (const UniversalId& id) return mResourcesManager.get (id.getType()); } +const CSMWorld::MetaData& CSMWorld::Data::getMetaData() const +{ + return mMetaData.getRecord (0).get(); +} + QAbstractItemModel *CSMWorld::Data::getTableModel (const CSMWorld::UniversalId& id) { std::map::iterator iter = mModelIndex.find (id.getType()); @@ -847,9 +855,12 @@ int CSMWorld::Data::startLoading (const boost::filesystem::path& path, bool base mBase = base; mProject = project; - mAuthor = mReader->getAuthor(); - mDescription = mReader->getDesc(); + MetaData metaData; + metaData.mId = "sys::meta"; + metaData.load (*mReader); + mMetaData.setRecord (0, Record (RecordBase::State_ModifiedOnly, 0, &metaData)); + return mReader->getRecordCount(); } @@ -1103,24 +1114,14 @@ int CSMWorld::Data::count (RecordBase::State state) const count (state, mPathgrids); } -void CSMWorld::Data::setDescription (const std::string& description) -{ - mDescription = description; -} - std::string CSMWorld::Data::getDescription() const { - return mDescription; -} - -void CSMWorld::Data::setAuthor (const std::string& author) -{ - mAuthor = author; + return mMetaData.getRecord (0).get().mDescription; } std::string CSMWorld::Data::getAuthor() const { - return mAuthor; + return mMetaData.getRecord (0).get().mAuthor; } std::vector CSMWorld::Data::getIds (bool listDeleted) const diff --git a/apps/opencs/model/world/data.hpp b/apps/opencs/model/world/data.hpp index 060e47bd9..edfd4bc31 100644 --- a/apps/opencs/model/world/data.hpp +++ b/apps/opencs/model/world/data.hpp @@ -44,6 +44,7 @@ #include "infocollection.hpp" #include "nestedinfocollection.hpp" #include "pathgrid.hpp" +#include "metadata.hpp" #ifndef Q_MOC_RUN #include "subcellcollection.hpp" #endif @@ -94,11 +95,10 @@ namespace CSMWorld RefIdCollection mReferenceables; RefCollection mRefs; IdCollection mFilters; + Collection mMetaData; const ResourcesManager& mResourcesManager; std::vector mModels; std::map mModelIndex; - std::string mAuthor; - std::string mDescription; ESM::ESMReader *mReader; const ESM::Dialogue *mDialogue; // last loaded dialogue bool mBase; @@ -238,6 +238,8 @@ namespace CSMWorld /// Throws an exception, if \a id does not match a resources list. const Resources& getResources (const UniversalId& id) const; + const MetaData& getMetaData() const; + QAbstractItemModel *getTableModel (const UniversalId& id); ///< If no table model is available for \a id, an exception is thrown. /// @@ -267,12 +269,8 @@ namespace CSMWorld int count (RecordBase::State state) const; ///< Return number of top-level records with the given \a state. - void setDescription (const std::string& description); - std::string getDescription() const; - void setAuthor (const std::string& author); - std::string getAuthor() const; signals: diff --git a/apps/opencs/model/world/metadata.cpp b/apps/opencs/model/world/metadata.cpp new file mode 100644 index 000000000..40b8e9519 --- /dev/null +++ b/apps/opencs/model/world/metadata.cpp @@ -0,0 +1,27 @@ + +#include "metadata.hpp" + +#include +#include +#include + +void CSMWorld::MetaData::blank() +{ + mFormat = ESM::Header::CurrentFormat; + mAuthor.clear(); + mDescription.clear(); +} + +void CSMWorld::MetaData::load (ESM::ESMReader& esm) +{ + mFormat = esm.getHeader().mFormat; + mAuthor = esm.getHeader().mData.author.toString(); + mDescription = esm.getHeader().mData.desc.toString(); +} + +void CSMWorld::MetaData::save (ESM::ESMWriter& esm) const +{ + esm.setFormat (mFormat); + esm.setAuthor (mAuthor); + esm.setDescription (mDescription); +} diff --git a/apps/opencs/model/world/metadata.hpp b/apps/opencs/model/world/metadata.hpp new file mode 100644 index 000000000..f8df2690e --- /dev/null +++ b/apps/opencs/model/world/metadata.hpp @@ -0,0 +1,29 @@ +#ifndef CSM_WOLRD_METADATA_H +#define CSM_WOLRD_METADATA_H + +#include + +namespace ESM +{ + class ESMReader; + class ESMWriter; +} + +namespace CSMWorld +{ + struct MetaData + { + std::string mId; + + int mFormat; + std::string mAuthor; + std::string mDescription; + + void blank(); + + void load (ESM::ESMReader& esm); + void save (ESM::ESMWriter& esm) const; + }; +} + +#endif diff --git a/apps/opencs/model/world/universalid.cpp b/apps/opencs/model/world/universalid.cpp index e496fe79b..584bf5e70 100644 --- a/apps/opencs/model/world/universalid.cpp +++ b/apps/opencs/model/world/universalid.cpp @@ -120,6 +120,7 @@ namespace { CSMWorld::UniversalId::Class_Record, CSMWorld::UniversalId::Type_MagicEffect, "Magic Effect", 0 }, { CSMWorld::UniversalId::Class_Record, CSMWorld::UniversalId::Type_Pathgrid, "Pathgrid", 0 }, { CSMWorld::UniversalId::Class_Record, CSMWorld::UniversalId::Type_StartScript, "Start Script", 0 }, + { CSMWorld::UniversalId::Class_Record, CSMWorld::UniversalId::Type_MetaData, "Meta Data", 0 }, { CSMWorld::UniversalId::Class_None, CSMWorld::UniversalId::Type_None, 0, 0 } // end marker }; diff --git a/apps/opencs/model/world/universalid.hpp b/apps/opencs/model/world/universalid.hpp index 0a9fa3847..752504bc4 100644 --- a/apps/opencs/model/world/universalid.hpp +++ b/apps/opencs/model/world/universalid.hpp @@ -131,6 +131,7 @@ namespace CSMWorld Type_StartScripts, Type_StartScript, Type_Search, + Type_MetaData, Type_RunLog }; From 1870b087e7b3f9454c5450cfdbe30f6b86358054 Mon Sep 17 00:00:00 2001 From: Marc Zinnschlag Date: Fri, 26 Jun 2015 13:13:22 +0200 Subject: [PATCH 28/45] ported setting of meta data for saving to the new mechanism --- apps/opencs/model/doc/savingstages.cpp | 6 ++---- apps/opencs/model/world/data.cpp | 10 ---------- apps/opencs/model/world/data.hpp | 4 ---- 3 files changed, 2 insertions(+), 18 deletions(-) diff --git a/apps/opencs/model/doc/savingstages.cpp b/apps/opencs/model/doc/savingstages.cpp index d6258da6a..f78c57ecd 100644 --- a/apps/opencs/model/doc/savingstages.cpp +++ b/apps/opencs/model/doc/savingstages.cpp @@ -53,18 +53,16 @@ void CSMDoc::WriteHeaderStage::perform (int stage, Messages& messages) mState.getWriter().clearMaster(); - mState.getWriter().setFormat (0); - if (mSimple) { mState.getWriter().setAuthor (""); mState.getWriter().setDescription (""); mState.getWriter().setRecordCount (0); + mState.getWriter().setFormat (ESM::Header::CurrentFormat); } else { - mState.getWriter().setAuthor (mDocument.getData().getAuthor()); - mState.getWriter().setDescription (mDocument.getData().getDescription()); + mDocument.getData().getMetaData().save (mState.getWriter()); mState.getWriter().setRecordCount ( mDocument.getData().count (CSMWorld::RecordBase::State_Modified) + mDocument.getData().count (CSMWorld::RecordBase::State_ModifiedOnly) + diff --git a/apps/opencs/model/world/data.cpp b/apps/opencs/model/world/data.cpp index 3bd892618..368c7a766 100644 --- a/apps/opencs/model/world/data.cpp +++ b/apps/opencs/model/world/data.cpp @@ -1114,16 +1114,6 @@ int CSMWorld::Data::count (RecordBase::State state) const count (state, mPathgrids); } -std::string CSMWorld::Data::getDescription() const -{ - return mMetaData.getRecord (0).get().mDescription; -} - -std::string CSMWorld::Data::getAuthor() const -{ - return mMetaData.getRecord (0).get().mAuthor; -} - std::vector CSMWorld::Data::getIds (bool listDeleted) const { std::vector ids; diff --git a/apps/opencs/model/world/data.hpp b/apps/opencs/model/world/data.hpp index edfd4bc31..15e39b9ba 100644 --- a/apps/opencs/model/world/data.hpp +++ b/apps/opencs/model/world/data.hpp @@ -269,10 +269,6 @@ namespace CSMWorld int count (RecordBase::State state) const; ///< Return number of top-level records with the given \a state. - std::string getDescription() const; - - std::string getAuthor() const; - signals: void idListChanged(); From 5a37530c1c296b15b273b5da3cc53e10b6db7a63 Mon Sep 17 00:00:00 2001 From: Marc Zinnschlag Date: Fri, 26 Jun 2015 15:17:18 +0200 Subject: [PATCH 29/45] added missing MetaData table UniversalId type --- apps/opencs/model/world/universalid.cpp | 1 + apps/opencs/model/world/universalid.hpp | 1 + 2 files changed, 2 insertions(+) diff --git a/apps/opencs/model/world/universalid.cpp b/apps/opencs/model/world/universalid.cpp index 584bf5e70..73d893a26 100644 --- a/apps/opencs/model/world/universalid.cpp +++ b/apps/opencs/model/world/universalid.cpp @@ -56,6 +56,7 @@ namespace { CSMWorld::UniversalId::Class_RecordList, CSMWorld::UniversalId::Type_MagicEffects, "Magic Effects", 0 }, { CSMWorld::UniversalId::Class_RecordList, CSMWorld::UniversalId::Type_Pathgrids, "Pathgrids", 0 }, { CSMWorld::UniversalId::Class_RecordList, CSMWorld::UniversalId::Type_StartScripts, "Start Scripts", 0 }, + { CSMWorld::UniversalId::Class_RecordList, CSMWorld::UniversalId::Type_MetaDatas, "Meta Data Table", 0 }, { CSMWorld::UniversalId::Class_None, CSMWorld::UniversalId::Type_None, 0, 0 } // end marker }; diff --git a/apps/opencs/model/world/universalid.hpp b/apps/opencs/model/world/universalid.hpp index 752504bc4..e9104fc22 100644 --- a/apps/opencs/model/world/universalid.hpp +++ b/apps/opencs/model/world/universalid.hpp @@ -131,6 +131,7 @@ namespace CSMWorld Type_StartScripts, Type_StartScript, Type_Search, + Type_MetaDatas, Type_MetaData, Type_RunLog }; From 10fbe6aada504ebd0e5afebdc5569382f5051806 Mon Sep 17 00:00:00 2001 From: Marc Zinnschlag Date: Fri, 26 Jun 2015 15:17:47 +0200 Subject: [PATCH 30/45] split DialogueSubView in SimpleDialogueSubView and DialogueSubView --- apps/opencs/view/world/dialoguesubview.cpp | 336 ++++++++++++--------- apps/opencs/view/world/dialoguesubview.hpp | 55 +++- 2 files changed, 226 insertions(+), 165 deletions(-) diff --git a/apps/opencs/view/world/dialoguesubview.cpp b/apps/opencs/view/world/dialoguesubview.cpp index 284c5928b..d588c2edb 100644 --- a/apps/opencs/view/world/dialoguesubview.cpp +++ b/apps/opencs/view/world/dialoguesubview.cpp @@ -548,12 +548,38 @@ void CSVWorld::EditWidget::remake(int row) this->setWidgetResizable(true); } -/* -==============================DialogueSubView========================================== -*/ -CSVWorld::DialogueSubView::DialogueSubView (const CSMWorld::UniversalId& id, CSMDoc::Document& document, - const CreatorFactoryBase& creatorFactory, bool sorting) : +QVBoxLayout& CSVWorld::SimpleDialogueSubView::getMainLayout() +{ + return *mMainLayout; +} + +CSMWorld::IdTable& CSVWorld::SimpleDialogueSubView::getTable() +{ + return *mTable; +} + +CSMWorld::CommandDispatcher& CSVWorld::SimpleDialogueSubView::getCommandDispatcher() +{ + return mCommandDispatcher; +} + +std::string CSVWorld::SimpleDialogueSubView::getCurrentId() const +{ + return mCurrentId; +} + +CSVWorld::EditWidget& CSVWorld::SimpleDialogueSubView::getEditWidget() +{ + return *mEditWidget; +} + +bool CSVWorld::SimpleDialogueSubView::isLocked() const +{ + return mLocked; +} + +CSVWorld::SimpleDialogueSubView::SimpleDialogueSubView (const CSMWorld::UniversalId& id, CSMDoc::Document& document) : SubView (id), mEditWidget(0), mMainLayout(NULL), @@ -570,42 +596,150 @@ CSVWorld::DialogueSubView::DialogueSubView (const CSMWorld::UniversalId& id, CSM QWidget *mainWidget = new QWidget(this); + mMainLayout = new QVBoxLayout(mainWidget); + setWidget (mainWidget); + + mEditWidget = new EditWidget(mainWidget, + mTable->getModelIndex(mCurrentId, 0).row(), mTable, mCommandDispatcher, document, false); + + mMainLayout->addWidget(mEditWidget); + mEditWidget->setSizePolicy(QSizePolicy::MinimumExpanding, QSizePolicy::MinimumExpanding); + + dataChanged(mTable->getModelIndex (mCurrentId, 0)); +} + +void CSVWorld::SimpleDialogueSubView::setEditLock (bool locked) +{ + if (!mEditWidget) // hack to indicate that mCurrentId is no longer valid + return; + + mLocked = locked; + QModelIndex currentIndex(mTable->getModelIndex(mCurrentId, 0)); + + if (currentIndex.isValid()) + { + CSMWorld::RecordBase::State state = static_cast(mTable->data (mTable->index (currentIndex.row(), 1)).toInt()); + + mEditWidget->setDisabled (state==CSMWorld::RecordBase::State_Deleted || locked); + + mCommandDispatcher.setEditLock (locked); + } + +} + +void CSVWorld::SimpleDialogueSubView::dataChanged (const QModelIndex & index) +{ + QModelIndex currentIndex(mTable->getModelIndex(mCurrentId, 0)); + + if (currentIndex.isValid() && + (index.parent().isValid() ? index.parent().row() : index.row()) == currentIndex.row()) + { + CSMWorld::RecordBase::State state = static_cast(mTable->data (mTable->index (currentIndex.row(), 1)).toInt()); + + mEditWidget->setDisabled (state==CSMWorld::RecordBase::State_Deleted || mLocked); + + // Check if the changed data should force refresh (rebuild) the dialogue subview + int flags = 0; + if (index.parent().isValid()) // TODO: check that index is topLeft + { + flags = static_cast(mTable)->nestedHeaderData (index.parent().column(), + index.column(), Qt::Horizontal, CSMWorld::ColumnBase::Role_Flags).toInt(); + } + else + { + flags = mTable->headerData (index.column(), + Qt::Horizontal, CSMWorld::ColumnBase::Role_Flags).toInt(); + } + + if (flags & CSMWorld::ColumnBase::Flag_Dialogue_Refresh) + { + int y = mEditWidget->verticalScrollBar()->value(); + mEditWidget->remake (index.parent().isValid() ? index.parent().row() : index.row()); + mEditWidget->verticalScrollBar()->setValue(y); + } + } +} + +void CSVWorld::SimpleDialogueSubView::rowsAboutToBeRemoved(const QModelIndex &parent, int start, int end) +{ + QModelIndex currentIndex(mTable->getModelIndex(mCurrentId, 0)); + + if (currentIndex.isValid() && currentIndex.row() >= start && currentIndex.row() <= end) + { + if(mEditWidget) + { + delete mEditWidget; + mEditWidget = 0; + } + emit closeRequest(this); + } +} + +void CSVWorld::SimpleDialogueSubView::requestFocus (const std::string& id) +{ + changeCurrentId(id); + + mEditWidget->remake(mTable->getModelIndex (id, 0).row()); +} + +void CSVWorld::SimpleDialogueSubView::changeCurrentId (const std::string& newId) +{ + std::vector selection; + mCurrentId = std::string(newId); + + selection.push_back(mCurrentId); + mCommandDispatcher.setSelection(selection); +} + + +CSVWorld::DialogueSubView::DialogueSubView (const CSMWorld::UniversalId& id, + CSMDoc::Document& document, const CreatorFactoryBase& creatorFactory, bool sorting) +: SimpleDialogueSubView (id, document) +{ + // bottom box + getMainLayout().addWidget (mBottom = new TableBottomBox (creatorFactory, document, id, this)); + + mBottom->setSizePolicy(QSizePolicy::Ignored, QSizePolicy::Fixed); + + connect(mBottom, SIGNAL(requestFocus(const std::string&)), this, SLOT(requestFocus(const std::string&))); + + // buttons QHBoxLayout *buttonsLayout = new QHBoxLayout; - QToolButton* prevButton = new QToolButton(mainWidget); + QToolButton* prevButton = new QToolButton (this); prevButton->setIcon(QIcon(":/go-previous.png")); prevButton->setToolTip ("Switch to previous record"); - QToolButton* nextButton = new QToolButton(mainWidget); + QToolButton* nextButton = new QToolButton (this); nextButton->setIcon(QIcon(":/go-next.png")); nextButton->setToolTip ("Switch to next record"); buttonsLayout->addWidget(prevButton, 0); buttonsLayout->addWidget(nextButton, 1); buttonsLayout->addStretch(2); - QToolButton* cloneButton = new QToolButton(mainWidget); + QToolButton* cloneButton = new QToolButton (this); cloneButton->setIcon(QIcon(":/edit-clone.png")); cloneButton->setToolTip ("Clone record"); - QToolButton* addButton = new QToolButton(mainWidget); + QToolButton* addButton = new QToolButton (this); addButton->setIcon(QIcon(":/add.png")); addButton->setToolTip ("Add new record"); - QToolButton* deleteButton = new QToolButton(mainWidget); + QToolButton* deleteButton = new QToolButton (this); deleteButton->setIcon(QIcon(":/edit-delete.png")); deleteButton->setToolTip ("Delete record"); - QToolButton* revertButton = new QToolButton(mainWidget); + QToolButton* revertButton = new QToolButton (this); revertButton->setIcon(QIcon(":/edit-undo.png")); revertButton->setToolTip ("Revert record"); - if (mTable->getFeatures() & CSMWorld::IdTable::Feature_Preview) + if (getTable().getFeatures() & CSMWorld::IdTable::Feature_Preview) { - QToolButton* previewButton = new QToolButton(mainWidget); + QToolButton* previewButton = new QToolButton (this); previewButton->setIcon(QIcon(":/edit-preview.png")); previewButton->setToolTip ("Open a preview of this record"); buttonsLayout->addWidget(previewButton); connect(previewButton, SIGNAL(clicked()), this, SLOT(showPreview())); } - if (mTable->getFeatures() & CSMWorld::IdTable::Feature_View) + if (getTable().getFeatures() & CSMWorld::IdTable::Feature_View) { - QToolButton* viewButton = new QToolButton(mainWidget); + QToolButton* viewButton = new QToolButton (this); viewButton->setIcon(QIcon(":/cell.png")); viewButton->setToolTip ("Open a scene view of the cell this record is located in"); buttonsLayout->addWidget(viewButton); @@ -620,22 +754,8 @@ CSVWorld::DialogueSubView::DialogueSubView (const CSMWorld::UniversalId& id, CSM connect(nextButton, SIGNAL(clicked()), this, SLOT(nextId())); connect(prevButton, SIGNAL(clicked()), this, SLOT(prevId())); connect(cloneButton, SIGNAL(clicked()), this, SLOT(cloneRequest())); - connect(revertButton, SIGNAL(clicked()), &mCommandDispatcher, SLOT(executeRevert())); - connect(deleteButton, SIGNAL(clicked()), &mCommandDispatcher, SLOT(executeDelete())); - - mMainLayout = new QVBoxLayout(mainWidget); - - mEditWidget = new EditWidget(mainWidget, - mTable->getModelIndex(mCurrentId, 0).row(), mTable, mCommandDispatcher, document, false); - - mMainLayout->addWidget(mEditWidget); - mEditWidget->setSizePolicy(QSizePolicy::MinimumExpanding, QSizePolicy::MinimumExpanding); - - mMainLayout->addWidget (mBottom = new TableBottomBox (creatorFactory, document, id, this)); - - mBottom->setSizePolicy(QSizePolicy::Ignored, QSizePolicy::Fixed); - - connect(mBottom, SIGNAL(requestFocus(const std::string&)), this, SLOT(requestFocus(const std::string&))); + connect(revertButton, SIGNAL(clicked()), &getCommandDispatcher(), SLOT(executeRevert())); + connect(deleteButton, SIGNAL(clicked()), &getCommandDispatcher(), SLOT(executeDelete())); connect(addButton, SIGNAL(clicked()), mBottom, SLOT(createRequest())); @@ -646,14 +766,19 @@ CSVWorld::DialogueSubView::DialogueSubView (const CSMWorld::UniversalId& id, CSM deleteButton->setDisabled (true); } - dataChanged(mTable->getModelIndex (mCurrentId, 0)); - mMainLayout->addLayout (buttonsLayout); - setWidget (mainWidget); + getMainLayout().addLayout (buttonsLayout); } -void CSVWorld::DialogueSubView::prevId () +void CSVWorld::DialogueSubView::cloneRequest() { - int newRow = mTable->getModelIndex(mCurrentId, 0).row() - 1; + mBottom->cloneRequest (getCurrentId(), + static_cast (getTable(). + data (getTable().getModelIndex(getCurrentId(), 2)).toInt())); +} + +void CSVWorld::DialogueSubView::prevId() +{ + int newRow = getTable().getModelIndex (getCurrentId(), 0).row() - 1; if (newRow < 0) { @@ -661,26 +786,26 @@ void CSVWorld::DialogueSubView::prevId () } while (newRow >= 0) { - QModelIndex newIndex(mTable->index(newRow, 0)); + QModelIndex newIndex (getTable().index(newRow, 0)); if (!newIndex.isValid()) { return; } - CSMWorld::RecordBase::State state = static_cast(mTable->data (mTable->index (newRow, 1)).toInt()); + CSMWorld::RecordBase::State state = static_cast (getTable().data (getTable().index (newRow, 1)).toInt()); if (!(state == CSMWorld::RecordBase::State_Deleted || state == CSMWorld::RecordBase::State_Erased)) { - mEditWidget->remake(newRow); + getEditWidget().remake (newRow); - setUniversalId(CSMWorld::UniversalId (static_cast (mTable->data (mTable->index (newRow, 2)).toInt()), - mTable->data (mTable->index (newRow, 0)).toString().toUtf8().constData())); + setUniversalId(CSMWorld::UniversalId (static_cast (getTable().data (getTable().index (newRow, 2)).toInt()), + getTable().data (getTable().index (newRow, 0)).toString().toUtf8().constData())); - changeCurrentId(std::string(mTable->data (mTable->index (newRow, 0)).toString().toUtf8().constData())); + changeCurrentId(std::string (getTable().data (getTable().index (newRow, 0)).toString().toUtf8().constData())); - mEditWidget->setDisabled(mLocked); + getEditWidget().setDisabled (isLocked()); - return; + return; } --newRow; } @@ -688,150 +813,63 @@ void CSVWorld::DialogueSubView::prevId () void CSVWorld::DialogueSubView::nextId () { - int newRow = mTable->getModelIndex(mCurrentId, 0).row() + 1; + int newRow = getTable().getModelIndex (getCurrentId(), 0).row() + 1; - if (newRow >= mTable->rowCount()) + if (newRow >= getTable().rowCount()) { return; } - while (newRow < mTable->rowCount()) + while (newRow < getTable().rowCount()) { - QModelIndex newIndex(mTable->index(newRow, 0)); + QModelIndex newIndex (getTable().index(newRow, 0)); if (!newIndex.isValid()) { return; } - CSMWorld::RecordBase::State state = static_cast(mTable->data (mTable->index (newRow, 1)).toInt()); + CSMWorld::RecordBase::State state = static_cast (getTable().data (getTable().index (newRow, 1)).toInt()); if (!(state == CSMWorld::RecordBase::State_Deleted)) { - mEditWidget->remake(newRow); + getEditWidget().remake(newRow); - setUniversalId(CSMWorld::UniversalId (static_cast (mTable->data (mTable->index (newRow, 2)).toInt()), - mTable->data (mTable->index (newRow, 0)).toString().toUtf8().constData())); + setUniversalId(CSMWorld::UniversalId (static_cast (getTable().data (getTable().index (newRow, 2)).toInt()), + getTable().data (getTable().index (newRow, 0)).toString().toUtf8().constData())); - changeCurrentId(std::string(mTable->data (mTable->index (newRow, 0)).toString().toUtf8().constData())); + changeCurrentId(std::string (getTable().data (getTable().index (newRow, 0)).toString().toUtf8().constData())); - mEditWidget->setDisabled(mLocked); + getEditWidget().setDisabled (isLocked()); - return; + return; } ++newRow; } } -void CSVWorld::DialogueSubView::setEditLock (bool locked) -{ - if (!mEditWidget) // hack to indicate that mCurrentId is no longer valid - return; - - mLocked = locked; - QModelIndex currentIndex(mTable->getModelIndex(mCurrentId, 0)); - - if (currentIndex.isValid()) - { - CSMWorld::RecordBase::State state = static_cast(mTable->data (mTable->index (currentIndex.row(), 1)).toInt()); - - mEditWidget->setDisabled (state==CSMWorld::RecordBase::State_Deleted || locked); - - mCommandDispatcher.setEditLock (locked); - } - -} - -void CSVWorld::DialogueSubView::dataChanged (const QModelIndex & index) -{ - QModelIndex currentIndex(mTable->getModelIndex(mCurrentId, 0)); - - if (currentIndex.isValid() && - (index.parent().isValid() ? index.parent().row() : index.row()) == currentIndex.row()) - { - CSMWorld::RecordBase::State state = static_cast(mTable->data (mTable->index (currentIndex.row(), 1)).toInt()); - - mEditWidget->setDisabled (state==CSMWorld::RecordBase::State_Deleted || mLocked); - - // Check if the changed data should force refresh (rebuild) the dialogue subview - int flags = 0; - if (index.parent().isValid()) // TODO: check that index is topLeft - { - flags = static_cast(mTable)->nestedHeaderData (index.parent().column(), - index.column(), Qt::Horizontal, CSMWorld::ColumnBase::Role_Flags).toInt(); - } - else - { - flags = mTable->headerData (index.column(), - Qt::Horizontal, CSMWorld::ColumnBase::Role_Flags).toInt(); - } - - if (flags & CSMWorld::ColumnBase::Flag_Dialogue_Refresh) - { - int y = mEditWidget->verticalScrollBar()->value(); - mEditWidget->remake (index.parent().isValid() ? index.parent().row() : index.row()); - mEditWidget->verticalScrollBar()->setValue(y); - } - } -} - -void CSVWorld::DialogueSubView::rowsAboutToBeRemoved(const QModelIndex &parent, int start, int end) -{ - QModelIndex currentIndex(mTable->getModelIndex(mCurrentId, 0)); - - if (currentIndex.isValid() && currentIndex.row() >= start && currentIndex.row() <= end) - { - if(mEditWidget) - { - delete mEditWidget; - mEditWidget = 0; - } - emit closeRequest(this); - } -} - -void CSVWorld::DialogueSubView::requestFocus (const std::string& id) -{ - changeCurrentId(id); - - mEditWidget->remake(mTable->getModelIndex (id, 0).row()); -} - -void CSVWorld::DialogueSubView::cloneRequest () -{ - mBottom->cloneRequest(mCurrentId, static_cast(mTable->data(mTable->getModelIndex(mCurrentId, 2)).toInt())); -} void CSVWorld::DialogueSubView::showPreview () { - QModelIndex currentIndex(mTable->getModelIndex(mCurrentId, 0)); + QModelIndex currentIndex (getTable().getModelIndex (getCurrentId(), 0)); if (currentIndex.isValid() && - mTable->getFeatures() & CSMWorld::IdTable::Feature_Preview && - currentIndex.row() < mTable->rowCount()) + getTable().getFeatures() & CSMWorld::IdTable::Feature_Preview && + currentIndex.row() < getTable().rowCount()) { - emit focusId(CSMWorld::UniversalId(CSMWorld::UniversalId::Type_Preview, mCurrentId), ""); + emit focusId(CSMWorld::UniversalId(CSMWorld::UniversalId::Type_Preview, getCurrentId()), ""); } } void CSVWorld::DialogueSubView::viewRecord () { - QModelIndex currentIndex(mTable->getModelIndex (mCurrentId, 0)); + QModelIndex currentIndex (getTable().getModelIndex (getCurrentId(), 0)); if (currentIndex.isValid() && - currentIndex.row() < mTable->rowCount()) + currentIndex.row() < getTable().rowCount()) { - std::pair params = mTable->view (currentIndex.row()); + std::pair params = getTable().view (currentIndex.row()); if (params.first.getType()!=CSMWorld::UniversalId::Type_None) emit focusId (params.first, params.second); } } - -void CSVWorld::DialogueSubView::changeCurrentId (const std::string& newId) -{ - std::vector selection; - mCurrentId = std::string(newId); - - selection.push_back(mCurrentId); - mCommandDispatcher.setSelection(selection); -} diff --git a/apps/opencs/view/world/dialoguesubview.hpp b/apps/opencs/view/world/dialoguesubview.hpp index 69e0dc864..5d6915d42 100644 --- a/apps/opencs/view/world/dialoguesubview.hpp +++ b/apps/opencs/view/world/dialoguesubview.hpp @@ -173,7 +173,7 @@ namespace CSVWorld void remake(int row); }; - class DialogueSubView : public CSVDoc::SubView + class SimpleDialogueSubView : public CSVDoc::SubView { Q_OBJECT @@ -184,32 +184,31 @@ namespace CSVWorld std::string mCurrentId; bool mLocked; const CSMDoc::Document& mDocument; - TableBottomBox* mBottom; CSMWorld::CommandDispatcher mCommandDispatcher; - public: + protected: - DialogueSubView (const CSMWorld::UniversalId& id, - CSMDoc::Document& document, - const CreatorFactoryBase& creatorFactory, - bool sorting = false); + QVBoxLayout& getMainLayout(); - virtual void setEditLock (bool locked); + CSMWorld::IdTable& getTable(); - private: - void changeCurrentId(const std::string& newCurrent); + CSMWorld::CommandDispatcher& getCommandDispatcher(); - private slots: + std::string getCurrentId() const; - void nextId(); + EditWidget& getEditWidget(); - void prevId(); + void changeCurrentId(const std::string& newCurrent); - void showPreview(); + bool isLocked() const; + + public: - void viewRecord(); + SimpleDialogueSubView (const CSMWorld::UniversalId& id, CSMDoc::Document& document); - void cloneRequest(); + virtual void setEditLock (bool locked); + + private slots: void dataChanged(const QModelIndex & index); ///\brief we need to care for deleting currently edited record @@ -218,6 +217,30 @@ namespace CSVWorld void rowsAboutToBeRemoved(const QModelIndex &parent, int start, int end); }; + + class DialogueSubView : public SimpleDialogueSubView + { + Q_OBJECT + + TableBottomBox* mBottom; + + public: + + DialogueSubView (const CSMWorld::UniversalId& id, CSMDoc::Document& document, + const CreatorFactoryBase& creatorFactory, bool sorting = false); + + private slots: + + void cloneRequest(); + + void nextId(); + + void prevId(); + + void showPreview(); + + void viewRecord(); + }; } #endif From 57015f366609f57a0ac727796585a2bace3915aa Mon Sep 17 00:00:00 2001 From: Marc Zinnschlag Date: Fri, 26 Jun 2015 15:50:36 +0200 Subject: [PATCH 31/45] fixed handling of numeric read-only fields in dialogue sub views --- apps/opencs/view/world/dialoguesubview.cpp | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/apps/opencs/view/world/dialoguesubview.cpp b/apps/opencs/view/world/dialoguesubview.cpp index d588c2edb..99650834e 100644 --- a/apps/opencs/view/world/dialoguesubview.cpp +++ b/apps/opencs/view/world/dialoguesubview.cpp @@ -64,16 +64,24 @@ void CSVWorld::NotEditableSubDelegate::setEditorData (QWidget* editor, const QMo } } + CSMWorld::Columns::ColumnId columnId = static_cast ( + mTable->getColumnId (index.column())); + if (QVariant::String == v.type()) { label->setText(v.toString()); } - else //else we are facing enums + else if (CSMWorld::Columns::hasEnums (columnId)) { int data = v.toInt(); - std::vector enumNames (CSMWorld::Columns::getEnums (static_cast (mTable->getColumnId (index.column())))); + std::vector enumNames (CSMWorld::Columns::getEnums (columnId)); + label->setText(QString::fromUtf8(enumNames.at(data).c_str())); } + else + { + label->setText (v.toString()); + } } void CSVWorld::NotEditableSubDelegate::setModelData(QWidget* editor, QAbstractItemModel* model, const QModelIndex& index) const From 1e033fa8fe87f8eac5b6414b697d5a55b066bead Mon Sep 17 00:00:00 2001 From: Marc Zinnschlag Date: Fri, 26 Jun 2015 16:11:00 +0200 Subject: [PATCH 32/45] added meta data dialogue sub view --- apps/opencs/model/world/columnimp.hpp | 72 +++++++++++++++++++++++++++ apps/opencs/model/world/columns.cpp | 4 ++ apps/opencs/model/world/columns.hpp | 4 ++ apps/opencs/model/world/data.cpp | 8 ++- apps/opencs/view/doc/view.cpp | 9 ++++ apps/opencs/view/doc/view.hpp | 2 + apps/opencs/view/world/subviews.cpp | 3 ++ 7 files changed, 101 insertions(+), 1 deletion(-) diff --git a/apps/opencs/model/world/columnimp.hpp b/apps/opencs/model/world/columnimp.hpp index a8ae5dfa1..ba23a3603 100644 --- a/apps/opencs/model/world/columnimp.hpp +++ b/apps/opencs/model/world/columnimp.hpp @@ -2308,6 +2308,78 @@ namespace CSMWorld return true; } }; + + template + struct FormatColumn : public Column + { + FormatColumn() + : Column (Columns::ColumnId_FileFormat, ColumnBase::Display_Integer) + {} + + virtual QVariant get (const Record& record) const + { + return record.get().mFormat; + } + + virtual bool isEditable() const + { + return false; + } + }; + + template + struct AuthorColumn : public Column + { + AuthorColumn() + : Column (Columns::ColumnId_Author, ColumnBase::Display_String) + {} + + virtual QVariant get (const Record& record) const + { + return QString::fromUtf8 (record.get().mAuthor.c_str()); + } + + virtual void set (Record& record, const QVariant& data) + { + ESXRecordT record2 = record.get(); + + record2.mAuthor = data.toString().toUtf8().constData(); + + record.setModified (record2); + } + + virtual bool isEditable() const + { + return true; + } + }; + + template + struct FileDescriptionColumn : public Column + { + FileDescriptionColumn() + : Column (Columns::ColumnId_FileDescription, ColumnBase::Display_LongString) + {} + + virtual QVariant get (const Record& record) const + { + return QString::fromUtf8 (record.get().mDescription.c_str()); + } + + virtual void set (Record& record, const QVariant& data) + { + ESXRecordT record2 = record.get(); + + record2.mDescription = data.toString().toUtf8().constData(); + + record.setModified (record2); + } + + virtual bool isEditable() const + { + return true; + } + }; } #endif diff --git a/apps/opencs/model/world/columns.cpp b/apps/opencs/model/world/columns.cpp index 9491c3246..d6e27caeb 100644 --- a/apps/opencs/model/world/columns.cpp +++ b/apps/opencs/model/world/columns.cpp @@ -311,6 +311,10 @@ namespace CSMWorld { ColumnId_WaterLevel, "Water Level" }, { ColumnId_MapColor, "Map Color" }, + { ColumnId_FileFormat, "File Format" }, + { ColumnId_FileDescription, "File Description" }, + { ColumnId_Author, "Author" }, + { ColumnId_UseValue1, "Use value 1" }, { ColumnId_UseValue2, "Use value 2" }, { ColumnId_UseValue3, "Use value 3" }, diff --git a/apps/opencs/model/world/columns.hpp b/apps/opencs/model/world/columns.hpp index 191bbdea8..d699c67b7 100644 --- a/apps/opencs/model/world/columns.hpp +++ b/apps/opencs/model/world/columns.hpp @@ -302,6 +302,10 @@ namespace CSMWorld ColumnId_WaterLevel = 273, ColumnId_MapColor = 274, + ColumnId_FileFormat = 275, + ColumnId_FileDescription = 276, + ColumnId_Author = 277, + // Allocated to a separate value range, so we don't get a collision should we ever need // to extend the number of use values. ColumnId_UseValue1 = 0x10000, diff --git a/apps/opencs/model/world/data.cpp b/apps/opencs/model/world/data.cpp index 368c7a766..29f7fa9b8 100644 --- a/apps/opencs/model/world/data.cpp +++ b/apps/opencs/model/world/data.cpp @@ -476,7 +476,13 @@ CSMWorld::Data::Data (ToUTF8::FromType encoding, const ResourcesManager& resourc ScriptColumn::Type_Lines)); mMetaData.appendBlankRecord ("sys::meta"); - + + mMetaData.addColumn (new StringIdColumn (true)); + mMetaData.addColumn (new RecordStateColumn); + mMetaData.addColumn (new FormatColumn); + mMetaData.addColumn (new AuthorColumn); + mMetaData.addColumn (new FileDescriptionColumn); + addModel (new IdTable (&mGlobals), UniversalId::Type_Global); addModel (new IdTable (&mGmsts), UniversalId::Type_Gmst); addModel (new IdTable (&mSkills), UniversalId::Type_Skill); diff --git a/apps/opencs/view/doc/view.cpp b/apps/opencs/view/doc/view.cpp index 64b066eb1..c4abb2622 100644 --- a/apps/opencs/view/doc/view.cpp +++ b/apps/opencs/view/doc/view.cpp @@ -70,6 +70,10 @@ void CSVDoc::View::setupFileMenu() connect (loadErrors, SIGNAL (triggered()), this, SLOT (loadErrorLog())); file->addAction (loadErrors); + QAction *meta = new QAction (tr ("Meta Data"), this); + connect (meta, SIGNAL (triggered()), this, SLOT (addMetaDataSubView())); + file->addAction (meta); + QAction *close = new QAction (tr ("&Close"), this); connect (close, SIGNAL (triggered()), this, SLOT (close())); file->addAction(close); @@ -813,6 +817,11 @@ void CSVDoc::View::addSearchSubView() addSubView (mDocument->newSearch()); } +void CSVDoc::View::addMetaDataSubView() +{ + addSubView (CSMWorld::UniversalId (CSMWorld::UniversalId::Type_MetaData, "sys::meta")); +} + void CSVDoc::View::abortOperation (int type) { mDocument->abortOperation (type); diff --git a/apps/opencs/view/doc/view.hpp b/apps/opencs/view/doc/view.hpp index 814dabc6b..7f4255f8f 100644 --- a/apps/opencs/view/doc/view.hpp +++ b/apps/opencs/view/doc/view.hpp @@ -224,6 +224,8 @@ namespace CSVDoc void addSearchSubView(); + void addMetaDataSubView(); + void toggleShowStatusBar (bool show); void loadErrorLog(); diff --git a/apps/opencs/view/world/subviews.cpp b/apps/opencs/view/world/subviews.cpp index ba3ab1358..b8a6ba429 100644 --- a/apps/opencs/view/world/subviews.cpp +++ b/apps/opencs/view/world/subviews.cpp @@ -170,6 +170,9 @@ void CSVWorld::addSubViewFactories (CSVDoc::SubViewFactoryManager& manager) manager.add (CSMWorld::UniversalId::Type_Filter, new CSVDoc::SubViewFactoryWithCreator > (false)); + manager.add (CSMWorld::UniversalId::Type_MetaData, + new CSVDoc::SubViewFactory); + //preview manager.add (CSMWorld::UniversalId::Type_Preview, new CSVDoc::SubViewFactory); } From a4c2c75d1fafd5458bfae3d555f55b8ab4a00844 Mon Sep 17 00:00:00 2001 From: Marc Zinnschlag Date: Fri, 26 Jun 2015 16:22:06 +0200 Subject: [PATCH 33/45] fixed overwriting of meta data when loading project file --- apps/opencs/model/world/data.cpp | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/apps/opencs/model/world/data.cpp b/apps/opencs/model/world/data.cpp index 29f7fa9b8..b38607748 100644 --- a/apps/opencs/model/world/data.cpp +++ b/apps/opencs/model/world/data.cpp @@ -861,11 +861,14 @@ int CSMWorld::Data::startLoading (const boost::filesystem::path& path, bool base mBase = base; mProject = project; - MetaData metaData; - metaData.mId = "sys::meta"; - metaData.load (*mReader); + if (!mProject && !mBase) + { + MetaData metaData; + metaData.mId = "sys::meta"; + metaData.load (*mReader); - mMetaData.setRecord (0, Record (RecordBase::State_ModifiedOnly, 0, &metaData)); + mMetaData.setRecord (0, Record (RecordBase::State_ModifiedOnly, 0, &metaData)); + } return mReader->getRecordCount(); } From 4487bda702da64a34913219ccf22a318e0545a21 Mon Sep 17 00:00:00 2001 From: Marc Zinnschlag Date: Fri, 26 Jun 2015 18:19:00 +0200 Subject: [PATCH 34/45] size limits for meta data strings --- apps/opencs/model/world/columnbase.cpp | 3 ++- apps/opencs/model/world/columnbase.hpp | 2 ++ apps/opencs/model/world/columnimp.hpp | 4 ++-- apps/opencs/view/world/util.cpp | 16 ++++++++++++++++ 4 files changed, 22 insertions(+), 3 deletions(-) diff --git a/apps/opencs/model/world/columnbase.cpp b/apps/opencs/model/world/columnbase.cpp index 938503875..f209e48c6 100644 --- a/apps/opencs/model/world/columnbase.cpp +++ b/apps/opencs/model/world/columnbase.cpp @@ -100,7 +100,8 @@ bool CSMWorld::ColumnBase::isId (Display display) bool CSMWorld::ColumnBase::isText (Display display) { - return display==Display_String || display==Display_LongString; + return display==Display_String || display==Display_LongString || + display==Display_String32 || display==Display_LongString256; } bool CSMWorld::ColumnBase::isScript (Display display) diff --git a/apps/opencs/model/world/columnbase.hpp b/apps/opencs/model/world/columnbase.hpp index 789823d5c..59f2836c2 100644 --- a/apps/opencs/model/world/columnbase.hpp +++ b/apps/opencs/model/world/columnbase.hpp @@ -123,6 +123,8 @@ namespace CSMWorld Display_InfoCondVar, Display_InfoCondComp, Display_RaceSkill, + Display_String32, + Display_LongString256, //top level columns that nest other columns Display_NestedHeader diff --git a/apps/opencs/model/world/columnimp.hpp b/apps/opencs/model/world/columnimp.hpp index ba23a3603..15dd2c15b 100644 --- a/apps/opencs/model/world/columnimp.hpp +++ b/apps/opencs/model/world/columnimp.hpp @@ -2331,7 +2331,7 @@ namespace CSMWorld struct AuthorColumn : public Column { AuthorColumn() - : Column (Columns::ColumnId_Author, ColumnBase::Display_String) + : Column (Columns::ColumnId_Author, ColumnBase::Display_String32) {} virtual QVariant get (const Record& record) const @@ -2358,7 +2358,7 @@ namespace CSMWorld struct FileDescriptionColumn : public Column { FileDescriptionColumn() - : Column (Columns::ColumnId_FileDescription, ColumnBase::Display_LongString) + : Column (Columns::ColumnId_FileDescription, ColumnBase::Display_LongString256) {} virtual QVariant get (const Record& record) const diff --git a/apps/opencs/view/world/util.cpp b/apps/opencs/view/world/util.cpp index 62cde4608..f21658581 100644 --- a/apps/opencs/view/world/util.cpp +++ b/apps/opencs/view/world/util.cpp @@ -232,6 +232,14 @@ QWidget *CSVWorld::CommandDelegate::createEditor (QWidget *parent, const QStyleO return edit; } + case CSMWorld::ColumnBase::Display_LongString256: + { + /// \todo implement size limit. QPlainTextEdit does not support a size limit. + QPlainTextEdit *edit = new QPlainTextEdit(parent); + edit->setUndoRedoEnabled (false); + return edit; + } + case CSMWorld::ColumnBase::Display_Boolean: return new QCheckBox(parent); @@ -245,6 +253,14 @@ QWidget *CSVWorld::CommandDelegate::createEditor (QWidget *parent, const QStyleO return new CSVWidget::DropLineEdit(display, parent); + case CSMWorld::ColumnBase::Display_String32: + { + // For other Display types (that represent record IDs) with drop support IdCompletionDelegate is used + CSVWidget::DropLineEdit *widget = new CSVWidget::DropLineEdit(display, parent); + widget->setMaxLength (32); + return widget; + } + default: return QStyledItemDelegate::createEditor (parent, option, index); From 6d5823e8aabefc0031a65c6157fa66de0afcd03c Mon Sep 17 00:00:00 2001 From: Marc Zinnschlag Date: Fri, 26 Jun 2015 18:54:49 +0200 Subject: [PATCH 35/45] killed some tabs --- apps/opencs/model/world/infotableproxymodel.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/opencs/model/world/infotableproxymodel.cpp b/apps/opencs/model/world/infotableproxymodel.cpp index e34c50566..6216291d0 100644 --- a/apps/opencs/model/world/infotableproxymodel.cpp +++ b/apps/opencs/model/world/infotableproxymodel.cpp @@ -9,7 +9,7 @@ namespace { QString toLower(const QString &str) { - return QString::fromUtf8(Misc::StringUtils::lowerCase(str.toStdString()).c_str()); + return QString::fromUtf8(Misc::StringUtils::lowerCase(str.toStdString()).c_str()); } } From 502cc852da0f10dae95ba10ec363a2be66707304 Mon Sep 17 00:00:00 2001 From: scrawl Date: Fri, 26 Jun 2015 20:16:32 +0200 Subject: [PATCH 36/45] Handle encoding conversions when saving TES3 header (Fixes #2727) --- components/esm/esmwriter.cpp | 9 +++++++++ components/esm/esmwriter.hpp | 1 + components/esm/loadtes3.cpp | 8 +++++++- 3 files changed, 17 insertions(+), 1 deletion(-) diff --git a/components/esm/esmwriter.cpp b/components/esm/esmwriter.cpp index c64678e70..4d9999143 100644 --- a/components/esm/esmwriter.cpp +++ b/components/esm/esmwriter.cpp @@ -174,6 +174,15 @@ namespace ESM endRecord(name); } + void ESMWriter::writeFixedSizeString(const std::string &data, int size) + { + std::string string; + if (!data.empty()) + string = mEncoder ? mEncoder->getLegacyEnc(data) : data; + string.resize(size); + write(string.c_str(), string.size()); + } + void ESMWriter::writeHString(const std::string& data) { if (data.size() == 0) diff --git a/components/esm/esmwriter.hpp b/components/esm/esmwriter.hpp index 30cec58b4..d11b3c940 100644 --- a/components/esm/esmwriter.hpp +++ b/components/esm/esmwriter.hpp @@ -120,6 +120,7 @@ public: void startSubRecord(const std::string& name); void endRecord(const std::string& name); void endRecord(uint32_t name); + void writeFixedSizeString(const std::string& data, int size); void writeHString(const std::string& data); void writeHCString(const std::string& data); void writeName(const std::string& data); diff --git a/components/esm/loadtes3.cpp b/components/esm/loadtes3.cpp index 9c0c55b8f..7d749c4d9 100644 --- a/components/esm/loadtes3.cpp +++ b/components/esm/loadtes3.cpp @@ -71,7 +71,13 @@ void ESM::Header::save (ESMWriter &esm) if (mFormat>0) esm.writeHNT ("FORM", mFormat); - esm.writeHNT ("HEDR", mData, 300); + esm.startSubRecord("HEDR"); + esm.writeT(mData.version); + esm.writeT(mData.type); + esm.writeFixedSizeString(mData.author.toString(), 32); + esm.writeFixedSizeString(mData.desc.toString(), 256); + esm.writeT(mData.records); + esm.endRecord("HEDR"); for (std::vector::iterator iter = mMaster.begin(); iter != mMaster.end(); ++iter) From 49dc30683f1e0d9366ab3afa65419e8f9d14c57d Mon Sep 17 00:00:00 2001 From: Marc Zinnschlag Date: Sat, 27 Jun 2015 12:49:56 +0200 Subject: [PATCH 37/45] refactored dialogue subview button bar into a new class --- apps/opencs/CMakeLists.txt | 2 +- apps/opencs/view/world/dialoguesubview.cpp | 74 +++------------ apps/opencs/view/world/recordbuttonbar.cpp | 100 +++++++++++++++++++++ apps/opencs/view/world/recordbuttonbar.hpp | 54 +++++++++++ 4 files changed, 166 insertions(+), 64 deletions(-) create mode 100644 apps/opencs/view/world/recordbuttonbar.cpp create mode 100644 apps/opencs/view/world/recordbuttonbar.hpp diff --git a/apps/opencs/CMakeLists.txt b/apps/opencs/CMakeLists.txt index 3399b9ddd..0607f67ee 100644 --- a/apps/opencs/CMakeLists.txt +++ b/apps/opencs/CMakeLists.txt @@ -64,7 +64,7 @@ opencs_units (view/world table tablesubview scriptsubview util regionmapsubview tablebottombox creator genericcreator cellcreator referenceablecreator referencecreator scenesubview infocreator scriptedit dialoguesubview previewsubview regionmap dragrecordtable nestedtable - dialoguespinbox + dialoguespinbox recordbuttonbar ) opencs_units_noqt (view/world diff --git a/apps/opencs/view/world/dialoguesubview.cpp b/apps/opencs/view/world/dialoguesubview.cpp index 99650834e..a2f25df44 100644 --- a/apps/opencs/view/world/dialoguesubview.cpp +++ b/apps/opencs/view/world/dialoguesubview.cpp @@ -40,6 +40,7 @@ #include "util.hpp" #include "tablebottombox.hpp" #include "nestedtable.hpp" +#include "recordbuttonbar.hpp" /* ==============================NotEditableSubDelegate========================================== */ @@ -712,69 +713,16 @@ CSVWorld::DialogueSubView::DialogueSubView (const CSMWorld::UniversalId& id, connect(mBottom, SIGNAL(requestFocus(const std::string&)), this, SLOT(requestFocus(const std::string&))); // buttons - QHBoxLayout *buttonsLayout = new QHBoxLayout; - QToolButton* prevButton = new QToolButton (this); - prevButton->setIcon(QIcon(":/go-previous.png")); - prevButton->setToolTip ("Switch to previous record"); - QToolButton* nextButton = new QToolButton (this); - nextButton->setIcon(QIcon(":/go-next.png")); - nextButton->setToolTip ("Switch to next record"); - buttonsLayout->addWidget(prevButton, 0); - buttonsLayout->addWidget(nextButton, 1); - buttonsLayout->addStretch(2); - - QToolButton* cloneButton = new QToolButton (this); - cloneButton->setIcon(QIcon(":/edit-clone.png")); - cloneButton->setToolTip ("Clone record"); - QToolButton* addButton = new QToolButton (this); - addButton->setIcon(QIcon(":/add.png")); - addButton->setToolTip ("Add new record"); - QToolButton* deleteButton = new QToolButton (this); - deleteButton->setIcon(QIcon(":/edit-delete.png")); - deleteButton->setToolTip ("Delete record"); - QToolButton* revertButton = new QToolButton (this); - revertButton->setIcon(QIcon(":/edit-undo.png")); - revertButton->setToolTip ("Revert record"); - - if (getTable().getFeatures() & CSMWorld::IdTable::Feature_Preview) - { - QToolButton* previewButton = new QToolButton (this); - previewButton->setIcon(QIcon(":/edit-preview.png")); - previewButton->setToolTip ("Open a preview of this record"); - buttonsLayout->addWidget(previewButton); - connect(previewButton, SIGNAL(clicked()), this, SLOT(showPreview())); - } - - if (getTable().getFeatures() & CSMWorld::IdTable::Feature_View) - { - QToolButton* viewButton = new QToolButton (this); - viewButton->setIcon(QIcon(":/cell.png")); - viewButton->setToolTip ("Open a scene view of the cell this record is located in"); - buttonsLayout->addWidget(viewButton); - connect(viewButton, SIGNAL(clicked()), this, SLOT(viewRecord())); - } - - buttonsLayout->addWidget(cloneButton); - buttonsLayout->addWidget(addButton); - buttonsLayout->addWidget(deleteButton); - buttonsLayout->addWidget(revertButton); - - connect(nextButton, SIGNAL(clicked()), this, SLOT(nextId())); - connect(prevButton, SIGNAL(clicked()), this, SLOT(prevId())); - connect(cloneButton, SIGNAL(clicked()), this, SLOT(cloneRequest())); - connect(revertButton, SIGNAL(clicked()), &getCommandDispatcher(), SLOT(executeRevert())); - connect(deleteButton, SIGNAL(clicked()), &getCommandDispatcher(), SLOT(executeDelete())); - - connect(addButton, SIGNAL(clicked()), mBottom, SLOT(createRequest())); - - if(!mBottom->canCreateAndDelete()) - { - cloneButton->setDisabled (true); - addButton->setDisabled (true); - deleteButton->setDisabled (true); - } - - getMainLayout().addLayout (buttonsLayout); + RecordButtonBar *buttons = new RecordButtonBar (getTable(), mBottom, + &getCommandDispatcher(), this); + + getMainLayout().addWidget (buttons); + + connect (buttons, SIGNAL(nextId()), this, SLOT(nextId())); + connect (buttons, SIGNAL (prevId()), this, SLOT(prevId())); + connect (buttons, SIGNAL (cloneRequest()), this, SLOT(cloneRequest())); + connect (buttons, SIGNAL (showPreview()), this, SLOT(showPreview())); + connect (buttons, SIGNAL (viewRecord()), this, SLOT(viewRecord())); } void CSVWorld::DialogueSubView::cloneRequest() diff --git a/apps/opencs/view/world/recordbuttonbar.cpp b/apps/opencs/view/world/recordbuttonbar.cpp new file mode 100644 index 000000000..2f5395317 --- /dev/null +++ b/apps/opencs/view/world/recordbuttonbar.cpp @@ -0,0 +1,100 @@ + +#include "recordbuttonbar.hpp" + +#include +#include + +#include "../../model/world/idtable.hpp" +#include "../../model/world/commanddispatcher.hpp" + +#include "../world/tablebottombox.hpp" + +CSVWorld::RecordButtonBar::RecordButtonBar (CSMWorld::IdTable& table, TableBottomBox *bottomBox, + CSMWorld::CommandDispatcher *commandDispatcher, QWidget *parent) +: QWidget (parent), mTable (table), mBottom (bottomBox), mCommandDispatcher (commandDispatcher) +{ + QHBoxLayout *buttonsLayout = new QHBoxLayout; + buttonsLayout->setContentsMargins (0, 0, 0, 0); + + // left section + QToolButton* prevButton = new QToolButton (this); + prevButton->setIcon(QIcon(":/go-previous.png")); + prevButton->setToolTip ("Switch to previous record"); + buttonsLayout->addWidget (prevButton, 0); + + QToolButton* nextButton = new QToolButton (this); + nextButton->setIcon(QIcon(":/go-next.png")); + nextButton->setToolTip ("Switch to next record"); + buttonsLayout->addWidget (nextButton, 1); + + buttonsLayout->addStretch(2); + + // optional buttons of the right section + if (mTable.getFeatures() & CSMWorld::IdTable::Feature_Preview) + { + QToolButton* previewButton = new QToolButton (this); + previewButton->setIcon(QIcon(":/edit-preview.png")); + previewButton->setToolTip ("Open a preview of this record"); + buttonsLayout->addWidget(previewButton); + connect (previewButton, SIGNAL(clicked()), this, SIGNAL (showPreview())); + } + + if (mTable.getFeatures() & CSMWorld::IdTable::Feature_View) + { + QToolButton* viewButton = new QToolButton (this); + viewButton->setIcon(QIcon(":/cell.png")); + viewButton->setToolTip ("Open a scene view of the cell this record is located in"); + buttonsLayout->addWidget(viewButton); + connect (viewButton, SIGNAL(clicked()), this, SIGNAL (viewRecord())); + } + + // right section + QToolButton* cloneButton = new QToolButton (this); + cloneButton->setIcon(QIcon(":/edit-clone.png")); + cloneButton->setToolTip ("Clone record"); + buttonsLayout->addWidget(cloneButton); + + QToolButton* addButton = new QToolButton (this); + addButton->setIcon(QIcon(":/add.png")); + addButton->setToolTip ("Add new record"); + buttonsLayout->addWidget(addButton); + + QToolButton* deleteButton = new QToolButton (this); + deleteButton->setIcon(QIcon(":/edit-delete.png")); + deleteButton->setToolTip ("Delete record"); + buttonsLayout->addWidget(deleteButton); + + QToolButton* revertButton = new QToolButton (this); + revertButton->setIcon(QIcon(":/edit-undo.png")); + revertButton->setToolTip ("Revert record"); + buttonsLayout->addWidget(revertButton); + + setLayout (buttonsLayout); + + // disabling and connections + if(!mBottom || !mBottom->canCreateAndDelete()) + { + cloneButton->setDisabled (true); + addButton->setDisabled (true); + deleteButton->setDisabled (true); + } + else + { + connect (addButton, SIGNAL (clicked()), mBottom, SLOT (createRequest())); + connect (cloneButton, SIGNAL (clicked()), this, SIGNAL (cloneRequest())); + } + + connect (nextButton, SIGNAL (clicked()), this, SIGNAL (nextId())); + connect (prevButton, SIGNAL (clicked()), this, SIGNAL (prevId())); + + if (!mCommandDispatcher) + { + revertButton->setDisabled (true); + deleteButton->setDisabled (true); + } + else + { + connect (revertButton, SIGNAL (clicked()), mCommandDispatcher, SLOT (executeRevert())); + connect (deleteButton, SIGNAL (clicked()), mCommandDispatcher, SLOT (executeDelete())); + } +} diff --git a/apps/opencs/view/world/recordbuttonbar.hpp b/apps/opencs/view/world/recordbuttonbar.hpp new file mode 100644 index 000000000..28e59407f --- /dev/null +++ b/apps/opencs/view/world/recordbuttonbar.hpp @@ -0,0 +1,54 @@ +#ifndef CSV_WORLD_RECORDBUTTONBAR_H +#define CSV_WORLD_RECORDBUTTONBAR_H + +#include + +namespace CSMWorld +{ + class IdTable; + class CommandDispatcher; +} + +namespace CSVWorld +{ + class TableBottomBox; + + /// \brief Button bar for use in dialogue-type subviews + /// + /// Contains the following buttons: + /// - next/prev + /// - clone + /// - add + /// - delete + /// - revert + /// - preview (optional) + /// - view (optional) + class RecordButtonBar : public QWidget + { + Q_OBJECT + + CSMWorld::IdTable& mTable; + TableBottomBox *mBottom; + CSMWorld::CommandDispatcher *mCommandDispatcher; + + public: + + RecordButtonBar (CSMWorld::IdTable& table, TableBottomBox *bottomBox = 0, + CSMWorld::CommandDispatcher *commandDispatcher = 0, QWidget *parent = 0); + + signals: + + void showPreview(); + + void viewRecord(); + + void nextId(); + + void prevId(); + + void cloneRequest(); + + }; +} + +#endif From 7f1129df3b22334f6531d82f9dee95f26bb860e3 Mon Sep 17 00:00:00 2001 From: Marc Zinnschlag Date: Sat, 27 Jun 2015 12:53:46 +0200 Subject: [PATCH 38/45] cleaned up DialogueSubView constructor; moved bottom box below button bar --- apps/opencs/view/world/dialoguesubview.cpp | 26 +++++++++++++--------- 1 file changed, 15 insertions(+), 11 deletions(-) diff --git a/apps/opencs/view/world/dialoguesubview.cpp b/apps/opencs/view/world/dialoguesubview.cpp index a2f25df44..5669d9680 100644 --- a/apps/opencs/view/world/dialoguesubview.cpp +++ b/apps/opencs/view/world/dialoguesubview.cpp @@ -706,23 +706,27 @@ CSVWorld::DialogueSubView::DialogueSubView (const CSMWorld::UniversalId& id, : SimpleDialogueSubView (id, document) { // bottom box - getMainLayout().addWidget (mBottom = new TableBottomBox (creatorFactory, document, id, this)); + mBottom = new TableBottomBox (creatorFactory, document, id, this); - mBottom->setSizePolicy(QSizePolicy::Ignored, QSizePolicy::Fixed); + mBottom->setSizePolicy (QSizePolicy::Ignored, QSizePolicy::Fixed); - connect(mBottom, SIGNAL(requestFocus(const std::string&)), this, SLOT(requestFocus(const std::string&))); + connect (mBottom, SIGNAL (requestFocus (const std::string&)), + this, SLOT (requestFocus (const std::string&))); - // buttons + // button bar RecordButtonBar *buttons = new RecordButtonBar (getTable(), mBottom, &getCommandDispatcher(), this); - - getMainLayout().addWidget (buttons); - connect (buttons, SIGNAL(nextId()), this, SLOT(nextId())); - connect (buttons, SIGNAL (prevId()), this, SLOT(prevId())); - connect (buttons, SIGNAL (cloneRequest()), this, SLOT(cloneRequest())); - connect (buttons, SIGNAL (showPreview()), this, SLOT(showPreview())); - connect (buttons, SIGNAL (viewRecord()), this, SLOT(viewRecord())); + // layout + getMainLayout().addWidget (buttons); + getMainLayout().addWidget (mBottom); + + // connections + connect (buttons, SIGNAL (nextId()), this, SLOT (nextId())); + connect (buttons, SIGNAL (prevId()), this, SLOT (prevId())); + connect (buttons, SIGNAL (cloneRequest()), this, SLOT (cloneRequest())); + connect (buttons, SIGNAL (showPreview()), this, SLOT (showPreview())); + connect (buttons, SIGNAL (viewRecord()), this, SLOT (viewRecord())); } void CSVWorld::DialogueSubView::cloneRequest() From 67694793586200ec9b2ff48ceacccdeda65d89ee Mon Sep 17 00:00:00 2001 From: Marc Zinnschlag Date: Sat, 27 Jun 2015 13:47:07 +0200 Subject: [PATCH 39/45] moved code for initiating record cloning from DialogueSubView to RecordButtonBar --- apps/opencs/view/doc/subview.cpp | 1 + apps/opencs/view/doc/subview.hpp | 2 ++ apps/opencs/view/world/dialoguesubview.cpp | 12 +++------ apps/opencs/view/world/dialoguesubview.hpp | 2 -- apps/opencs/view/world/recordbuttonbar.cpp | 30 +++++++++++++++++++--- apps/opencs/view/world/recordbuttonbar.hpp | 17 +++++++++--- 6 files changed, 46 insertions(+), 18 deletions(-) diff --git a/apps/opencs/view/doc/subview.cpp b/apps/opencs/view/doc/subview.cpp index f4f0c6afe..e0c2fbc46 100644 --- a/apps/opencs/view/doc/subview.cpp +++ b/apps/opencs/view/doc/subview.cpp @@ -45,6 +45,7 @@ void CSVDoc::SubView::setUniversalId (const CSMWorld::UniversalId& id) { mUniversalId = id; setWindowTitle (QString::fromUtf8(mUniversalId.toString().c_str())); + emit universalIdChanged (mUniversalId); } void CSVDoc::SubView::closeEvent (QCloseEvent *event) diff --git a/apps/opencs/view/doc/subview.hpp b/apps/opencs/view/doc/subview.hpp index b323f9ed9..189bb40eb 100644 --- a/apps/opencs/view/doc/subview.hpp +++ b/apps/opencs/view/doc/subview.hpp @@ -68,6 +68,8 @@ namespace CSVDoc void updateSubViewIndicies (SubView *view = 0); + void universalIdChanged (const CSMWorld::UniversalId& universalId); + protected slots: void closeRequest(); diff --git a/apps/opencs/view/world/dialoguesubview.cpp b/apps/opencs/view/world/dialoguesubview.cpp index 5669d9680..92b9807e8 100644 --- a/apps/opencs/view/world/dialoguesubview.cpp +++ b/apps/opencs/view/world/dialoguesubview.cpp @@ -714,7 +714,7 @@ CSVWorld::DialogueSubView::DialogueSubView (const CSMWorld::UniversalId& id, this, SLOT (requestFocus (const std::string&))); // button bar - RecordButtonBar *buttons = new RecordButtonBar (getTable(), mBottom, + RecordButtonBar *buttons = new RecordButtonBar (id, getTable(), mBottom, &getCommandDispatcher(), this); // layout @@ -724,16 +724,10 @@ CSVWorld::DialogueSubView::DialogueSubView (const CSMWorld::UniversalId& id, // connections connect (buttons, SIGNAL (nextId()), this, SLOT (nextId())); connect (buttons, SIGNAL (prevId()), this, SLOT (prevId())); - connect (buttons, SIGNAL (cloneRequest()), this, SLOT (cloneRequest())); connect (buttons, SIGNAL (showPreview()), this, SLOT (showPreview())); connect (buttons, SIGNAL (viewRecord()), this, SLOT (viewRecord())); -} - -void CSVWorld::DialogueSubView::cloneRequest() -{ - mBottom->cloneRequest (getCurrentId(), - static_cast (getTable(). - data (getTable().getModelIndex(getCurrentId(), 2)).toInt())); + connect (this, SIGNAL (universalIdChanged (const CSMWorld::UniversalId&)), + buttons, SLOT (universalIdChanged (const CSMWorld::UniversalId&))); } void CSVWorld::DialogueSubView::prevId() diff --git a/apps/opencs/view/world/dialoguesubview.hpp b/apps/opencs/view/world/dialoguesubview.hpp index 5d6915d42..6c0fcc59b 100644 --- a/apps/opencs/view/world/dialoguesubview.hpp +++ b/apps/opencs/view/world/dialoguesubview.hpp @@ -231,8 +231,6 @@ namespace CSVWorld private slots: - void cloneRequest(); - void nextId(); void prevId(); diff --git a/apps/opencs/view/world/recordbuttonbar.cpp b/apps/opencs/view/world/recordbuttonbar.cpp index 2f5395317..1560a31a5 100644 --- a/apps/opencs/view/world/recordbuttonbar.cpp +++ b/apps/opencs/view/world/recordbuttonbar.cpp @@ -9,9 +9,11 @@ #include "../world/tablebottombox.hpp" -CSVWorld::RecordButtonBar::RecordButtonBar (CSMWorld::IdTable& table, TableBottomBox *bottomBox, +CSVWorld::RecordButtonBar::RecordButtonBar (const CSMWorld::UniversalId& id, + CSMWorld::IdTable& table, TableBottomBox *bottomBox, CSMWorld::CommandDispatcher *commandDispatcher, QWidget *parent) -: QWidget (parent), mTable (table), mBottom (bottomBox), mCommandDispatcher (commandDispatcher) +: QWidget (parent), mId (id), mTable (table), mBottom (bottomBox), + mCommandDispatcher (commandDispatcher) { QHBoxLayout *buttonsLayout = new QHBoxLayout; buttonsLayout->setContentsMargins (0, 0, 0, 0); @@ -81,7 +83,7 @@ CSVWorld::RecordButtonBar::RecordButtonBar (CSMWorld::IdTable& table, TableBotto else { connect (addButton, SIGNAL (clicked()), mBottom, SLOT (createRequest())); - connect (cloneButton, SIGNAL (clicked()), this, SIGNAL (cloneRequest())); + connect (cloneButton, SIGNAL (clicked()), this, SLOT (cloneRequest())); } connect (nextButton, SIGNAL (clicked()), this, SIGNAL (nextId())); @@ -98,3 +100,25 @@ CSVWorld::RecordButtonBar::RecordButtonBar (CSMWorld::IdTable& table, TableBotto connect (deleteButton, SIGNAL (clicked()), mCommandDispatcher, SLOT (executeDelete())); } } + +void CSVWorld::RecordButtonBar::universalIdChanged (const CSMWorld::UniversalId& id) +{ + mId = id; +} + +void CSVWorld::RecordButtonBar::cloneRequest() +{ + if (mBottom) + { + int typeColumn = mTable.searchColumnIndex (CSMWorld::Columns::ColumnId_RecordType); + + if (typeColumn!=-1) + { + QModelIndex typeIndex = mTable.getModelIndex (mId.getId(), typeColumn); + CSMWorld::UniversalId::Type type = static_cast ( + mTable.data (typeIndex).toInt()); + + mBottom->cloneRequest (mId.getId(), type); + } + } +} diff --git a/apps/opencs/view/world/recordbuttonbar.hpp b/apps/opencs/view/world/recordbuttonbar.hpp index 28e59407f..08f16a687 100644 --- a/apps/opencs/view/world/recordbuttonbar.hpp +++ b/apps/opencs/view/world/recordbuttonbar.hpp @@ -3,6 +3,8 @@ #include +#include "../../model/world/universalid.hpp" + namespace CSMWorld { class IdTable; @@ -27,15 +29,25 @@ namespace CSVWorld { Q_OBJECT + CSMWorld::UniversalId mId; CSMWorld::IdTable& mTable; TableBottomBox *mBottom; CSMWorld::CommandDispatcher *mCommandDispatcher; public: - RecordButtonBar (CSMWorld::IdTable& table, TableBottomBox *bottomBox = 0, + RecordButtonBar (const CSMWorld::UniversalId& id, + CSMWorld::IdTable& table, TableBottomBox *bottomBox = 0, CSMWorld::CommandDispatcher *commandDispatcher = 0, QWidget *parent = 0); + public slots: + + void universalIdChanged (const CSMWorld::UniversalId& id); + + private slots: + + void cloneRequest(); + signals: void showPreview(); @@ -45,9 +57,6 @@ namespace CSVWorld void nextId(); void prevId(); - - void cloneRequest(); - }; } From d5e6d8a58bf666518cb21e7508e8f28b335effd4 Mon Sep 17 00:00:00 2001 From: Marc Zinnschlag Date: Sat, 27 Jun 2015 14:25:48 +0200 Subject: [PATCH 40/45] disable dialogue subview buttons while document is locked --- apps/opencs/view/world/dialoguesubview.cpp | 20 ++++-- apps/opencs/view/world/dialoguesubview.hpp | 5 ++ apps/opencs/view/world/recordbuttonbar.cpp | 81 ++++++++++++---------- apps/opencs/view/world/recordbuttonbar.hpp | 13 ++++ 4 files changed, 77 insertions(+), 42 deletions(-) diff --git a/apps/opencs/view/world/dialoguesubview.cpp b/apps/opencs/view/world/dialoguesubview.cpp index 92b9807e8..ffb606497 100644 --- a/apps/opencs/view/world/dialoguesubview.cpp +++ b/apps/opencs/view/world/dialoguesubview.cpp @@ -714,20 +714,26 @@ CSVWorld::DialogueSubView::DialogueSubView (const CSMWorld::UniversalId& id, this, SLOT (requestFocus (const std::string&))); // button bar - RecordButtonBar *buttons = new RecordButtonBar (id, getTable(), mBottom, + mButtons = new RecordButtonBar (id, getTable(), mBottom, &getCommandDispatcher(), this); // layout - getMainLayout().addWidget (buttons); + getMainLayout().addWidget (mButtons); getMainLayout().addWidget (mBottom); // connections - connect (buttons, SIGNAL (nextId()), this, SLOT (nextId())); - connect (buttons, SIGNAL (prevId()), this, SLOT (prevId())); - connect (buttons, SIGNAL (showPreview()), this, SLOT (showPreview())); - connect (buttons, SIGNAL (viewRecord()), this, SLOT (viewRecord())); + connect (mButtons, SIGNAL (nextId()), this, SLOT (nextId())); + connect (mButtons, SIGNAL (prevId()), this, SLOT (prevId())); + connect (mButtons, SIGNAL (showPreview()), this, SLOT (showPreview())); + connect (mButtons, SIGNAL (viewRecord()), this, SLOT (viewRecord())); connect (this, SIGNAL (universalIdChanged (const CSMWorld::UniversalId&)), - buttons, SLOT (universalIdChanged (const CSMWorld::UniversalId&))); + mButtons, SLOT (universalIdChanged (const CSMWorld::UniversalId&))); +} + +void CSVWorld::DialogueSubView::setEditLock (bool locked) +{ + SimpleDialogueSubView::setEditLock (locked); + mButtons->setEditLock (locked); } void CSVWorld::DialogueSubView::prevId() diff --git a/apps/opencs/view/world/dialoguesubview.hpp b/apps/opencs/view/world/dialoguesubview.hpp index 6c0fcc59b..63b25d06e 100644 --- a/apps/opencs/view/world/dialoguesubview.hpp +++ b/apps/opencs/view/world/dialoguesubview.hpp @@ -218,17 +218,22 @@ namespace CSVWorld void rowsAboutToBeRemoved(const QModelIndex &parent, int start, int end); }; + class RecordButtonBar; + class DialogueSubView : public SimpleDialogueSubView { Q_OBJECT TableBottomBox* mBottom; + RecordButtonBar *mButtons; public: DialogueSubView (const CSMWorld::UniversalId& id, CSMDoc::Document& document, const CreatorFactoryBase& creatorFactory, bool sorting = false); + virtual void setEditLock (bool locked); + private slots: void nextId(); diff --git a/apps/opencs/view/world/recordbuttonbar.cpp b/apps/opencs/view/world/recordbuttonbar.cpp index 1560a31a5..93a6a5823 100644 --- a/apps/opencs/view/world/recordbuttonbar.cpp +++ b/apps/opencs/view/world/recordbuttonbar.cpp @@ -9,11 +9,25 @@ #include "../world/tablebottombox.hpp" +void CSVWorld::RecordButtonBar::updateModificationButtons() +{ + bool createAndDeleteDisabled = !mBottom || !mBottom->canCreateAndDelete() || mLocked; + + mCloneButton->setDisabled (createAndDeleteDisabled); + mAddButton->setDisabled (createAndDeleteDisabled); + mDeleteButton->setDisabled (createAndDeleteDisabled); + + bool commandDisabled = !mCommandDispatcher || mLocked; + + mRevertButton->setDisabled (commandDisabled); + mDeleteButton->setDisabled (commandDisabled); +} + CSVWorld::RecordButtonBar::RecordButtonBar (const CSMWorld::UniversalId& id, CSMWorld::IdTable& table, TableBottomBox *bottomBox, CSMWorld::CommandDispatcher *commandDispatcher, QWidget *parent) : QWidget (parent), mId (id), mTable (table), mBottom (bottomBox), - mCommandDispatcher (commandDispatcher) + mCommandDispatcher (commandDispatcher), mLocked (false) { QHBoxLayout *buttonsLayout = new QHBoxLayout; buttonsLayout->setContentsMargins (0, 0, 0, 0); @@ -51,54 +65,51 @@ CSVWorld::RecordButtonBar::RecordButtonBar (const CSMWorld::UniversalId& id, } // right section - QToolButton* cloneButton = new QToolButton (this); - cloneButton->setIcon(QIcon(":/edit-clone.png")); - cloneButton->setToolTip ("Clone record"); - buttonsLayout->addWidget(cloneButton); + mCloneButton = new QToolButton (this); + mCloneButton->setIcon(QIcon(":/edit-clone.png")); + mCloneButton->setToolTip ("Clone record"); + buttonsLayout->addWidget(mCloneButton); - QToolButton* addButton = new QToolButton (this); - addButton->setIcon(QIcon(":/add.png")); - addButton->setToolTip ("Add new record"); - buttonsLayout->addWidget(addButton); + mAddButton = new QToolButton (this); + mAddButton->setIcon(QIcon(":/add.png")); + mAddButton->setToolTip ("Add new record"); + buttonsLayout->addWidget(mAddButton); - QToolButton* deleteButton = new QToolButton (this); - deleteButton->setIcon(QIcon(":/edit-delete.png")); - deleteButton->setToolTip ("Delete record"); - buttonsLayout->addWidget(deleteButton); + mDeleteButton = new QToolButton (this); + mDeleteButton->setIcon(QIcon(":/edit-delete.png")); + mDeleteButton->setToolTip ("Delete record"); + buttonsLayout->addWidget(mDeleteButton); - QToolButton* revertButton = new QToolButton (this); - revertButton->setIcon(QIcon(":/edit-undo.png")); - revertButton->setToolTip ("Revert record"); - buttonsLayout->addWidget(revertButton); + mRevertButton = new QToolButton (this); + mRevertButton->setIcon(QIcon(":/edit-undo.png")); + mRevertButton->setToolTip ("Revert record"); + buttonsLayout->addWidget(mRevertButton); setLayout (buttonsLayout); - // disabling and connections - if(!mBottom || !mBottom->canCreateAndDelete()) - { - cloneButton->setDisabled (true); - addButton->setDisabled (true); - deleteButton->setDisabled (true); - } - else + // connections + if(mBottom && mBottom->canCreateAndDelete()) { - connect (addButton, SIGNAL (clicked()), mBottom, SLOT (createRequest())); - connect (cloneButton, SIGNAL (clicked()), this, SLOT (cloneRequest())); + connect (mAddButton, SIGNAL (clicked()), mBottom, SLOT (createRequest())); + connect (mCloneButton, SIGNAL (clicked()), this, SLOT (cloneRequest())); } connect (nextButton, SIGNAL (clicked()), this, SIGNAL (nextId())); connect (prevButton, SIGNAL (clicked()), this, SIGNAL (prevId())); - if (!mCommandDispatcher) - { - revertButton->setDisabled (true); - deleteButton->setDisabled (true); - } - else + if (mCommandDispatcher) { - connect (revertButton, SIGNAL (clicked()), mCommandDispatcher, SLOT (executeRevert())); - connect (deleteButton, SIGNAL (clicked()), mCommandDispatcher, SLOT (executeDelete())); + connect (mRevertButton, SIGNAL (clicked()), mCommandDispatcher, SLOT (executeRevert())); + connect (mDeleteButton, SIGNAL (clicked()), mCommandDispatcher, SLOT (executeDelete())); } + + updateModificationButtons(); +} + +void CSVWorld::RecordButtonBar::setEditLock (bool locked) +{ + mLocked = locked; + updateModificationButtons(); } void CSVWorld::RecordButtonBar::universalIdChanged (const CSMWorld::UniversalId& id) diff --git a/apps/opencs/view/world/recordbuttonbar.hpp b/apps/opencs/view/world/recordbuttonbar.hpp index 08f16a687..95b567594 100644 --- a/apps/opencs/view/world/recordbuttonbar.hpp +++ b/apps/opencs/view/world/recordbuttonbar.hpp @@ -5,6 +5,8 @@ #include "../../model/world/universalid.hpp" +class QToolButton; + namespace CSMWorld { class IdTable; @@ -33,13 +35,24 @@ namespace CSVWorld CSMWorld::IdTable& mTable; TableBottomBox *mBottom; CSMWorld::CommandDispatcher *mCommandDispatcher; + QToolButton *mCloneButton; + QToolButton *mAddButton; + QToolButton *mDeleteButton; + QToolButton *mRevertButton; + bool mLocked; + + private: + void updateModificationButtons(); + public: RecordButtonBar (const CSMWorld::UniversalId& id, CSMWorld::IdTable& table, TableBottomBox *bottomBox = 0, CSMWorld::CommandDispatcher *commandDispatcher = 0, QWidget *parent = 0); + void setEditLock (bool locked); + public slots: void universalIdChanged (const CSMWorld::UniversalId& id); From a8c26ec0c11a5252de2e75fd26d9d83ef1afc13e Mon Sep 17 00:00:00 2001 From: Marc Zinnschlag Date: Sat, 27 Jun 2015 14:42:22 +0200 Subject: [PATCH 41/45] moved most of the code for next/prev buttons from DialogueSubView to RecordBUttonBar --- apps/opencs/view/world/dialoguesubview.cpp | 88 ++++------------------ apps/opencs/view/world/dialoguesubview.hpp | 6 +- apps/opencs/view/world/recordbuttonbar.cpp | 28 ++++++- apps/opencs/view/world/recordbuttonbar.hpp | 8 +- 4 files changed, 47 insertions(+), 83 deletions(-) diff --git a/apps/opencs/view/world/dialoguesubview.cpp b/apps/opencs/view/world/dialoguesubview.cpp index ffb606497..cf9d69f02 100644 --- a/apps/opencs/view/world/dialoguesubview.cpp +++ b/apps/opencs/view/world/dialoguesubview.cpp @@ -722,10 +722,10 @@ CSVWorld::DialogueSubView::DialogueSubView (const CSMWorld::UniversalId& id, getMainLayout().addWidget (mBottom); // connections - connect (mButtons, SIGNAL (nextId()), this, SLOT (nextId())); - connect (mButtons, SIGNAL (prevId()), this, SLOT (prevId())); connect (mButtons, SIGNAL (showPreview()), this, SLOT (showPreview())); connect (mButtons, SIGNAL (viewRecord()), this, SLOT (viewRecord())); + connect (mButtons, SIGNAL (switchToRow (int)), this, SLOT (switchToRow (int))); + connect (this, SIGNAL (universalIdChanged (const CSMWorld::UniversalId&)), mButtons, SLOT (universalIdChanged (const CSMWorld::UniversalId&))); } @@ -736,78 +736,6 @@ void CSVWorld::DialogueSubView::setEditLock (bool locked) mButtons->setEditLock (locked); } -void CSVWorld::DialogueSubView::prevId() -{ - int newRow = getTable().getModelIndex (getCurrentId(), 0).row() - 1; - - if (newRow < 0) - { - return; - } - while (newRow >= 0) - { - QModelIndex newIndex (getTable().index(newRow, 0)); - - if (!newIndex.isValid()) - { - return; - } - - CSMWorld::RecordBase::State state = static_cast (getTable().data (getTable().index (newRow, 1)).toInt()); - if (!(state == CSMWorld::RecordBase::State_Deleted || state == CSMWorld::RecordBase::State_Erased)) - { - getEditWidget().remake (newRow); - - setUniversalId(CSMWorld::UniversalId (static_cast (getTable().data (getTable().index (newRow, 2)).toInt()), - getTable().data (getTable().index (newRow, 0)).toString().toUtf8().constData())); - - changeCurrentId(std::string (getTable().data (getTable().index (newRow, 0)).toString().toUtf8().constData())); - - getEditWidget().setDisabled (isLocked()); - - return; - } - --newRow; - } -} - -void CSVWorld::DialogueSubView::nextId () -{ - int newRow = getTable().getModelIndex (getCurrentId(), 0).row() + 1; - - if (newRow >= getTable().rowCount()) - { - return; - } - - while (newRow < getTable().rowCount()) - { - QModelIndex newIndex (getTable().index(newRow, 0)); - - if (!newIndex.isValid()) - { - return; - } - - CSMWorld::RecordBase::State state = static_cast (getTable().data (getTable().index (newRow, 1)).toInt()); - if (!(state == CSMWorld::RecordBase::State_Deleted)) - { - getEditWidget().remake(newRow); - - setUniversalId(CSMWorld::UniversalId (static_cast (getTable().data (getTable().index (newRow, 2)).toInt()), - getTable().data (getTable().index (newRow, 0)).toString().toUtf8().constData())); - - changeCurrentId(std::string (getTable().data (getTable().index (newRow, 0)).toString().toUtf8().constData())); - - getEditWidget().setDisabled (isLocked()); - - return; - } - ++newRow; - } -} - - void CSVWorld::DialogueSubView::showPreview () { QModelIndex currentIndex (getTable().getModelIndex (getCurrentId(), 0)); @@ -833,3 +761,15 @@ void CSVWorld::DialogueSubView::viewRecord () emit focusId (params.first, params.second); } } + +void CSVWorld::DialogueSubView::switchToRow (int row) +{ + getEditWidget().remake (row); + + setUniversalId (CSMWorld::UniversalId (static_cast (getTable().data (getTable().index (row, 2)).toInt()), + getTable().data (getTable().index (row, 0)).toString().toUtf8().constData())); + + changeCurrentId(std::string (getTable().data (getTable().index (row, 0)).toString().toUtf8().constData())); + + getEditWidget().setDisabled (isLocked()); +} diff --git a/apps/opencs/view/world/dialoguesubview.hpp b/apps/opencs/view/world/dialoguesubview.hpp index 63b25d06e..ff70a37d3 100644 --- a/apps/opencs/view/world/dialoguesubview.hpp +++ b/apps/opencs/view/world/dialoguesubview.hpp @@ -236,13 +236,11 @@ namespace CSVWorld private slots: - void nextId(); - - void prevId(); - void showPreview(); void viewRecord(); + + void switchToRow (int row); }; } diff --git a/apps/opencs/view/world/recordbuttonbar.cpp b/apps/opencs/view/world/recordbuttonbar.cpp index 93a6a5823..375ab68c3 100644 --- a/apps/opencs/view/world/recordbuttonbar.cpp +++ b/apps/opencs/view/world/recordbuttonbar.cpp @@ -94,8 +94,8 @@ CSVWorld::RecordButtonBar::RecordButtonBar (const CSMWorld::UniversalId& id, connect (mCloneButton, SIGNAL (clicked()), this, SLOT (cloneRequest())); } - connect (nextButton, SIGNAL (clicked()), this, SIGNAL (nextId())); - connect (prevButton, SIGNAL (clicked()), this, SIGNAL (prevId())); + connect (nextButton, SIGNAL (clicked()), this, SLOT (nextId())); + connect (prevButton, SIGNAL (clicked()), this, SLOT (prevId())); if (mCommandDispatcher) { @@ -133,3 +133,27 @@ void CSVWorld::RecordButtonBar::cloneRequest() } } } + +void CSVWorld::RecordButtonBar::nextId() +{ + int newRow = mTable.getModelIndex (mId.getId(), 0).row() + 1; + + if (newRow >= mTable.rowCount()) + { + return; + } + + emit switchToRow (newRow); +} + +void CSVWorld::RecordButtonBar::prevId() +{ + int newRow = mTable.getModelIndex (mId.getId(), 0).row() - 1; + + if (newRow < 0) + { + return; + } + + emit switchToRow (newRow); +} diff --git a/apps/opencs/view/world/recordbuttonbar.hpp b/apps/opencs/view/world/recordbuttonbar.hpp index 95b567594..6a5fadca5 100644 --- a/apps/opencs/view/world/recordbuttonbar.hpp +++ b/apps/opencs/view/world/recordbuttonbar.hpp @@ -60,6 +60,10 @@ namespace CSVWorld private slots: void cloneRequest(); + + void nextId(); + + void prevId(); signals: @@ -67,9 +71,7 @@ namespace CSVWorld void viewRecord(); - void nextId(); - - void prevId(); + void switchToRow (int row); }; } From 9aa153984aa0e5b8cfe347eadada6b1be262b0c4 Mon Sep 17 00:00:00 2001 From: Marc Zinnschlag Date: Sat, 27 Jun 2015 15:02:50 +0200 Subject: [PATCH 42/45] fixed inconsistent handling of deleted records in dialogue; general cleanup --- apps/opencs/view/world/dialoguesubview.cpp | 19 ++++++++++++++----- apps/opencs/view/world/recordbuttonbar.cpp | 17 +++++++---------- 2 files changed, 21 insertions(+), 15 deletions(-) diff --git a/apps/opencs/view/world/dialoguesubview.cpp b/apps/opencs/view/world/dialoguesubview.cpp index cf9d69f02..4ef06766c 100644 --- a/apps/opencs/view/world/dialoguesubview.cpp +++ b/apps/opencs/view/world/dialoguesubview.cpp @@ -764,12 +764,21 @@ void CSVWorld::DialogueSubView::viewRecord () void CSVWorld::DialogueSubView::switchToRow (int row) { - getEditWidget().remake (row); + int idColumn = getTable().findColumnIndex (CSMWorld::Columns::ColumnId_Id); + std::string id = getTable().data (getTable().index (row, idColumn)).toString().toUtf8().constData(); + + int typeColumn = getTable().findColumnIndex (CSMWorld::Columns::ColumnId_RecordType); + CSMWorld::UniversalId::Type type = static_cast ( + getTable().data (getTable().index (row, typeColumn)).toInt()); - setUniversalId (CSMWorld::UniversalId (static_cast (getTable().data (getTable().index (row, 2)).toInt()), - getTable().data (getTable().index (row, 0)).toString().toUtf8().constData())); + setUniversalId (CSMWorld::UniversalId (type, id)); + changeCurrentId (id); + + getEditWidget().remake (row); - changeCurrentId(std::string (getTable().data (getTable().index (row, 0)).toString().toUtf8().constData())); + int stateColumn = getTable().findColumnIndex (CSMWorld::Columns::ColumnId_Modification); + CSMWorld::RecordBase::State state = static_cast ( + getTable().data (getTable().index (row, stateColumn)).toInt()); - getEditWidget().setDisabled (isLocked()); + getEditWidget().setDisabled (isLocked() || state==CSMWorld::RecordBase::State_Deleted); } diff --git a/apps/opencs/view/world/recordbuttonbar.cpp b/apps/opencs/view/world/recordbuttonbar.cpp index 375ab68c3..db2320341 100644 --- a/apps/opencs/view/world/recordbuttonbar.cpp +++ b/apps/opencs/view/world/recordbuttonbar.cpp @@ -121,16 +121,13 @@ void CSVWorld::RecordButtonBar::cloneRequest() { if (mBottom) { - int typeColumn = mTable.searchColumnIndex (CSMWorld::Columns::ColumnId_RecordType); - - if (typeColumn!=-1) - { - QModelIndex typeIndex = mTable.getModelIndex (mId.getId(), typeColumn); - CSMWorld::UniversalId::Type type = static_cast ( - mTable.data (typeIndex).toInt()); - - mBottom->cloneRequest (mId.getId(), type); - } + int typeColumn = mTable.findColumnIndex (CSMWorld::Columns::ColumnId_RecordType); + + QModelIndex typeIndex = mTable.getModelIndex (mId.getId(), typeColumn); + CSMWorld::UniversalId::Type type = static_cast ( + mTable.data (typeIndex).toInt()); + + mBottom->cloneRequest (mId.getId(), type); } } From 95522fcad29cd72a58c16fa064b5bd9553689642 Mon Sep 17 00:00:00 2001 From: Marc Zinnschlag Date: Sat, 27 Jun 2015 15:29:54 +0200 Subject: [PATCH 43/45] more general cleanup --- apps/opencs/view/world/dialoguesubview.cpp | 51 +++++++++------------- apps/opencs/view/world/dialoguesubview.hpp | 24 +++++----- 2 files changed, 31 insertions(+), 44 deletions(-) diff --git a/apps/opencs/view/world/dialoguesubview.cpp b/apps/opencs/view/world/dialoguesubview.cpp index 4ef06766c..69255f821 100644 --- a/apps/opencs/view/world/dialoguesubview.cpp +++ b/apps/opencs/view/world/dialoguesubview.cpp @@ -17,8 +17,6 @@ #include #include #include -#include -#include #include #include @@ -573,11 +571,6 @@ CSMWorld::CommandDispatcher& CSVWorld::SimpleDialogueSubView::getCommandDispatch return mCommandDispatcher; } -std::string CSVWorld::SimpleDialogueSubView::getCurrentId() const -{ - return mCurrentId; -} - CSVWorld::EditWidget& CSVWorld::SimpleDialogueSubView::getEditWidget() { return *mEditWidget; @@ -593,7 +586,6 @@ CSVWorld::SimpleDialogueSubView::SimpleDialogueSubView (const CSMWorld::Universa mEditWidget(0), mMainLayout(NULL), mTable(dynamic_cast(document.getData().getTableModel(id))), - mUndoStack(document.getUndoStack()), mLocked(false), mDocument(document), mCommandDispatcher (document, CSMWorld::UniversalId::getParentType (id.getType())) @@ -601,7 +593,7 @@ CSVWorld::SimpleDialogueSubView::SimpleDialogueSubView (const CSMWorld::Universa connect(mTable, SIGNAL(dataChanged (const QModelIndex&, const QModelIndex&)), this, SLOT(dataChanged(const QModelIndex&))); connect(mTable, SIGNAL(rowsAboutToBeRemoved(const QModelIndex&, int, int)), this, SLOT(rowsAboutToBeRemoved(const QModelIndex&, int, int))); - changeCurrentId(id.getId()); + updateCurrentId(); QWidget *mainWidget = new QWidget(this); @@ -609,21 +601,21 @@ CSVWorld::SimpleDialogueSubView::SimpleDialogueSubView (const CSMWorld::Universa setWidget (mainWidget); mEditWidget = new EditWidget(mainWidget, - mTable->getModelIndex(mCurrentId, 0).row(), mTable, mCommandDispatcher, document, false); + mTable->getModelIndex(getUniversalId().getId(), 0).row(), mTable, mCommandDispatcher, document, false); mMainLayout->addWidget(mEditWidget); mEditWidget->setSizePolicy(QSizePolicy::MinimumExpanding, QSizePolicy::MinimumExpanding); - dataChanged(mTable->getModelIndex (mCurrentId, 0)); + dataChanged(mTable->getModelIndex (getUniversalId().getId(), 0)); } void CSVWorld::SimpleDialogueSubView::setEditLock (bool locked) { - if (!mEditWidget) // hack to indicate that mCurrentId is no longer valid + if (!mEditWidget) // hack to indicate that getUniversalId().getId() is no longer valid return; mLocked = locked; - QModelIndex currentIndex(mTable->getModelIndex(mCurrentId, 0)); + QModelIndex currentIndex(mTable->getModelIndex(getUniversalId().getId(), 0)); if (currentIndex.isValid()) { @@ -638,7 +630,7 @@ void CSVWorld::SimpleDialogueSubView::setEditLock (bool locked) void CSVWorld::SimpleDialogueSubView::dataChanged (const QModelIndex & index) { - QModelIndex currentIndex(mTable->getModelIndex(mCurrentId, 0)); + QModelIndex currentIndex(mTable->getModelIndex(getUniversalId().getId(), 0)); if (currentIndex.isValid() && (index.parent().isValid() ? index.parent().row() : index.row()) == currentIndex.row()) @@ -671,7 +663,7 @@ void CSVWorld::SimpleDialogueSubView::dataChanged (const QModelIndex & index) void CSVWorld::SimpleDialogueSubView::rowsAboutToBeRemoved(const QModelIndex &parent, int start, int end) { - QModelIndex currentIndex(mTable->getModelIndex(mCurrentId, 0)); + QModelIndex currentIndex(mTable->getModelIndex(getUniversalId().getId(), 0)); if (currentIndex.isValid() && currentIndex.row() >= start && currentIndex.row() <= end) { @@ -684,19 +676,10 @@ void CSVWorld::SimpleDialogueSubView::rowsAboutToBeRemoved(const QModelIndex &pa } } -void CSVWorld::SimpleDialogueSubView::requestFocus (const std::string& id) -{ - changeCurrentId(id); - - mEditWidget->remake(mTable->getModelIndex (id, 0).row()); -} - -void CSVWorld::SimpleDialogueSubView::changeCurrentId (const std::string& newId) +void CSVWorld::SimpleDialogueSubView::updateCurrentId() { std::vector selection; - mCurrentId = std::string(newId); - - selection.push_back(mCurrentId); + selection.push_back (getUniversalId().getId()); mCommandDispatcher.setSelection(selection); } @@ -738,19 +721,19 @@ void CSVWorld::DialogueSubView::setEditLock (bool locked) void CSVWorld::DialogueSubView::showPreview () { - QModelIndex currentIndex (getTable().getModelIndex (getCurrentId(), 0)); + QModelIndex currentIndex (getTable().getModelIndex (getUniversalId().getId(), 0)); if (currentIndex.isValid() && getTable().getFeatures() & CSMWorld::IdTable::Feature_Preview && currentIndex.row() < getTable().rowCount()) { - emit focusId(CSMWorld::UniversalId(CSMWorld::UniversalId::Type_Preview, getCurrentId()), ""); + emit focusId(CSMWorld::UniversalId(CSMWorld::UniversalId::Type_Preview, getUniversalId().getId()), ""); } } void CSVWorld::DialogueSubView::viewRecord () { - QModelIndex currentIndex (getTable().getModelIndex (getCurrentId(), 0)); + QModelIndex currentIndex (getTable().getModelIndex (getUniversalId().getId(), 0)); if (currentIndex.isValid() && currentIndex.row() < getTable().rowCount()) @@ -772,7 +755,7 @@ void CSVWorld::DialogueSubView::switchToRow (int row) getTable().data (getTable().index (row, typeColumn)).toInt()); setUniversalId (CSMWorld::UniversalId (type, id)); - changeCurrentId (id); + updateCurrentId(); getEditWidget().remake (row); @@ -782,3 +765,11 @@ void CSVWorld::DialogueSubView::switchToRow (int row) getEditWidget().setDisabled (isLocked() || state==CSMWorld::RecordBase::State_Deleted); } + +void CSVWorld::DialogueSubView::requestFocus (const std::string& id) +{ + QModelIndex index = getTable().getModelIndex (id, 0); + + if (index.isValid()) + switchToRow (index.row()); +} diff --git a/apps/opencs/view/world/dialoguesubview.hpp b/apps/opencs/view/world/dialoguesubview.hpp index ff70a37d3..aec98d69c 100644 --- a/apps/opencs/view/world/dialoguesubview.hpp +++ b/apps/opencs/view/world/dialoguesubview.hpp @@ -175,16 +175,14 @@ namespace CSVWorld class SimpleDialogueSubView : public CSVDoc::SubView { - Q_OBJECT + Q_OBJECT - EditWidget* mEditWidget; - QVBoxLayout* mMainLayout; - CSMWorld::IdTable* mTable; - QUndoStack& mUndoStack; - std::string mCurrentId; - bool mLocked; - const CSMDoc::Document& mDocument; - CSMWorld::CommandDispatcher mCommandDispatcher; + EditWidget* mEditWidget; + QVBoxLayout* mMainLayout; + CSMWorld::IdTable* mTable; + bool mLocked; + const CSMDoc::Document& mDocument; + CSMWorld::CommandDispatcher mCommandDispatcher; protected: @@ -194,11 +192,9 @@ namespace CSVWorld CSMWorld::CommandDispatcher& getCommandDispatcher(); - std::string getCurrentId() const; - EditWidget& getEditWidget(); - void changeCurrentId(const std::string& newCurrent); + void updateCurrentId(); bool isLocked() const; @@ -213,8 +209,6 @@ namespace CSVWorld void dataChanged(const QModelIndex & index); ///\brief we need to care for deleting currently edited record - void requestFocus (const std::string& id); - void rowsAboutToBeRemoved(const QModelIndex &parent, int start, int end); }; @@ -241,6 +235,8 @@ namespace CSVWorld void viewRecord(); void switchToRow (int row); + + void requestFocus (const std::string& id); }; } From e27a75bd103430a3b88190b4e63612706116ba24 Mon Sep 17 00:00:00 2001 From: Marc Zinnschlag Date: Sat, 27 Jun 2015 15:56:41 +0200 Subject: [PATCH 44/45] added user setting for cyclic prev/next --- apps/opencs/model/settings/usersettings.cpp | 8 ++++++++ apps/opencs/view/world/recordbuttonbar.cpp | 16 +++++++++++++--- 2 files changed, 21 insertions(+), 3 deletions(-) diff --git a/apps/opencs/model/settings/usersettings.cpp b/apps/opencs/model/settings/usersettings.cpp index 3e59d0582..bcf7c3ba9 100644 --- a/apps/opencs/model/settings/usersettings.cpp +++ b/apps/opencs/model/settings/usersettings.cpp @@ -356,6 +356,14 @@ void CSMSettings::UserSettings::buildSettingModelDefaults() formatId->setToolTip ("(Default: Blue) Use one of the following formats:" + tooltip); } + declareSection ("general-input", "General Input"); + { + Setting *cycle = createSetting (Type_CheckBox, "cycle", "Cyclic next/previous"); + cycle->setDefaultValue ("false"); + cycle->setToolTip ("When using next/previous functions at the last/first item of a " + "list go to the first/last item"); + } + { /****************************************************************** * There are three types of values: diff --git a/apps/opencs/view/world/recordbuttonbar.cpp b/apps/opencs/view/world/recordbuttonbar.cpp index db2320341..5dcc1d5cd 100644 --- a/apps/opencs/view/world/recordbuttonbar.cpp +++ b/apps/opencs/view/world/recordbuttonbar.cpp @@ -7,6 +7,8 @@ #include "../../model/world/idtable.hpp" #include "../../model/world/commanddispatcher.hpp" +#include "../../model/settings/usersettings.hpp" + #include "../world/tablebottombox.hpp" void CSVWorld::RecordButtonBar::updateModificationButtons() @@ -132,12 +134,16 @@ void CSVWorld::RecordButtonBar::cloneRequest() } void CSVWorld::RecordButtonBar::nextId() -{ +{ int newRow = mTable.getModelIndex (mId.getId(), 0).row() + 1; if (newRow >= mTable.rowCount()) { - return; + if (CSMSettings::UserSettings::instance().settingValue ("general-input/cycle") + =="true") + newRow = 0; + else + return; } emit switchToRow (newRow); @@ -149,7 +155,11 @@ void CSVWorld::RecordButtonBar::prevId() if (newRow < 0) { - return; + if (CSMSettings::UserSettings::instance().settingValue ("general-input/cycle") + =="true") + newRow = mTable.rowCount()-1; + else + return; } emit switchToRow (newRow); From 15bb2855a99d548b3f13aa799dc188dd0dab2b56 Mon Sep 17 00:00:00 2001 From: Marc Zinnschlag Date: Sat, 27 Jun 2015 16:57:45 +0200 Subject: [PATCH 45/45] disable prev/next buttons if there is no previous/next record --- apps/opencs/view/world/dialoguesubview.cpp | 6 +++ apps/opencs/view/world/dialoguesubview.hpp | 2 + apps/opencs/view/world/recordbuttonbar.cpp | 61 ++++++++++++++++++---- apps/opencs/view/world/recordbuttonbar.hpp | 11 +++- 4 files changed, 69 insertions(+), 11 deletions(-) diff --git a/apps/opencs/view/world/dialoguesubview.cpp b/apps/opencs/view/world/dialoguesubview.cpp index 69255f821..1d3eb5313 100644 --- a/apps/opencs/view/world/dialoguesubview.cpp +++ b/apps/opencs/view/world/dialoguesubview.cpp @@ -719,6 +719,12 @@ void CSVWorld::DialogueSubView::setEditLock (bool locked) mButtons->setEditLock (locked); } +void CSVWorld::DialogueSubView::updateUserSetting (const QString& name, const QStringList& value) +{ + SimpleDialogueSubView::updateUserSetting (name, value); + mButtons->updateUserSetting (name, value); +} + void CSVWorld::DialogueSubView::showPreview () { QModelIndex currentIndex (getTable().getModelIndex (getUniversalId().getId(), 0)); diff --git a/apps/opencs/view/world/dialoguesubview.hpp b/apps/opencs/view/world/dialoguesubview.hpp index aec98d69c..be58be5ad 100644 --- a/apps/opencs/view/world/dialoguesubview.hpp +++ b/apps/opencs/view/world/dialoguesubview.hpp @@ -228,6 +228,8 @@ namespace CSVWorld virtual void setEditLock (bool locked); + virtual void updateUserSetting (const QString& name, const QStringList& value); + private slots: void showPreview(); diff --git a/apps/opencs/view/world/recordbuttonbar.cpp b/apps/opencs/view/world/recordbuttonbar.cpp index 5dcc1d5cd..63c0dd0a1 100644 --- a/apps/opencs/view/world/recordbuttonbar.cpp +++ b/apps/opencs/view/world/recordbuttonbar.cpp @@ -25,6 +25,29 @@ void CSVWorld::RecordButtonBar::updateModificationButtons() mDeleteButton->setDisabled (commandDisabled); } +void CSVWorld::RecordButtonBar::updatePrevNextButtons() +{ + int rows = mTable.rowCount(); + + if (rows<=1) + { + mPrevButton->setDisabled (true); + mNextButton->setDisabled (true); + } + else if (CSMSettings::UserSettings::instance().settingValue ("general-input/cycle")=="true") + { + mPrevButton->setDisabled (false); + mNextButton->setDisabled (false); + } + else + { + int row = mTable.getModelIndex (mId.getId(), 0).row(); + + mPrevButton->setDisabled (row<=0); + mNextButton->setDisabled (row>=rows-1); + } +} + CSVWorld::RecordButtonBar::RecordButtonBar (const CSMWorld::UniversalId& id, CSMWorld::IdTable& table, TableBottomBox *bottomBox, CSMWorld::CommandDispatcher *commandDispatcher, QWidget *parent) @@ -35,15 +58,15 @@ CSVWorld::RecordButtonBar::RecordButtonBar (const CSMWorld::UniversalId& id, buttonsLayout->setContentsMargins (0, 0, 0, 0); // left section - QToolButton* prevButton = new QToolButton (this); - prevButton->setIcon(QIcon(":/go-previous.png")); - prevButton->setToolTip ("Switch to previous record"); - buttonsLayout->addWidget (prevButton, 0); + mPrevButton = new QToolButton (this); + mPrevButton->setIcon(QIcon(":/go-previous.png")); + mPrevButton->setToolTip ("Switch to previous record"); + buttonsLayout->addWidget (mPrevButton, 0); - QToolButton* nextButton = new QToolButton (this); - nextButton->setIcon(QIcon(":/go-next.png")); - nextButton->setToolTip ("Switch to next record"); - buttonsLayout->addWidget (nextButton, 1); + mNextButton = new QToolButton (this); + mNextButton->setIcon(QIcon(":/go-next.png")); + mNextButton->setToolTip ("Switch to next record"); + buttonsLayout->addWidget (mNextButton, 1); buttonsLayout->addStretch(2); @@ -96,8 +119,8 @@ CSVWorld::RecordButtonBar::RecordButtonBar (const CSMWorld::UniversalId& id, connect (mCloneButton, SIGNAL (clicked()), this, SLOT (cloneRequest())); } - connect (nextButton, SIGNAL (clicked()), this, SLOT (nextId())); - connect (prevButton, SIGNAL (clicked()), this, SLOT (prevId())); + connect (mNextButton, SIGNAL (clicked()), this, SLOT (nextId())); + connect (mPrevButton, SIGNAL (clicked()), this, SLOT (prevId())); if (mCommandDispatcher) { @@ -105,7 +128,13 @@ CSVWorld::RecordButtonBar::RecordButtonBar (const CSMWorld::UniversalId& id, connect (mDeleteButton, SIGNAL (clicked()), mCommandDispatcher, SLOT (executeDelete())); } + connect (&mTable, SIGNAL (rowsInserted (const QModelIndex&, int, int)), + this, SLOT (rowNumberChanged (const QModelIndex&, int, int))); + connect (&mTable, SIGNAL (rowsRemoved (const QModelIndex&, int, int)), + this, SLOT (rowNumberChanged (const QModelIndex&, int, int))); + updateModificationButtons(); + updatePrevNextButtons(); } void CSVWorld::RecordButtonBar::setEditLock (bool locked) @@ -114,9 +143,16 @@ void CSVWorld::RecordButtonBar::setEditLock (bool locked) updateModificationButtons(); } +void CSVWorld::RecordButtonBar::updateUserSetting (const QString& name, const QStringList& value) +{ + if (name=="general-input/cycle") + updatePrevNextButtons(); +} + void CSVWorld::RecordButtonBar::universalIdChanged (const CSMWorld::UniversalId& id) { mId = id; + updatePrevNextButtons(); } void CSVWorld::RecordButtonBar::cloneRequest() @@ -164,3 +200,8 @@ void CSVWorld::RecordButtonBar::prevId() emit switchToRow (newRow); } + +void CSVWorld::RecordButtonBar::rowNumberChanged (const QModelIndex& parent, int start, int end) +{ + updatePrevNextButtons(); +} diff --git a/apps/opencs/view/world/recordbuttonbar.hpp b/apps/opencs/view/world/recordbuttonbar.hpp index 6a5fadca5..93ca45518 100644 --- a/apps/opencs/view/world/recordbuttonbar.hpp +++ b/apps/opencs/view/world/recordbuttonbar.hpp @@ -6,6 +6,7 @@ #include "../../model/world/universalid.hpp" class QToolButton; +class QModelIndex; namespace CSMWorld { @@ -35,6 +36,8 @@ namespace CSVWorld CSMWorld::IdTable& mTable; TableBottomBox *mBottom; CSMWorld::CommandDispatcher *mCommandDispatcher; + QToolButton *mPrevButton; + QToolButton *mNextButton; QToolButton *mCloneButton; QToolButton *mAddButton; QToolButton *mDeleteButton; @@ -44,6 +47,8 @@ namespace CSVWorld private: void updateModificationButtons(); + + void updatePrevNextButtons(); public: @@ -52,7 +57,9 @@ namespace CSVWorld CSMWorld::CommandDispatcher *commandDispatcher = 0, QWidget *parent = 0); void setEditLock (bool locked); - + + void updateUserSetting (const QString& name, const QStringList& value); + public slots: void universalIdChanged (const CSMWorld::UniversalId& id); @@ -64,6 +71,8 @@ namespace CSVWorld void nextId(); void prevId(); + + void rowNumberChanged (const QModelIndex& parent, int start, int end); signals: