From a80e80dd940bdc855e0bd7a0b456af5e40c8a692 Mon Sep 17 00:00:00 2001 From: Marc Zinnschlag Date: Tue, 23 Jul 2013 21:59:02 +0200 Subject: [PATCH 01/23] added layout to table sub view --- apps/opencs/view/doc/subview.cpp | 5 ----- apps/opencs/view/world/tablesubview.cpp | 15 ++++++++++++++- 2 files changed, 14 insertions(+), 6 deletions(-) diff --git a/apps/opencs/view/doc/subview.cpp b/apps/opencs/view/doc/subview.cpp index 731adabb35..153700d321 100644 --- a/apps/opencs/view/doc/subview.cpp +++ b/apps/opencs/view/doc/subview.cpp @@ -1,15 +1,10 @@ #include "subview.hpp" - CSVDoc::SubView::SubView (const CSMWorld::UniversalId& id) : mUniversalId (id) { /// \todo add a button to the title bar that clones this sub view setWindowTitle (mUniversalId.toString().c_str()); - - /// \todo remove (for testing only) - setMinimumWidth (100); - setMinimumHeight (60); } CSMWorld::UniversalId CSVDoc::SubView::getUniversalId() const diff --git a/apps/opencs/view/world/tablesubview.cpp b/apps/opencs/view/world/tablesubview.cpp index 65cba4b02e..502dcc2928 100644 --- a/apps/opencs/view/world/tablesubview.cpp +++ b/apps/opencs/view/world/tablesubview.cpp @@ -1,6 +1,8 @@ #include "tablesubview.hpp" +#include + #include "../../model/doc/document.hpp" #include "table.hpp" @@ -9,7 +11,18 @@ CSVWorld::TableSubView::TableSubView (const CSMWorld::UniversalId& id, CSMDoc::D bool createAndDelete) : SubView (id) { - setWidget (mTable = new Table (id, document.getData(), document.getUndoStack(), createAndDelete)); + QVBoxLayout *layout = new QVBoxLayout; + + layout->setContentsMargins (QMargins (0, 0, 0, 0)); + + layout->addWidget ( + mTable = new Table (id, document.getData(), document.getUndoStack(), createAndDelete), 2); + + QWidget *widget = new QWidget; + + widget->setLayout (layout); + + setWidget (widget); connect (mTable, SIGNAL (editRequest (int)), this, SLOT (editRequest (int))); } From 55e7e71c1176c090f51abc633d070240f1ccc3bb Mon Sep 17 00:00:00 2001 From: Marc Zinnschlag Date: Thu, 25 Jul 2013 14:29:56 +0200 Subject: [PATCH 02/23] added optional per-subview status bar --- apps/opencs/CMakeLists.txt | 2 +- apps/opencs/view/doc/subview.cpp | 2 + apps/opencs/view/doc/subview.hpp | 3 + apps/opencs/view/doc/view.cpp | 17 ++++ apps/opencs/view/doc/view.hpp | 3 + apps/opencs/view/world/table.cpp | 48 ++++++++++ apps/opencs/view/world/table.hpp | 13 +++ apps/opencs/view/world/tablebottombox.cpp | 111 ++++++++++++++++++++++ apps/opencs/view/world/tablebottombox.hpp | 39 ++++++++ apps/opencs/view/world/tablesubview.cpp | 16 ++++ apps/opencs/view/world/tablesubview.hpp | 8 +- 11 files changed, 260 insertions(+), 2 deletions(-) create mode 100644 apps/opencs/view/world/tablebottombox.cpp create mode 100644 apps/opencs/view/world/tablebottombox.hpp diff --git a/apps/opencs/CMakeLists.txt b/apps/opencs/CMakeLists.txt index 66c446baef..d2568ce022 100644 --- a/apps/opencs/CMakeLists.txt +++ b/apps/opencs/CMakeLists.txt @@ -57,7 +57,7 @@ opencs_hdrs_noqt (view/doc opencs_units (view/world - table tablesubview scriptsubview util regionmapsubview + table tablesubview scriptsubview util regionmapsubview tablebottombox ) opencs_units_noqt (view/world diff --git a/apps/opencs/view/doc/subview.cpp b/apps/opencs/view/doc/subview.cpp index 153700d321..09361a1c03 100644 --- a/apps/opencs/view/doc/subview.cpp +++ b/apps/opencs/view/doc/subview.cpp @@ -15,3 +15,5 @@ CSMWorld::UniversalId CSVDoc::SubView::getUniversalId() const void CSVDoc::SubView::updateEditorSetting (const QString &settingName, const QString &settingValue) { } + +void CSVDoc::SubView::setStatusBar (bool show) {} \ No newline at end of file diff --git a/apps/opencs/view/doc/subview.hpp b/apps/opencs/view/doc/subview.hpp index 280a2a4879..aa073f81dd 100644 --- a/apps/opencs/view/doc/subview.hpp +++ b/apps/opencs/view/doc/subview.hpp @@ -37,6 +37,9 @@ namespace CSVDoc virtual void setEditLock (bool locked) = 0; virtual void updateEditorSetting (const QString &, const QString &); + virtual void setStatusBar (bool show); + ///< Default implementation: ignored + signals: void focusId (const CSMWorld::UniversalId& universalId); diff --git a/apps/opencs/view/doc/view.cpp b/apps/opencs/view/doc/view.cpp index 63fab56dbf..b3374c4a50 100644 --- a/apps/opencs/view/doc/view.cpp +++ b/apps/opencs/view/doc/view.cpp @@ -78,6 +78,11 @@ void CSVDoc::View::setupViewMenu() QAction *newWindow = new QAction (tr ("&New View"), this); connect (newWindow, SIGNAL (triggered()), this, SLOT (newView())); view->addAction (newWindow); + + mShowStatusBar = new QAction (tr ("Show Status Bar"), this); + mShowStatusBar->setCheckable (true); + connect (mShowStatusBar, SIGNAL (toggled (bool)), this, SLOT (toggleShowStatusBar (bool))); + view->addAction (mShowStatusBar); } void CSVDoc::View::setupWorldMenu() @@ -282,6 +287,9 @@ void CSVDoc::View::addSubView (const CSMWorld::UniversalId& id) /// \todo add an user setting to reuse sub views (on a per document basis or on a per top level view basis) SubView *view = mSubViewFactory.makeSubView (id, *mDocument); + + view->setStatusBar (mShowStatusBar->isChecked()); + mSubViewWindow.addDockWidget (Qt::TopDockWidgetArea, view); connect (view, SIGNAL (focusId (const CSMWorld::UniversalId&)), this, @@ -436,3 +444,12 @@ void CSVDoc::View::updateEditorSetting (const QString &settingName, const QStrin else if (settingName == "Height") resizeViewHeight (settingValue.toInt()); } + +void CSVDoc::View::toggleShowStatusBar (bool show) +{ + foreach (QObject *view, mSubViewWindow.children()) + { + if (CSVDoc::SubView *subView = dynamic_cast (view)) + subView->setStatusBar (show); + } +} diff --git a/apps/opencs/view/doc/view.hpp b/apps/opencs/view/doc/view.hpp index 4e6b216a1d..c0163ce615 100644 --- a/apps/opencs/view/doc/view.hpp +++ b/apps/opencs/view/doc/view.hpp @@ -38,6 +38,7 @@ namespace CSVDoc QAction *mRedo; QAction *mSave; QAction *mVerify; + QAction *mShowStatusBar; std::vector mEditingActions; Operations *mOperations; SubViewFactoryManager mSubViewFactory; @@ -158,6 +159,8 @@ namespace CSVDoc void addRegionMapSubView(); void showUserSettings(); + + void toggleShowStatusBar (bool show); }; } diff --git a/apps/opencs/view/world/table.cpp b/apps/opencs/view/world/table.cpp index 90ce42b345..9085592df6 100644 --- a/apps/opencs/view/world/table.cpp +++ b/apps/opencs/view/world/table.cpp @@ -44,6 +44,7 @@ void CSVWorld::Table::contextMenuEvent (QContextMenuEvent *event) std::vector CSVWorld::Table::listRevertableSelectedIds() const { + /// \todo columns filtering fixes QModelIndexList selectedRows = selectionModel()->selectedRows(); std::vector revertableIds; @@ -64,6 +65,7 @@ std::vector CSVWorld::Table::listRevertableSelectedIds() const std::vector CSVWorld::Table::listDeletableSelectedIds() const { + /// \todo columns filtering fixes QModelIndexList selectedRows = selectionModel()->selectedRows(); std::vector deletableIds; @@ -137,6 +139,17 @@ CSVWorld::Table::Table (const CSMWorld::UniversalId& id, CSMWorld::Data& data, Q mDeleteAction = new QAction (tr ("Delete Record"), this); connect (mDeleteAction, SIGNAL (triggered()), this, SLOT (deleteRecord())); addAction (mDeleteAction); + + connect (mProxyModel, SIGNAL (rowsInserted (const QModelIndex&, int, int)), + this, SLOT (tableSizeUpdate())); + + /// \note This signal could instead be connected to a slot that filters out changes not affecting + /// the records status column (for permanence reasons) + connect (mProxyModel, SIGNAL (dataChanged (const QModelIndex&, const QModelIndex&)), + this, SLOT (tableSizeUpdate())); + + connect (selectionModel(), SIGNAL (selectionChanged (const QItemSelection&, const QItemSelection&)), + this, SLOT (selectionSizeUpdate ())); } void CSVWorld::Table::setEditLock (bool locked) @@ -231,3 +244,38 @@ void CSVWorld::Table::updateEditorSetting (const QString &settingName, const QSt updateEditorSetting (settingName, settingValue)) emit dataChanged (mModel->index (0, i), mModel->index (mModel->rowCount()-1, i)); } + +void CSVWorld::Table::tableSizeUpdate() +{ + int size = 0; + int deleted = 0; + int modified = 0; + + if (mModel->columnCount()>0) + { + int rows = mModel->rowCount(); + + for (int i=0; imapToSource (mProxyModel->index (i, 0)); + + /// \todo Do not use hardcoded column numbers + int state = mModel->data (mModel->index (index.row(), 1)).toInt(); + + switch (state) + { + case CSMWorld::RecordBase::State_BaseOnly: ++size; break; + case CSMWorld::RecordBase::State_Modified: ++size; ++modified; break; + case CSMWorld::RecordBase::State_ModifiedOnly: ++size; ++modified; break; + case CSMWorld::RecordBase:: State_Deleted: ++deleted; ++modified; break; + } + } + } + + tableSizeChanged (size, deleted, modified); +} + +void CSVWorld::Table::selectionSizeUpdate() +{ + selectionSizeChanged (selectionModel()->selectedRows().size()); +} \ No newline at end of file diff --git a/apps/opencs/view/world/table.hpp b/apps/opencs/view/world/table.hpp index eedfeb8a1d..dd8e82ed71 100644 --- a/apps/opencs/view/world/table.hpp +++ b/apps/opencs/view/world/table.hpp @@ -60,6 +60,13 @@ namespace CSVWorld void editRequest (int row); + void selectionSizeChanged (int size); + + void tableSizeChanged (int size, int deleted, int modified); + ///< \param size Number of not deleted records + /// \param deleted Number of deleted records + /// \param modified Number of added and modified records + private slots: void createRecord(); @@ -69,6 +76,12 @@ namespace CSVWorld void deleteRecord(); void editRecord(); + + public slots: + + void tableSizeUpdate(); + + void selectionSizeUpdate(); }; } diff --git a/apps/opencs/view/world/tablebottombox.cpp b/apps/opencs/view/world/tablebottombox.cpp new file mode 100644 index 0000000000..c8ddb662c9 --- /dev/null +++ b/apps/opencs/view/world/tablebottombox.cpp @@ -0,0 +1,111 @@ + +#include "tablebottombox.hpp" + +#include + +#include +#include +#include + +void CSVWorld::TableBottomBox::updateStatus() +{ + if (mShowStatusBar) + { + static const char *sLabels[4] = { "record", "deleted", "touched", "selected" }; + static const char *sLabelsPlural[4] = { "records", "deleted", "touched", "selected" }; + + std::ostringstream stream; + + bool first = true; + + for (int i=0; i<4; ++i) + { + if (mStatusCount[i]>0) + { + if (first) + first = false; + else + stream << ", "; + + stream + << mStatusCount[i] << ' ' + << (mStatusCount[i]==1 ? sLabels[i] : sLabelsPlural[i]); + } + } + + mStatus->setText (QString::fromUtf8 (stream.str().c_str())); + } +} + +CSVWorld::TableBottomBox::TableBottomBox (QWidget *parent) +: QWidget (parent), mShowStatusBar (false) +{ + for (int i=0; i<4; ++i) + mStatusCount[i] = 0; + + setVisible (false); + + QStackedLayout *layout = new QStackedLayout; + + mStatus = new QLabel; + + QStatusBar *statusBar = new QStatusBar; + + statusBar->addWidget (mStatus); + + layout->addWidget (statusBar); + + QStatusBar *statusBar2 = new QStatusBar; + + layout->addWidget (statusBar2); + + setLayout (layout); +} + +void CSVWorld::TableBottomBox::setStatusBar (bool show) +{ + if (show!=mShowStatusBar) + { + setVisible (show); + + mShowStatusBar = show; + + if (show) + updateStatus(); + } +} + +void CSVWorld::TableBottomBox::selectionSizeChanged (int size) +{ + if (mStatusCount[3]!=size) + { + mStatusCount[3] = size; + updateStatus(); + } +} + +void CSVWorld::TableBottomBox::tableSizeChanged (int size, int deleted, int modified) +{ + bool changed = false; + + if (mStatusCount[0]!=size) + { + mStatusCount[0] = size; + changed = true; + } + + if (mStatusCount[1]!=deleted) + { + mStatusCount[1] = deleted; + changed = true; + } + + if (mStatusCount[2]!=modified) + { + mStatusCount[2] = modified; + changed = true; + } + + if (changed) + updateStatus(); +} \ No newline at end of file diff --git a/apps/opencs/view/world/tablebottombox.hpp b/apps/opencs/view/world/tablebottombox.hpp new file mode 100644 index 0000000000..2663da8555 --- /dev/null +++ b/apps/opencs/view/world/tablebottombox.hpp @@ -0,0 +1,39 @@ +#ifndef CSV_WORLD_BOTTOMBOX_H +#define CSV_WORLD_BOTTOMBOX_H + +#include + +class QLabel; + +namespace CSVWorld +{ + class TableBottomBox : public QWidget + { + Q_OBJECT + + bool mShowStatusBar; + QLabel *mStatus; + int mStatusCount[4]; + + private: + + void updateStatus(); + + public: + + TableBottomBox (QWidget *parent = 0); + + void setStatusBar (bool show); + + public slots: + + void selectionSizeChanged (int size); + + void tableSizeChanged (int size, int deleted, int modified); + ///< \param size Number of not deleted records + /// \param deleted Number of deleted records + /// \param modified Number of added and modified records + }; +} + +#endif diff --git a/apps/opencs/view/world/tablesubview.cpp b/apps/opencs/view/world/tablesubview.cpp index 502dcc2928..7f9c671c09 100644 --- a/apps/opencs/view/world/tablesubview.cpp +++ b/apps/opencs/view/world/tablesubview.cpp @@ -6,6 +6,7 @@ #include "../../model/doc/document.hpp" #include "table.hpp" +#include "tablebottombox.hpp" CSVWorld::TableSubView::TableSubView (const CSMWorld::UniversalId& id, CSMDoc::Document& document, bool createAndDelete) @@ -18,6 +19,8 @@ CSVWorld::TableSubView::TableSubView (const CSMWorld::UniversalId& id, CSMDoc::D layout->addWidget ( mTable = new Table (id, document.getData(), document.getUndoStack(), createAndDelete), 2); + layout->addWidget (mBottom = new TableBottomBox (this), 0); + QWidget *widget = new QWidget; widget->setLayout (layout); @@ -25,6 +28,14 @@ CSVWorld::TableSubView::TableSubView (const CSMWorld::UniversalId& id, CSMDoc::D setWidget (widget); connect (mTable, SIGNAL (editRequest (int)), this, SLOT (editRequest (int))); + + connect (mTable, SIGNAL (selectionSizeChanged (int)), + mBottom, SLOT (selectionSizeChanged (int))); + connect (mTable, SIGNAL (tableSizeChanged (int, int, int)), + mBottom, SLOT (tableSizeChanged (int, int, int))); + + mTable->tableSizeUpdate(); + mTable->selectionSizeUpdate(); } void CSVWorld::TableSubView::setEditLock (bool locked) @@ -41,3 +52,8 @@ void CSVWorld::TableSubView::updateEditorSetting(const QString &settingName, con { mTable->updateEditorSetting(settingName, settingValue); } + +void CSVWorld::TableSubView::setStatusBar (bool show) +{ + mBottom->setStatusBar (show); +} \ No newline at end of file diff --git a/apps/opencs/view/world/tablesubview.hpp b/apps/opencs/view/world/tablesubview.hpp index ccee50dbc4..79450eccec 100644 --- a/apps/opencs/view/world/tablesubview.hpp +++ b/apps/opencs/view/world/tablesubview.hpp @@ -13,18 +13,24 @@ namespace CSMDoc namespace CSVWorld { class Table; + class TableBottomBox; class TableSubView : public CSVDoc::SubView { Q_OBJECT Table *mTable; + TableBottomBox *mBottom; public: TableSubView (const CSMWorld::UniversalId& id, CSMDoc::Document& document, bool createAndDelete); + virtual void setEditLock (bool locked); - void updateEditorSetting (const QString &, const QString &); + + virtual void updateEditorSetting (const QString& key, const QString& value); + + virtual void setStatusBar (bool show); private slots: From 4327b81bc3a4decb476dca3a2ec46e9dc63c51bc Mon Sep 17 00:00:00 2001 From: Marc Zinnschlag Date: Thu, 25 Jul 2013 14:38:53 +0200 Subject: [PATCH 03/23] fixed column handling in table (had problems with filtered out columns before) --- apps/opencs/view/world/table.cpp | 56 ++++++++++++++++++++++---------- 1 file changed, 38 insertions(+), 18 deletions(-) diff --git a/apps/opencs/view/world/table.cpp b/apps/opencs/view/world/table.cpp index 9085592df6..d8a840be4d 100644 --- a/apps/opencs/view/world/table.cpp +++ b/apps/opencs/view/world/table.cpp @@ -44,20 +44,30 @@ void CSVWorld::Table::contextMenuEvent (QContextMenuEvent *event) std::vector CSVWorld::Table::listRevertableSelectedIds() const { - /// \todo columns filtering fixes - QModelIndexList selectedRows = selectionModel()->selectedRows(); - + /// \todo Do not use hardcoded column numbers std::vector revertableIds; - for (QModelIndexList::const_iterator iter (selectedRows.begin()); iter!=selectedRows.end(); ++iter) + if (mProxyModel->columnCount()>0) { - std::string id = mProxyModel->data (*iter).toString().toStdString(); + QModelIndexList selectedRows = selectionModel()->selectedRows(); - CSMWorld::RecordBase::State state = - static_cast (mModel->data (mModel->getModelIndex (id, 1)).toInt()); + for (QModelIndexList::const_iterator iter (selectedRows.begin()); iter!=selectedRows.end(); + ++iter) + { + QModelIndex index = mProxyModel->mapToSource (mProxyModel->index (iter->row(), 0)); - if (state!=CSMWorld::RecordBase::State_BaseOnly) - revertableIds.push_back (id); + CSMWorld::RecordBase::State state = + static_cast ( + mModel->data (mModel->index (index.row(), 1)).toInt()); + + if (state!=CSMWorld::RecordBase::State_BaseOnly) + { + std::string id = mModel->data (mModel->index (index.row(), 0)). + toString().toUtf8().constData(); + + revertableIds.push_back (id); + } + } } return revertableIds; @@ -65,20 +75,30 @@ std::vector CSVWorld::Table::listRevertableSelectedIds() const std::vector CSVWorld::Table::listDeletableSelectedIds() const { - /// \todo columns filtering fixes - QModelIndexList selectedRows = selectionModel()->selectedRows(); - + /// \todo Do not use hardcoded column numbers std::vector deletableIds; - for (QModelIndexList::const_iterator iter (selectedRows.begin()); iter!=selectedRows.end(); ++iter) + if (mProxyModel->columnCount()>0) { - std::string id = mProxyModel->data (*iter).toString().toStdString(); + QModelIndexList selectedRows = selectionModel()->selectedRows(); - CSMWorld::RecordBase::State state = - static_cast (mModel->data (mModel->getModelIndex (id, 1)).toInt()); + for (QModelIndexList::const_iterator iter (selectedRows.begin()); iter!=selectedRows.end(); + ++iter) + { + QModelIndex index = mProxyModel->mapToSource (mProxyModel->index (iter->row(), 0)); - if (state!=CSMWorld::RecordBase::State_Deleted) - deletableIds.push_back (id); + CSMWorld::RecordBase::State state = + static_cast ( + mModel->data (mModel->index (index.row(), 1)).toInt()); + + if (state!=CSMWorld::RecordBase::State_Deleted) + { + std::string id = mModel->data (mModel->index (index.row(), 0)). + toString().toUtf8().constData(); + + deletableIds.push_back (id); + } + } } return deletableIds; From ba5ca5beed93cad436f73f4bdad6a631619417bc Mon Sep 17 00:00:00 2001 From: Marc Zinnschlag Date: Fri, 26 Jul 2013 12:34:30 +0200 Subject: [PATCH 04/23] replaced createAndDelete flag with a new class hierarhy (Creator) --- apps/opencs/CMakeLists.txt | 2 +- apps/opencs/view/doc/subviewfactoryimp.hpp | 22 +++----- apps/opencs/view/world/creator.cpp | 12 +++++ apps/opencs/view/world/creator.hpp | 58 ++++++++++++++++++++++ apps/opencs/view/world/genericcreator.cpp | 2 + apps/opencs/view/world/genericcreator.hpp | 14 ++++++ apps/opencs/view/world/subviews.cpp | 11 ++-- apps/opencs/view/world/tablesubview.cpp | 6 ++- apps/opencs/view/world/tablesubview.hpp | 5 +- 9 files changed, 108 insertions(+), 24 deletions(-) create mode 100644 apps/opencs/view/world/creator.cpp create mode 100644 apps/opencs/view/world/creator.hpp create mode 100644 apps/opencs/view/world/genericcreator.cpp create mode 100644 apps/opencs/view/world/genericcreator.hpp diff --git a/apps/opencs/CMakeLists.txt b/apps/opencs/CMakeLists.txt index d2568ce022..6102671ff7 100644 --- a/apps/opencs/CMakeLists.txt +++ b/apps/opencs/CMakeLists.txt @@ -63,7 +63,7 @@ opencs_units (view/world opencs_units_noqt (view/world dialoguesubview subviews enumdelegate vartypedelegate recordstatusdelegate refidtypedelegate datadisplaydelegate - scripthighlighter + scripthighlighter creator genericcreator ) diff --git a/apps/opencs/view/doc/subviewfactoryimp.hpp b/apps/opencs/view/doc/subviewfactoryimp.hpp index d16e0b2b7b..1278c8b275 100644 --- a/apps/opencs/view/doc/subviewfactoryimp.hpp +++ b/apps/opencs/view/doc/subviewfactoryimp.hpp @@ -22,28 +22,20 @@ namespace CSVDoc return new SubViewT (id, document); } - template - class SubViewFactoryWithCreateFlag : public SubViewFactoryBase + + template + class SubViewFactoryWithCreator : public SubViewFactoryBase { - bool mCreateAndDelete; - public: - SubViewFactoryWithCreateFlag (bool createAndDelete); - virtual CSVDoc::SubView *makeSubView (const CSMWorld::UniversalId& id, CSMDoc::Document& document); }; - template - SubViewFactoryWithCreateFlag::SubViewFactoryWithCreateFlag (bool createAndDelete) - : mCreateAndDelete (createAndDelete) - {} - - template - CSVDoc::SubView *SubViewFactoryWithCreateFlag::makeSubView (const CSMWorld::UniversalId& id, - CSMDoc::Document& document) + template + CSVDoc::SubView *SubViewFactoryWithCreator::makeSubView ( + const CSMWorld::UniversalId& id, CSMDoc::Document& document) { - return new SubViewT (id, document, mCreateAndDelete); + return new SubViewT (id, document, CreatorFactoryT().makeCreator()); } } diff --git a/apps/opencs/view/world/creator.cpp b/apps/opencs/view/world/creator.cpp new file mode 100644 index 0000000000..7d57c2ec73 --- /dev/null +++ b/apps/opencs/view/world/creator.cpp @@ -0,0 +1,12 @@ + +#include "creator.hpp" + +CSVWorld::Creator:: ~Creator() {} + +CSVWorld::CreatorFactoryBase::~CreatorFactoryBase() {} + + +CSVWorld::Creator *CSVWorld::NullCreatorFactory::makeCreator() const +{ + return 0; +} \ No newline at end of file diff --git a/apps/opencs/view/world/creator.hpp b/apps/opencs/view/world/creator.hpp new file mode 100644 index 0000000000..b9dc5629f4 --- /dev/null +++ b/apps/opencs/view/world/creator.hpp @@ -0,0 +1,58 @@ +#ifndef CSV_WORLD_CREATOR_H +#define CSV_WORLD_CREATOR_H + +namespace CSVWorld +{ + /// \brief Record creator UI base class + class Creator + { + public: + + virtual ~Creator(); + }; + + /// \brief Base class for Creator factory + class CreatorFactoryBase + { + public: + + virtual ~CreatorFactoryBase(); + + virtual Creator *makeCreator() const = 0; + ///< The ownership of the returned Creator is transferred to the caller. + /// + /// \note The function can return a 0-pointer, which means no UI for creating/deleting + /// records should be provided. + }; + + /// \brief Creator factory that does not produces any creator + class NullCreatorFactory : public CreatorFactoryBase + { + public: + + virtual Creator *makeCreator() const; + ///< The ownership of the returned Creator is transferred to the caller. + /// + /// \note The function always returns 0. + }; + + template + class CreatorFactory : public CreatorFactoryBase + { + public: + + virtual Creator *makeCreator() const; + ///< The ownership of the returned Creator is transferred to the caller. + /// + /// \note The function can return a 0-pointer, which means no UI for creating/deleting + /// records should be provided. + }; + + template + Creator *CreatorFactory::makeCreator() const + { + return new CreatorT; + } +} + +#endif \ No newline at end of file diff --git a/apps/opencs/view/world/genericcreator.cpp b/apps/opencs/view/world/genericcreator.cpp new file mode 100644 index 0000000000..4685df339c --- /dev/null +++ b/apps/opencs/view/world/genericcreator.cpp @@ -0,0 +1,2 @@ + +#include "genericcreator.hpp" \ No newline at end of file diff --git a/apps/opencs/view/world/genericcreator.hpp b/apps/opencs/view/world/genericcreator.hpp new file mode 100644 index 0000000000..28024041ff --- /dev/null +++ b/apps/opencs/view/world/genericcreator.hpp @@ -0,0 +1,14 @@ +#ifndef CSV_WORLD_GENERICCREATOR_H +#define CSV_WORLD_GENERICCREATOR_H + +#include "creator.hpp" + +namespace CSVWorld +{ + class GenericCreator : public Creator + { + public: + }; +} + +#endif \ No newline at end of file diff --git a/apps/opencs/view/world/subviews.cpp b/apps/opencs/view/world/subviews.cpp index 1c06ea2f60..3ad4b36c6d 100644 --- a/apps/opencs/view/world/subviews.cpp +++ b/apps/opencs/view/world/subviews.cpp @@ -7,14 +7,15 @@ #include "dialoguesubview.hpp" #include "scriptsubview.hpp" #include "regionmapsubview.hpp" +#include "genericcreator.hpp" void CSVWorld::addSubViewFactories (CSVDoc::SubViewFactoryManager& manager) { manager.add (CSMWorld::UniversalId::Type_Gmsts, - new CSVDoc::SubViewFactoryWithCreateFlag (false)); + new CSVDoc::SubViewFactoryWithCreator); manager.add (CSMWorld::UniversalId::Type_Skills, - new CSVDoc::SubViewFactoryWithCreateFlag (false)); + new CSVDoc::SubViewFactoryWithCreator); static const CSMWorld::UniversalId::Type sTableTypes[] = { @@ -35,12 +36,10 @@ void CSVWorld::addSubViewFactories (CSVDoc::SubViewFactoryManager& manager) }; for (int i=0; sTableTypes[i]!=CSMWorld::UniversalId::Type_None; ++i) - manager.add (sTableTypes[i], new CSVDoc::SubViewFactoryWithCreateFlag (true)); + manager.add (sTableTypes[i], + new CSVDoc::SubViewFactoryWithCreator >); manager.add (CSMWorld::UniversalId::Type_Script, new CSVDoc::SubViewFactory); manager.add (CSMWorld::UniversalId::Type_RegionMap, new CSVDoc::SubViewFactory); - -// manager.add (CSMWorld::UniversalId::Type_Global, -// new CSVDoc::SubViewFactoryWithCreateFlag (true)); } \ No newline at end of file diff --git a/apps/opencs/view/world/tablesubview.cpp b/apps/opencs/view/world/tablesubview.cpp index 7f9c671c09..03f0822d12 100644 --- a/apps/opencs/view/world/tablesubview.cpp +++ b/apps/opencs/view/world/tablesubview.cpp @@ -7,11 +7,15 @@ #include "table.hpp" #include "tablebottombox.hpp" +#include "creator.hpp" CSVWorld::TableSubView::TableSubView (const CSMWorld::UniversalId& id, CSMDoc::Document& document, - bool createAndDelete) + Creator *creator) : SubView (id) { + bool createAndDelete = creator!=0; + delete creator; + QVBoxLayout *layout = new QVBoxLayout; layout->setContentsMargins (QMargins (0, 0, 0, 0)); diff --git a/apps/opencs/view/world/tablesubview.hpp b/apps/opencs/view/world/tablesubview.hpp index 79450eccec..1148be9e03 100644 --- a/apps/opencs/view/world/tablesubview.hpp +++ b/apps/opencs/view/world/tablesubview.hpp @@ -14,6 +14,7 @@ namespace CSVWorld { class Table; class TableBottomBox; + class Creator; class TableSubView : public CSVDoc::SubView { @@ -24,7 +25,9 @@ namespace CSVWorld public: - TableSubView (const CSMWorld::UniversalId& id, CSMDoc::Document& document, bool createAndDelete); + TableSubView (const CSMWorld::UniversalId& id, CSMDoc::Document& document, + Creator *creator = 0); + ///< The ownership of \a creator is transferred to this. virtual void setEditLock (bool locked); From 6c4bdc010181f832935572ebca8b8abf3c9b518b Mon Sep 17 00:00:00 2001 From: Marc Zinnschlag Date: Fri, 26 Jul 2013 12:42:15 +0200 Subject: [PATCH 05/23] minor cleanup; less pointer usage --- apps/opencs/view/doc/subviewfactoryimp.hpp | 2 +- apps/opencs/view/world/tablesubview.cpp | 8 +++++--- apps/opencs/view/world/tablesubview.hpp | 5 ++--- 3 files changed, 8 insertions(+), 7 deletions(-) diff --git a/apps/opencs/view/doc/subviewfactoryimp.hpp b/apps/opencs/view/doc/subviewfactoryimp.hpp index 1278c8b275..2c4158f854 100644 --- a/apps/opencs/view/doc/subviewfactoryimp.hpp +++ b/apps/opencs/view/doc/subviewfactoryimp.hpp @@ -35,7 +35,7 @@ namespace CSVDoc CSVDoc::SubView *SubViewFactoryWithCreator::makeSubView ( const CSMWorld::UniversalId& id, CSMDoc::Document& document) { - return new SubViewT (id, document, CreatorFactoryT().makeCreator()); + return new SubViewT (id, document, CreatorFactoryT()); } } diff --git a/apps/opencs/view/world/tablesubview.cpp b/apps/opencs/view/world/tablesubview.cpp index 03f0822d12..f236a079af 100644 --- a/apps/opencs/view/world/tablesubview.cpp +++ b/apps/opencs/view/world/tablesubview.cpp @@ -10,16 +10,18 @@ #include "creator.hpp" CSVWorld::TableSubView::TableSubView (const CSMWorld::UniversalId& id, CSMDoc::Document& document, - Creator *creator) + const CreatorFactoryBase& creatorFactory) : SubView (id) { - bool createAndDelete = creator!=0; - delete creator; QVBoxLayout *layout = new QVBoxLayout; layout->setContentsMargins (QMargins (0, 0, 0, 0)); + Creator *creator = creatorFactory.makeCreator(); + bool createAndDelete = creator!=0; + delete creator; + layout->addWidget ( mTable = new Table (id, document.getData(), document.getUndoStack(), createAndDelete), 2); diff --git a/apps/opencs/view/world/tablesubview.hpp b/apps/opencs/view/world/tablesubview.hpp index 1148be9e03..d61c789356 100644 --- a/apps/opencs/view/world/tablesubview.hpp +++ b/apps/opencs/view/world/tablesubview.hpp @@ -14,7 +14,7 @@ namespace CSVWorld { class Table; class TableBottomBox; - class Creator; + class CreatorFactoryBase; class TableSubView : public CSVDoc::SubView { @@ -26,8 +26,7 @@ namespace CSVWorld public: TableSubView (const CSMWorld::UniversalId& id, CSMDoc::Document& document, - Creator *creator = 0); - ///< The ownership of \a creator is transferred to this. + const CreatorFactoryBase& creatorFactory); virtual void setEditLock (bool locked); From ed83e2e70a794157254c0cbdbe05411562f45ca7 Mon Sep 17 00:00:00 2001 From: Marc Zinnschlag Date: Fri, 26 Jul 2013 12:51:45 +0200 Subject: [PATCH 06/23] added creator to bottom box; more cleanup --- apps/opencs/view/world/tablebottombox.cpp | 16 +++++++++++++++- apps/opencs/view/world/tablebottombox.hpp | 17 ++++++++++++++++- apps/opencs/view/world/tablesubview.cpp | 10 +++------- 3 files changed, 34 insertions(+), 9 deletions(-) diff --git a/apps/opencs/view/world/tablebottombox.cpp b/apps/opencs/view/world/tablebottombox.cpp index c8ddb662c9..dbd518c60d 100644 --- a/apps/opencs/view/world/tablebottombox.cpp +++ b/apps/opencs/view/world/tablebottombox.cpp @@ -7,6 +7,8 @@ #include #include +#include "creator.hpp" + void CSVWorld::TableBottomBox::updateStatus() { if (mShowStatusBar) @@ -37,7 +39,7 @@ void CSVWorld::TableBottomBox::updateStatus() } } -CSVWorld::TableBottomBox::TableBottomBox (QWidget *parent) +CSVWorld::TableBottomBox::TableBottomBox (const CreatorFactoryBase& creatorFactory, QWidget *parent) : QWidget (parent), mShowStatusBar (false) { for (int i=0; i<4; ++i) @@ -60,6 +62,13 @@ CSVWorld::TableBottomBox::TableBottomBox (QWidget *parent) layout->addWidget (statusBar2); setLayout (layout); + + mCreator = creatorFactory.makeCreator(); +} + +CSVWorld::TableBottomBox::~TableBottomBox() +{ + delete mCreator; } void CSVWorld::TableBottomBox::setStatusBar (bool show) @@ -75,6 +84,11 @@ void CSVWorld::TableBottomBox::setStatusBar (bool show) } } +bool CSVWorld::TableBottomBox::canCreateAndDelete() const +{ + return mCreator; +} + void CSVWorld::TableBottomBox::selectionSizeChanged (int size) { if (mStatusCount[3]!=size) diff --git a/apps/opencs/view/world/tablebottombox.hpp b/apps/opencs/view/world/tablebottombox.hpp index 2663da8555..0f25f787b2 100644 --- a/apps/opencs/view/world/tablebottombox.hpp +++ b/apps/opencs/view/world/tablebottombox.hpp @@ -7,6 +7,9 @@ class QLabel; namespace CSVWorld { + class CreatorFactoryBase; + class Creator; + class TableBottomBox : public QWidget { Q_OBJECT @@ -14,17 +17,29 @@ namespace CSVWorld bool mShowStatusBar; QLabel *mStatus; int mStatusCount[4]; + Creator *mCreator; private: + // not implemented + TableBottomBox (const TableBottomBox&); + TableBottomBox& operator= (const TableBottomBox&); + void updateStatus(); public: - TableBottomBox (QWidget *parent = 0); + TableBottomBox (const CreatorFactoryBase& creatorFactory, QWidget *parent = 0); + + virtual ~TableBottomBox(); void setStatusBar (bool show); + bool canCreateAndDelete() const; + ///< Is record creation and deletion supported? + /// + /// \note The BotomBox does not partake in the deletion of records. + public slots: void selectionSizeChanged (int size); diff --git a/apps/opencs/view/world/tablesubview.cpp b/apps/opencs/view/world/tablesubview.cpp index f236a079af..2173c0a483 100644 --- a/apps/opencs/view/world/tablesubview.cpp +++ b/apps/opencs/view/world/tablesubview.cpp @@ -18,14 +18,10 @@ CSVWorld::TableSubView::TableSubView (const CSMWorld::UniversalId& id, CSMDoc::D layout->setContentsMargins (QMargins (0, 0, 0, 0)); - Creator *creator = creatorFactory.makeCreator(); - bool createAndDelete = creator!=0; - delete creator; + layout->addWidget (mBottom = new TableBottomBox (creatorFactory, this), 0); - layout->addWidget ( - mTable = new Table (id, document.getData(), document.getUndoStack(), createAndDelete), 2); - - layout->addWidget (mBottom = new TableBottomBox (this), 0); + layout->insertWidget (0, mTable = + new Table (id, document.getData(), document.getUndoStack(), mBottom->canCreateAndDelete()), 2); QWidget *widget = new QWidget; From d899cbb4495a988260a1821d3fe80c91e9231a41 Mon Sep 17 00:00:00 2001 From: Marc Zinnschlag Date: Fri, 26 Jul 2013 18:14:34 +0200 Subject: [PATCH 07/23] removed some junk --- apps/opencs/view/world/tablebottombox.cpp | 4 ---- 1 file changed, 4 deletions(-) diff --git a/apps/opencs/view/world/tablebottombox.cpp b/apps/opencs/view/world/tablebottombox.cpp index dbd518c60d..bc90ebbc23 100644 --- a/apps/opencs/view/world/tablebottombox.cpp +++ b/apps/opencs/view/world/tablebottombox.cpp @@ -57,10 +57,6 @@ CSVWorld::TableBottomBox::TableBottomBox (const CreatorFactoryBase& creatorFacto layout->addWidget (statusBar); - QStatusBar *statusBar2 = new QStatusBar; - - layout->addWidget (statusBar2); - setLayout (layout); mCreator = creatorFactory.makeCreator(); From b8ac45defedc3f102cb34730e51613f95f956dd6 Mon Sep 17 00:00:00 2001 From: Marc Zinnschlag Date: Fri, 26 Jul 2013 18:22:31 +0200 Subject: [PATCH 08/23] added creator to bottom box layout and re-routed add record event to bottom box --- apps/opencs/view/world/creator.hpp | 4 +++- apps/opencs/view/world/table.cpp | 2 +- apps/opencs/view/world/table.hpp | 3 +++ apps/opencs/view/world/tablebottombox.cpp | 8 ++++++++ apps/opencs/view/world/tablebottombox.hpp | 2 ++ apps/opencs/view/world/tablesubview.cpp | 3 +++ 6 files changed, 20 insertions(+), 2 deletions(-) diff --git a/apps/opencs/view/world/creator.hpp b/apps/opencs/view/world/creator.hpp index b9dc5629f4..54342ccdc7 100644 --- a/apps/opencs/view/world/creator.hpp +++ b/apps/opencs/view/world/creator.hpp @@ -1,10 +1,12 @@ #ifndef CSV_WORLD_CREATOR_H #define CSV_WORLD_CREATOR_H +#include + namespace CSVWorld { /// \brief Record creator UI base class - class Creator + class Creator : public QWidget { public: diff --git a/apps/opencs/view/world/table.cpp b/apps/opencs/view/world/table.cpp index d8a840be4d..441828e69c 100644 --- a/apps/opencs/view/world/table.cpp +++ b/apps/opencs/view/world/table.cpp @@ -148,7 +148,7 @@ CSVWorld::Table::Table (const CSMWorld::UniversalId& id, CSMWorld::Data& data, Q if (createAndDelete) { mCreateAction = new QAction (tr ("Add Record"), this); - connect (mCreateAction, SIGNAL (triggered()), this, SLOT (createRecord())); + connect (mCreateAction, SIGNAL (triggered()), this, SIGNAL (createRequest())); addAction (mCreateAction); } diff --git a/apps/opencs/view/world/table.hpp b/apps/opencs/view/world/table.hpp index dd8e82ed71..913f048894 100644 --- a/apps/opencs/view/world/table.hpp +++ b/apps/opencs/view/world/table.hpp @@ -67,6 +67,8 @@ namespace CSVWorld /// \param deleted Number of deleted records /// \param modified Number of added and modified records + void createRequest(); + private slots: void createRecord(); @@ -82,6 +84,7 @@ namespace CSVWorld void tableSizeUpdate(); void selectionSizeUpdate(); + }; } diff --git a/apps/opencs/view/world/tablebottombox.cpp b/apps/opencs/view/world/tablebottombox.cpp index bc90ebbc23..a48325575e 100644 --- a/apps/opencs/view/world/tablebottombox.cpp +++ b/apps/opencs/view/world/tablebottombox.cpp @@ -60,6 +60,8 @@ CSVWorld::TableBottomBox::TableBottomBox (const CreatorFactoryBase& creatorFacto setLayout (layout); mCreator = creatorFactory.makeCreator(); + + layout->addWidget (mCreator); } CSVWorld::TableBottomBox::~TableBottomBox() @@ -118,4 +120,10 @@ void CSVWorld::TableBottomBox::tableSizeChanged (int size, int deleted, int modi if (changed) updateStatus(); +} + +#include +void CSVWorld::TableBottomBox::createRequest() +{ + std::cout<<"create"<tableSizeUpdate(); mTable->selectionSizeUpdate(); + + if (mBottom->canCreateAndDelete()) + connect (mTable, SIGNAL (createRequest()), mBottom, SLOT (createRequest())); } void CSVWorld::TableSubView::setEditLock (bool locked) From fee748d4b5931e0d6c97b0689e0a0884beb03504 Mon Sep 17 00:00:00 2001 From: Marc Zinnschlag Date: Fri, 26 Jul 2013 21:09:23 +0200 Subject: [PATCH 09/23] added creator bar UI and cancel button --- apps/opencs/CMakeLists.txt | 4 +-- apps/opencs/view/world/creator.hpp | 8 ++++++ apps/opencs/view/world/genericcreator.cpp | 29 ++++++++++++++++++- apps/opencs/view/world/genericcreator.hpp | 6 ++++ apps/opencs/view/world/tablebottombox.cpp | 35 ++++++++++++++++------- apps/opencs/view/world/tablebottombox.hpp | 10 +++++++ 6 files changed, 79 insertions(+), 13 deletions(-) diff --git a/apps/opencs/CMakeLists.txt b/apps/opencs/CMakeLists.txt index 6102671ff7..bca37755c5 100644 --- a/apps/opencs/CMakeLists.txt +++ b/apps/opencs/CMakeLists.txt @@ -57,13 +57,13 @@ opencs_hdrs_noqt (view/doc opencs_units (view/world - table tablesubview scriptsubview util regionmapsubview tablebottombox + table tablesubview scriptsubview util regionmapsubview tablebottombox creator genericcreator ) opencs_units_noqt (view/world dialoguesubview subviews enumdelegate vartypedelegate recordstatusdelegate refidtypedelegate datadisplaydelegate - scripthighlighter creator genericcreator + scripthighlighter ) diff --git a/apps/opencs/view/world/creator.hpp b/apps/opencs/view/world/creator.hpp index 54342ccdc7..f5485534c7 100644 --- a/apps/opencs/view/world/creator.hpp +++ b/apps/opencs/view/world/creator.hpp @@ -8,9 +8,17 @@ namespace CSVWorld /// \brief Record creator UI base class class Creator : public QWidget { + Q_OBJECT + public: virtual ~Creator(); + + virtual void reset() = 0; + + signals: + + void done(); }; /// \brief Base class for Creator factory diff --git a/apps/opencs/view/world/genericcreator.cpp b/apps/opencs/view/world/genericcreator.cpp index 4685df339c..6dbd847115 100644 --- a/apps/opencs/view/world/genericcreator.cpp +++ b/apps/opencs/view/world/genericcreator.cpp @@ -1,2 +1,29 @@ -#include "genericcreator.hpp" \ No newline at end of file +#include "genericcreator.hpp" + +#include +#include +#include + +CSVWorld::GenericCreator::GenericCreator() +{ + QHBoxLayout *layout = new QHBoxLayout; + + QLineEdit *name = new QLineEdit; + layout->addWidget (name, 1); + + QPushButton *createButton = new QPushButton ("Create"); + layout->addWidget (createButton); + + QPushButton *cancelButton = new QPushButton ("Cancel"); + layout->addWidget (cancelButton); + + connect (cancelButton, SIGNAL (clicked (bool)), this, SIGNAL (done())); + + setLayout (layout); +} + +void CSVWorld::GenericCreator::reset() +{ + +} \ No newline at end of file diff --git a/apps/opencs/view/world/genericcreator.hpp b/apps/opencs/view/world/genericcreator.hpp index 28024041ff..7ab125dfc3 100644 --- a/apps/opencs/view/world/genericcreator.hpp +++ b/apps/opencs/view/world/genericcreator.hpp @@ -7,7 +7,13 @@ namespace CSVWorld { class GenericCreator : public Creator { + Q_OBJECT + public: + + GenericCreator(); + + virtual void reset(); }; } diff --git a/apps/opencs/view/world/tablebottombox.cpp b/apps/opencs/view/world/tablebottombox.cpp index a48325575e..d84e66390d 100644 --- a/apps/opencs/view/world/tablebottombox.cpp +++ b/apps/opencs/view/world/tablebottombox.cpp @@ -40,28 +40,30 @@ void CSVWorld::TableBottomBox::updateStatus() } CSVWorld::TableBottomBox::TableBottomBox (const CreatorFactoryBase& creatorFactory, QWidget *parent) -: QWidget (parent), mShowStatusBar (false) +: QWidget (parent), mShowStatusBar (false), mCreating (false) { for (int i=0; i<4; ++i) mStatusCount[i] = 0; setVisible (false); - QStackedLayout *layout = new QStackedLayout; + mLayout = new QStackedLayout; mStatus = new QLabel; - QStatusBar *statusBar = new QStatusBar; + mStatusBar = new QStatusBar; - statusBar->addWidget (mStatus); + mStatusBar->addWidget (mStatus); - layout->addWidget (statusBar); + mLayout->addWidget (mStatusBar); - setLayout (layout); + setLayout (mLayout); mCreator = creatorFactory.makeCreator(); - layout->addWidget (mCreator); + mLayout->addWidget (mCreator); + + connect (mCreator, SIGNAL (done()), this, SLOT (createRequestDone())); } CSVWorld::TableBottomBox::~TableBottomBox() @@ -73,7 +75,7 @@ void CSVWorld::TableBottomBox::setStatusBar (bool show) { if (show!=mShowStatusBar) { - setVisible (show); + setVisible (show || mCreating); mShowStatusBar = show; @@ -87,6 +89,18 @@ bool CSVWorld::TableBottomBox::canCreateAndDelete() const return mCreator; } +void CSVWorld::TableBottomBox::createRequestDone() +{ + if (!mShowStatusBar) + setVisible (false); + else + updateStatus(); + + mLayout->setCurrentWidget (mStatusBar); + + mCreating = false; +} + void CSVWorld::TableBottomBox::selectionSizeChanged (int size) { if (mStatusCount[3]!=size) @@ -122,8 +136,9 @@ void CSVWorld::TableBottomBox::tableSizeChanged (int size, int deleted, int modi updateStatus(); } -#include void CSVWorld::TableBottomBox::createRequest() { - std::cout<<"create"<setCurrentWidget (mCreator); + setVisible (true); + mCreating = true; } \ No newline at end of file diff --git a/apps/opencs/view/world/tablebottombox.hpp b/apps/opencs/view/world/tablebottombox.hpp index dd00ea27ce..8f2ceda112 100644 --- a/apps/opencs/view/world/tablebottombox.hpp +++ b/apps/opencs/view/world/tablebottombox.hpp @@ -4,6 +4,8 @@ #include class QLabel; +class QStackedLayout; +class QStatusBar; namespace CSVWorld { @@ -16,8 +18,11 @@ namespace CSVWorld bool mShowStatusBar; QLabel *mStatus; + QStatusBar *mStatusBar; int mStatusCount[4]; Creator *mCreator; + bool mCreating; + QStackedLayout *mLayout; private: @@ -40,6 +45,11 @@ namespace CSVWorld /// /// \note The BotomBox does not partake in the deletion of records. + private slots: + + void createRequestDone(); + ///< \note This slot being called does not imply success. + public slots: void selectionSizeChanged (int size); From f93af52486c8e84324bb41a5c90cf22ea6a66b85 Mon Sep 17 00:00:00 2001 From: Marc Zinnschlag Date: Sat, 27 Jul 2013 13:28:12 +0200 Subject: [PATCH 10/23] handling down a reference to Data and the undo stack to the creators --- apps/opencs/view/world/creator.cpp | 3 ++- apps/opencs/view/world/creator.hpp | 17 ++++++++++++----- apps/opencs/view/world/genericcreator.cpp | 2 +- apps/opencs/view/world/genericcreator.hpp | 2 +- apps/opencs/view/world/tablebottombox.cpp | 5 +++-- apps/opencs/view/world/tablebottombox.hpp | 9 ++++++++- apps/opencs/view/world/tablesubview.cpp | 4 ++-- 7 files changed, 29 insertions(+), 13 deletions(-) diff --git a/apps/opencs/view/world/creator.cpp b/apps/opencs/view/world/creator.cpp index 7d57c2ec73..c0378151ed 100644 --- a/apps/opencs/view/world/creator.cpp +++ b/apps/opencs/view/world/creator.cpp @@ -6,7 +6,8 @@ CSVWorld::Creator:: ~Creator() {} CSVWorld::CreatorFactoryBase::~CreatorFactoryBase() {} -CSVWorld::Creator *CSVWorld::NullCreatorFactory::makeCreator() const +CSVWorld::Creator *CSVWorld::NullCreatorFactory::makeCreator (CSMWorld::Data& data, + QUndoStack& undoStack) const { return 0; } \ No newline at end of file diff --git a/apps/opencs/view/world/creator.hpp b/apps/opencs/view/world/creator.hpp index f5485534c7..9f586bcba6 100644 --- a/apps/opencs/view/world/creator.hpp +++ b/apps/opencs/view/world/creator.hpp @@ -3,6 +3,13 @@ #include +class QUndoStack; + +namespace CSMWorld +{ + class Data; +} + namespace CSVWorld { /// \brief Record creator UI base class @@ -28,7 +35,7 @@ namespace CSVWorld virtual ~CreatorFactoryBase(); - virtual Creator *makeCreator() const = 0; + virtual Creator *makeCreator (CSMWorld::Data& data, QUndoStack& undoStack) const = 0; ///< The ownership of the returned Creator is transferred to the caller. /// /// \note The function can return a 0-pointer, which means no UI for creating/deleting @@ -40,7 +47,7 @@ namespace CSVWorld { public: - virtual Creator *makeCreator() const; + virtual Creator *makeCreator (CSMWorld::Data& data, QUndoStack& undoStack) const; ///< The ownership of the returned Creator is transferred to the caller. /// /// \note The function always returns 0. @@ -51,7 +58,7 @@ namespace CSVWorld { public: - virtual Creator *makeCreator() const; + virtual Creator *makeCreator (CSMWorld::Data& data, QUndoStack& undoStac) const; ///< The ownership of the returned Creator is transferred to the caller. /// /// \note The function can return a 0-pointer, which means no UI for creating/deleting @@ -59,9 +66,9 @@ namespace CSVWorld }; template - Creator *CreatorFactory::makeCreator() const + Creator *CreatorFactory::makeCreator (CSMWorld::Data& data, QUndoStack& undoStack) const { - return new CreatorT; + return new CreatorT (data, undoStack); } } diff --git a/apps/opencs/view/world/genericcreator.cpp b/apps/opencs/view/world/genericcreator.cpp index 6dbd847115..9a855fc4b9 100644 --- a/apps/opencs/view/world/genericcreator.cpp +++ b/apps/opencs/view/world/genericcreator.cpp @@ -5,7 +5,7 @@ #include #include -CSVWorld::GenericCreator::GenericCreator() +CSVWorld::GenericCreator::GenericCreator (CSMWorld::Data& data, QUndoStack& undoStack) { QHBoxLayout *layout = new QHBoxLayout; diff --git a/apps/opencs/view/world/genericcreator.hpp b/apps/opencs/view/world/genericcreator.hpp index 7ab125dfc3..553315ae34 100644 --- a/apps/opencs/view/world/genericcreator.hpp +++ b/apps/opencs/view/world/genericcreator.hpp @@ -11,7 +11,7 @@ namespace CSVWorld public: - GenericCreator(); + GenericCreator (CSMWorld::Data& data, QUndoStack& undoStack); virtual void reset(); }; diff --git a/apps/opencs/view/world/tablebottombox.cpp b/apps/opencs/view/world/tablebottombox.cpp index d84e66390d..ae2b3d9208 100644 --- a/apps/opencs/view/world/tablebottombox.cpp +++ b/apps/opencs/view/world/tablebottombox.cpp @@ -39,7 +39,8 @@ void CSVWorld::TableBottomBox::updateStatus() } } -CSVWorld::TableBottomBox::TableBottomBox (const CreatorFactoryBase& creatorFactory, QWidget *parent) +CSVWorld::TableBottomBox::TableBottomBox (const CreatorFactoryBase& creatorFactory, + CSMWorld::Data& data, QUndoStack& undoStack, QWidget *parent) : QWidget (parent), mShowStatusBar (false), mCreating (false) { for (int i=0; i<4; ++i) @@ -59,7 +60,7 @@ CSVWorld::TableBottomBox::TableBottomBox (const CreatorFactoryBase& creatorFacto setLayout (mLayout); - mCreator = creatorFactory.makeCreator(); + mCreator = creatorFactory.makeCreator (data, undoStack); mLayout->addWidget (mCreator); diff --git a/apps/opencs/view/world/tablebottombox.hpp b/apps/opencs/view/world/tablebottombox.hpp index 8f2ceda112..50741167c1 100644 --- a/apps/opencs/view/world/tablebottombox.hpp +++ b/apps/opencs/view/world/tablebottombox.hpp @@ -6,6 +6,12 @@ class QLabel; class QStackedLayout; class QStatusBar; +class QUndoStack; + +namespace CSMWorld +{ + class Data; +} namespace CSVWorld { @@ -34,7 +40,8 @@ namespace CSVWorld public: - TableBottomBox (const CreatorFactoryBase& creatorFactory, QWidget *parent = 0); + TableBottomBox (const CreatorFactoryBase& creatorFactory, CSMWorld::Data& data, + QUndoStack& undoStack, QWidget *parent = 0); virtual ~TableBottomBox(); diff --git a/apps/opencs/view/world/tablesubview.cpp b/apps/opencs/view/world/tablesubview.cpp index 61a731289c..a76042842d 100644 --- a/apps/opencs/view/world/tablesubview.cpp +++ b/apps/opencs/view/world/tablesubview.cpp @@ -13,12 +13,12 @@ CSVWorld::TableSubView::TableSubView (const CSMWorld::UniversalId& id, CSMDoc::D const CreatorFactoryBase& creatorFactory) : SubView (id) { - QVBoxLayout *layout = new QVBoxLayout; layout->setContentsMargins (QMargins (0, 0, 0, 0)); - layout->addWidget (mBottom = new TableBottomBox (creatorFactory, this), 0); + layout->addWidget (mBottom = + new TableBottomBox (creatorFactory, document.getData(), document.getUndoStack(), this), 0); layout->insertWidget (0, mTable = new Table (id, document.getData(), document.getUndoStack(), mBottom->canCreateAndDelete()), 2); From 2d46a1db2fa7ca235dde8eb9a98a4dbbc55b6017 Mon Sep 17 00:00:00 2001 From: Marc Zinnschlag Date: Sun, 28 Jul 2013 13:39:33 +0200 Subject: [PATCH 11/23] changed CreateCommand to work directly on the model instead of the proxy --- apps/opencs/model/world/commands.cpp | 4 ++-- apps/opencs/model/world/commands.hpp | 6 +++--- apps/opencs/model/world/idtableproxymodel.cpp | 5 ----- apps/opencs/model/world/idtableproxymodel.hpp | 2 -- 4 files changed, 5 insertions(+), 12 deletions(-) diff --git a/apps/opencs/model/world/commands.cpp b/apps/opencs/model/world/commands.cpp index eaded5b702..3bcdf8b050 100644 --- a/apps/opencs/model/world/commands.cpp +++ b/apps/opencs/model/world/commands.cpp @@ -3,7 +3,7 @@ #include -#include "idtableproxymodel.hpp" +#include "idtable.hpp" #include "idtable.hpp" CSMWorld::ModifyCommand::ModifyCommand (QAbstractItemModel& model, const QModelIndex& index, @@ -25,7 +25,7 @@ void CSMWorld::ModifyCommand::undo() mModel.setData (mIndex, mOld); } -CSMWorld::CreateCommand::CreateCommand (IdTableProxyModel& model, const std::string& id, QUndoCommand *parent) +CSMWorld::CreateCommand::CreateCommand (IdTable& model, const std::string& id, QUndoCommand *parent) : QUndoCommand (parent), mModel (model), mId (id) { setText (("Create record " + id).c_str()); diff --git a/apps/opencs/model/world/commands.hpp b/apps/opencs/model/world/commands.hpp index af419215dc..1fa124277f 100644 --- a/apps/opencs/model/world/commands.hpp +++ b/apps/opencs/model/world/commands.hpp @@ -14,7 +14,7 @@ class QAbstractItemModel; namespace CSMWorld { - class IdTableProxyModel; + class IdTable; class IdTable; class RecordBase; @@ -37,12 +37,12 @@ namespace CSMWorld class CreateCommand : public QUndoCommand { - IdTableProxyModel& mModel; + IdTable& mModel; std::string mId; public: - CreateCommand (IdTableProxyModel& model, const std::string& id, QUndoCommand *parent = 0); + CreateCommand (IdTable& model, const std::string& id, QUndoCommand *parent = 0); virtual void redo(); diff --git a/apps/opencs/model/world/idtableproxymodel.cpp b/apps/opencs/model/world/idtableproxymodel.cpp index 78995f60bc..e99e1575ce 100644 --- a/apps/opencs/model/world/idtableproxymodel.cpp +++ b/apps/opencs/model/world/idtableproxymodel.cpp @@ -7,11 +7,6 @@ CSMWorld::IdTableProxyModel::IdTableProxyModel (QObject *parent) : QSortFilterProxyModel (parent) {} -void CSMWorld::IdTableProxyModel::addRecord (const std::string& id) -{ - dynamic_cast (*sourceModel()).addRecord (id); -} - QModelIndex CSMWorld::IdTableProxyModel::getModelIndex (const std::string& id, int column) const { return mapFromSource (dynamic_cast (*sourceModel()).getModelIndex (id, column)); diff --git a/apps/opencs/model/world/idtableproxymodel.hpp b/apps/opencs/model/world/idtableproxymodel.hpp index 3f1537cce6..200b99fe20 100644 --- a/apps/opencs/model/world/idtableproxymodel.hpp +++ b/apps/opencs/model/world/idtableproxymodel.hpp @@ -15,8 +15,6 @@ namespace CSMWorld IdTableProxyModel (QObject *parent = 0); - virtual void addRecord (const std::string& id); - virtual QModelIndex getModelIndex (const std::string& id, int column) const; }; } From 00fcb79f082be9ecd7b6041d8ff576c1bc08c556 Mon Sep 17 00:00:00 2001 From: Marc Zinnschlag Date: Sun, 28 Jul 2013 13:43:16 +0200 Subject: [PATCH 12/23] moved record creation to GenericCreator class (now taking ID from user instead of using a procedurally generated one) --- apps/opencs/view/world/creator.cpp | 2 +- apps/opencs/view/world/creator.hpp | 15 ++++-- apps/opencs/view/world/genericcreator.cpp | 66 ++++++++++++++++++++--- apps/opencs/view/world/genericcreator.hpp | 29 +++++++++- apps/opencs/view/world/table.cpp | 16 ------ apps/opencs/view/world/table.hpp | 2 - apps/opencs/view/world/tablebottombox.cpp | 5 +- apps/opencs/view/world/tablebottombox.hpp | 3 +- apps/opencs/view/world/tablesubview.cpp | 2 +- 9 files changed, 104 insertions(+), 36 deletions(-) diff --git a/apps/opencs/view/world/creator.cpp b/apps/opencs/view/world/creator.cpp index c0378151ed..d753a2b476 100644 --- a/apps/opencs/view/world/creator.cpp +++ b/apps/opencs/view/world/creator.cpp @@ -7,7 +7,7 @@ CSVWorld::CreatorFactoryBase::~CreatorFactoryBase() {} CSVWorld::Creator *CSVWorld::NullCreatorFactory::makeCreator (CSMWorld::Data& data, - QUndoStack& undoStack) const + QUndoStack& undoStack, const CSMWorld::UniversalId& id) const { return 0; } \ No newline at end of file diff --git a/apps/opencs/view/world/creator.hpp b/apps/opencs/view/world/creator.hpp index 9f586bcba6..564a5584e0 100644 --- a/apps/opencs/view/world/creator.hpp +++ b/apps/opencs/view/world/creator.hpp @@ -8,6 +8,7 @@ class QUndoStack; namespace CSMWorld { class Data; + class UniversalId; } namespace CSVWorld @@ -35,7 +36,8 @@ namespace CSVWorld virtual ~CreatorFactoryBase(); - virtual Creator *makeCreator (CSMWorld::Data& data, QUndoStack& undoStack) const = 0; + virtual Creator *makeCreator (CSMWorld::Data& data, QUndoStack& undoStack, + const CSMWorld::UniversalId& id) const = 0; ///< The ownership of the returned Creator is transferred to the caller. /// /// \note The function can return a 0-pointer, which means no UI for creating/deleting @@ -47,7 +49,8 @@ namespace CSVWorld { public: - virtual Creator *makeCreator (CSMWorld::Data& data, QUndoStack& undoStack) const; + virtual Creator *makeCreator (CSMWorld::Data& data, QUndoStack& undoStack, + const CSMWorld::UniversalId& id) const; ///< The ownership of the returned Creator is transferred to the caller. /// /// \note The function always returns 0. @@ -58,7 +61,8 @@ namespace CSVWorld { public: - virtual Creator *makeCreator (CSMWorld::Data& data, QUndoStack& undoStac) const; + virtual Creator *makeCreator (CSMWorld::Data& data, QUndoStack& undoStack, + const CSMWorld::UniversalId& id) const; ///< The ownership of the returned Creator is transferred to the caller. /// /// \note The function can return a 0-pointer, which means no UI for creating/deleting @@ -66,9 +70,10 @@ namespace CSVWorld }; template - Creator *CreatorFactory::makeCreator (CSMWorld::Data& data, QUndoStack& undoStack) const + Creator *CreatorFactory::makeCreator (CSMWorld::Data& data, QUndoStack& undoStack, + const CSMWorld::UniversalId& id) const { - return new CreatorT (data, undoStack); + return new CreatorT (data, undoStack, id); } } diff --git a/apps/opencs/view/world/genericcreator.cpp b/apps/opencs/view/world/genericcreator.cpp index 9a855fc4b9..10cbf9447b 100644 --- a/apps/opencs/view/world/genericcreator.cpp +++ b/apps/opencs/view/world/genericcreator.cpp @@ -4,26 +4,78 @@ #include #include #include +#include -CSVWorld::GenericCreator::GenericCreator (CSMWorld::Data& data, QUndoStack& undoStack) +#include "../../model/world/commands.hpp" +#include "../../model/world/data.hpp" +#include "../../model/world/idtable.hpp" + +void CSVWorld::GenericCreator::update() +{ + mErrors = getErrors(); + + mCreate->setToolTip (QString::fromUtf8 (mErrors.c_str())); + + mCreate->setEnabled (mErrors.empty()); +} + +CSVWorld::GenericCreator::GenericCreator (CSMWorld::Data& data, QUndoStack& undoStack, + const CSMWorld::UniversalId& id) +: mData (data), mUndoStack (undoStack), mListId (id) { QHBoxLayout *layout = new QHBoxLayout; - QLineEdit *name = new QLineEdit; - layout->addWidget (name, 1); + mId = new QLineEdit; + layout->addWidget (mId, 1); - QPushButton *createButton = new QPushButton ("Create"); - layout->addWidget (createButton); + mCreate = new QPushButton ("Create"); + layout->addWidget (mCreate); QPushButton *cancelButton = new QPushButton ("Cancel"); layout->addWidget (cancelButton); - connect (cancelButton, SIGNAL (clicked (bool)), this, SIGNAL (done())); - setLayout (layout); + + connect (cancelButton, SIGNAL (clicked (bool)), this, SIGNAL (done())); + connect (mCreate, SIGNAL (clicked (bool)), this, SLOT (create())); + + connect (mId, SIGNAL (textChanged (const QString&)), this, SLOT (textChanged (const QString&))); } void CSVWorld::GenericCreator::reset() { + mId->setText (""); + update(); +} +std::string CSVWorld::GenericCreator::getErrors() const +{ + std::string errors; + + std::string id = mId->text().toUtf8().constData(); + + if (id.empty()) + { + errors = "Missing ID"; + } + else + { + + } + + return errors; +} + +void CSVWorld::GenericCreator::textChanged (const QString& text) +{ + update(); +} + +void CSVWorld::GenericCreator::create() +{ + mUndoStack.push (new CSMWorld::CreateCommand ( + dynamic_cast (*mData.getTableModel (mListId)), + mId->text().toUtf8().constData())); + + emit done(); } \ No newline at end of file diff --git a/apps/opencs/view/world/genericcreator.hpp b/apps/opencs/view/world/genericcreator.hpp index 553315ae34..a89b4c31f2 100644 --- a/apps/opencs/view/world/genericcreator.hpp +++ b/apps/opencs/view/world/genericcreator.hpp @@ -1,19 +1,46 @@ #ifndef CSV_WORLD_GENERICCREATOR_H #define CSV_WORLD_GENERICCREATOR_H +class QPushButton; +class QLineEdit; + #include "creator.hpp" +#include "../../model/world/universalid.hpp" + namespace CSVWorld { class GenericCreator : public Creator { Q_OBJECT + CSMWorld::Data& mData; + QUndoStack& mUndoStack; + CSMWorld::UniversalId mListId; + QPushButton *mCreate; + QLineEdit *mId; + std::string mErrors; + + private: + + void update(); + public: - GenericCreator (CSMWorld::Data& data, QUndoStack& undoStack); + GenericCreator (CSMWorld::Data& data, QUndoStack& undoStack, + const CSMWorld::UniversalId& id); virtual void reset(); + + virtual std::string getErrors() const; + ///< Return formatted error descriptions for the current state of the creator. if an empty + /// string is returned, there is no error. + + private slots: + + void textChanged (const QString& text); + + void create(); }; } diff --git a/apps/opencs/view/world/table.cpp b/apps/opencs/view/world/table.cpp index 441828e69c..c35d7358a0 100644 --- a/apps/opencs/view/world/table.cpp +++ b/apps/opencs/view/world/table.cpp @@ -187,22 +187,6 @@ CSMWorld::UniversalId CSVWorld::Table::getUniversalId (int row) const mProxyModel->data (mProxyModel->index (row, 0)).toString().toStdString()); } -#include /// \todo remove -void CSVWorld::Table::createRecord() -{ - if (!mEditLock) - { - /// \todo ask the user for an ID instead. - static int index = 0; - - std::ostringstream stream; - stream << "id" << index++; - - mUndoStack.push (new CSMWorld::CreateCommand (*mProxyModel, stream.str())); - } - -} - void CSVWorld::Table::revertRecord() { if (!mEditLock) diff --git a/apps/opencs/view/world/table.hpp b/apps/opencs/view/world/table.hpp index 913f048894..2a59270b89 100644 --- a/apps/opencs/view/world/table.hpp +++ b/apps/opencs/view/world/table.hpp @@ -71,8 +71,6 @@ namespace CSVWorld private slots: - void createRecord(); - void revertRecord(); void deleteRecord(); diff --git a/apps/opencs/view/world/tablebottombox.cpp b/apps/opencs/view/world/tablebottombox.cpp index ae2b3d9208..f796d89600 100644 --- a/apps/opencs/view/world/tablebottombox.cpp +++ b/apps/opencs/view/world/tablebottombox.cpp @@ -40,7 +40,7 @@ void CSVWorld::TableBottomBox::updateStatus() } CSVWorld::TableBottomBox::TableBottomBox (const CreatorFactoryBase& creatorFactory, - CSMWorld::Data& data, QUndoStack& undoStack, QWidget *parent) + CSMWorld::Data& data, QUndoStack& undoStack, const CSMWorld::UniversalId& id, QWidget *parent) : QWidget (parent), mShowStatusBar (false), mCreating (false) { for (int i=0; i<4; ++i) @@ -60,7 +60,7 @@ CSVWorld::TableBottomBox::TableBottomBox (const CreatorFactoryBase& creatorFacto setLayout (mLayout); - mCreator = creatorFactory.makeCreator (data, undoStack); + mCreator = creatorFactory.makeCreator (data, undoStack, id); mLayout->addWidget (mCreator); @@ -139,6 +139,7 @@ void CSVWorld::TableBottomBox::tableSizeChanged (int size, int deleted, int modi void CSVWorld::TableBottomBox::createRequest() { + mCreator->reset(); mLayout->setCurrentWidget (mCreator); setVisible (true); mCreating = true; diff --git a/apps/opencs/view/world/tablebottombox.hpp b/apps/opencs/view/world/tablebottombox.hpp index 50741167c1..62c552c93a 100644 --- a/apps/opencs/view/world/tablebottombox.hpp +++ b/apps/opencs/view/world/tablebottombox.hpp @@ -11,6 +11,7 @@ class QUndoStack; namespace CSMWorld { class Data; + class UniversalId; } namespace CSVWorld @@ -41,7 +42,7 @@ namespace CSVWorld public: TableBottomBox (const CreatorFactoryBase& creatorFactory, CSMWorld::Data& data, - QUndoStack& undoStack, QWidget *parent = 0); + QUndoStack& undoStack, const CSMWorld::UniversalId& id, QWidget *parent = 0); virtual ~TableBottomBox(); diff --git a/apps/opencs/view/world/tablesubview.cpp b/apps/opencs/view/world/tablesubview.cpp index a76042842d..8a828c9bd2 100644 --- a/apps/opencs/view/world/tablesubview.cpp +++ b/apps/opencs/view/world/tablesubview.cpp @@ -18,7 +18,7 @@ CSVWorld::TableSubView::TableSubView (const CSMWorld::UniversalId& id, CSMDoc::D layout->setContentsMargins (QMargins (0, 0, 0, 0)); layout->addWidget (mBottom = - new TableBottomBox (creatorFactory, document.getData(), document.getUndoStack(), this), 0); + new TableBottomBox (creatorFactory, document.getData(), document.getUndoStack(), id, this), 0); layout->insertWidget (0, mTable = new Table (id, document.getData(), document.getUndoStack(), mBottom->canCreateAndDelete()), 2); From 4f6e99c391b0ef8408f3ef8bc7fc04ac879cdc5b Mon Sep 17 00:00:00 2001 From: Marc Zinnschlag Date: Sun, 28 Jul 2013 14:00:26 +0200 Subject: [PATCH 13/23] more compact layout for the bottom box --- apps/opencs/view/world/genericcreator.cpp | 1 + apps/opencs/view/world/tablebottombox.cpp | 1 + 2 files changed, 2 insertions(+) diff --git a/apps/opencs/view/world/genericcreator.cpp b/apps/opencs/view/world/genericcreator.cpp index 10cbf9447b..f4dd53207d 100644 --- a/apps/opencs/view/world/genericcreator.cpp +++ b/apps/opencs/view/world/genericcreator.cpp @@ -24,6 +24,7 @@ CSVWorld::GenericCreator::GenericCreator (CSMWorld::Data& data, QUndoStack& undo : mData (data), mUndoStack (undoStack), mListId (id) { QHBoxLayout *layout = new QHBoxLayout; + layout->setContentsMargins (0, 0, 0, 0); mId = new QLineEdit; layout->addWidget (mId, 1); diff --git a/apps/opencs/view/world/tablebottombox.cpp b/apps/opencs/view/world/tablebottombox.cpp index f796d89600..b6d0e7807c 100644 --- a/apps/opencs/view/world/tablebottombox.cpp +++ b/apps/opencs/view/world/tablebottombox.cpp @@ -49,6 +49,7 @@ CSVWorld::TableBottomBox::TableBottomBox (const CreatorFactoryBase& creatorFacto setVisible (false); mLayout = new QStackedLayout; + mLayout->setContentsMargins (0, 0, 0, 0); mStatus = new QLabel; From 32c697abc65986b18f32690f89e9687ac2d53b51 Mon Sep 17 00:00:00 2001 From: Marc Zinnschlag Date: Sun, 28 Jul 2013 14:40:11 +0200 Subject: [PATCH 14/23] validate IDs entered by the user --- apps/opencs/CMakeLists.txt | 2 +- apps/opencs/view/world/genericcreator.cpp | 3 +++ apps/opencs/view/world/idvalidator.cpp | 26 +++++++++++++++++++++++ apps/opencs/view/world/idvalidator.hpp | 23 ++++++++++++++++++++ 4 files changed, 53 insertions(+), 1 deletion(-) create mode 100644 apps/opencs/view/world/idvalidator.cpp create mode 100644 apps/opencs/view/world/idvalidator.hpp diff --git a/apps/opencs/CMakeLists.txt b/apps/opencs/CMakeLists.txt index bca37755c5..233c3d0fe9 100644 --- a/apps/opencs/CMakeLists.txt +++ b/apps/opencs/CMakeLists.txt @@ -63,7 +63,7 @@ opencs_units (view/world opencs_units_noqt (view/world dialoguesubview subviews enumdelegate vartypedelegate recordstatusdelegate refidtypedelegate datadisplaydelegate - scripthighlighter + scripthighlighter idvalidator ) diff --git a/apps/opencs/view/world/genericcreator.cpp b/apps/opencs/view/world/genericcreator.cpp index f4dd53207d..f30ada0923 100644 --- a/apps/opencs/view/world/genericcreator.cpp +++ b/apps/opencs/view/world/genericcreator.cpp @@ -10,6 +10,8 @@ #include "../../model/world/data.hpp" #include "../../model/world/idtable.hpp" +#include "idvalidator.hpp" + void CSVWorld::GenericCreator::update() { mErrors = getErrors(); @@ -27,6 +29,7 @@ CSVWorld::GenericCreator::GenericCreator (CSMWorld::Data& data, QUndoStack& undo layout->setContentsMargins (0, 0, 0, 0); mId = new QLineEdit; + mId->setValidator (new IdValidator (this)); layout->addWidget (mId, 1); mCreate = new QPushButton ("Create"); diff --git a/apps/opencs/view/world/idvalidator.cpp b/apps/opencs/view/world/idvalidator.cpp new file mode 100644 index 0000000000..cf6e5d77ba --- /dev/null +++ b/apps/opencs/view/world/idvalidator.cpp @@ -0,0 +1,26 @@ + +#include "idvalidator.hpp" + +bool CSVWorld::IdValidator::isValid (const QChar& c, bool first) const +{ + if (c.isLetter() || c=='_') + return true; + + if (!first && (c.isDigit() || c.isSpace())) + return true; + + return false; +} + +CSVWorld::IdValidator::IdValidator (QObject *parent) : QValidator (parent) {} + +QValidator::State CSVWorld::IdValidator::validate (QString& input, int& pos) const +{ + bool first = true; + + for (QString::const_iterator iter (input.begin()); iter!=input.end(); ++iter, first = false) + if (!isValid (*iter, first)) + return QValidator::Invalid; + + return QValidator::Acceptable; +} \ No newline at end of file diff --git a/apps/opencs/view/world/idvalidator.hpp b/apps/opencs/view/world/idvalidator.hpp new file mode 100644 index 0000000000..db0ecb27a7 --- /dev/null +++ b/apps/opencs/view/world/idvalidator.hpp @@ -0,0 +1,23 @@ +#ifndef CSV_WORLD_IDVALIDATOR_H +#define CSV_WORLD_IDVALIDATOR_H + +#include + +namespace CSVWorld +{ + class IdValidator : public QValidator + { + private: + + bool isValid (const QChar& c, bool first) const; + + public: + + IdValidator (QObject *parent = 0); + + virtual State validate (QString& input, int& pos) const; + + }; +} + +#endif From 124a70906f06849ba42e0e804d41505cab2cda75 Mon Sep 17 00:00:00 2001 From: Marc Zinnschlag Date: Sun, 28 Jul 2013 14:51:47 +0200 Subject: [PATCH 15/23] added creator edit lock --- apps/opencs/view/world/creator.hpp | 2 ++ apps/opencs/view/world/genericcreator.cpp | 21 +++++++++++++++------ apps/opencs/view/world/genericcreator.hpp | 3 +++ apps/opencs/view/world/tablebottombox.cpp | 6 ++++++ apps/opencs/view/world/tablebottombox.hpp | 2 ++ apps/opencs/view/world/tablesubview.cpp | 1 + 6 files changed, 29 insertions(+), 6 deletions(-) diff --git a/apps/opencs/view/world/creator.hpp b/apps/opencs/view/world/creator.hpp index 564a5584e0..a5c1991c39 100644 --- a/apps/opencs/view/world/creator.hpp +++ b/apps/opencs/view/world/creator.hpp @@ -24,6 +24,8 @@ namespace CSVWorld virtual void reset() = 0; + virtual void setEditLock (bool locked) = 0; + signals: void done(); diff --git a/apps/opencs/view/world/genericcreator.cpp b/apps/opencs/view/world/genericcreator.cpp index f30ada0923..cdfd715160 100644 --- a/apps/opencs/view/world/genericcreator.cpp +++ b/apps/opencs/view/world/genericcreator.cpp @@ -18,12 +18,12 @@ void CSVWorld::GenericCreator::update() mCreate->setToolTip (QString::fromUtf8 (mErrors.c_str())); - mCreate->setEnabled (mErrors.empty()); + mCreate->setEnabled (mErrors.empty() && !mLocked); } CSVWorld::GenericCreator::GenericCreator (CSMWorld::Data& data, QUndoStack& undoStack, const CSMWorld::UniversalId& id) -: mData (data), mUndoStack (undoStack), mListId (id) +: mData (data), mUndoStack (undoStack), mListId (id), mLocked (false) { QHBoxLayout *layout = new QHBoxLayout; layout->setContentsMargins (0, 0, 0, 0); @@ -46,6 +46,12 @@ CSVWorld::GenericCreator::GenericCreator (CSMWorld::Data& data, QUndoStack& undo connect (mId, SIGNAL (textChanged (const QString&)), this, SLOT (textChanged (const QString&))); } +void CSVWorld::GenericCreator::setEditLock (bool locked) +{ + mLocked = locked; + update(); +} + void CSVWorld::GenericCreator::reset() { mId->setText (""); @@ -77,9 +83,12 @@ void CSVWorld::GenericCreator::textChanged (const QString& text) void CSVWorld::GenericCreator::create() { - mUndoStack.push (new CSMWorld::CreateCommand ( - dynamic_cast (*mData.getTableModel (mListId)), - mId->text().toUtf8().constData())); + if (!mLocked) + { + mUndoStack.push (new CSMWorld::CreateCommand ( + dynamic_cast (*mData.getTableModel (mListId)), + mId->text().toUtf8().constData())); - emit done(); + emit done(); + } } \ No newline at end of file diff --git a/apps/opencs/view/world/genericcreator.hpp b/apps/opencs/view/world/genericcreator.hpp index a89b4c31f2..b9ea58ad5c 100644 --- a/apps/opencs/view/world/genericcreator.hpp +++ b/apps/opencs/view/world/genericcreator.hpp @@ -20,6 +20,7 @@ namespace CSVWorld QPushButton *mCreate; QLineEdit *mId; std::string mErrors; + bool mLocked; private: @@ -30,6 +31,8 @@ namespace CSVWorld GenericCreator (CSMWorld::Data& data, QUndoStack& undoStack, const CSMWorld::UniversalId& id); + virtual void setEditLock (bool locked); + virtual void reset(); virtual std::string getErrors() const; diff --git a/apps/opencs/view/world/tablebottombox.cpp b/apps/opencs/view/world/tablebottombox.cpp index b6d0e7807c..6a5dc83c1e 100644 --- a/apps/opencs/view/world/tablebottombox.cpp +++ b/apps/opencs/view/world/tablebottombox.cpp @@ -68,6 +68,12 @@ CSVWorld::TableBottomBox::TableBottomBox (const CreatorFactoryBase& creatorFacto connect (mCreator, SIGNAL (done()), this, SLOT (createRequestDone())); } +void CSVWorld::TableBottomBox::setEditLock (bool locked) +{ + if (mCreator) + mCreator->setEditLock (locked); +} + CSVWorld::TableBottomBox::~TableBottomBox() { delete mCreator; diff --git a/apps/opencs/view/world/tablebottombox.hpp b/apps/opencs/view/world/tablebottombox.hpp index 62c552c93a..21e68f51a3 100644 --- a/apps/opencs/view/world/tablebottombox.hpp +++ b/apps/opencs/view/world/tablebottombox.hpp @@ -46,6 +46,8 @@ namespace CSVWorld virtual ~TableBottomBox(); + void setEditLock (bool locked); + void setStatusBar (bool show); bool canCreateAndDelete() const; diff --git a/apps/opencs/view/world/tablesubview.cpp b/apps/opencs/view/world/tablesubview.cpp index 8a828c9bd2..fb1a255cb6 100644 --- a/apps/opencs/view/world/tablesubview.cpp +++ b/apps/opencs/view/world/tablesubview.cpp @@ -46,6 +46,7 @@ CSVWorld::TableSubView::TableSubView (const CSMWorld::UniversalId& id, CSMDoc::D void CSVWorld::TableSubView::setEditLock (bool locked) { mTable->setEditLock (locked); + mBottom->setEditLock (locked); } void CSVWorld::TableSubView::editRequest (int row) From 5ec9d370cb1a68738e098397ba1691e17e539c23 Mon Sep 17 00:00:00 2001 From: Marc Zinnschlag Date: Sun, 28 Jul 2013 15:27:15 +0200 Subject: [PATCH 16/23] check if ID is already in use when creating new IDs --- apps/opencs/model/world/data.cpp | 20 +++++++++++++++++++- apps/opencs/model/world/data.hpp | 2 ++ apps/opencs/view/world/genericcreator.cpp | 4 ++-- 3 files changed, 23 insertions(+), 3 deletions(-) diff --git a/apps/opencs/model/world/data.cpp b/apps/opencs/model/world/data.cpp index d54b3ac161..2a95dfafeb 100644 --- a/apps/opencs/model/world/data.cpp +++ b/apps/opencs/model/world/data.cpp @@ -394,4 +394,22 @@ void CSMWorld::Data::loadFile (const boost::filesystem::path& path, bool base) reader.skipRecord(); } } -} \ No newline at end of file +} + +bool CSMWorld::Data::hasId (const std::string& id) const +{ + return + getGlobals().searchId (id)!=-1 || + getGmsts().searchId (id)!=-1 || + getSkills().searchId (id)!=-1 || + getClasses().searchId (id)!=-1 || + getFactions().searchId (id)!=-1 || + getRaces().searchId (id)!=-1 || + getSounds().searchId (id)!=-1 || + getScripts().searchId (id)!=-1 || + getRegions().searchId (id)!=-1 || + getBirthsigns().searchId (id)!=-1 || + getSpells().searchId (id)!=-1 || + getCells().searchId (id)!=-1 || + getReferenceables().searchId (id)!=-1; +} diff --git a/apps/opencs/model/world/data.hpp b/apps/opencs/model/world/data.hpp index ca030d9b22..10a1fe50de 100644 --- a/apps/opencs/model/world/data.hpp +++ b/apps/opencs/model/world/data.hpp @@ -123,6 +123,8 @@ namespace CSMWorld void loadFile (const boost::filesystem::path& path, bool base); ///< Merging content of a file into base or modified. + + bool hasId (const std::string& id) const; }; } diff --git a/apps/opencs/view/world/genericcreator.cpp b/apps/opencs/view/world/genericcreator.cpp index cdfd715160..0ed7fde6d6 100644 --- a/apps/opencs/view/world/genericcreator.cpp +++ b/apps/opencs/view/world/genericcreator.cpp @@ -68,9 +68,9 @@ std::string CSVWorld::GenericCreator::getErrors() const { errors = "Missing ID"; } - else + else if (mData.hasId (id)) { - + errors = "ID is already in use"; } return errors; From 899e18b2cfe2c8333457c46ce092eb7c07c9d949 Mon Sep 17 00:00:00 2001 From: Marc Zinnschlag Date: Sun, 28 Jul 2013 15:28:35 +0200 Subject: [PATCH 17/23] report ID errors also via input field tool tips --- apps/opencs/view/world/genericcreator.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/apps/opencs/view/world/genericcreator.cpp b/apps/opencs/view/world/genericcreator.cpp index 0ed7fde6d6..de9c5941fd 100644 --- a/apps/opencs/view/world/genericcreator.cpp +++ b/apps/opencs/view/world/genericcreator.cpp @@ -17,6 +17,7 @@ void CSVWorld::GenericCreator::update() mErrors = getErrors(); mCreate->setToolTip (QString::fromUtf8 (mErrors.c_str())); + mId->setToolTip (QString::fromUtf8 (mErrors.c_str())); mCreate->setEnabled (mErrors.empty() && !mLocked); } From 82958e65146bf8ac06aefb33efe02098e03376e7 Mon Sep 17 00:00:00 2001 From: Marc Zinnschlag Date: Sun, 28 Jul 2013 18:08:57 +0200 Subject: [PATCH 18/23] added custom creator for cell records --- apps/opencs/CMakeLists.txt | 1 + apps/opencs/view/world/cellcreator.cpp | 81 +++++++++++++++++++++++ apps/opencs/view/world/cellcreator.hpp | 40 +++++++++++ apps/opencs/view/world/genericcreator.cpp | 32 ++++++--- apps/opencs/view/world/genericcreator.hpp | 12 +++- apps/opencs/view/world/subviews.cpp | 5 +- 6 files changed, 160 insertions(+), 11 deletions(-) create mode 100644 apps/opencs/view/world/cellcreator.cpp create mode 100644 apps/opencs/view/world/cellcreator.hpp diff --git a/apps/opencs/CMakeLists.txt b/apps/opencs/CMakeLists.txt index 233c3d0fe9..8e5d81d764 100644 --- a/apps/opencs/CMakeLists.txt +++ b/apps/opencs/CMakeLists.txt @@ -58,6 +58,7 @@ opencs_hdrs_noqt (view/doc opencs_units (view/world table tablesubview scriptsubview util regionmapsubview tablebottombox creator genericcreator + cellcreator ) opencs_units_noqt (view/world diff --git a/apps/opencs/view/world/cellcreator.cpp b/apps/opencs/view/world/cellcreator.cpp new file mode 100644 index 0000000000..74fb068700 --- /dev/null +++ b/apps/opencs/view/world/cellcreator.cpp @@ -0,0 +1,81 @@ + +#include "cellcreator.hpp" + +#include +#include + +#include +#include +#include + +std::string CSVWorld::CellCreator::getId() const +{ + if (mType->currentIndex()==0) + return GenericCreator::getId(); + + std::ostringstream stream; + + stream << "#" << mX->value() << " " << mY->value(); + + return stream.str(); +} + +CSVWorld::CellCreator::CellCreator (CSMWorld::Data& data, QUndoStack& undoStack, + const CSMWorld::UniversalId& id) +: GenericCreator (data, undoStack, id) +{ + mY = new QSpinBox (this); + mY->setVisible (false); + mY->setMinimum (std::numeric_limits::min()); + mY->setMaximum (std::numeric_limits::max()); + connect (mY, SIGNAL (valueChanged (int)), this, SLOT (valueChanged (int))); + insertAtBeginning (mY, true); + + mYLabel = new QLabel ("Y", this); + mYLabel->setVisible (false); + insertAtBeginning (mYLabel, false); + + mX = new QSpinBox (this); + mX->setVisible (false); + mX->setMinimum (std::numeric_limits::min()); + mX->setMaximum (std::numeric_limits::max()); + connect (mX, SIGNAL (valueChanged (int)), this, SLOT (valueChanged (int))); + insertAtBeginning (mX, true); + + mXLabel = new QLabel ("X", this); + mXLabel->setVisible (false); + insertAtBeginning (mXLabel, false); + + mType = new QComboBox (this); + + mType->addItem ("Interior Cell"); + mType->addItem ("Exterior Cell"); + + connect (mType, SIGNAL (currentIndexChanged (int)), this, SLOT (setType (int))); + + insertAtBeginning (mType, false); +} + +void CSVWorld::CellCreator::reset() +{ + mX->setValue (0); + mY->setValue (0); + mType->setCurrentIndex (0); + GenericCreator::reset(); +} + +void CSVWorld::CellCreator::setType (int index) +{ + setManualEditing (index==0); + mXLabel->setVisible (index==1); + mX->setVisible (index==1); + mYLabel->setVisible (index==1); + mY->setVisible (index==1); + + update(); +} + +void CSVWorld::CellCreator::valueChanged (int index) +{ + update(); +} \ No newline at end of file diff --git a/apps/opencs/view/world/cellcreator.hpp b/apps/opencs/view/world/cellcreator.hpp new file mode 100644 index 0000000000..a5473e2c97 --- /dev/null +++ b/apps/opencs/view/world/cellcreator.hpp @@ -0,0 +1,40 @@ +#ifndef CSV_WORLD_CELLCREATOR_H +#define CSV_WORLD_CELLCREATOR_H + +class QLabel; +class QSpinBox; +class QComboBox; + +#include "genericcreator.hpp" + +namespace CSVWorld +{ + class CellCreator : public GenericCreator + { + Q_OBJECT + + QComboBox *mType; + QLabel *mXLabel; + QSpinBox *mX; + QLabel *mYLabel; + QSpinBox *mY; + + protected: + + virtual std::string getId() const; + + public: + + CellCreator (CSMWorld::Data& data, QUndoStack& undoStack, const CSMWorld::UniversalId& id); + + virtual void reset(); + + private slots: + + void setType (int index); + + void valueChanged (int index); + }; +} + +#endif diff --git a/apps/opencs/view/world/genericcreator.cpp b/apps/opencs/view/world/genericcreator.cpp index de9c5941fd..ba965bc94d 100644 --- a/apps/opencs/view/world/genericcreator.cpp +++ b/apps/opencs/view/world/genericcreator.cpp @@ -22,24 +22,39 @@ void CSVWorld::GenericCreator::update() mCreate->setEnabled (mErrors.empty() && !mLocked); } +void CSVWorld::GenericCreator::setManualEditing (bool enabled) +{ + mId->setVisible (enabled); +} + +void CSVWorld::GenericCreator::insertAtBeginning (QWidget *widget, bool stretched) +{ + mLayout->insertWidget (0, widget, stretched ? 1 : 0); +} + +std::string CSVWorld::GenericCreator::getId() const +{ + return mId->text().toUtf8().constData(); +} + CSVWorld::GenericCreator::GenericCreator (CSMWorld::Data& data, QUndoStack& undoStack, const CSMWorld::UniversalId& id) : mData (data), mUndoStack (undoStack), mListId (id), mLocked (false) { - QHBoxLayout *layout = new QHBoxLayout; - layout->setContentsMargins (0, 0, 0, 0); + mLayout = new QHBoxLayout; + mLayout->setContentsMargins (0, 0, 0, 0); mId = new QLineEdit; mId->setValidator (new IdValidator (this)); - layout->addWidget (mId, 1); + mLayout->addWidget (mId, 1); mCreate = new QPushButton ("Create"); - layout->addWidget (mCreate); + mLayout->addWidget (mCreate); QPushButton *cancelButton = new QPushButton ("Cancel"); - layout->addWidget (cancelButton); + mLayout->addWidget (cancelButton); - setLayout (layout); + setLayout (mLayout); connect (cancelButton, SIGNAL (clicked (bool)), this, SIGNAL (done())); connect (mCreate, SIGNAL (clicked (bool)), this, SLOT (create())); @@ -63,7 +78,7 @@ std::string CSVWorld::GenericCreator::getErrors() const { std::string errors; - std::string id = mId->text().toUtf8().constData(); + std::string id = getId(); if (id.empty()) { @@ -87,8 +102,7 @@ void CSVWorld::GenericCreator::create() if (!mLocked) { mUndoStack.push (new CSMWorld::CreateCommand ( - dynamic_cast (*mData.getTableModel (mListId)), - mId->text().toUtf8().constData())); + dynamic_cast (*mData.getTableModel (mListId)), getId())); emit done(); } diff --git a/apps/opencs/view/world/genericcreator.hpp b/apps/opencs/view/world/genericcreator.hpp index b9ea58ad5c..2798d89a14 100644 --- a/apps/opencs/view/world/genericcreator.hpp +++ b/apps/opencs/view/world/genericcreator.hpp @@ -3,6 +3,7 @@ class QPushButton; class QLineEdit; +class QHBoxLayout; #include "creator.hpp" @@ -20,12 +21,20 @@ namespace CSVWorld QPushButton *mCreate; QLineEdit *mId; std::string mErrors; + QHBoxLayout *mLayout; bool mLocked; - private: + protected: void update(); + virtual void setManualEditing (bool enabled); + ///< Enable/disable manual ID editing (enabled by default). + + void insertAtBeginning (QWidget *widget, bool stretched); + + virtual std::string getId() const; + public: GenericCreator (CSMWorld::Data& data, QUndoStack& undoStack, @@ -39,6 +48,7 @@ namespace CSVWorld ///< Return formatted error descriptions for the current state of the creator. if an empty /// string is returned, there is no error. + private slots: void textChanged (const QString& text); diff --git a/apps/opencs/view/world/subviews.cpp b/apps/opencs/view/world/subviews.cpp index 3ad4b36c6d..9fbbe4a0da 100644 --- a/apps/opencs/view/world/subviews.cpp +++ b/apps/opencs/view/world/subviews.cpp @@ -8,6 +8,7 @@ #include "scriptsubview.hpp" #include "regionmapsubview.hpp" #include "genericcreator.hpp" +#include "cellcreator.hpp" void CSVWorld::addSubViewFactories (CSVDoc::SubViewFactoryManager& manager) { @@ -28,7 +29,6 @@ void CSVWorld::addSubViewFactories (CSVDoc::SubViewFactoryManager& manager) CSMWorld::UniversalId::Type_Regions, CSMWorld::UniversalId::Type_Birthsigns, CSMWorld::UniversalId::Type_Spells, - CSMWorld::UniversalId::Type_Cells, CSMWorld::UniversalId::Type_Referenceables, CSMWorld::UniversalId::Type_References, @@ -39,6 +39,9 @@ void CSVWorld::addSubViewFactories (CSVDoc::SubViewFactoryManager& manager) manager.add (sTableTypes[i], new CSVDoc::SubViewFactoryWithCreator >); + manager.add (CSMWorld::UniversalId::Type_Cells, + new CSVDoc::SubViewFactoryWithCreator >); + manager.add (CSMWorld::UniversalId::Type_Script, new CSVDoc::SubViewFactory); manager.add (CSMWorld::UniversalId::Type_RegionMap, new CSVDoc::SubViewFactory); From 661b290c4924ca1526c30797b94716f0f8ddd269 Mon Sep 17 00:00:00 2001 From: Marc Zinnschlag Date: Mon, 29 Jul 2013 15:00:41 +0200 Subject: [PATCH 19/23] automatically scroll table to the position of a newly created record --- apps/opencs/view/world/creator.hpp | 4 ++++ apps/opencs/view/world/genericcreator.cpp | 5 ++++- apps/opencs/view/world/table.cpp | 8 ++++++++ apps/opencs/view/world/table.hpp | 2 ++ apps/opencs/view/world/tablebottombox.cpp | 3 +++ apps/opencs/view/world/tablebottombox.hpp | 6 ++++++ apps/opencs/view/world/tablesubview.cpp | 3 +++ 7 files changed, 30 insertions(+), 1 deletion(-) diff --git a/apps/opencs/view/world/creator.hpp b/apps/opencs/view/world/creator.hpp index a5c1991c39..df9b116eed 100644 --- a/apps/opencs/view/world/creator.hpp +++ b/apps/opencs/view/world/creator.hpp @@ -29,6 +29,10 @@ namespace CSVWorld signals: void done(); + + void requestFocus (const std::string& id); + ///< Request owner of this creator to focus the just created \a id. The owner may + /// ignore this request. }; /// \brief Base class for Creator factory diff --git a/apps/opencs/view/world/genericcreator.cpp b/apps/opencs/view/world/genericcreator.cpp index ba965bc94d..41ae5c90a7 100644 --- a/apps/opencs/view/world/genericcreator.cpp +++ b/apps/opencs/view/world/genericcreator.cpp @@ -101,9 +101,12 @@ void CSVWorld::GenericCreator::create() { if (!mLocked) { + std::string id = getId(); + mUndoStack.push (new CSMWorld::CreateCommand ( - dynamic_cast (*mData.getTableModel (mListId)), getId())); + dynamic_cast (*mData.getTableModel (mListId)), id)); emit done(); + emit requestFocus (id); } } \ No newline at end of file diff --git a/apps/opencs/view/world/table.cpp b/apps/opencs/view/world/table.cpp index c35d7358a0..fdbf67e427 100644 --- a/apps/opencs/view/world/table.cpp +++ b/apps/opencs/view/world/table.cpp @@ -282,4 +282,12 @@ void CSVWorld::Table::tableSizeUpdate() void CSVWorld::Table::selectionSizeUpdate() { selectionSizeChanged (selectionModel()->selectedRows().size()); +} + +void CSVWorld::Table::requestFocus (const std::string& id) +{ + QModelIndex index = mProxyModel->getModelIndex (id, 0); + + if (index.isValid()) + scrollTo (index, QAbstractItemView::PositionAtTop); } \ No newline at end of file diff --git a/apps/opencs/view/world/table.hpp b/apps/opencs/view/world/table.hpp index 2a59270b89..0c24e7b54c 100644 --- a/apps/opencs/view/world/table.hpp +++ b/apps/opencs/view/world/table.hpp @@ -83,6 +83,8 @@ namespace CSVWorld void selectionSizeUpdate(); + void requestFocus (const std::string& id); + }; } diff --git a/apps/opencs/view/world/tablebottombox.cpp b/apps/opencs/view/world/tablebottombox.cpp index 6a5dc83c1e..6cf21a1322 100644 --- a/apps/opencs/view/world/tablebottombox.cpp +++ b/apps/opencs/view/world/tablebottombox.cpp @@ -66,6 +66,9 @@ CSVWorld::TableBottomBox::TableBottomBox (const CreatorFactoryBase& creatorFacto mLayout->addWidget (mCreator); connect (mCreator, SIGNAL (done()), this, SLOT (createRequestDone())); + + connect (mCreator, SIGNAL (requestFocus (const std::string&)), + this, SIGNAL (requestFocus (const std::string&))); } void CSVWorld::TableBottomBox::setEditLock (bool locked) diff --git a/apps/opencs/view/world/tablebottombox.hpp b/apps/opencs/view/world/tablebottombox.hpp index 21e68f51a3..a5ae5e0bd9 100644 --- a/apps/opencs/view/world/tablebottombox.hpp +++ b/apps/opencs/view/world/tablebottombox.hpp @@ -55,6 +55,12 @@ namespace CSVWorld /// /// \note The BotomBox does not partake in the deletion of records. + signals: + + void requestFocus (const std::string& id); + ///< Request owner of this box to focus the just created \a id. The owner may + /// ignore this request. + private slots: void createRequestDone(); diff --git a/apps/opencs/view/world/tablesubview.cpp b/apps/opencs/view/world/tablesubview.cpp index fb1a255cb6..af3d186e85 100644 --- a/apps/opencs/view/world/tablesubview.cpp +++ b/apps/opencs/view/world/tablesubview.cpp @@ -41,6 +41,9 @@ CSVWorld::TableSubView::TableSubView (const CSMWorld::UniversalId& id, CSMDoc::D if (mBottom->canCreateAndDelete()) connect (mTable, SIGNAL (createRequest()), mBottom, SLOT (createRequest())); + + connect (mBottom, SIGNAL (requestFocus (const std::string&)), + mTable, SLOT (requestFocus (const std::string&))); } void CSVWorld::TableSubView::setEditLock (bool locked) From 34c825ce5287ef5894a74c08f0511c857fe372b5 Mon Sep 17 00:00:00 2001 From: Marc Zinnschlag Date: Mon, 29 Jul 2013 16:21:42 +0200 Subject: [PATCH 20/23] added icons and type listing to UniversalId class --- apps/opencs/model/world/universalid.cpp | 137 +++++++++++-------- apps/opencs/model/world/universalid.hpp | 21 ++- apps/opencs/view/world/refidtypedelegate.cpp | 29 ++-- 3 files changed, 103 insertions(+), 84 deletions(-) diff --git a/apps/opencs/model/world/universalid.cpp b/apps/opencs/model/world/universalid.cpp index c66101950b..5c85ff6208 100644 --- a/apps/opencs/model/world/universalid.cpp +++ b/apps/opencs/model/world/universalid.cpp @@ -12,81 +12,82 @@ namespace CSMWorld::UniversalId::Class mClass; CSMWorld::UniversalId::Type mType; const char *mName; + const char *mIcon; }; static const TypeData sNoArg[] = { - { CSMWorld::UniversalId::Class_None, CSMWorld::UniversalId::Type_None, "empty" }, - { CSMWorld::UniversalId::Class_RecordList, CSMWorld::UniversalId::Type_Globals, "Global Variables" }, - { CSMWorld::UniversalId::Class_RecordList, CSMWorld::UniversalId::Type_Gmsts, "Game Settings" }, - { CSMWorld::UniversalId::Class_RecordList, CSMWorld::UniversalId::Type_Skills, "Skills" }, - { CSMWorld::UniversalId::Class_RecordList, CSMWorld::UniversalId::Type_Classes, "Classes" }, - { CSMWorld::UniversalId::Class_RecordList, CSMWorld::UniversalId::Type_Factions, "Factions" }, - { CSMWorld::UniversalId::Class_RecordList, CSMWorld::UniversalId::Type_Races, "Races" }, - { CSMWorld::UniversalId::Class_RecordList, CSMWorld::UniversalId::Type_Sounds, "Sounds" }, - { CSMWorld::UniversalId::Class_RecordList, CSMWorld::UniversalId::Type_Scripts, "Scripts" }, - { CSMWorld::UniversalId::Class_RecordList, CSMWorld::UniversalId::Type_Regions, "Regions" }, - { CSMWorld::UniversalId::Class_RecordList, CSMWorld::UniversalId::Type_Birthsigns, "Birthsigns" }, - { CSMWorld::UniversalId::Class_RecordList, CSMWorld::UniversalId::Type_Spells, "Spells" }, - { CSMWorld::UniversalId::Class_RecordList, CSMWorld::UniversalId::Type_Cells, "Cells" }, + { CSMWorld::UniversalId::Class_None, CSMWorld::UniversalId::Type_None, "empty", 0 }, + { CSMWorld::UniversalId::Class_RecordList, CSMWorld::UniversalId::Type_Globals, "Global Variables", 0 }, + { CSMWorld::UniversalId::Class_RecordList, CSMWorld::UniversalId::Type_Gmsts, "Game Settings", 0 }, + { CSMWorld::UniversalId::Class_RecordList, CSMWorld::UniversalId::Type_Skills, "Skills", 0 }, + { CSMWorld::UniversalId::Class_RecordList, CSMWorld::UniversalId::Type_Classes, "Classes", 0 }, + { CSMWorld::UniversalId::Class_RecordList, CSMWorld::UniversalId::Type_Factions, "Factions", 0 }, + { CSMWorld::UniversalId::Class_RecordList, CSMWorld::UniversalId::Type_Races, "Races", 0 }, + { CSMWorld::UniversalId::Class_RecordList, CSMWorld::UniversalId::Type_Sounds, "Sounds", 0 }, + { CSMWorld::UniversalId::Class_RecordList, CSMWorld::UniversalId::Type_Scripts, "Scripts", 0 }, + { CSMWorld::UniversalId::Class_RecordList, CSMWorld::UniversalId::Type_Regions, "Regions", 0 }, + { CSMWorld::UniversalId::Class_RecordList, CSMWorld::UniversalId::Type_Birthsigns, "Birthsigns", 0 }, + { CSMWorld::UniversalId::Class_RecordList, CSMWorld::UniversalId::Type_Spells, "Spells", 0 }, + { CSMWorld::UniversalId::Class_RecordList, CSMWorld::UniversalId::Type_Cells, "Cells", 0 }, { CSMWorld::UniversalId::Class_RecordList, CSMWorld::UniversalId::Type_Referenceables, - "Referenceables" }, + "Referenceables", 0 }, { CSMWorld::UniversalId::Class_RecordList, CSMWorld::UniversalId::Type_References, - "References" }, + "References", 0 }, { CSMWorld::UniversalId::Class_NonRecord, CSMWorld::UniversalId::Type_RegionMap, - "Region Map" }, + "Region Map", 0 }, - { CSMWorld::UniversalId::Class_None, CSMWorld::UniversalId::Type_None, 0 } // end marker + { CSMWorld::UniversalId::Class_None, CSMWorld::UniversalId::Type_None, 0, 0 } // end marker }; static const TypeData sIdArg[] = { - { CSMWorld::UniversalId::Class_Record, CSMWorld::UniversalId::Type_Global, "Global Variable" }, - { CSMWorld::UniversalId::Class_Record, CSMWorld::UniversalId::Type_Gmst, "Game Setting" }, - { CSMWorld::UniversalId::Class_Record, CSMWorld::UniversalId::Type_Skill, "Skill" }, - { CSMWorld::UniversalId::Class_Record, CSMWorld::UniversalId::Type_Class, "Class" }, - { CSMWorld::UniversalId::Class_Record, CSMWorld::UniversalId::Type_Faction, "Faction" }, - { CSMWorld::UniversalId::Class_Record, CSMWorld::UniversalId::Type_Race, "Race" }, - { CSMWorld::UniversalId::Class_Record, CSMWorld::UniversalId::Type_Sound, "Sound" }, - { CSMWorld::UniversalId::Class_Record, CSMWorld::UniversalId::Type_Script, "Script" }, - { CSMWorld::UniversalId::Class_Record, CSMWorld::UniversalId::Type_Region, "Region" }, - { CSMWorld::UniversalId::Class_Record, CSMWorld::UniversalId::Type_Birthsign, "Birthsign" }, - { CSMWorld::UniversalId::Class_Record, CSMWorld::UniversalId::Type_Spell, "Spell" }, - { CSMWorld::UniversalId::Class_Record, CSMWorld::UniversalId::Type_Cell, "Cell" }, - { CSMWorld::UniversalId::Class_Record, CSMWorld::UniversalId::Type_Referenceable, "Referenceables" }, - { CSMWorld::UniversalId::Class_Record, CSMWorld::UniversalId::Type_Activator, "Activator" }, - { CSMWorld::UniversalId::Class_Record, CSMWorld::UniversalId::Type_Potion, "Potion" }, - { CSMWorld::UniversalId::Class_Record, CSMWorld::UniversalId::Type_Apparatus, "Apparatus" }, - { CSMWorld::UniversalId::Class_Record, CSMWorld::UniversalId::Type_Armor, "Armor" }, - { CSMWorld::UniversalId::Class_Record, CSMWorld::UniversalId::Type_Book, "Book" }, - { CSMWorld::UniversalId::Class_Record, CSMWorld::UniversalId::Type_Clothing, "Clothing" }, - { CSMWorld::UniversalId::Class_Record, CSMWorld::UniversalId::Type_Container, "Container" }, - { CSMWorld::UniversalId::Class_Record, CSMWorld::UniversalId::Type_Creature, "Creature" }, - { CSMWorld::UniversalId::Class_Record, CSMWorld::UniversalId::Type_Door, "Door" }, - { CSMWorld::UniversalId::Class_Record, CSMWorld::UniversalId::Type_Ingredient, "Ingredient" }, - { CSMWorld::UniversalId::Class_Record, CSMWorld::UniversalId::Type_CreatureLevelledList, - "Creature Levelled List" }, - { CSMWorld::UniversalId::Class_Record, CSMWorld::UniversalId::Type_ItemLevelledList, - "Item Levelled List" }, - { CSMWorld::UniversalId::Class_Record, CSMWorld::UniversalId::Type_Light, "Light" }, - { CSMWorld::UniversalId::Class_Record, CSMWorld::UniversalId::Type_Lockpick, "Lockpick" }, - { CSMWorld::UniversalId::Class_Record, CSMWorld::UniversalId::Type_Miscellaneous, - "Miscellaneous" }, - { CSMWorld::UniversalId::Class_Record, CSMWorld::UniversalId::Type_Npc, "NPC" }, - { CSMWorld::UniversalId::Class_Record, CSMWorld::UniversalId::Type_Probe, "Probe" }, - { CSMWorld::UniversalId::Class_Record, CSMWorld::UniversalId::Type_Repair, "Repair" }, - { CSMWorld::UniversalId::Class_Record, CSMWorld::UniversalId::Type_Static, "Static" }, - { CSMWorld::UniversalId::Class_Record, CSMWorld::UniversalId::Type_Weapon, "Weapon" }, - { CSMWorld::UniversalId::Class_Record, CSMWorld::UniversalId::Type_Reference, "Reference" }, + { CSMWorld::UniversalId::Class_Record, CSMWorld::UniversalId::Type_Global, "Global Variable", 0 }, + { CSMWorld::UniversalId::Class_Record, CSMWorld::UniversalId::Type_Gmst, "Game Setting", 0 }, + { CSMWorld::UniversalId::Class_Record, CSMWorld::UniversalId::Type_Skill, "Skill", 0 }, + { CSMWorld::UniversalId::Class_Record, CSMWorld::UniversalId::Type_Class, "Class", 0 }, + { CSMWorld::UniversalId::Class_Record, CSMWorld::UniversalId::Type_Faction, "Faction", 0 }, + { CSMWorld::UniversalId::Class_Record, CSMWorld::UniversalId::Type_Race, "Race", 0 }, + { CSMWorld::UniversalId::Class_Record, CSMWorld::UniversalId::Type_Sound, "Sound", 0 }, + { CSMWorld::UniversalId::Class_Record, CSMWorld::UniversalId::Type_Script, "Script", 0 }, + { CSMWorld::UniversalId::Class_Record, CSMWorld::UniversalId::Type_Region, "Region", 0 }, + { CSMWorld::UniversalId::Class_Record, CSMWorld::UniversalId::Type_Birthsign, "Birthsign", 0 }, + { CSMWorld::UniversalId::Class_Record, CSMWorld::UniversalId::Type_Spell, "Spell", 0 }, + { CSMWorld::UniversalId::Class_Record, CSMWorld::UniversalId::Type_Cell, "Cell", 0 }, + { CSMWorld::UniversalId::Class_Record, CSMWorld::UniversalId::Type_Referenceable, "Referenceables", 0 }, + { CSMWorld::UniversalId::Class_RefRecord, CSMWorld::UniversalId::Type_Activator, "Activator", ":./activator.png" }, + { CSMWorld::UniversalId::Class_RefRecord, CSMWorld::UniversalId::Type_Potion, "Potion", ":./potion.png" }, + { CSMWorld::UniversalId::Class_RefRecord, CSMWorld::UniversalId::Type_Apparatus, "Apparatus", ":./apparatus.png" }, + { CSMWorld::UniversalId::Class_RefRecord, CSMWorld::UniversalId::Type_Armor, "Armor", ":./armor.png" }, + { CSMWorld::UniversalId::Class_RefRecord, CSMWorld::UniversalId::Type_Book, "Book", ":./book.png" }, + { CSMWorld::UniversalId::Class_RefRecord, CSMWorld::UniversalId::Type_Clothing, "Clothing", ":./clothing.png" }, + { CSMWorld::UniversalId::Class_RefRecord, CSMWorld::UniversalId::Type_Container, "Container", ":./container.png" }, + { CSMWorld::UniversalId::Class_RefRecord, CSMWorld::UniversalId::Type_Creature, "Creature", ":./creature.png" }, + { CSMWorld::UniversalId::Class_RefRecord, CSMWorld::UniversalId::Type_Door, "Door", ":./door.png" }, + { CSMWorld::UniversalId::Class_RefRecord, CSMWorld::UniversalId::Type_Ingredient, "Ingredient", ":./ingredient.png" }, + { CSMWorld::UniversalId::Class_RefRecord, CSMWorld::UniversalId::Type_CreatureLevelledList, + "Creature Levelled List", ":./creature.png" }, + { CSMWorld::UniversalId::Class_RefRecord, CSMWorld::UniversalId::Type_ItemLevelledList, + "Item Levelled List", ":./item.png" }, + { CSMWorld::UniversalId::Class_RefRecord, CSMWorld::UniversalId::Type_Light, "Light", ":./light.png" }, + { CSMWorld::UniversalId::Class_RefRecord, CSMWorld::UniversalId::Type_Lockpick, "Lockpick", ":./lockpick.png" }, + { CSMWorld::UniversalId::Class_RefRecord, CSMWorld::UniversalId::Type_Miscellaneous, + "Miscellaneous", ":./misc.png" }, + { CSMWorld::UniversalId::Class_RefRecord, CSMWorld::UniversalId::Type_Npc, "NPC", ":./npc.png" }, + { CSMWorld::UniversalId::Class_RefRecord, CSMWorld::UniversalId::Type_Probe, "Probe", ":./probe.png" }, + { CSMWorld::UniversalId::Class_RefRecord, CSMWorld::UniversalId::Type_Repair, "Repair", ":./repair.png" }, + { CSMWorld::UniversalId::Class_RefRecord, CSMWorld::UniversalId::Type_Static, "Static", ":./static.png" }, + { CSMWorld::UniversalId::Class_RefRecord, CSMWorld::UniversalId::Type_Weapon, "Weapon", ":./weapon.png" }, + { CSMWorld::UniversalId::Class_SubRecord, CSMWorld::UniversalId::Type_Reference, "Reference", 0 }, - { CSMWorld::UniversalId::Class_None, CSMWorld::UniversalId::Type_None, 0 } // end marker + { CSMWorld::UniversalId::Class_None, CSMWorld::UniversalId::Type_None, 0, 0 } // end marker }; static const TypeData sIndexArg[] = { - { CSMWorld::UniversalId::Class_Transient, CSMWorld::UniversalId::Type_VerificationResults, "Verification Results" }, + { CSMWorld::UniversalId::Class_Transient, CSMWorld::UniversalId::Type_VerificationResults, "Verification Results", 0 }, - { CSMWorld::UniversalId::Class_None, CSMWorld::UniversalId::Type_None, 0 } // end marker + { CSMWorld::UniversalId::Class_None, CSMWorld::UniversalId::Type_None, 0, 0 } // end marker }; static const unsigned int IDARG_SIZE = sizeof (sIdArg) / sizeof (TypeData); @@ -268,6 +269,28 @@ std::string CSMWorld::UniversalId::toString() const return stream.str(); } +std::string CSMWorld::UniversalId::getIcon() const +{ + const TypeData *typeData = mArgumentType==ArgumentType_None ? sNoArg : + (mArgumentType==ArgumentType_Id ? sIdArg : sIndexArg); + + for (int i=0; typeData[i].mName; ++i) + if (typeData[i].mType==mType) + return typeData[i].mIcon ? typeData[i].mIcon : ""; + + throw std::logic_error ("failed to retrieve UniversalId type icon"); +} + +std::vector CSMWorld::UniversalId::listReferenceableTypes() +{ + std::vector list; + + for (int i=0; sIdArg[i].mName; ++i) + if (sIdArg[i].mClass==Class_RefRecord) + list.push_back (sIdArg[i].mType); + + return list; +} std::pair CSMWorld::UniversalId::getIdArgPair (unsigned int index) { diff --git a/apps/opencs/model/world/universalid.hpp b/apps/opencs/model/world/universalid.hpp index 453da3ef32..7dc4c851aa 100644 --- a/apps/opencs/model/world/universalid.hpp +++ b/apps/opencs/model/world/universalid.hpp @@ -3,6 +3,7 @@ #include #include +#include #include @@ -14,13 +15,14 @@ namespace CSMWorld enum Class { - Class_None = 0, - Class_Record, - Class_SubRecord, - Class_RecordList, - Class_Collection, // multiple types of records combined - Class_Transient, // not part of the world data or the project data - Class_NonRecord // record like data that is not part of the world + Class_None = 0, + Class_Record, + Class_RefRecord, // referenceable record + Class_SubRecord, + Class_RecordList, + Class_Collection, // multiple types of records combined + Class_Transient, // not part of the world data or the project data + Class_NonRecord // record like data that is not part of the world }; enum ArgumentType @@ -126,6 +128,11 @@ namespace CSMWorld std::string toString() const; + std::string getIcon() const; + ///< Will return an empty string, if no icon is available. + + static std::vector listReferenceableTypes(); + static std::pair getIdArgPair (unsigned int index); static unsigned int getIdArgSize (); }; diff --git a/apps/opencs/view/world/refidtypedelegate.cpp b/apps/opencs/view/world/refidtypedelegate.cpp index 40bf88584d..bf3acbb206 100755 --- a/apps/opencs/view/world/refidtypedelegate.cpp +++ b/apps/opencs/view/world/refidtypedelegate.cpp @@ -27,26 +27,15 @@ CSVWorld::RefIdTypeDelegateFactory::UidTypeList CSVWorld::RefIdTypeDelegateFacto { UidTypeList list; - list.push_back (std::make_pair (CSMWorld::UniversalId::Type_Activator, ":./activator.png")); - list.push_back (std::make_pair (CSMWorld::UniversalId::Type_Potion, ":./potion.png")); - list.push_back (std::make_pair (CSMWorld::UniversalId::Type_Apparatus, ":./apparatus.png")); - list.push_back (std::make_pair (CSMWorld::UniversalId::Type_Armor, ":./armor.png")); - list.push_back (std::make_pair (CSMWorld::UniversalId::Type_Book, ":./book.png")); - list.push_back (std::make_pair (CSMWorld::UniversalId::Type_Clothing, ":./clothing.png")); - list.push_back (std::make_pair (CSMWorld::UniversalId::Type_Container, ":./container.png")); - list.push_back (std::make_pair (CSMWorld::UniversalId::Type_Creature, ":./creature.png")); - list.push_back (std::make_pair (CSMWorld::UniversalId::Type_Door, ":./door.png")); - list.push_back (std::make_pair (CSMWorld::UniversalId::Type_Ingredient, ":./ingredient.png")); - list.push_back (std::make_pair (CSMWorld::UniversalId::Type_CreatureLevelledList, ":./creature.png")); - list.push_back (std::make_pair (CSMWorld::UniversalId::Type_ItemLevelledList, ":./item.png")); - list.push_back (std::make_pair (CSMWorld::UniversalId::Type_Light, ":./light.png")); - list.push_back (std::make_pair (CSMWorld::UniversalId::Type_Lockpick, ":./lockpick.png")); - list.push_back (std::make_pair (CSMWorld::UniversalId::Type_Miscellaneous, ":./misc.png")); - list.push_back (std::make_pair (CSMWorld::UniversalId::Type_Npc, ":./npc.png")); - list.push_back (std::make_pair (CSMWorld::UniversalId::Type_Probe, ":./probe.png")); - list.push_back (std::make_pair (CSMWorld::UniversalId::Type_Repair, ":./repair.png")); - list.push_back (std::make_pair (CSMWorld::UniversalId::Type_Static, ":./static.png")); - list.push_back (std::make_pair (CSMWorld::UniversalId::Type_Weapon, ":./weapon.png")); + std::vector types = CSMWorld::UniversalId::listReferenceableTypes(); + + for (std::vector::const_iterator iter (types.begin()); + iter!=types.end(); ++iter) + { + CSMWorld::UniversalId id (*iter, ""); + + list.push_back (std::make_pair (id.getType(), id.getIcon().c_str())); + } return list; } From 57be764cce50d6d922dfad8156d8cd0ced4305e1 Mon Sep 17 00:00:00 2001 From: Marc Zinnschlag Date: Tue, 30 Jul 2013 10:27:17 +0200 Subject: [PATCH 21/23] added specialised Creator for referenceable records --- apps/opencs/CMakeLists.txt | 2 +- apps/opencs/model/world/commands.cpp | 9 +++- apps/opencs/model/world/commands.hpp | 5 +++ apps/opencs/model/world/idtable.cpp | 4 +- apps/opencs/model/world/idtable.hpp | 5 ++- apps/opencs/view/world/genericcreator.cpp | 15 ++++++- apps/opencs/view/world/genericcreator.hpp | 9 ++++ .../view/world/referenceablecreator.cpp | 43 +++++++++++++++++++ .../view/world/referenceablecreator.hpp | 30 +++++++++++++ apps/opencs/view/world/subviews.cpp | 5 ++- 10 files changed, 119 insertions(+), 8 deletions(-) create mode 100644 apps/opencs/view/world/referenceablecreator.cpp create mode 100644 apps/opencs/view/world/referenceablecreator.hpp diff --git a/apps/opencs/CMakeLists.txt b/apps/opencs/CMakeLists.txt index 8e5d81d764..75258a175a 100644 --- a/apps/opencs/CMakeLists.txt +++ b/apps/opencs/CMakeLists.txt @@ -58,7 +58,7 @@ opencs_hdrs_noqt (view/doc opencs_units (view/world table tablesubview scriptsubview util regionmapsubview tablebottombox creator genericcreator - cellcreator + cellcreator referenceablecreator ) opencs_units_noqt (view/world diff --git a/apps/opencs/model/world/commands.cpp b/apps/opencs/model/world/commands.cpp index 3bcdf8b050..9281e6e330 100644 --- a/apps/opencs/model/world/commands.cpp +++ b/apps/opencs/model/world/commands.cpp @@ -26,14 +26,19 @@ void CSMWorld::ModifyCommand::undo() } CSMWorld::CreateCommand::CreateCommand (IdTable& model, const std::string& id, QUndoCommand *parent) -: QUndoCommand (parent), mModel (model), mId (id) +: QUndoCommand (parent), mModel (model), mId (id), mType (UniversalId::Type_None) { setText (("Create record " + id).c_str()); } +void CSMWorld::CreateCommand::setType (UniversalId::Type type) +{ + mType = type; +} + void CSMWorld::CreateCommand::redo() { - mModel.addRecord (mId); + mModel.addRecord (mId, mType); } void CSMWorld::CreateCommand::undo() diff --git a/apps/opencs/model/world/commands.hpp b/apps/opencs/model/world/commands.hpp index 1fa124277f..6272c3fb7b 100644 --- a/apps/opencs/model/world/commands.hpp +++ b/apps/opencs/model/world/commands.hpp @@ -9,6 +9,8 @@ #include #include +#include "universalid.hpp" + class QModelIndex; class QAbstractItemModel; @@ -39,11 +41,14 @@ namespace CSMWorld { IdTable& mModel; std::string mId; + UniversalId::Type mType; public: CreateCommand (IdTable& model, const std::string& id, QUndoCommand *parent = 0); + void setType (UniversalId::Type type); + virtual void redo(); virtual void undo(); diff --git a/apps/opencs/model/world/idtable.cpp b/apps/opencs/model/world/idtable.cpp index 25258398bd..3d36b55038 100644 --- a/apps/opencs/model/world/idtable.cpp +++ b/apps/opencs/model/world/idtable.cpp @@ -116,13 +116,13 @@ QModelIndex CSMWorld::IdTable::parent (const QModelIndex& index) const return QModelIndex(); } -void CSMWorld::IdTable::addRecord (const std::string& id) +void CSMWorld::IdTable::addRecord (const std::string& id, UniversalId::Type type) { int index = mIdCollection->getAppendIndex(); beginInsertRows (QModelIndex(), index, index); - mIdCollection->appendBlankRecord (id); + mIdCollection->appendBlankRecord (id, type); endInsertRows(); } diff --git a/apps/opencs/model/world/idtable.hpp b/apps/opencs/model/world/idtable.hpp index 98bf6ad6d1..556d7f0bad 100644 --- a/apps/opencs/model/world/idtable.hpp +++ b/apps/opencs/model/world/idtable.hpp @@ -3,6 +3,8 @@ #include +#include "universalid.hpp" + namespace CSMWorld { class CollectionBase; @@ -44,7 +46,8 @@ namespace CSMWorld virtual QModelIndex parent (const QModelIndex& index) const; - void addRecord (const std::string& id); + void addRecord (const std::string& id, UniversalId::Type type = UniversalId::Type_None); + ///< \param type Will be ignored, unless the collection supports multiple record types QModelIndex getModelIndex (const std::string& id, int column) const; diff --git a/apps/opencs/view/world/genericcreator.cpp b/apps/opencs/view/world/genericcreator.cpp index 41ae5c90a7..6c402818ce 100644 --- a/apps/opencs/view/world/genericcreator.cpp +++ b/apps/opencs/view/world/genericcreator.cpp @@ -1,6 +1,8 @@ #include "genericcreator.hpp" +#include + #include #include #include @@ -32,11 +34,18 @@ void CSVWorld::GenericCreator::insertAtBeginning (QWidget *widget, bool stretche mLayout->insertWidget (0, widget, stretched ? 1 : 0); } +void CSVWorld::GenericCreator::insertBeforeButtons (QWidget *widget, bool stretched) +{ + mLayout->insertWidget (mLayout->count()-2, widget, stretched ? 1 : 0); +} + std::string CSVWorld::GenericCreator::getId() const { return mId->text().toUtf8().constData(); } +void CSVWorld::GenericCreator::configureCreateCommand (CSMWorld::CreateCommand& command) const {} + CSVWorld::GenericCreator::GenericCreator (CSMWorld::Data& data, QUndoStack& undoStack, const CSMWorld::UniversalId& id) : mData (data), mUndoStack (undoStack), mListId (id), mLocked (false) @@ -103,9 +112,13 @@ void CSVWorld::GenericCreator::create() { std::string id = getId(); - mUndoStack.push (new CSMWorld::CreateCommand ( + std::auto_ptr command (new CSMWorld::CreateCommand ( dynamic_cast (*mData.getTableModel (mListId)), id)); + configureCreateCommand (*command); + + mUndoStack.push (command.release()); + emit done(); emit requestFocus (id); } diff --git a/apps/opencs/view/world/genericcreator.hpp b/apps/opencs/view/world/genericcreator.hpp index 2798d89a14..9022b7e390 100644 --- a/apps/opencs/view/world/genericcreator.hpp +++ b/apps/opencs/view/world/genericcreator.hpp @@ -9,6 +9,11 @@ class QHBoxLayout; #include "../../model/world/universalid.hpp" +namespace CSMWorld +{ + class CreateCommand; +} + namespace CSVWorld { class GenericCreator : public Creator @@ -33,8 +38,12 @@ namespace CSVWorld void insertAtBeginning (QWidget *widget, bool stretched); + void insertBeforeButtons (QWidget *widget, bool stretched); + virtual std::string getId() const; + virtual void configureCreateCommand (CSMWorld::CreateCommand& command) const; + public: GenericCreator (CSMWorld::Data& data, QUndoStack& undoStack, diff --git a/apps/opencs/view/world/referenceablecreator.cpp b/apps/opencs/view/world/referenceablecreator.cpp new file mode 100644 index 0000000000..718fe9ca7c --- /dev/null +++ b/apps/opencs/view/world/referenceablecreator.cpp @@ -0,0 +1,43 @@ + +#include "referenceablecreator.hpp" + +#include +#include + +#include "../../model/world/universalid.hpp" +#include "../../model/world/commands.hpp" + +void CSVWorld::ReferenceableCreator::configureCreateCommand (CSMWorld::CreateCommand& command) const +{ + command.setType ( + static_cast (mType->itemData (mType->currentIndex()).toInt())); +} + +CSVWorld::ReferenceableCreator::ReferenceableCreator (CSMWorld::Data& data, QUndoStack& undoStack, + const CSMWorld::UniversalId& id) +: GenericCreator (data, undoStack, id) +{ + QLabel *label = new QLabel ("Type", this); + insertBeforeButtons (label, false); + + std::vector types = CSMWorld::UniversalId::listReferenceableTypes(); + + mType = new QComboBox (this); + + for (std::vector::const_iterator iter (types.begin()); + iter!=types.end(); ++iter) + { + CSMWorld::UniversalId id (*iter, ""); + + mType->addItem (QIcon (id.getIcon().c_str()), id.getTypeName().c_str(), + static_cast (id.getType())); + } + + insertBeforeButtons (mType, false); +} + +void CSVWorld::ReferenceableCreator::reset() +{ + mType->setCurrentIndex (0); + GenericCreator::reset(); +} \ No newline at end of file diff --git a/apps/opencs/view/world/referenceablecreator.hpp b/apps/opencs/view/world/referenceablecreator.hpp new file mode 100644 index 0000000000..06e0e582be --- /dev/null +++ b/apps/opencs/view/world/referenceablecreator.hpp @@ -0,0 +1,30 @@ +#ifndef CSV_WORLD_REFERENCEABLECREATOR_H +#define CSV_WORLD_REFERENCEABLECREATOR_H + +class QComboBox; + +#include "genericcreator.hpp" + +namespace CSVWorld +{ + class ReferenceableCreator : public GenericCreator + { + Q_OBJECT + + QComboBox *mType; + + private: + + virtual void configureCreateCommand (CSMWorld::CreateCommand& command) const; + + public: + + ReferenceableCreator (CSMWorld::Data& data, QUndoStack& undoStack, + const CSMWorld::UniversalId& id); + + virtual void reset(); + + }; +} + +#endif diff --git a/apps/opencs/view/world/subviews.cpp b/apps/opencs/view/world/subviews.cpp index 9fbbe4a0da..22eb0ea4cf 100644 --- a/apps/opencs/view/world/subviews.cpp +++ b/apps/opencs/view/world/subviews.cpp @@ -9,6 +9,7 @@ #include "regionmapsubview.hpp" #include "genericcreator.hpp" #include "cellcreator.hpp" +#include "referenceablecreator.hpp" void CSVWorld::addSubViewFactories (CSVDoc::SubViewFactoryManager& manager) { @@ -29,7 +30,6 @@ void CSVWorld::addSubViewFactories (CSVDoc::SubViewFactoryManager& manager) CSMWorld::UniversalId::Type_Regions, CSMWorld::UniversalId::Type_Birthsigns, CSMWorld::UniversalId::Type_Spells, - CSMWorld::UniversalId::Type_Referenceables, CSMWorld::UniversalId::Type_References, CSMWorld::UniversalId::Type_None // end marker @@ -42,6 +42,9 @@ void CSVWorld::addSubViewFactories (CSVDoc::SubViewFactoryManager& manager) manager.add (CSMWorld::UniversalId::Type_Cells, new CSVDoc::SubViewFactoryWithCreator >); + manager.add (CSMWorld::UniversalId::Type_Referenceables, + new CSVDoc::SubViewFactoryWithCreator >); + manager.add (CSMWorld::UniversalId::Type_Script, new CSVDoc::SubViewFactory); manager.add (CSMWorld::UniversalId::Type_RegionMap, new CSVDoc::SubViewFactory); From 102700a49879388b6850cdcadabfc51bb1caa177 Mon Sep 17 00:00:00 2001 From: Marc Zinnschlag Date: Tue, 30 Jul 2013 12:53:03 +0200 Subject: [PATCH 22/23] added specialised Creator for references --- apps/opencs/CMakeLists.txt | 2 +- apps/opencs/model/world/commands.cpp | 8 +++ apps/opencs/model/world/commands.hpp | 4 ++ apps/opencs/model/world/data.cpp | 10 +++ apps/opencs/model/world/data.hpp | 4 ++ apps/opencs/model/world/refcollection.cpp | 12 ++-- apps/opencs/model/world/refcollection.hpp | 2 + apps/opencs/view/world/genericcreator.cpp | 10 +++ apps/opencs/view/world/genericcreator.hpp | 4 ++ apps/opencs/view/world/referencecreator.cpp | 70 +++++++++++++++++++++ apps/opencs/view/world/referencecreator.hpp | 40 ++++++++++++ apps/opencs/view/world/subviews.cpp | 9 ++- 12 files changed, 169 insertions(+), 6 deletions(-) create mode 100644 apps/opencs/view/world/referencecreator.cpp create mode 100644 apps/opencs/view/world/referencecreator.hpp diff --git a/apps/opencs/CMakeLists.txt b/apps/opencs/CMakeLists.txt index 75258a175a..6da863b974 100644 --- a/apps/opencs/CMakeLists.txt +++ b/apps/opencs/CMakeLists.txt @@ -58,7 +58,7 @@ opencs_hdrs_noqt (view/doc opencs_units (view/world table tablesubview scriptsubview util regionmapsubview tablebottombox creator genericcreator - cellcreator referenceablecreator + cellcreator referenceablecreator referencecreator ) opencs_units_noqt (view/world diff --git a/apps/opencs/model/world/commands.cpp b/apps/opencs/model/world/commands.cpp index 9281e6e330..43ecaca63c 100644 --- a/apps/opencs/model/world/commands.cpp +++ b/apps/opencs/model/world/commands.cpp @@ -31,6 +31,11 @@ CSMWorld::CreateCommand::CreateCommand (IdTable& model, const std::string& id, Q setText (("Create record " + id).c_str()); } +void CSMWorld::CreateCommand::addValue (int column, const QVariant& value) +{ + mValues[column] = value; +} + void CSMWorld::CreateCommand::setType (UniversalId::Type type) { mType = type; @@ -39,6 +44,9 @@ void CSMWorld::CreateCommand::setType (UniversalId::Type type) void CSMWorld::CreateCommand::redo() { mModel.addRecord (mId, mType); + + for (std::map::const_iterator iter (mValues.begin()); iter!=mValues.end(); ++iter) + mModel.setData (mModel.getModelIndex (mId, iter->first), iter->second); } void CSMWorld::CreateCommand::undo() diff --git a/apps/opencs/model/world/commands.hpp b/apps/opencs/model/world/commands.hpp index 6272c3fb7b..3fc2522ea5 100644 --- a/apps/opencs/model/world/commands.hpp +++ b/apps/opencs/model/world/commands.hpp @@ -4,6 +4,7 @@ #include "record.hpp" #include +#include #include #include @@ -42,6 +43,7 @@ namespace CSMWorld IdTable& mModel; std::string mId; UniversalId::Type mType; + std::map mValues; public: @@ -49,6 +51,8 @@ namespace CSMWorld void setType (UniversalId::Type type); + void addValue (int column, const QVariant& value); + virtual void redo(); virtual void undo(); diff --git a/apps/opencs/model/world/data.cpp b/apps/opencs/model/world/data.cpp index 2a95dfafeb..594bc19c2e 100644 --- a/apps/opencs/model/world/data.cpp +++ b/apps/opencs/model/world/data.cpp @@ -300,6 +300,16 @@ CSMWorld::RefIdCollection& CSMWorld::Data::getReferenceables() return mReferenceables; } +const CSMWorld::RefCollection& CSMWorld::Data::getReferences() const +{ + return mRefs; +} + +CSMWorld::RefCollection& CSMWorld::Data::getReferences() +{ + return mRefs; +} + QAbstractItemModel *CSMWorld::Data::getTableModel (const UniversalId& id) { std::map::iterator iter = mModelIndex.find (id.getType()); diff --git a/apps/opencs/model/world/data.hpp b/apps/opencs/model/world/data.hpp index 10a1fe50de..8b2403db39 100644 --- a/apps/opencs/model/world/data.hpp +++ b/apps/opencs/model/world/data.hpp @@ -112,6 +112,10 @@ namespace CSMWorld RefIdCollection& getReferenceables(); + const RefCollection& getReferences() const; + + RefCollection& getReferences(); + QAbstractItemModel *getTableModel (const UniversalId& id); ///< If no table model is available for \a id, an exception is thrown. /// diff --git a/apps/opencs/model/world/refcollection.cpp b/apps/opencs/model/world/refcollection.cpp index 6a1e8045b3..085817753e 100644 --- a/apps/opencs/model/world/refcollection.cpp +++ b/apps/opencs/model/world/refcollection.cpp @@ -21,10 +21,7 @@ void CSMWorld::RefCollection::load (ESM::ESMReader& reader, int cellIndex, bool while (cell2.getNextRef (reader, ref)) { /// \todo handle deleted and moved references - std::ostringstream stream; - stream << "ref#" << mNextId++; - - ref.load (reader, cell2, stream.str()); + ref.load (reader, cell2, getNewId()); Record record2; record2.mState = base ? RecordBase::State_BaseOnly : RecordBase::State_ModifiedOnly; @@ -34,4 +31,11 @@ void CSMWorld::RefCollection::load (ESM::ESMReader& reader, int cellIndex, bool } mCells.setRecord (cellIndex, cell); +} + +std::string CSMWorld::RefCollection::getNewId() +{ + std::ostringstream stream; + stream << "ref#" << mNextId++; + return stream.str(); } \ No newline at end of file diff --git a/apps/opencs/model/world/refcollection.hpp b/apps/opencs/model/world/refcollection.hpp index a2063590b9..895315a179 100644 --- a/apps/opencs/model/world/refcollection.hpp +++ b/apps/opencs/model/world/refcollection.hpp @@ -21,6 +21,8 @@ namespace CSMWorld void load (ESM::ESMReader& reader, int cellIndex, bool base); ///< Load a sequence of references. + + std::string getNewId(); }; } diff --git a/apps/opencs/view/world/genericcreator.cpp b/apps/opencs/view/world/genericcreator.cpp index 6c402818ce..7502b65551 100644 --- a/apps/opencs/view/world/genericcreator.cpp +++ b/apps/opencs/view/world/genericcreator.cpp @@ -46,6 +46,16 @@ std::string CSVWorld::GenericCreator::getId() const void CSVWorld::GenericCreator::configureCreateCommand (CSMWorld::CreateCommand& command) const {} +const CSMWorld::Data& CSVWorld::GenericCreator::getData() const +{ + return mData; +} + +CSMWorld::Data& CSVWorld::GenericCreator::getData() +{ + return mData; +} + CSVWorld::GenericCreator::GenericCreator (CSMWorld::Data& data, QUndoStack& undoStack, const CSMWorld::UniversalId& id) : mData (data), mUndoStack (undoStack), mListId (id), mLocked (false) diff --git a/apps/opencs/view/world/genericcreator.hpp b/apps/opencs/view/world/genericcreator.hpp index 9022b7e390..5409f08399 100644 --- a/apps/opencs/view/world/genericcreator.hpp +++ b/apps/opencs/view/world/genericcreator.hpp @@ -44,6 +44,10 @@ namespace CSVWorld virtual void configureCreateCommand (CSMWorld::CreateCommand& command) const; + const CSMWorld::Data& getData() const; + + CSMWorld::Data& getData(); + public: GenericCreator (CSMWorld::Data& data, QUndoStack& undoStack, diff --git a/apps/opencs/view/world/referencecreator.cpp b/apps/opencs/view/world/referencecreator.cpp new file mode 100644 index 0000000000..48a168a354 --- /dev/null +++ b/apps/opencs/view/world/referencecreator.cpp @@ -0,0 +1,70 @@ + +#include "referencecreator.hpp" + +#include +#include + +#include "../../model/world/data.hpp" +#include "../../model/world/commands.hpp" + +std::string CSVWorld::ReferenceCreator::getId() const +{ + return mId; +} + +void CSVWorld::ReferenceCreator::configureCreateCommand (CSMWorld::CreateCommand& command) const +{ + /// \todo avoid using hard-coded column numbers + command.addValue (2, mCell->text()); +} + +CSVWorld::ReferenceCreator::ReferenceCreator (CSMWorld::Data& data, QUndoStack& undoStack, + const CSMWorld::UniversalId& id) +: GenericCreator (data, undoStack, id) +{ + QLabel *label = new QLabel ("Cell", this); + insertBeforeButtons (label, false); + + mCell = new QLineEdit (this); + insertBeforeButtons (mCell, true); + + setManualEditing (false); + + connect (mCell, SIGNAL (textChanged (const QString&)), this, SLOT (cellChanged())); +} + +void CSVWorld::ReferenceCreator::reset() +{ + mCell->setText (""); + mId = getData().getReferences().getNewId(); + GenericCreator::reset(); +} + +std::string CSVWorld::ReferenceCreator::getErrors() const +{ + std::string errors = GenericCreator::getErrors(); + + std::string cell = mCell->text().toUtf8().constData(); + + if (cell.empty()) + { + if (!errors.empty()) + errors += "
"; + + errors += "Missing Cell ID"; + } + else if (getData().getCells().searchId (cell)==-1) + { + if (!errors.empty()) + errors += "
"; + + errors += "Invalid Cell ID"; + } + + return errors; +} + +void CSVWorld::ReferenceCreator::cellChanged() +{ + update(); +} \ No newline at end of file diff --git a/apps/opencs/view/world/referencecreator.hpp b/apps/opencs/view/world/referencecreator.hpp new file mode 100644 index 0000000000..27f81564fd --- /dev/null +++ b/apps/opencs/view/world/referencecreator.hpp @@ -0,0 +1,40 @@ +#ifndef CSV_WORLD_REFERENCECREATOR_H +#define CSV_WORLD_REFERENCECREATOR_H + +#include "genericcreator.hpp" + +class QLineEdit; + +namespace CSVWorld +{ + class ReferenceCreator : public GenericCreator + { + Q_OBJECT + + QLineEdit *mCell; + std::string mId; + + private: + + virtual std::string getId() const; + + virtual void configureCreateCommand (CSMWorld::CreateCommand& command) const; + + public: + + ReferenceCreator (CSMWorld::Data& data, QUndoStack& undoStack, + const CSMWorld::UniversalId& id); + + virtual void reset(); + + virtual std::string getErrors() const; + ///< Return formatted error descriptions for the current state of the creator. if an empty + /// string is returned, there is no error. + + private slots: + + void cellChanged(); + }; +} + +#endif diff --git a/apps/opencs/view/world/subviews.cpp b/apps/opencs/view/world/subviews.cpp index 22eb0ea4cf..8990e2c724 100644 --- a/apps/opencs/view/world/subviews.cpp +++ b/apps/opencs/view/world/subviews.cpp @@ -10,9 +10,12 @@ #include "genericcreator.hpp" #include "cellcreator.hpp" #include "referenceablecreator.hpp" +#include "referencecreator.hpp" void CSVWorld::addSubViewFactories (CSVDoc::SubViewFactoryManager& manager) { + // Regular record tables (including references which are actually sub-records, but are promoted + // to top-level records within the editor) manager.add (CSMWorld::UniversalId::Type_Gmsts, new CSVDoc::SubViewFactoryWithCreator); @@ -30,7 +33,6 @@ void CSVWorld::addSubViewFactories (CSVDoc::SubViewFactoryManager& manager) CSMWorld::UniversalId::Type_Regions, CSMWorld::UniversalId::Type_Birthsigns, CSMWorld::UniversalId::Type_Spells, - CSMWorld::UniversalId::Type_References, CSMWorld::UniversalId::Type_None // end marker }; @@ -45,7 +47,12 @@ void CSVWorld::addSubViewFactories (CSVDoc::SubViewFactoryManager& manager) manager.add (CSMWorld::UniversalId::Type_Referenceables, new CSVDoc::SubViewFactoryWithCreator >); + manager.add (CSMWorld::UniversalId::Type_References, + new CSVDoc::SubViewFactoryWithCreator >); + + // Subviews for editing/viewing individual records manager.add (CSMWorld::UniversalId::Type_Script, new CSVDoc::SubViewFactory); + // Other stuff (combined record tables) manager.add (CSMWorld::UniversalId::Type_RegionMap, new CSVDoc::SubViewFactory); } \ No newline at end of file From 434f97c95c7593028fd4f250f11709e6c5f3b925 Mon Sep 17 00:00:00 2001 From: Marc Zinnschlag Date: Tue, 30 Jul 2013 12:55:02 +0200 Subject: [PATCH 23/23] fixed two missing icons --- apps/opencs/model/world/universalid.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/apps/opencs/model/world/universalid.cpp b/apps/opencs/model/world/universalid.cpp index 5c85ff6208..4674f23f16 100644 --- a/apps/opencs/model/world/universalid.cpp +++ b/apps/opencs/model/world/universalid.cpp @@ -68,11 +68,11 @@ namespace { CSMWorld::UniversalId::Class_RefRecord, CSMWorld::UniversalId::Type_CreatureLevelledList, "Creature Levelled List", ":./creature.png" }, { CSMWorld::UniversalId::Class_RefRecord, CSMWorld::UniversalId::Type_ItemLevelledList, - "Item Levelled List", ":./item.png" }, + "Item Levelled List", ":./leveled-item.png" }, { CSMWorld::UniversalId::Class_RefRecord, CSMWorld::UniversalId::Type_Light, "Light", ":./light.png" }, { CSMWorld::UniversalId::Class_RefRecord, CSMWorld::UniversalId::Type_Lockpick, "Lockpick", ":./lockpick.png" }, { CSMWorld::UniversalId::Class_RefRecord, CSMWorld::UniversalId::Type_Miscellaneous, - "Miscellaneous", ":./misc.png" }, + "Miscellaneous", ":./miscellaneous.png" }, { CSMWorld::UniversalId::Class_RefRecord, CSMWorld::UniversalId::Type_Npc, "NPC", ":./npc.png" }, { CSMWorld::UniversalId::Class_RefRecord, CSMWorld::UniversalId::Type_Probe, "Probe", ":./probe.png" }, { CSMWorld::UniversalId::Class_RefRecord, CSMWorld::UniversalId::Type_Repair, "Repair", ":./repair.png" },