From c3cd6e8a8aaccf74a8e62d6460a938584be4fc4c Mon Sep 17 00:00:00 2001 From: Marc Zinnschlag Date: Wed, 21 Nov 2012 17:31:18 +0100 Subject: [PATCH 01/49] new attempt at the editor --- CMakeLists.txt | 7 +++- apps/opencs/CMakeLists.txt | 44 +++++++++++++++++++++++ apps/opencs/main.cpp | 5 +++ apps/opencs/model/doc/document.cpp | 4 +++ apps/opencs/model/doc/document.hpp | 17 +++++++++ apps/opencs/model/doc/documentmanager.cpp | 37 +++++++++++++++++++ apps/opencs/model/doc/documentmanager.hpp | 31 ++++++++++++++++ 7 files changed, 144 insertions(+), 1 deletion(-) create mode 100644 apps/opencs/CMakeLists.txt create mode 100644 apps/opencs/main.cpp create mode 100644 apps/opencs/model/doc/document.cpp create mode 100644 apps/opencs/model/doc/document.hpp create mode 100644 apps/opencs/model/doc/documentmanager.cpp create mode 100644 apps/opencs/model/doc/documentmanager.hpp diff --git a/CMakeLists.txt b/CMakeLists.txt index 78388e20f4..d657de6ed9 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -31,6 +31,7 @@ option(OGRE_STATIC "Link static build of Ogre and Ogre Plugins into the binaries option(BUILD_ESMTOOL "build ESM inspector" ON) option(BUILD_LAUNCHER "build Launcher" ON) option(BUILD_MWINIIMPORTER "build MWiniImporter" ON) +option(BUILD_OPENCS "build OpenMW Construction Set" ON) option(BUILD_WITH_CODE_COVERAGE "Enable code coverage with gconv" OFF) option(BUILD_UNITTESTS "Enable Unittests with Google C++ Unittest ang GMock frameworks" OFF) @@ -244,7 +245,7 @@ if (APPLE) else () set(OGRE_PLUGIN_DIR ${OGRE_PLUGIN_DIR_DBG}) endif () - + #set(OGRE_PLUGIN_DIR "${OGRE_PLUGIN_DIR}/") configure_file(${OpenMW_SOURCE_DIR}/files/mac/Info.plist @@ -462,6 +463,10 @@ if (BUILD_MWINIIMPORTER) add_subdirectory( apps/mwiniimporter ) endif() +if (BUILD_OPENCS) + add_subdirectory (apps/opencs) +endif() + # UnitTests if (BUILD_UNITTESTS) add_subdirectory( apps/openmw_test_suite ) diff --git a/apps/opencs/CMakeLists.txt b/apps/opencs/CMakeLists.txt new file mode 100644 index 0000000000..d213f68f91 --- /dev/null +++ b/apps/opencs/CMakeLists.txt @@ -0,0 +1,44 @@ + +set (OPENCS_SRC + main.cpp + + model/doc/documentmanager.cpp model/doc/document.cpp + ) + +set (OPENCS_HDR + model/doc/documentmanager.hpp model/doc/document.hpp + ) + +set (OPENCS_US + ) + +set (OPENCS_RES + ) + +source_group (opencs FILES ${OPENCS_SRC} ${OPENCS_HDR}) + +if(WIN32) + set(QT_USE_QTMAIN TRUE) +endif(WIN32) + +find_package(Qt4 COMPONENTS QtCore QtGui QtXml QtXmlPatterns REQUIRED) +include(${QT_USE_FILE}) + +qt4_wrap_ui(OPENCS_UI_HDR ${OPENCS_UI}) +qt4_wrap_cpp(OPENCS_MOC_SRC ${OPENCS_HDR}) +qt4_add_resources(OPENCS_RES_SRC ${OPENCS_RES}) + +include_directories(${CMAKE_CURRENT_BINARY_DIR}) + +add_executable(opencs + ${OPENCS_SRC} + ${OPENCS_UI_HDR} + ${OPENCS_MOC_SRC} + ${OPENCS_RES_SRC} +) + +target_link_libraries(opencs + ${Boost_LIBRARIES} + ${QT_LIBRARIES} + components +) \ No newline at end of file diff --git a/apps/opencs/main.cpp b/apps/opencs/main.cpp new file mode 100644 index 0000000000..cd443603b7 --- /dev/null +++ b/apps/opencs/main.cpp @@ -0,0 +1,5 @@ + +int main(int argc, char *argv[]) +{ + +} \ No newline at end of file diff --git a/apps/opencs/model/doc/document.cpp b/apps/opencs/model/doc/document.cpp new file mode 100644 index 0000000000..7154c484ba --- /dev/null +++ b/apps/opencs/model/doc/document.cpp @@ -0,0 +1,4 @@ + +#include "document.hpp" + +CSMDoc::Document::Document() {} \ No newline at end of file diff --git a/apps/opencs/model/doc/document.hpp b/apps/opencs/model/doc/document.hpp new file mode 100644 index 0000000000..7badf8fd75 --- /dev/null +++ b/apps/opencs/model/doc/document.hpp @@ -0,0 +1,17 @@ +#ifndef CSM_DOCUMENT_H +#define CSM_DOCUMENT_H + +namespace CSMDoc +{ + class Document + { + Document (const Document&); + Document& operator= (const Document&); + + public: + + Document(); + }; +} + +#endif \ No newline at end of file diff --git a/apps/opencs/model/doc/documentmanager.cpp b/apps/opencs/model/doc/documentmanager.cpp new file mode 100644 index 0000000000..68595f2d41 --- /dev/null +++ b/apps/opencs/model/doc/documentmanager.cpp @@ -0,0 +1,37 @@ + +#include "documentmanager.hpp" + +#include +#include + +#include "document.hpp" + +CSMDoc::DocumentManager::DocumentManager() {} + +CSMDoc::DocumentManager::~DocumentManager() +{ + for (std::vector::iterator iter (mDocuments.begin()); iter!=mDocuments.end(); ++iter) + delete *iter; +} + +CSMDoc::Document *CSMDoc::DocumentManager::addDocument() +{ + Document *document = new Document; + + mDocuments.push_back (document); + + return document; +} + +bool CSMDoc::DocumentManager::removeDocument (Document *document) +{ + std::vector::iterator iter = std::find (mDocuments.begin(), mDocuments.end(), document); + + if (iter==mDocuments.end()) + throw std::runtime_error ("removing invalid document"); + + mDocuments.erase (iter); + delete document; + + return mDocuments.empty(); +} \ No newline at end of file diff --git a/apps/opencs/model/doc/documentmanager.hpp b/apps/opencs/model/doc/documentmanager.hpp new file mode 100644 index 0000000000..7f0d388bc8 --- /dev/null +++ b/apps/opencs/model/doc/documentmanager.hpp @@ -0,0 +1,31 @@ +#ifndef CSM_DOCUMENTMGR_H +#define CSM_DOCUMENTMGR_H + +#include + +namespace CSMDoc +{ + class Document; + + class DocumentManager + { + std::vector mDocuments; + + DocumentManager (const DocumentManager&); + DocumentManager& operator= (const DocumentManager&); + + public: + + DocumentManager(); + + ~DocumentManager(); + + Document *addDocument(); + ///< The ownership of the returned document is not transferred to the caller. + + bool removeDocument (Document *document); + ///< \return last document removed? + }; +} + +#endif \ No newline at end of file From 9834bb3ad52db108a11d6afe1a26d31f6833d925 Mon Sep 17 00:00:00 2001 From: Marc Zinnschlag Date: Thu, 22 Nov 2012 13:30:02 +0100 Subject: [PATCH 02/49] basic document handling --- apps/opencs/CMakeLists.txt | 8 ++++- apps/opencs/editor.cpp | 21 +++++++++++++ apps/opencs/editor.hpp | 29 +++++++++++++++++ apps/opencs/main.cpp | 8 +++++ apps/opencs/model/doc/document.hpp | 5 +-- apps/opencs/model/doc/documentmanager.hpp | 4 +-- apps/opencs/view/doc/view.cpp | 8 +++++ apps/opencs/view/doc/view.hpp | 30 ++++++++++++++++++ apps/opencs/view/doc/viewmanager.cpp | 26 ++++++++++++++++ apps/opencs/view/doc/viewmanager.hpp | 38 +++++++++++++++++++++++ 10 files changed, 172 insertions(+), 5 deletions(-) create mode 100644 apps/opencs/editor.cpp create mode 100644 apps/opencs/editor.hpp create mode 100644 apps/opencs/view/doc/view.cpp create mode 100644 apps/opencs/view/doc/view.hpp create mode 100644 apps/opencs/view/doc/viewmanager.cpp create mode 100644 apps/opencs/view/doc/viewmanager.hpp diff --git a/apps/opencs/CMakeLists.txt b/apps/opencs/CMakeLists.txt index d213f68f91..d7f113447a 100644 --- a/apps/opencs/CMakeLists.txt +++ b/apps/opencs/CMakeLists.txt @@ -1,12 +1,18 @@ set (OPENCS_SRC - main.cpp + main.cpp editor.cpp model/doc/documentmanager.cpp model/doc/document.cpp + + view/doc/viewmanager.cpp view/doc/view.cpp ) set (OPENCS_HDR + editor.hpp + model/doc/documentmanager.hpp model/doc/document.hpp + + view/doc/viewmanager.hpp view/doc/view.hpp ) set (OPENCS_US diff --git a/apps/opencs/editor.cpp b/apps/opencs/editor.cpp new file mode 100644 index 0000000000..0a8a137f6a --- /dev/null +++ b/apps/opencs/editor.cpp @@ -0,0 +1,21 @@ + +#include "editor.hpp" + +#include + +CS::Editor::Editor() +{ +} + +void CS::Editor::createDocument() +{ + CSMDoc::Document *document = mDocumentManager.addDocument(); + mViewManager.addView (document); +} + +int CS::Editor::run() +{ + createDocument(); + + return QApplication::exec(); +} \ No newline at end of file diff --git a/apps/opencs/editor.hpp b/apps/opencs/editor.hpp new file mode 100644 index 0000000000..6e183b843b --- /dev/null +++ b/apps/opencs/editor.hpp @@ -0,0 +1,29 @@ +#ifndef CS_EDITOR_H +#define CS_EDITOR_H + +#include "model/doc/documentmanager.hpp" +#include "view/doc/viewmanager.hpp" + +namespace CS +{ + class Editor + { + CSMDoc::DocumentManager mDocumentManager; + CSVDoc::ViewManager mViewManager; + + // not implemented + Editor (const Editor&); + Editor& operator= (const Editor&); + + public: + + Editor(); + + void createDocument(); + + int run(); + ///< \return error status + }; +} + +#endif \ No newline at end of file diff --git a/apps/opencs/main.cpp b/apps/opencs/main.cpp index cd443603b7..15772eba0e 100644 --- a/apps/opencs/main.cpp +++ b/apps/opencs/main.cpp @@ -1,5 +1,13 @@ +#include "editor.hpp" + +#include + int main(int argc, char *argv[]) { + QApplication mApplication (argc, argv); + + CS::Editor editor; + return editor.run(); } \ No newline at end of file diff --git a/apps/opencs/model/doc/document.hpp b/apps/opencs/model/doc/document.hpp index 7badf8fd75..e440859629 100644 --- a/apps/opencs/model/doc/document.hpp +++ b/apps/opencs/model/doc/document.hpp @@ -1,10 +1,11 @@ -#ifndef CSM_DOCUMENT_H -#define CSM_DOCUMENT_H +#ifndef CSM_DOC_DOCUMENT_H +#define CSM_DOC_DOCUMENT_H namespace CSMDoc { class Document { + // not implemented Document (const Document&); Document& operator= (const Document&); diff --git a/apps/opencs/model/doc/documentmanager.hpp b/apps/opencs/model/doc/documentmanager.hpp index 7f0d388bc8..f20f3101d9 100644 --- a/apps/opencs/model/doc/documentmanager.hpp +++ b/apps/opencs/model/doc/documentmanager.hpp @@ -1,5 +1,5 @@ -#ifndef CSM_DOCUMENTMGR_H -#define CSM_DOCUMENTMGR_H +#ifndef CSM_DOC_DOCUMENTMGR_H +#define CSM_DOC_DOCUMENTMGR_H #include diff --git a/apps/opencs/view/doc/view.cpp b/apps/opencs/view/doc/view.cpp new file mode 100644 index 0000000000..2bad69badb --- /dev/null +++ b/apps/opencs/view/doc/view.cpp @@ -0,0 +1,8 @@ + +#include "view.hpp" + +CSVDoc::View::View (CSMDoc::Document *document) : mDocument (document) +{ + resize (200, 200); + setWindowTitle ("New Document"); +} \ No newline at end of file diff --git a/apps/opencs/view/doc/view.hpp b/apps/opencs/view/doc/view.hpp new file mode 100644 index 0000000000..797eef0835 --- /dev/null +++ b/apps/opencs/view/doc/view.hpp @@ -0,0 +1,30 @@ +#ifndef CSV_DOC_VIEW_H +#define CSV_DOC_VIEW_H + +#include + +namespace CSMDoc +{ + class Document; +} + +namespace CSVDoc +{ + class View : public QWidget + { + Q_OBJECT + + CSMDoc::Document *mDocument; + + // not implemented + View (const View&); + View& operator= (const View&); + + public: + + View (CSMDoc::Document *document); + ///< The ownership of \a document is not transferred to *this. + }; +} + +#endif \ No newline at end of file diff --git a/apps/opencs/view/doc/viewmanager.cpp b/apps/opencs/view/doc/viewmanager.cpp new file mode 100644 index 0000000000..59b79be47b --- /dev/null +++ b/apps/opencs/view/doc/viewmanager.cpp @@ -0,0 +1,26 @@ + +#include "viewmanager.hpp" + +#include "view.hpp" + +CSVDoc::ViewManager::ViewManager() +{ + +} + +CSVDoc::ViewManager::~ViewManager() +{ + for (std::vector::iterator iter (mViews.begin()); iter!=mViews.end(); ++iter) + delete *iter; +} + +CSVDoc::View *CSVDoc::ViewManager::addView (CSMDoc::Document *document) +{ + View *view = new View (document); + + mViews.push_back (view); + + view->show(); + + return view; +} \ No newline at end of file diff --git a/apps/opencs/view/doc/viewmanager.hpp b/apps/opencs/view/doc/viewmanager.hpp new file mode 100644 index 0000000000..dc6a07bce7 --- /dev/null +++ b/apps/opencs/view/doc/viewmanager.hpp @@ -0,0 +1,38 @@ +#ifndef CSV_DOC_VIEWMANAGER_H +#define CSV_DOC_VIEWMANAGER_H + +#include + +namespace CSMDoc +{ + class Document; +} + +namespace CSVDoc +{ + class View; + + class ViewManager + { + std::vector mViews; + + // not implemented + ViewManager (const ViewManager&); + ViewManager& operator= (const ViewManager&); + + public: + + ViewManager(); + + ~ViewManager(); + + View *addView (CSMDoc::Document *document); + ///< The ownership of the returned view is not transferred. + + + + }; + +} + +#endif \ No newline at end of file From 758371d7e4c346f92b715bb3cb26ec9dfbd58e55 Mon Sep 17 00:00:00 2001 From: Marc Zinnschlag Date: Thu, 22 Nov 2012 14:10:23 +0100 Subject: [PATCH 03/49] implemented view/document closing --- apps/opencs/editor.cpp | 2 +- apps/opencs/view/doc/view.cpp | 25 ++++++++++++++++- apps/opencs/view/doc/view.hpp | 13 ++++++++- apps/opencs/view/doc/viewmanager.cpp | 41 ++++++++++++++++++++++++++-- apps/opencs/view/doc/viewmanager.hpp | 10 ++++++- 5 files changed, 85 insertions(+), 6 deletions(-) diff --git a/apps/opencs/editor.cpp b/apps/opencs/editor.cpp index 0a8a137f6a..264ae75434 100644 --- a/apps/opencs/editor.cpp +++ b/apps/opencs/editor.cpp @@ -3,7 +3,7 @@ #include -CS::Editor::Editor() +CS::Editor::Editor() : mViewManager (mDocumentManager) { } diff --git a/apps/opencs/view/doc/view.cpp b/apps/opencs/view/doc/view.cpp index 2bad69badb..51078d4481 100644 --- a/apps/opencs/view/doc/view.cpp +++ b/apps/opencs/view/doc/view.cpp @@ -1,8 +1,31 @@ #include "view.hpp" -CSVDoc::View::View (CSMDoc::Document *document) : mDocument (document) +#include + +#include + +#include "viewmanager.hpp" + +void CSVDoc::View::closeEvent (QCloseEvent *event) +{ + if (!mViewManager.closeRequest (this)) + event->ignore(); +} + +CSVDoc::View::View (ViewManager& viewManager, CSMDoc::Document *document) +: mViewManager (viewManager), mDocument (document) { resize (200, 200); setWindowTitle ("New Document"); +} + +const CSMDoc::Document *CSVDoc::View::getDocument() const +{ + return mDocument; +} + +CSMDoc::Document *CSVDoc::View::getDocument() +{ + return mDocument; } \ No newline at end of file diff --git a/apps/opencs/view/doc/view.hpp b/apps/opencs/view/doc/view.hpp index 797eef0835..b12bb7e41a 100644 --- a/apps/opencs/view/doc/view.hpp +++ b/apps/opencs/view/doc/view.hpp @@ -10,20 +10,31 @@ namespace CSMDoc namespace CSVDoc { + class ViewManager; + class View : public QWidget { Q_OBJECT + ViewManager& mViewManager; CSMDoc::Document *mDocument; // not implemented View (const View&); View& operator= (const View&); + private: + + void closeEvent (QCloseEvent *event); + public: - View (CSMDoc::Document *document); + View (ViewManager& viewManager, CSMDoc::Document *document); ///< The ownership of \a document is not transferred to *this. + + const CSMDoc::Document *getDocument() const; + + CSMDoc::Document *getDocument(); }; } diff --git a/apps/opencs/view/doc/viewmanager.cpp b/apps/opencs/view/doc/viewmanager.cpp index 59b79be47b..da73213f71 100644 --- a/apps/opencs/view/doc/viewmanager.cpp +++ b/apps/opencs/view/doc/viewmanager.cpp @@ -1,9 +1,12 @@ #include "viewmanager.hpp" +#include "../../model/doc/documentmanager.hpp" + #include "view.hpp" -CSVDoc::ViewManager::ViewManager() +CSVDoc::ViewManager::ViewManager (CSMDoc::DocumentManager& documentManager) +: mDocumentManager (documentManager) { } @@ -12,15 +15,49 @@ CSVDoc::ViewManager::~ViewManager() { for (std::vector::iterator iter (mViews.begin()); iter!=mViews.end(); ++iter) delete *iter; + + for (std::vector::iterator iter (mClosed.begin()); iter!=mClosed.end(); ++iter) + delete *iter; } CSVDoc::View *CSVDoc::ViewManager::addView (CSMDoc::Document *document) { - View *view = new View (document); + View *view = new View (*this, document); mViews.push_back (view); view->show(); return view; +} + +int CSVDoc::ViewManager::countViews (const CSMDoc::Document *document) const +{ + int count = 0; + + for (std::vector::const_iterator iter (mViews.begin()); iter!=mViews.end(); ++iter) + if ((*iter)->getDocument()==document) + ++count; + + return count; +} + +bool CSVDoc::ViewManager::closeRequest (View *view) +{ + std::vector::iterator iter = std::find (mViews.begin(), mViews.end(), view); + + if (iter!=mViews.end()) + { + bool last = countViews (view->getDocument())<=1; + + /// \todo check if document has not been saved -> return false and start close dialogue + + mViews.erase (iter); + mClosed.push_back (view); + + if (last) + mDocumentManager.removeDocument (view->getDocument()); + } + + return true; } \ No newline at end of file diff --git a/apps/opencs/view/doc/viewmanager.hpp b/apps/opencs/view/doc/viewmanager.hpp index dc6a07bce7..6901590ed8 100644 --- a/apps/opencs/view/doc/viewmanager.hpp +++ b/apps/opencs/view/doc/viewmanager.hpp @@ -6,6 +6,7 @@ namespace CSMDoc { class Document; + class DocumentManager; } namespace CSVDoc @@ -14,7 +15,9 @@ namespace CSVDoc class ViewManager { + CSMDoc::DocumentManager& mDocumentManager; std::vector mViews; + std::vector mClosed; // not implemented ViewManager (const ViewManager&); @@ -22,13 +25,18 @@ namespace CSVDoc public: - ViewManager(); + ViewManager (CSMDoc::DocumentManager& documentManager); ~ViewManager(); View *addView (CSMDoc::Document *document); ///< The ownership of the returned view is not transferred. + int countViews (const CSMDoc::Document *document) const; + ///< Return number of views for \a document. + + bool closeRequest (View *view); + }; From 789cecb9df5616fd49717ec006b3c7962a73b408 Mon Sep 17 00:00:00 2001 From: Marc Zinnschlag Date: Thu, 22 Nov 2012 14:49:58 +0100 Subject: [PATCH 04/49] added main menu and implemented new view function --- apps/opencs/view/doc/view.cpp | 20 ++++++++++++++++++++ apps/opencs/view/doc/view.hpp | 12 ++++++++++-- 2 files changed, 30 insertions(+), 2 deletions(-) diff --git a/apps/opencs/view/doc/view.cpp b/apps/opencs/view/doc/view.cpp index 51078d4481..847462964a 100644 --- a/apps/opencs/view/doc/view.cpp +++ b/apps/opencs/view/doc/view.cpp @@ -4,6 +4,7 @@ #include #include +#include #include "viewmanager.hpp" @@ -13,11 +14,25 @@ void CSVDoc::View::closeEvent (QCloseEvent *event) event->ignore(); } +void CSVDoc::View::setupUi() +{ + // window menu + QMenu *view = menuBar()->addMenu (tr ("&View")); + + QAction *newWindow = new QAction (tr ("&New View"), this); + connect (newWindow, SIGNAL (triggered()), this, SLOT (newView())); + + view->addAction (newWindow); +} + CSVDoc::View::View (ViewManager& viewManager, CSMDoc::Document *document) : mViewManager (viewManager), mDocument (document) { + setCentralWidget (new QWidget); resize (200, 200); setWindowTitle ("New Document"); + + setupUi(); } const CSMDoc::Document *CSVDoc::View::getDocument() const @@ -28,4 +43,9 @@ const CSMDoc::Document *CSVDoc::View::getDocument() const CSMDoc::Document *CSVDoc::View::getDocument() { return mDocument; +} + +void CSVDoc::View::newView() +{ + mViewManager.addView (mDocument); } \ No newline at end of file diff --git a/apps/opencs/view/doc/view.hpp b/apps/opencs/view/doc/view.hpp index b12bb7e41a..df88ff2cc8 100644 --- a/apps/opencs/view/doc/view.hpp +++ b/apps/opencs/view/doc/view.hpp @@ -1,7 +1,9 @@ #ifndef CSV_DOC_VIEW_H #define CSV_DOC_VIEW_H -#include +#include + +class QAction; namespace CSMDoc { @@ -12,7 +14,7 @@ namespace CSVDoc { class ViewManager; - class View : public QWidget + class View : public QMainWindow { Q_OBJECT @@ -27,6 +29,8 @@ namespace CSVDoc void closeEvent (QCloseEvent *event); + void setupUi(); + public: View (ViewManager& viewManager, CSMDoc::Document *document); @@ -35,6 +39,10 @@ namespace CSVDoc const CSMDoc::Document *getDocument() const; CSMDoc::Document *getDocument(); + + private slots: + + void newView(); }; } From 1ddcea1f072e5cd727f5066c911f0a1015cfd983 Mon Sep 17 00:00:00 2001 From: Marc Zinnschlag Date: Thu, 22 Nov 2012 15:09:04 +0100 Subject: [PATCH 05/49] display view indices in title bar --- apps/opencs/view/doc/view.cpp | 30 +++++++++++++++++++++++----- apps/opencs/view/doc/view.hpp | 8 +++++++- apps/opencs/view/doc/viewmanager.cpp | 26 +++++++++++++++++++++++- apps/opencs/view/doc/viewmanager.hpp | 2 ++ 4 files changed, 59 insertions(+), 7 deletions(-) diff --git a/apps/opencs/view/doc/view.cpp b/apps/opencs/view/doc/view.cpp index 847462964a..406ce7dc74 100644 --- a/apps/opencs/view/doc/view.cpp +++ b/apps/opencs/view/doc/view.cpp @@ -1,7 +1,7 @@ #include "view.hpp" -#include +#include #include #include @@ -16,7 +16,7 @@ void CSVDoc::View::closeEvent (QCloseEvent *event) void CSVDoc::View::setupUi() { - // window menu + // view menu QMenu *view = menuBar()->addMenu (tr ("&View")); QAction *newWindow = new QAction (tr ("&New View"), this); @@ -25,12 +25,25 @@ void CSVDoc::View::setupUi() view->addAction (newWindow); } -CSVDoc::View::View (ViewManager& viewManager, CSMDoc::Document *document) -: mViewManager (viewManager), mDocument (document) +void CSVDoc::View::updateTitle() +{ + std::ostringstream stream; + + stream << "New Document "; + + if (mViewTotal>1) + stream << " [" << (mViewIndex+1) << "/" << mViewTotal << "]"; + + setWindowTitle (stream.str().c_str()); +} + +CSVDoc::View::View (ViewManager& viewManager, CSMDoc::Document *document, int totalViews) +: mViewManager (viewManager), mDocument (document), mViewIndex (totalViews-1), mViewTotal (totalViews) { setCentralWidget (new QWidget); resize (200, 200); - setWindowTitle ("New Document"); + + updateTitle(); setupUi(); } @@ -45,6 +58,13 @@ CSMDoc::Document *CSVDoc::View::getDocument() return mDocument; } +void CSVDoc::View::setIndex (int viewIndex, int totalViews) +{ + mViewIndex = viewIndex; + mViewTotal = totalViews; + updateTitle(); +} + void CSVDoc::View::newView() { mViewManager.addView (mDocument); diff --git a/apps/opencs/view/doc/view.hpp b/apps/opencs/view/doc/view.hpp index df88ff2cc8..78ec45a5d1 100644 --- a/apps/opencs/view/doc/view.hpp +++ b/apps/opencs/view/doc/view.hpp @@ -20,6 +20,8 @@ namespace CSVDoc ViewManager& mViewManager; CSMDoc::Document *mDocument; + int mViewIndex; + int mViewTotal; // not implemented View (const View&); @@ -31,15 +33,19 @@ namespace CSVDoc void setupUi(); + void updateTitle(); + public: - View (ViewManager& viewManager, CSMDoc::Document *document); + View (ViewManager& viewManager, CSMDoc::Document *document, int totalViews); ///< The ownership of \a document is not transferred to *this. const CSMDoc::Document *getDocument() const; CSMDoc::Document *getDocument(); + void setIndex (int viewIndex, int totalViews); + private slots: void newView(); diff --git a/apps/opencs/view/doc/viewmanager.cpp b/apps/opencs/view/doc/viewmanager.cpp index da73213f71..f6ac6e43df 100644 --- a/apps/opencs/view/doc/viewmanager.cpp +++ b/apps/opencs/view/doc/viewmanager.cpp @@ -1,10 +1,30 @@ #include "viewmanager.hpp" +#include + #include "../../model/doc/documentmanager.hpp" #include "view.hpp" +void CSVDoc::ViewManager::updateIndices() +{ + std::map > documents; + + for (std::vector::const_iterator iter (mViews.begin()); iter!=mViews.end(); ++iter) + { + std::map >::iterator document = documents.find ((*iter)->getDocument()); + + if (document==documents.end()) + document = + documents.insert ( + std::make_pair ((*iter)->getDocument(), std::make_pair (0, countViews ((*iter)->getDocument())))). + first; + + (*iter)->setIndex (document->second.first++, document->second.second); + } +} + CSVDoc::ViewManager::ViewManager (CSMDoc::DocumentManager& documentManager) : mDocumentManager (documentManager) { @@ -22,12 +42,14 @@ CSVDoc::ViewManager::~ViewManager() CSVDoc::View *CSVDoc::ViewManager::addView (CSMDoc::Document *document) { - View *view = new View (*this, document); + View *view = new View (*this, document, countViews (document)+1); mViews.push_back (view); view->show(); + updateIndices(); + return view; } @@ -57,6 +79,8 @@ bool CSVDoc::ViewManager::closeRequest (View *view) if (last) mDocumentManager.removeDocument (view->getDocument()); + else + updateIndices(); } return true; diff --git a/apps/opencs/view/doc/viewmanager.hpp b/apps/opencs/view/doc/viewmanager.hpp index 6901590ed8..765fafbeab 100644 --- a/apps/opencs/view/doc/viewmanager.hpp +++ b/apps/opencs/view/doc/viewmanager.hpp @@ -23,6 +23,8 @@ namespace CSVDoc ViewManager (const ViewManager&); ViewManager& operator= (const ViewManager&); + void updateIndices(); + public: ViewManager (CSMDoc::DocumentManager& documentManager); From ed3d8b8ca2a4cd5dea2870f5bbbcf3f7de6abb0c Mon Sep 17 00:00:00 2001 From: Marc Zinnschlag Date: Thu, 22 Nov 2012 15:54:31 +0100 Subject: [PATCH 06/49] added undo stack and undo/redo actions --- apps/opencs/model/doc/document.cpp | 7 ++++++- apps/opencs/model/doc/document.hpp | 6 ++++++ apps/opencs/view/doc/view.cpp | 25 ++++++++++++++++++++++--- apps/opencs/view/doc/view.hpp | 4 ++++ 4 files changed, 38 insertions(+), 4 deletions(-) diff --git a/apps/opencs/model/doc/document.cpp b/apps/opencs/model/doc/document.cpp index 7154c484ba..448598a4e4 100644 --- a/apps/opencs/model/doc/document.cpp +++ b/apps/opencs/model/doc/document.cpp @@ -1,4 +1,9 @@ #include "document.hpp" -CSMDoc::Document::Document() {} \ No newline at end of file +CSMDoc::Document::Document() {} + +QUndoStack& CSMDoc::Document::getUndoStack() +{ + return mUndoStack; +} \ No newline at end of file diff --git a/apps/opencs/model/doc/document.hpp b/apps/opencs/model/doc/document.hpp index e440859629..1dea7afc28 100644 --- a/apps/opencs/model/doc/document.hpp +++ b/apps/opencs/model/doc/document.hpp @@ -1,10 +1,14 @@ #ifndef CSM_DOC_DOCUMENT_H #define CSM_DOC_DOCUMENT_H +#include + namespace CSMDoc { class Document { + QUndoStack mUndoStack; + // not implemented Document (const Document&); Document& operator= (const Document&); @@ -12,6 +16,8 @@ namespace CSMDoc public: Document(); + + QUndoStack& getUndoStack(); }; } diff --git a/apps/opencs/view/doc/view.cpp b/apps/opencs/view/doc/view.cpp index 406ce7dc74..7a2296fed2 100644 --- a/apps/opencs/view/doc/view.cpp +++ b/apps/opencs/view/doc/view.cpp @@ -6,6 +6,8 @@ #include #include +#include "../../model/doc/document.hpp" + #include "viewmanager.hpp" void CSVDoc::View::closeEvent (QCloseEvent *event) @@ -14,17 +16,34 @@ void CSVDoc::View::closeEvent (QCloseEvent *event) event->ignore(); } -void CSVDoc::View::setupUi() +void CSVDoc::View::setupEditMenu() +{ + QMenu *edit = menuBar()->addMenu (tr ("&Edit")); + + QAction *undo = mDocument->getUndoStack().createUndoAction (this, tr("&Undo")); + undo->setShortcuts (QKeySequence::Undo); + edit->addAction (undo); + + QAction *redo = mDocument->getUndoStack().createRedoAction (this, tr("&Redo")); + redo->setShortcuts (QKeySequence::Redo); + edit->addAction (redo); +} + +void CSVDoc::View::setupViewMenu() { - // view menu QMenu *view = menuBar()->addMenu (tr ("&View")); QAction *newWindow = new QAction (tr ("&New View"), this); connect (newWindow, SIGNAL (triggered()), this, SLOT (newView())); - view->addAction (newWindow); } +void CSVDoc::View::setupUi() +{ + setupEditMenu(); + setupViewMenu(); +} + void CSVDoc::View::updateTitle() { std::ostringstream stream; diff --git a/apps/opencs/view/doc/view.hpp b/apps/opencs/view/doc/view.hpp index 78ec45a5d1..457cc84fa6 100644 --- a/apps/opencs/view/doc/view.hpp +++ b/apps/opencs/view/doc/view.hpp @@ -31,6 +31,10 @@ namespace CSVDoc void closeEvent (QCloseEvent *event); + void setupEditMenu(); + + void setupViewMenu(); + void setupUi(); void updateTitle(); From 8e546ebd30a6fb8c983bf11ccd9ce22f073b31ed Mon Sep 17 00:00:00 2001 From: Marc Zinnschlag Date: Thu, 22 Nov 2012 16:00:23 +0100 Subject: [PATCH 07/49] added test command --- apps/opencs/view/doc/view.cpp | 10 ++++++++++ apps/opencs/view/doc/view.hpp | 2 ++ 2 files changed, 12 insertions(+) diff --git a/apps/opencs/view/doc/view.cpp b/apps/opencs/view/doc/view.cpp index 7a2296fed2..c5792b27a6 100644 --- a/apps/opencs/view/doc/view.cpp +++ b/apps/opencs/view/doc/view.cpp @@ -27,6 +27,11 @@ void CSVDoc::View::setupEditMenu() QAction *redo = mDocument->getUndoStack().createRedoAction (this, tr("&Redo")); redo->setShortcuts (QKeySequence::Redo); edit->addAction (redo); + + // test + QAction *test = new QAction (tr ("&Test Command"), this); + connect (test, SIGNAL (triggered()), this, SLOT (test())); + edit->addAction (test); } void CSVDoc::View::setupViewMenu() @@ -87,4 +92,9 @@ void CSVDoc::View::setIndex (int viewIndex, int totalViews) void CSVDoc::View::newView() { mViewManager.addView (mDocument); +} + +void CSVDoc::View::test() +{ + mDocument->getUndoStack().push (new QUndoCommand()); } \ No newline at end of file diff --git a/apps/opencs/view/doc/view.hpp b/apps/opencs/view/doc/view.hpp index 457cc84fa6..2c312715a7 100644 --- a/apps/opencs/view/doc/view.hpp +++ b/apps/opencs/view/doc/view.hpp @@ -53,6 +53,8 @@ namespace CSVDoc private slots: void newView(); + + void test(); }; } From d7c63d4c74472e7bffd47531319c94343feb646f Mon Sep 17 00:00:00 2001 From: Marc Zinnschlag Date: Thu, 22 Nov 2012 23:42:17 +0100 Subject: [PATCH 08/49] track document modification state and display it in the top level window title bar --- apps/opencs/model/doc/document.cpp | 20 +++++++++++++++++++- apps/opencs/model/doc/document.hpp | 22 +++++++++++++++++++++- apps/opencs/view/doc/view.cpp | 8 ++++++++ apps/opencs/view/doc/view.hpp | 2 ++ apps/opencs/view/doc/viewmanager.cpp | 15 +++++++++++++++ apps/opencs/view/doc/viewmanager.hpp | 11 ++++++++--- 6 files changed, 73 insertions(+), 5 deletions(-) diff --git a/apps/opencs/model/doc/document.cpp b/apps/opencs/model/doc/document.cpp index 448598a4e4..8770b3b90a 100644 --- a/apps/opencs/model/doc/document.cpp +++ b/apps/opencs/model/doc/document.cpp @@ -1,9 +1,27 @@ #include "document.hpp" -CSMDoc::Document::Document() {} +CSMDoc::Document::Document() +{ + connect (&mUndoStack, SIGNAL (cleanChanged (bool)), this, SLOT (modificationStateChanged (bool))); +} QUndoStack& CSMDoc::Document::getUndoStack() { return mUndoStack; +} + +int CSMDoc::Document::getState() const +{ + int state = 0; + + if (!mUndoStack.isClean()) + state |= State_Modified; + + return state; +} + +void CSMDoc::Document::modificationStateChanged (bool clean) +{ + emit stateChanged (getState(), this); } \ No newline at end of file diff --git a/apps/opencs/model/doc/document.hpp b/apps/opencs/model/doc/document.hpp index 1dea7afc28..0499aaf9fb 100644 --- a/apps/opencs/model/doc/document.hpp +++ b/apps/opencs/model/doc/document.hpp @@ -2,11 +2,21 @@ #define CSM_DOC_DOCUMENT_H #include +#include namespace CSMDoc { - class Document + class Document : public QObject { + Q_OBJECT + + public: + + enum State + { + State_Modified = 1 + }; + QUndoStack mUndoStack; // not implemented @@ -18,6 +28,16 @@ namespace CSMDoc Document(); QUndoStack& getUndoStack(); + + int getState() const; + + signals: + + void stateChanged (int state, CSMDoc::Document *document); + + private slots: + + void modificationStateChanged (bool clean); }; } diff --git a/apps/opencs/view/doc/view.cpp b/apps/opencs/view/doc/view.cpp index c5792b27a6..be753e2161 100644 --- a/apps/opencs/view/doc/view.cpp +++ b/apps/opencs/view/doc/view.cpp @@ -55,6 +55,9 @@ void CSVDoc::View::updateTitle() stream << "New Document "; + if (mDocument->getState() & CSMDoc::Document::State_Modified) + stream << " *"; + if (mViewTotal>1) stream << " [" << (mViewIndex+1) << "/" << mViewTotal << "]"; @@ -89,6 +92,11 @@ void CSVDoc::View::setIndex (int viewIndex, int totalViews) updateTitle(); } +void CSVDoc::View::updateDocumentState() +{ + updateTitle(); +} + void CSVDoc::View::newView() { mViewManager.addView (mDocument); diff --git a/apps/opencs/view/doc/view.hpp b/apps/opencs/view/doc/view.hpp index 2c312715a7..67eafe2d5c 100644 --- a/apps/opencs/view/doc/view.hpp +++ b/apps/opencs/view/doc/view.hpp @@ -50,6 +50,8 @@ namespace CSVDoc void setIndex (int viewIndex, int totalViews); + void updateDocumentState(); + private slots: void newView(); diff --git a/apps/opencs/view/doc/viewmanager.cpp b/apps/opencs/view/doc/viewmanager.cpp index f6ac6e43df..ad391dabeb 100644 --- a/apps/opencs/view/doc/viewmanager.cpp +++ b/apps/opencs/view/doc/viewmanager.cpp @@ -4,6 +4,7 @@ #include #include "../../model/doc/documentmanager.hpp" +#include "../../model/doc/document.hpp" #include "view.hpp" @@ -42,6 +43,13 @@ CSVDoc::ViewManager::~ViewManager() CSVDoc::View *CSVDoc::ViewManager::addView (CSMDoc::Document *document) { + if (countViews (document)==0) + { + // new document + connect (document, SIGNAL (stateChanged (int, CSMDoc::Document *)), + this, SLOT (documentStateChanged (int, CSMDoc::Document *))); + } + View *view = new View (*this, document, countViews (document)+1); mViews.push_back (view); @@ -84,4 +92,11 @@ bool CSVDoc::ViewManager::closeRequest (View *view) } return true; +} + +void CSVDoc::ViewManager::documentStateChanged (int state, CSMDoc::Document *document) +{ + for (std::vector::const_iterator iter (mViews.begin()); iter!=mViews.end(); ++iter) + if ((*iter)->getDocument()==document) + (*iter)->updateDocumentState(); } \ No newline at end of file diff --git a/apps/opencs/view/doc/viewmanager.hpp b/apps/opencs/view/doc/viewmanager.hpp index 765fafbeab..1565b7c371 100644 --- a/apps/opencs/view/doc/viewmanager.hpp +++ b/apps/opencs/view/doc/viewmanager.hpp @@ -3,6 +3,8 @@ #include +#include + namespace CSMDoc { class Document; @@ -13,8 +15,10 @@ namespace CSVDoc { class View; - class ViewManager + class ViewManager : public QObject { + Q_OBJECT + CSMDoc::DocumentManager& mDocumentManager; std::vector mViews; std::vector mClosed; @@ -29,7 +33,7 @@ namespace CSVDoc ViewManager (CSMDoc::DocumentManager& documentManager); - ~ViewManager(); + virtual ~ViewManager(); View *addView (CSMDoc::Document *document); ///< The ownership of the returned view is not transferred. @@ -39,8 +43,9 @@ namespace CSVDoc bool closeRequest (View *view); + private slots: - + void documentStateChanged (int state, CSMDoc::Document *document); }; } From 5838929371d37b2f4b8771d3c1a8fb17b3989b06 Mon Sep 17 00:00:00 2001 From: Marc Zinnschlag Date: Fri, 23 Nov 2012 00:36:01 +0100 Subject: [PATCH 09/49] implemented a dummy save function (does not actually save anything) --- apps/opencs/model/doc/document.cpp | 30 ++++++++++++++++++++++++++++ apps/opencs/model/doc/document.hpp | 15 +++++++++++++- apps/opencs/view/doc/view.cpp | 15 ++++++++++++++ apps/opencs/view/doc/view.hpp | 4 ++++ apps/opencs/view/doc/viewmanager.cpp | 2 +- 5 files changed, 64 insertions(+), 2 deletions(-) diff --git a/apps/opencs/model/doc/document.cpp b/apps/opencs/model/doc/document.cpp index 8770b3b90a..8788ecb9f8 100644 --- a/apps/opencs/model/doc/document.cpp +++ b/apps/opencs/model/doc/document.cpp @@ -4,6 +4,10 @@ CSMDoc::Document::Document() { connect (&mUndoStack, SIGNAL (cleanChanged (bool)), this, SLOT (modificationStateChanged (bool))); + + // dummy implementation -> remove when proper save is implemented. + mSaveCount = 0; + connect (&mSaveTimer, SIGNAL(timeout()), this, SLOT (saving())); } QUndoStack& CSMDoc::Document::getUndoStack() @@ -18,10 +22,36 @@ int CSMDoc::Document::getState() const if (!mUndoStack.isClean()) state |= State_Modified; + if (mSaveCount) + state |= State_Locked | State_Saving; + return state; } +void CSMDoc::Document::save() +{ + mSaveCount = 1; + mSaveTimer.start (500); +} + +void CSMDoc::Document::abortSave() +{ + mSaveTimer.stop(); +} + void CSMDoc::Document::modificationStateChanged (bool clean) { emit stateChanged (getState(), this); +} + +void CSMDoc::Document::saving() +{ + ++mSaveCount; + + if (mSaveCount>15) + { + mSaveCount = 0; + mSaveTimer.stop(); + mUndoStack.setClean(); + } } \ No newline at end of file diff --git a/apps/opencs/model/doc/document.hpp b/apps/opencs/model/doc/document.hpp index 0499aaf9fb..90589b09cd 100644 --- a/apps/opencs/model/doc/document.hpp +++ b/apps/opencs/model/doc/document.hpp @@ -3,6 +3,7 @@ #include #include +#include namespace CSMDoc { @@ -14,11 +15,16 @@ namespace CSMDoc enum State { - State_Modified = 1 + State_Modified = 1, + State_Locked = 2, + State_Saving = 4 }; QUndoStack mUndoStack; + int mSaveCount; ///< dummy implementation -> remove when proper save is implemented. + QTimer mSaveTimer; ///< dummy implementation -> remove when proper save is implemented. + // not implemented Document (const Document&); Document& operator= (const Document&); @@ -31,6 +37,10 @@ namespace CSMDoc int getState() const; + void save(); + + void abortSave(); + signals: void stateChanged (int state, CSMDoc::Document *document); @@ -38,6 +48,9 @@ namespace CSMDoc private slots: void modificationStateChanged (bool clean); + + void saving(); + ///< dummy implementation -> remove when proper save is implemented. }; } diff --git a/apps/opencs/view/doc/view.cpp b/apps/opencs/view/doc/view.cpp index be753e2161..59852bef0b 100644 --- a/apps/opencs/view/doc/view.cpp +++ b/apps/opencs/view/doc/view.cpp @@ -16,6 +16,15 @@ void CSVDoc::View::closeEvent (QCloseEvent *event) event->ignore(); } +void CSVDoc::View::setupFileMenu() +{ + QMenu *file = menuBar()->addMenu (tr ("&File")); + + QAction *save = new QAction (tr ("&Save"), this); + connect (save, SIGNAL (triggered()), this, SLOT (save())); + file->addAction (save); +} + void CSVDoc::View::setupEditMenu() { QMenu *edit = menuBar()->addMenu (tr ("&Edit")); @@ -45,6 +54,7 @@ void CSVDoc::View::setupViewMenu() void CSVDoc::View::setupUi() { + setupFileMenu(); setupEditMenu(); setupViewMenu(); } @@ -105,4 +115,9 @@ void CSVDoc::View::newView() void CSVDoc::View::test() { mDocument->getUndoStack().push (new QUndoCommand()); +} + +void CSVDoc::View::save() +{ + mDocument->save(); } \ No newline at end of file diff --git a/apps/opencs/view/doc/view.hpp b/apps/opencs/view/doc/view.hpp index 67eafe2d5c..be7d23fd07 100644 --- a/apps/opencs/view/doc/view.hpp +++ b/apps/opencs/view/doc/view.hpp @@ -31,6 +31,8 @@ namespace CSVDoc void closeEvent (QCloseEvent *event); + void setupFileMenu(); + void setupEditMenu(); void setupViewMenu(); @@ -57,6 +59,8 @@ namespace CSVDoc void newView(); void test(); + + void save(); }; } diff --git a/apps/opencs/view/doc/viewmanager.cpp b/apps/opencs/view/doc/viewmanager.cpp index ad391dabeb..c7f147660a 100644 --- a/apps/opencs/view/doc/viewmanager.cpp +++ b/apps/opencs/view/doc/viewmanager.cpp @@ -99,4 +99,4 @@ void CSVDoc::ViewManager::documentStateChanged (int state, CSMDoc::Document *doc for (std::vector::const_iterator iter (mViews.begin()); iter!=mViews.end(); ++iter) if ((*iter)->getDocument()==document) (*iter)->updateDocumentState(); -} \ No newline at end of file +} From 931eb08114184442f856239f1f32f1da25ddde6d Mon Sep 17 00:00:00 2001 From: Marc Zinnschlag Date: Fri, 23 Nov 2012 00:51:04 +0100 Subject: [PATCH 10/49] implemented edit locking (used during saves) --- apps/opencs/model/doc/document.cpp | 3 +++ apps/opencs/view/doc/view.cpp | 26 ++++++++++++++++++++------ apps/opencs/view/doc/view.hpp | 7 +++++++ 3 files changed, 30 insertions(+), 6 deletions(-) diff --git a/apps/opencs/model/doc/document.cpp b/apps/opencs/model/doc/document.cpp index 8788ecb9f8..16af492a9b 100644 --- a/apps/opencs/model/doc/document.cpp +++ b/apps/opencs/model/doc/document.cpp @@ -32,11 +32,13 @@ void CSMDoc::Document::save() { mSaveCount = 1; mSaveTimer.start (500); + emit stateChanged (getState(), this); } void CSMDoc::Document::abortSave() { mSaveTimer.stop(); + emit stateChanged (getState(), this); } void CSMDoc::Document::modificationStateChanged (bool clean) @@ -53,5 +55,6 @@ void CSMDoc::Document::saving() mSaveCount = 0; mSaveTimer.stop(); mUndoStack.setClean(); + emit stateChanged (getState(), this); } } \ No newline at end of file diff --git a/apps/opencs/view/doc/view.cpp b/apps/opencs/view/doc/view.cpp index 59852bef0b..85db5e51f8 100644 --- a/apps/opencs/view/doc/view.cpp +++ b/apps/opencs/view/doc/view.cpp @@ -23,24 +23,26 @@ void CSVDoc::View::setupFileMenu() QAction *save = new QAction (tr ("&Save"), this); connect (save, SIGNAL (triggered()), this, SLOT (save())); file->addAction (save); + mEditingActions.push_back (save); } void CSVDoc::View::setupEditMenu() { QMenu *edit = menuBar()->addMenu (tr ("&Edit")); - QAction *undo = mDocument->getUndoStack().createUndoAction (this, tr("&Undo")); - undo->setShortcuts (QKeySequence::Undo); - edit->addAction (undo); + mUndo = mDocument->getUndoStack().createUndoAction (this, tr("&Undo")); + mUndo->setShortcuts (QKeySequence::Undo); + edit->addAction (mUndo); - QAction *redo = mDocument->getUndoStack().createRedoAction (this, tr("&Redo")); - redo->setShortcuts (QKeySequence::Redo); - edit->addAction (redo); + mRedo= mDocument->getUndoStack().createRedoAction (this, tr("&Redo")); + mRedo->setShortcuts (QKeySequence::Redo); + edit->addAction (mRedo); // test QAction *test = new QAction (tr ("&Test Command"), this); connect (test, SIGNAL (triggered()), this, SLOT (test())); edit->addAction (test); + mEditingActions.push_back (test); } void CSVDoc::View::setupViewMenu() @@ -74,6 +76,17 @@ void CSVDoc::View::updateTitle() setWindowTitle (stream.str().c_str()); } +void CSVDoc::View::updateActions() +{ + bool editing = !(mDocument->getState() & CSMDoc::Document::State_Locked); + + for (std::vector::iterator iter (mEditingActions.begin()); iter!=mEditingActions.end(); ++iter) + (*iter)->setEnabled (editing); + + mUndo->setEnabled (editing & mDocument->getUndoStack().canUndo()); + mRedo->setEnabled (editing & mDocument->getUndoStack().canRedo()); +} + CSVDoc::View::View (ViewManager& viewManager, CSMDoc::Document *document, int totalViews) : mViewManager (viewManager), mDocument (document), mViewIndex (totalViews-1), mViewTotal (totalViews) { @@ -105,6 +118,7 @@ void CSVDoc::View::setIndex (int viewIndex, int totalViews) void CSVDoc::View::updateDocumentState() { updateTitle(); + updateActions(); } void CSVDoc::View::newView() diff --git a/apps/opencs/view/doc/view.hpp b/apps/opencs/view/doc/view.hpp index be7d23fd07..bab1429590 100644 --- a/apps/opencs/view/doc/view.hpp +++ b/apps/opencs/view/doc/view.hpp @@ -1,6 +1,8 @@ #ifndef CSV_DOC_VIEW_H #define CSV_DOC_VIEW_H +#include + #include class QAction; @@ -22,6 +24,9 @@ namespace CSVDoc CSMDoc::Document *mDocument; int mViewIndex; int mViewTotal; + QAction *mUndo; + QAction *mRedo; + std::vector mEditingActions; // not implemented View (const View&); @@ -41,6 +46,8 @@ namespace CSVDoc void updateTitle(); + void updateActions(); + public: View (ViewManager& viewManager, CSMDoc::Document *document, int totalViews); From 03aacd326395c8548d5091bf5b83b92e6b969d69 Mon Sep 17 00:00:00 2001 From: Marc Zinnschlag Date: Fri, 23 Nov 2012 10:25:34 +0100 Subject: [PATCH 11/49] added progress tracking --- apps/opencs/model/doc/document.cpp | 5 ++++- apps/opencs/model/doc/document.hpp | 5 ++++- apps/opencs/view/doc/view.cpp | 5 +++++ apps/opencs/view/doc/view.hpp | 2 ++ apps/opencs/view/doc/viewmanager.cpp | 11 +++++++++++ apps/opencs/view/doc/viewmanager.hpp | 2 ++ 6 files changed, 28 insertions(+), 2 deletions(-) diff --git a/apps/opencs/model/doc/document.cpp b/apps/opencs/model/doc/document.cpp index 16af492a9b..3c2c5cd8a8 100644 --- a/apps/opencs/model/doc/document.cpp +++ b/apps/opencs/model/doc/document.cpp @@ -23,7 +23,7 @@ int CSMDoc::Document::getState() const state |= State_Modified; if (mSaveCount) - state |= State_Locked | State_Saving; + state |= State_Locked | State_Saving | State_Progress; return state; } @@ -33,6 +33,7 @@ void CSMDoc::Document::save() mSaveCount = 1; mSaveTimer.start (500); emit stateChanged (getState(), this); + emit progress (1, 16, this); } void CSMDoc::Document::abortSave() @@ -50,6 +51,8 @@ void CSMDoc::Document::saving() { ++mSaveCount; + emit progress (mSaveCount, 16, this); + if (mSaveCount>15) { mSaveCount = 0; diff --git a/apps/opencs/model/doc/document.hpp b/apps/opencs/model/doc/document.hpp index 90589b09cd..b1c9ead863 100644 --- a/apps/opencs/model/doc/document.hpp +++ b/apps/opencs/model/doc/document.hpp @@ -17,7 +17,8 @@ namespace CSMDoc { State_Modified = 1, State_Locked = 2, - State_Saving = 4 + State_Saving = 4, + State_Progress = 8 }; QUndoStack mUndoStack; @@ -45,6 +46,8 @@ namespace CSMDoc void stateChanged (int state, CSMDoc::Document *document); + void progress (int current, int max, CSMDoc::Document *document); + private slots: void modificationStateChanged (bool clean); diff --git a/apps/opencs/view/doc/view.cpp b/apps/opencs/view/doc/view.cpp index 85db5e51f8..8f3efc673c 100644 --- a/apps/opencs/view/doc/view.cpp +++ b/apps/opencs/view/doc/view.cpp @@ -121,6 +121,11 @@ void CSVDoc::View::updateDocumentState() updateActions(); } +void CSVDoc::View::updateProgress (int current, int max) +{ + +} + void CSVDoc::View::newView() { mViewManager.addView (mDocument); diff --git a/apps/opencs/view/doc/view.hpp b/apps/opencs/view/doc/view.hpp index bab1429590..ab945188f5 100644 --- a/apps/opencs/view/doc/view.hpp +++ b/apps/opencs/view/doc/view.hpp @@ -61,6 +61,8 @@ namespace CSVDoc void updateDocumentState(); + void updateProgress (int current, int max); + private slots: void newView(); diff --git a/apps/opencs/view/doc/viewmanager.cpp b/apps/opencs/view/doc/viewmanager.cpp index c7f147660a..752501b199 100644 --- a/apps/opencs/view/doc/viewmanager.cpp +++ b/apps/opencs/view/doc/viewmanager.cpp @@ -48,6 +48,9 @@ CSVDoc::View *CSVDoc::ViewManager::addView (CSMDoc::Document *document) // new document connect (document, SIGNAL (stateChanged (int, CSMDoc::Document *)), this, SLOT (documentStateChanged (int, CSMDoc::Document *))); + + connect (document, SIGNAL (progress (int, int, CSMDoc::Document *)), + this, SLOT (progress (int, int, CSMDoc::Document *))); } View *view = new View (*this, document, countViews (document)+1); @@ -80,6 +83,7 @@ bool CSVDoc::ViewManager::closeRequest (View *view) { bool last = countViews (view->getDocument())<=1; + /// \todo check if save is in progress -> warn user about possible data loss /// \todo check if document has not been saved -> return false and start close dialogue mViews.erase (iter); @@ -100,3 +104,10 @@ void CSVDoc::ViewManager::documentStateChanged (int state, CSMDoc::Document *doc if ((*iter)->getDocument()==document) (*iter)->updateDocumentState(); } + +void CSVDoc::ViewManager::progress (int current, int max, CSMDoc::Document *document) +{ + for (std::vector::const_iterator iter (mViews.begin()); iter!=mViews.end(); ++iter) + if ((*iter)->getDocument()==document) + (*iter)->updateProgress (current, max); +} \ No newline at end of file diff --git a/apps/opencs/view/doc/viewmanager.hpp b/apps/opencs/view/doc/viewmanager.hpp index 1565b7c371..8cfc36f3fd 100644 --- a/apps/opencs/view/doc/viewmanager.hpp +++ b/apps/opencs/view/doc/viewmanager.hpp @@ -46,6 +46,8 @@ namespace CSVDoc private slots: void documentStateChanged (int state, CSMDoc::Document *document); + + void progress (int current, int max, CSMDoc::Document *document); }; } From 04158d03b05cc63ba238835821a4125ea0ba8869 Mon Sep 17 00:00:00 2001 From: Marc Zinnschlag Date: Fri, 23 Nov 2012 10:30:14 +0100 Subject: [PATCH 12/49] clean up properly after closing a top level window --- apps/opencs/view/doc/viewmanager.cpp | 5 +---- apps/opencs/view/doc/viewmanager.hpp | 1 - 2 files changed, 1 insertion(+), 5 deletions(-) diff --git a/apps/opencs/view/doc/viewmanager.cpp b/apps/opencs/view/doc/viewmanager.cpp index 752501b199..7f94f52a2a 100644 --- a/apps/opencs/view/doc/viewmanager.cpp +++ b/apps/opencs/view/doc/viewmanager.cpp @@ -36,9 +36,6 @@ CSVDoc::ViewManager::~ViewManager() { for (std::vector::iterator iter (mViews.begin()); iter!=mViews.end(); ++iter) delete *iter; - - for (std::vector::iterator iter (mClosed.begin()); iter!=mClosed.end(); ++iter) - delete *iter; } CSVDoc::View *CSVDoc::ViewManager::addView (CSMDoc::Document *document) @@ -87,7 +84,7 @@ bool CSVDoc::ViewManager::closeRequest (View *view) /// \todo check if document has not been saved -> return false and start close dialogue mViews.erase (iter); - mClosed.push_back (view); + view->deleteLater(); if (last) mDocumentManager.removeDocument (view->getDocument()); diff --git a/apps/opencs/view/doc/viewmanager.hpp b/apps/opencs/view/doc/viewmanager.hpp index 8cfc36f3fd..bcf6dc59e2 100644 --- a/apps/opencs/view/doc/viewmanager.hpp +++ b/apps/opencs/view/doc/viewmanager.hpp @@ -21,7 +21,6 @@ namespace CSVDoc CSMDoc::DocumentManager& mDocumentManager; std::vector mViews; - std::vector mClosed; // not implemented ViewManager (const ViewManager&); From eaa58e0530c3624ee186f5f43ef02f63203354a3 Mon Sep 17 00:00:00 2001 From: Marc Zinnschlag Date: Fri, 23 Nov 2012 10:52:46 +0100 Subject: [PATCH 13/49] preparations for multiple parallel progress-type operations --- apps/opencs/model/doc/document.cpp | 6 +++--- apps/opencs/model/doc/document.hpp | 5 ++--- apps/opencs/view/doc/view.cpp | 11 ++++++----- apps/opencs/view/doc/view.hpp | 3 ++- apps/opencs/view/doc/viewmanager.cpp | 8 ++++---- apps/opencs/view/doc/viewmanager.hpp | 2 +- 6 files changed, 18 insertions(+), 17 deletions(-) diff --git a/apps/opencs/model/doc/document.cpp b/apps/opencs/model/doc/document.cpp index 3c2c5cd8a8..c4f830531a 100644 --- a/apps/opencs/model/doc/document.cpp +++ b/apps/opencs/model/doc/document.cpp @@ -23,7 +23,7 @@ int CSMDoc::Document::getState() const state |= State_Modified; if (mSaveCount) - state |= State_Locked | State_Saving | State_Progress; + state |= State_Locked | State_Saving; return state; } @@ -33,7 +33,7 @@ void CSMDoc::Document::save() mSaveCount = 1; mSaveTimer.start (500); emit stateChanged (getState(), this); - emit progress (1, 16, this); + emit progress (1, 16, State_Saving, this); } void CSMDoc::Document::abortSave() @@ -51,7 +51,7 @@ void CSMDoc::Document::saving() { ++mSaveCount; - emit progress (mSaveCount, 16, this); + emit progress (mSaveCount, 16, State_Saving, this); if (mSaveCount>15) { diff --git a/apps/opencs/model/doc/document.hpp b/apps/opencs/model/doc/document.hpp index b1c9ead863..8553427a1c 100644 --- a/apps/opencs/model/doc/document.hpp +++ b/apps/opencs/model/doc/document.hpp @@ -17,8 +17,7 @@ namespace CSMDoc { State_Modified = 1, State_Locked = 2, - State_Saving = 4, - State_Progress = 8 + State_Saving = 4 }; QUndoStack mUndoStack; @@ -46,7 +45,7 @@ namespace CSMDoc void stateChanged (int state, CSMDoc::Document *document); - void progress (int current, int max, CSMDoc::Document *document); + void progress (int current, int max, int type, CSMDoc::Document *document); private slots: diff --git a/apps/opencs/view/doc/view.cpp b/apps/opencs/view/doc/view.cpp index 8f3efc673c..3e9701669c 100644 --- a/apps/opencs/view/doc/view.cpp +++ b/apps/opencs/view/doc/view.cpp @@ -20,10 +20,9 @@ void CSVDoc::View::setupFileMenu() { QMenu *file = menuBar()->addMenu (tr ("&File")); - QAction *save = new QAction (tr ("&Save"), this); - connect (save, SIGNAL (triggered()), this, SLOT (save())); - file->addAction (save); - mEditingActions.push_back (save); + mSave = new QAction (tr ("&Save"), this); + connect (mSave, SIGNAL (triggered()), this, SLOT (save())); + file->addAction (mSave); } void CSVDoc::View::setupEditMenu() @@ -85,6 +84,8 @@ void CSVDoc::View::updateActions() mUndo->setEnabled (editing & mDocument->getUndoStack().canUndo()); mRedo->setEnabled (editing & mDocument->getUndoStack().canRedo()); + + mSave->setEnabled (!(mDocument->getState() & CSMDoc::Document::State_Saving)); } CSVDoc::View::View (ViewManager& viewManager, CSMDoc::Document *document, int totalViews) @@ -121,7 +122,7 @@ void CSVDoc::View::updateDocumentState() updateActions(); } -void CSVDoc::View::updateProgress (int current, int max) +void CSVDoc::View::updateProgress (int current, int max, int type) { } diff --git a/apps/opencs/view/doc/view.hpp b/apps/opencs/view/doc/view.hpp index ab945188f5..1836ced8b6 100644 --- a/apps/opencs/view/doc/view.hpp +++ b/apps/opencs/view/doc/view.hpp @@ -26,6 +26,7 @@ namespace CSVDoc int mViewTotal; QAction *mUndo; QAction *mRedo; + QAction *mSave; std::vector mEditingActions; // not implemented @@ -61,7 +62,7 @@ namespace CSVDoc void updateDocumentState(); - void updateProgress (int current, int max); + void updateProgress (int current, int max, int type); private slots: diff --git a/apps/opencs/view/doc/viewmanager.cpp b/apps/opencs/view/doc/viewmanager.cpp index 7f94f52a2a..ed31fdb754 100644 --- a/apps/opencs/view/doc/viewmanager.cpp +++ b/apps/opencs/view/doc/viewmanager.cpp @@ -46,8 +46,8 @@ CSVDoc::View *CSVDoc::ViewManager::addView (CSMDoc::Document *document) connect (document, SIGNAL (stateChanged (int, CSMDoc::Document *)), this, SLOT (documentStateChanged (int, CSMDoc::Document *))); - connect (document, SIGNAL (progress (int, int, CSMDoc::Document *)), - this, SLOT (progress (int, int, CSMDoc::Document *))); + connect (document, SIGNAL (progress (int, int, int, CSMDoc::Document *)), + this, SLOT (progress (int, int, int, CSMDoc::Document *))); } View *view = new View (*this, document, countViews (document)+1); @@ -102,9 +102,9 @@ void CSVDoc::ViewManager::documentStateChanged (int state, CSMDoc::Document *doc (*iter)->updateDocumentState(); } -void CSVDoc::ViewManager::progress (int current, int max, CSMDoc::Document *document) +void CSVDoc::ViewManager::progress (int current, int max, int type, CSMDoc::Document *document) { for (std::vector::const_iterator iter (mViews.begin()); iter!=mViews.end(); ++iter) if ((*iter)->getDocument()==document) - (*iter)->updateProgress (current, max); + (*iter)->updateProgress (current, max, type); } \ No newline at end of file diff --git a/apps/opencs/view/doc/viewmanager.hpp b/apps/opencs/view/doc/viewmanager.hpp index bcf6dc59e2..eac4902502 100644 --- a/apps/opencs/view/doc/viewmanager.hpp +++ b/apps/opencs/view/doc/viewmanager.hpp @@ -46,7 +46,7 @@ namespace CSVDoc void documentStateChanged (int state, CSMDoc::Document *document); - void progress (int current, int max, CSMDoc::Document *document); + void progress (int current, int max, int type, CSMDoc::Document *document); }; } From 2fc183d595a59ff9d84b67dc32448234ebe4d6ff Mon Sep 17 00:00:00 2001 From: Marc Zinnschlag Date: Fri, 23 Nov 2012 12:20:35 +0100 Subject: [PATCH 14/49] added operations progress bar --- apps/opencs/CMakeLists.txt | 4 +-- apps/opencs/model/doc/document.cpp | 13 +++++--- apps/opencs/model/doc/document.hpp | 4 +-- apps/opencs/view/doc/operation.cpp | 49 ++++++++++++++++++++++++++++ apps/opencs/view/doc/operation.hpp | 31 ++++++++++++++++++ apps/opencs/view/doc/operations.cpp | 47 ++++++++++++++++++++++++++ apps/opencs/view/doc/operations.hpp | 37 +++++++++++++++++++++ apps/opencs/view/doc/view.cpp | 20 ++++++++++-- apps/opencs/view/doc/view.hpp | 4 ++- apps/opencs/view/doc/viewmanager.cpp | 8 ++--- apps/opencs/view/doc/viewmanager.hpp | 2 +- 11 files changed, 202 insertions(+), 17 deletions(-) create mode 100644 apps/opencs/view/doc/operation.cpp create mode 100644 apps/opencs/view/doc/operation.hpp create mode 100644 apps/opencs/view/doc/operations.cpp create mode 100644 apps/opencs/view/doc/operations.hpp diff --git a/apps/opencs/CMakeLists.txt b/apps/opencs/CMakeLists.txt index d7f113447a..66b9f4942a 100644 --- a/apps/opencs/CMakeLists.txt +++ b/apps/opencs/CMakeLists.txt @@ -4,7 +4,7 @@ set (OPENCS_SRC model/doc/documentmanager.cpp model/doc/document.cpp - view/doc/viewmanager.cpp view/doc/view.cpp + view/doc/viewmanager.cpp view/doc/view.cpp view/doc/operations.cpp view/doc/operation.cpp ) set (OPENCS_HDR @@ -12,7 +12,7 @@ set (OPENCS_HDR model/doc/documentmanager.hpp model/doc/document.hpp - view/doc/viewmanager.hpp view/doc/view.hpp + view/doc/viewmanager.hpp view/doc/view.hpp view/doc/operations.hpp view/doc/operation.hpp ) set (OPENCS_US diff --git a/apps/opencs/model/doc/document.cpp b/apps/opencs/model/doc/document.cpp index c4f830531a..473d723754 100644 --- a/apps/opencs/model/doc/document.cpp +++ b/apps/opencs/model/doc/document.cpp @@ -33,13 +33,16 @@ void CSMDoc::Document::save() mSaveCount = 1; mSaveTimer.start (500); emit stateChanged (getState(), this); - emit progress (1, 16, State_Saving, this); + emit progress (1, 16, State_Saving, 1, this); } -void CSMDoc::Document::abortSave() +void CSMDoc::Document::abortOperation (int type) { - mSaveTimer.stop(); - emit stateChanged (getState(), this); + if (type==State_Saving) + { + mSaveTimer.stop(); + emit stateChanged (getState(), this); + } } void CSMDoc::Document::modificationStateChanged (bool clean) @@ -51,7 +54,7 @@ void CSMDoc::Document::saving() { ++mSaveCount; - emit progress (mSaveCount, 16, State_Saving, this); + emit progress (mSaveCount, 16, State_Saving, 1, this); if (mSaveCount>15) { diff --git a/apps/opencs/model/doc/document.hpp b/apps/opencs/model/doc/document.hpp index 8553427a1c..3bed0151de 100644 --- a/apps/opencs/model/doc/document.hpp +++ b/apps/opencs/model/doc/document.hpp @@ -39,13 +39,13 @@ namespace CSMDoc void save(); - void abortSave(); + void abortOperation (int type); signals: void stateChanged (int state, CSMDoc::Document *document); - void progress (int current, int max, int type, CSMDoc::Document *document); + void progress (int current, int max, int type, int threads, CSMDoc::Document *document); private slots: diff --git a/apps/opencs/view/doc/operation.cpp b/apps/opencs/view/doc/operation.cpp new file mode 100644 index 0000000000..cd9477557a --- /dev/null +++ b/apps/opencs/view/doc/operation.cpp @@ -0,0 +1,49 @@ + +#include "operation.hpp" + +#include + +#include "../../model/doc/document.hpp" + +void CSVDoc::Operation::updateLabel (int threads) +{ + if (threads==-1 || ((threads==0)!=mStalling)) + { + std::string name ("unknown operation"); + + switch (mType) + { + case CSMDoc::Document::State_Saving: name = "saving"; break; + } + + std::ostringstream stream; + + if ((mStalling = (threads<=0))) + { + stream << name << " (waiting for a free worker thread)"; + } + else + { + stream << name << " (%p%)"; + } + + setFormat (stream.str().c_str()); + } +} + +CSVDoc::Operation::Operation (int type) : mType (type), mStalling (false) +{ + updateLabel(); +} + +void CSVDoc::Operation::setProgress (int current, int max, int threads) +{ + updateLabel (threads); + setRange (0, max); + setValue (current); +} + +int CSVDoc::Operation::getType() const +{ + return mType; +} \ No newline at end of file diff --git a/apps/opencs/view/doc/operation.hpp b/apps/opencs/view/doc/operation.hpp new file mode 100644 index 0000000000..362725b6f4 --- /dev/null +++ b/apps/opencs/view/doc/operation.hpp @@ -0,0 +1,31 @@ +#ifndef CSV_DOC_OPERATION_H +#define CSV_DOC_OPERATION_H + +#include + +namespace CSVDoc +{ + class Operation : public QProgressBar + { + Q_OBJECT + + int mType; + bool mStalling; + + // not implemented + Operation (const Operation&); + Operation& operator= (const Operation&); + + void updateLabel (int threads = -1); + + public: + + Operation (int type); + + void setProgress (int current, int max, int threads); + + int getType() const; + }; +} + +#endif \ No newline at end of file diff --git a/apps/opencs/view/doc/operations.cpp b/apps/opencs/view/doc/operations.cpp new file mode 100644 index 0000000000..ba444a119a --- /dev/null +++ b/apps/opencs/view/doc/operations.cpp @@ -0,0 +1,47 @@ + +#include "operations.hpp" + +#include + +#include "operation.hpp" + +CSVDoc::Operations::Operations() +{ + /// \todo make widget height fixed (exactly the height required to display all operations) + + setFeatures (QDockWidget::NoDockWidgetFeatures); + + QWidget *widget = new QWidget; + setWidget (widget); + + mLayout = new QVBoxLayout; + + widget->setLayout (mLayout); +} + +void CSVDoc::Operations::setProgress (int current, int max, int type, int threads) +{ + for (std::vector::iterator iter (mOperations.begin()); iter!=mOperations.end(); ++iter) + if ((*iter)->getType()==type) + { + (*iter)->setProgress (current, max, threads); + return; + } + + Operation *operation = new Operation (type); + + mLayout->addWidget (operation); + mOperations.push_back (operation); + operation->setProgress (current, max, threads); +} + +void CSVDoc::Operations::quitOperation (int type) +{ + for (std::vector::iterator iter (mOperations.begin()); iter!=mOperations.end(); ++iter) + if ((*iter)->getType()==type) + { + delete *iter; + mOperations.erase (iter); + break; + } +} \ No newline at end of file diff --git a/apps/opencs/view/doc/operations.hpp b/apps/opencs/view/doc/operations.hpp new file mode 100644 index 0000000000..b966774502 --- /dev/null +++ b/apps/opencs/view/doc/operations.hpp @@ -0,0 +1,37 @@ +#ifndef CSV_DOC_OPERATIONS_H +#define CSV_DOC_OPERATIONS_H + +#include + +#include + +class QVBoxLayout; + +namespace CSVDoc +{ + class Operation; + + class Operations : public QDockWidget + { + Q_OBJECT + + QVBoxLayout *mLayout; + std::vector mOperations; + + // not implemented + Operations (const Operations&); + Operations& operator= (const Operations&); + + public: + + Operations(); + + void setProgress (int current, int max, int type, int threads); + ///< Implicitly starts the operation, if it is not running already. + + void quitOperation (int type); + ///< Calling this function for an operation that is not running is a no-op. + }; +} + +#endif \ No newline at end of file diff --git a/apps/opencs/view/doc/view.cpp b/apps/opencs/view/doc/view.cpp index 3e9701669c..fe018ab3bb 100644 --- a/apps/opencs/view/doc/view.cpp +++ b/apps/opencs/view/doc/view.cpp @@ -9,6 +9,7 @@ #include "../../model/doc/document.hpp" #include "viewmanager.hpp" +#include "operations.hpp" void CSVDoc::View::closeEvent (QCloseEvent *event) { @@ -94,6 +95,9 @@ CSVDoc::View::View (ViewManager& viewManager, CSMDoc::Document *document, int to setCentralWidget (new QWidget); resize (200, 200); + mOperations = new Operations; + addDockWidget (Qt::BottomDockWidgetArea, mOperations); + updateTitle(); setupUi(); @@ -120,11 +124,23 @@ void CSVDoc::View::updateDocumentState() { updateTitle(); updateActions(); + + static const int operations[] = + { + CSMDoc::Document::State_Saving, + -1 // end marker + }; + + int state = mDocument->getState() ; + + for (int i=0; operations[i]!=-1; ++i) + if (!(state & operations[i])) + mOperations->quitOperation (operations[i]); } -void CSVDoc::View::updateProgress (int current, int max, int type) +void CSVDoc::View::updateProgress (int current, int max, int type, int threads) { - + mOperations->setProgress (current, max, type, threads); } void CSVDoc::View::newView() diff --git a/apps/opencs/view/doc/view.hpp b/apps/opencs/view/doc/view.hpp index 1836ced8b6..191af36b51 100644 --- a/apps/opencs/view/doc/view.hpp +++ b/apps/opencs/view/doc/view.hpp @@ -15,6 +15,7 @@ namespace CSMDoc namespace CSVDoc { class ViewManager; + class Operations; class View : public QMainWindow { @@ -28,6 +29,7 @@ namespace CSVDoc QAction *mRedo; QAction *mSave; std::vector mEditingActions; + Operations *mOperations; // not implemented View (const View&); @@ -62,7 +64,7 @@ namespace CSVDoc void updateDocumentState(); - void updateProgress (int current, int max, int type); + void updateProgress (int current, int max, int type, int threads); private slots: diff --git a/apps/opencs/view/doc/viewmanager.cpp b/apps/opencs/view/doc/viewmanager.cpp index ed31fdb754..673afbad82 100644 --- a/apps/opencs/view/doc/viewmanager.cpp +++ b/apps/opencs/view/doc/viewmanager.cpp @@ -46,8 +46,8 @@ CSVDoc::View *CSVDoc::ViewManager::addView (CSMDoc::Document *document) connect (document, SIGNAL (stateChanged (int, CSMDoc::Document *)), this, SLOT (documentStateChanged (int, CSMDoc::Document *))); - connect (document, SIGNAL (progress (int, int, int, CSMDoc::Document *)), - this, SLOT (progress (int, int, int, CSMDoc::Document *))); + connect (document, SIGNAL (progress (int, int, int, int, CSMDoc::Document *)), + this, SLOT (progress (int, int, int, int, CSMDoc::Document *))); } View *view = new View (*this, document, countViews (document)+1); @@ -102,9 +102,9 @@ void CSVDoc::ViewManager::documentStateChanged (int state, CSMDoc::Document *doc (*iter)->updateDocumentState(); } -void CSVDoc::ViewManager::progress (int current, int max, int type, CSMDoc::Document *document) +void CSVDoc::ViewManager::progress (int current, int max, int type, int threads, CSMDoc::Document *document) { for (std::vector::const_iterator iter (mViews.begin()); iter!=mViews.end(); ++iter) if ((*iter)->getDocument()==document) - (*iter)->updateProgress (current, max, type); + (*iter)->updateProgress (current, max, type, threads); } \ No newline at end of file diff --git a/apps/opencs/view/doc/viewmanager.hpp b/apps/opencs/view/doc/viewmanager.hpp index eac4902502..caf75a0cdb 100644 --- a/apps/opencs/view/doc/viewmanager.hpp +++ b/apps/opencs/view/doc/viewmanager.hpp @@ -46,7 +46,7 @@ namespace CSVDoc void documentStateChanged (int state, CSMDoc::Document *document); - void progress (int current, int max, int type, CSMDoc::Document *document); + void progress (int current, int max, int type, int threads, CSMDoc::Document *document); }; } From 997386d8736b036bdb3dd1a7a38e904d4793a755 Mon Sep 17 00:00:00 2001 From: Marc Zinnschlag Date: Fri, 23 Nov 2012 13:15:45 +0100 Subject: [PATCH 15/49] implemented world verify function (doesn't do anything yet; mostly meant as a test for multi-operation interface) --- apps/opencs/model/doc/document.cpp | 34 ++++++++++++++++++++++++++++++ apps/opencs/model/doc/document.hpp | 11 +++++++++- apps/opencs/view/doc/operation.cpp | 3 +++ apps/opencs/view/doc/view.cpp | 18 +++++++++++++++- apps/opencs/view/doc/view.hpp | 5 +++++ 5 files changed, 69 insertions(+), 2 deletions(-) diff --git a/apps/opencs/model/doc/document.cpp b/apps/opencs/model/doc/document.cpp index 473d723754..5c39e16c0f 100644 --- a/apps/opencs/model/doc/document.cpp +++ b/apps/opencs/model/doc/document.cpp @@ -8,6 +8,10 @@ CSMDoc::Document::Document() // dummy implementation -> remove when proper save is implemented. mSaveCount = 0; connect (&mSaveTimer, SIGNAL(timeout()), this, SLOT (saving())); + + // dummy implementation -> remove when proper verify is implemented. + mVerifyCount = 0; + connect (&mVerifyTimer, SIGNAL(timeout()), this, SLOT (verifying())); } QUndoStack& CSMDoc::Document::getUndoStack() @@ -25,6 +29,9 @@ int CSMDoc::Document::getState() const if (mSaveCount) state |= State_Locked | State_Saving; + if (mVerifyCount) + state |= State_Locked | State_Verifying; + return state; } @@ -36,6 +43,14 @@ void CSMDoc::Document::save() emit progress (1, 16, State_Saving, 1, this); } +void CSMDoc::Document::verify() +{ + mVerifyCount = 1; + mVerifyTimer.start (500); + emit stateChanged (getState(), this); + emit progress (1, 20, State_Verifying, 1, this); +} + void CSMDoc::Document::abortOperation (int type) { if (type==State_Saving) @@ -43,6 +58,11 @@ void CSMDoc::Document::abortOperation (int type) mSaveTimer.stop(); emit stateChanged (getState(), this); } + else if (type==State_Verifying) + { + mVerifyTimer.stop(); + emit stateChanged (getState(), this); + } } void CSMDoc::Document::modificationStateChanged (bool clean) @@ -63,4 +83,18 @@ void CSMDoc::Document::saving() mUndoStack.setClean(); emit stateChanged (getState(), this); } +} + +void CSMDoc::Document::verifying() +{ + ++mVerifyCount; + + emit progress (mVerifyCount, 20, State_Verifying, 1, this); + + if (mVerifyCount>19) + { + mVerifyCount = 0; + mVerifyTimer.stop(); + emit stateChanged (getState(), this); + } } \ No newline at end of file diff --git a/apps/opencs/model/doc/document.hpp b/apps/opencs/model/doc/document.hpp index 3bed0151de..e691bb38f6 100644 --- a/apps/opencs/model/doc/document.hpp +++ b/apps/opencs/model/doc/document.hpp @@ -17,7 +17,8 @@ namespace CSMDoc { State_Modified = 1, State_Locked = 2, - State_Saving = 4 + State_Saving = 4, + State_Verifying = 8 }; QUndoStack mUndoStack; @@ -25,6 +26,9 @@ namespace CSMDoc int mSaveCount; ///< dummy implementation -> remove when proper save is implemented. QTimer mSaveTimer; ///< dummy implementation -> remove when proper save is implemented. + int mVerifyCount; ///< dummy implementation -> remove when proper verify is implemented. + QTimer mVerifyTimer; ///< dummy implementation -> remove when proper verify is implemented. + // not implemented Document (const Document&); Document& operator= (const Document&); @@ -39,6 +43,8 @@ namespace CSMDoc void save(); + void verify(); + void abortOperation (int type); signals: @@ -53,6 +59,9 @@ namespace CSMDoc void saving(); ///< dummy implementation -> remove when proper save is implemented. + + void verifying(); + ///< dummy implementation -> remove when proper verify is implemented. }; } diff --git a/apps/opencs/view/doc/operation.cpp b/apps/opencs/view/doc/operation.cpp index cd9477557a..02a93f9c53 100644 --- a/apps/opencs/view/doc/operation.cpp +++ b/apps/opencs/view/doc/operation.cpp @@ -14,6 +14,7 @@ void CSVDoc::Operation::updateLabel (int threads) switch (mType) { case CSMDoc::Document::State_Saving: name = "saving"; break; + case CSMDoc::Document::State_Verifying: name = "verifying"; break; } std::ostringstream stream; @@ -34,6 +35,8 @@ void CSVDoc::Operation::updateLabel (int threads) CSVDoc::Operation::Operation (int type) : mType (type), mStalling (false) { updateLabel(); + + /// \todo assign different progress bar colours to allow the user to distinguish easily between operation types } void CSVDoc::Operation::setProgress (int current, int max, int threads) diff --git a/apps/opencs/view/doc/view.cpp b/apps/opencs/view/doc/view.cpp index fe018ab3bb..8ed1f83b8d 100644 --- a/apps/opencs/view/doc/view.cpp +++ b/apps/opencs/view/doc/view.cpp @@ -54,11 +54,21 @@ void CSVDoc::View::setupViewMenu() view->addAction (newWindow); } +void CSVDoc::View::setupWorldMenu() +{ + QMenu *world = menuBar()->addMenu (tr ("&World")); + + mVerify = new QAction (tr ("&Verify"), this); + connect (mVerify, SIGNAL (triggered()), this, SLOT (verify())); + world->addAction (mVerify); +} + void CSVDoc::View::setupUi() { setupFileMenu(); setupEditMenu(); setupViewMenu(); + setupWorldMenu(); } void CSVDoc::View::updateTitle() @@ -87,6 +97,7 @@ void CSVDoc::View::updateActions() mRedo->setEnabled (editing & mDocument->getUndoStack().canRedo()); mSave->setEnabled (!(mDocument->getState() & CSMDoc::Document::State_Saving)); + mVerify->setEnabled (!(mDocument->getState() & CSMDoc::Document::State_Verifying)); } CSVDoc::View::View (ViewManager& viewManager, CSMDoc::Document *document, int totalViews) @@ -127,7 +138,7 @@ void CSVDoc::View::updateDocumentState() static const int operations[] = { - CSMDoc::Document::State_Saving, + CSMDoc::Document::State_Saving, CSMDoc::Document::State_Verifying, -1 // end marker }; @@ -156,4 +167,9 @@ void CSVDoc::View::test() void CSVDoc::View::save() { mDocument->save(); +} + +void CSVDoc::View::verify() +{ + mDocument->verify(); } \ No newline at end of file diff --git a/apps/opencs/view/doc/view.hpp b/apps/opencs/view/doc/view.hpp index 191af36b51..15394a7d85 100644 --- a/apps/opencs/view/doc/view.hpp +++ b/apps/opencs/view/doc/view.hpp @@ -28,6 +28,7 @@ namespace CSVDoc QAction *mUndo; QAction *mRedo; QAction *mSave; + QAction *mVerify; std::vector mEditingActions; Operations *mOperations; @@ -45,6 +46,8 @@ namespace CSVDoc void setupViewMenu(); + void setupWorldMenu(); + void setupUi(); void updateTitle(); @@ -73,6 +76,8 @@ namespace CSVDoc void test(); void save(); + + void verify(); }; } From 303506d24b00a0bbcbb7f796fa071b5f750c3be9 Mon Sep 17 00:00:00 2001 From: Marc Zinnschlag Date: Fri, 23 Nov 2012 14:05:49 +0100 Subject: [PATCH 16/49] added new document function --- apps/opencs/editor.cpp | 12 ++++++++++-- apps/opencs/editor.hpp | 14 +++++++++++--- apps/opencs/model/doc/document.cpp | 9 ++++++++- apps/opencs/model/doc/document.hpp | 9 ++++++++- apps/opencs/model/doc/documentmanager.cpp | 4 ++-- apps/opencs/model/doc/documentmanager.hpp | 3 ++- apps/opencs/view/doc/view.cpp | 8 ++++++-- apps/opencs/view/doc/view.hpp | 4 ++++ apps/opencs/view/doc/viewmanager.cpp | 2 ++ apps/opencs/view/doc/viewmanager.hpp | 4 ++++ 10 files changed, 57 insertions(+), 12 deletions(-) diff --git a/apps/opencs/editor.cpp b/apps/opencs/editor.cpp index 264ae75434..c03a1dc5dc 100644 --- a/apps/opencs/editor.cpp +++ b/apps/opencs/editor.cpp @@ -1,20 +1,28 @@ #include "editor.hpp" +#include + #include -CS::Editor::Editor() : mViewManager (mDocumentManager) +CS::Editor::Editor() : mViewManager (mDocumentManager), mNewDocumentIndex (0) { + connect (&mViewManager, SIGNAL (newDocumentRequest ()), this, SLOT (createDocument ())); } void CS::Editor::createDocument() { - CSMDoc::Document *document = mDocumentManager.addDocument(); + std::ostringstream stream; + + stream << "NewDocument" << (++mNewDocumentIndex); + + CSMDoc::Document *document = mDocumentManager.addDocument (stream.str()); mViewManager.addView (document); } int CS::Editor::run() { + /// \todo Instead of creating an empty document, open a small welcome dialogue window with buttons for new/load/recent projects createDocument(); return QApplication::exec(); diff --git a/apps/opencs/editor.hpp b/apps/opencs/editor.hpp index 6e183b843b..60f7beaf1d 100644 --- a/apps/opencs/editor.hpp +++ b/apps/opencs/editor.hpp @@ -1,13 +1,19 @@ #ifndef CS_EDITOR_H #define CS_EDITOR_H +#include + #include "model/doc/documentmanager.hpp" #include "view/doc/viewmanager.hpp" namespace CS { - class Editor + class Editor : public QObject { + Q_OBJECT + + int mNewDocumentIndex; ///< \todo remove when the proper new document dialogue is implemented. + CSMDoc::DocumentManager mDocumentManager; CSVDoc::ViewManager mViewManager; @@ -19,10 +25,12 @@ namespace CS Editor(); - void createDocument(); - int run(); ///< \return error status + + public slots: + + void createDocument(); }; } diff --git a/apps/opencs/model/doc/document.cpp b/apps/opencs/model/doc/document.cpp index 5c39e16c0f..cd65e83aef 100644 --- a/apps/opencs/model/doc/document.cpp +++ b/apps/opencs/model/doc/document.cpp @@ -1,8 +1,10 @@ #include "document.hpp" -CSMDoc::Document::Document() +CSMDoc::Document::Document (const std::string& name) { + mName = name; ///< \todo replace with ESX list + connect (&mUndoStack, SIGNAL (cleanChanged (bool)), this, SLOT (modificationStateChanged (bool))); // dummy implementation -> remove when proper save is implemented. @@ -35,6 +37,11 @@ int CSMDoc::Document::getState() const return state; } +const std::string& CSMDoc::Document::getName() const +{ + return mName; +} + void CSMDoc::Document::save() { mSaveCount = 1; diff --git a/apps/opencs/model/doc/document.hpp b/apps/opencs/model/doc/document.hpp index e691bb38f6..0249d8e5ce 100644 --- a/apps/opencs/model/doc/document.hpp +++ b/apps/opencs/model/doc/document.hpp @@ -1,6 +1,8 @@ #ifndef CSM_DOC_DOCUMENT_H #define CSM_DOC_DOCUMENT_H +#include + #include #include #include @@ -21,6 +23,7 @@ namespace CSMDoc State_Verifying = 8 }; + std::string mName; ///< \todo replace name with ESX list QUndoStack mUndoStack; int mSaveCount; ///< dummy implementation -> remove when proper save is implemented. @@ -35,12 +38,16 @@ namespace CSMDoc public: - Document(); + Document (const std::string& name); + ///< \todo replace name with ESX list QUndoStack& getUndoStack(); int getState() const; + const std::string& getName() const; + ///< \todo replace with ESX list + void save(); void verify(); diff --git a/apps/opencs/model/doc/documentmanager.cpp b/apps/opencs/model/doc/documentmanager.cpp index 68595f2d41..8ae2764f24 100644 --- a/apps/opencs/model/doc/documentmanager.cpp +++ b/apps/opencs/model/doc/documentmanager.cpp @@ -14,9 +14,9 @@ CSMDoc::DocumentManager::~DocumentManager() delete *iter; } -CSMDoc::Document *CSMDoc::DocumentManager::addDocument() +CSMDoc::Document *CSMDoc::DocumentManager::addDocument (const std::string& name) { - Document *document = new Document; + Document *document = new Document (name); mDocuments.push_back (document); diff --git a/apps/opencs/model/doc/documentmanager.hpp b/apps/opencs/model/doc/documentmanager.hpp index f20f3101d9..730c7fae1d 100644 --- a/apps/opencs/model/doc/documentmanager.hpp +++ b/apps/opencs/model/doc/documentmanager.hpp @@ -2,6 +2,7 @@ #define CSM_DOC_DOCUMENTMGR_H #include +#include namespace CSMDoc { @@ -20,7 +21,7 @@ namespace CSMDoc ~DocumentManager(); - Document *addDocument(); + Document *addDocument (const std::string& name); ///< The ownership of the returned document is not transferred to the caller. bool removeDocument (Document *document); diff --git a/apps/opencs/view/doc/view.cpp b/apps/opencs/view/doc/view.cpp index 8ed1f83b8d..5c7199aa4b 100644 --- a/apps/opencs/view/doc/view.cpp +++ b/apps/opencs/view/doc/view.cpp @@ -21,6 +21,10 @@ void CSVDoc::View::setupFileMenu() { QMenu *file = menuBar()->addMenu (tr ("&File")); + QAction *new_ = new QAction (tr ("New"), this); + connect (new_, SIGNAL (triggered()), this, SIGNAL (newDocumentRequest())); + file->addAction (new_); + mSave = new QAction (tr ("&Save"), this); connect (mSave, SIGNAL (triggered()), this, SLOT (save())); file->addAction (mSave); @@ -75,7 +79,7 @@ void CSVDoc::View::updateTitle() { std::ostringstream stream; - stream << "New Document "; + stream << mDocument->getName(); if (mDocument->getState() & CSMDoc::Document::State_Modified) stream << " *"; @@ -104,7 +108,7 @@ CSVDoc::View::View (ViewManager& viewManager, CSMDoc::Document *document, int to : mViewManager (viewManager), mDocument (document), mViewIndex (totalViews-1), mViewTotal (totalViews) { setCentralWidget (new QWidget); - resize (200, 200); + resize (200, 200); /// \todo get default size from settings and set reasonable minimal size mOperations = new Operations; addDockWidget (Qt::BottomDockWidgetArea, mOperations); diff --git a/apps/opencs/view/doc/view.hpp b/apps/opencs/view/doc/view.hpp index 15394a7d85..d15d942fc0 100644 --- a/apps/opencs/view/doc/view.hpp +++ b/apps/opencs/view/doc/view.hpp @@ -69,6 +69,10 @@ namespace CSVDoc void updateProgress (int current, int max, int type, int threads); + signals: + + void newDocumentRequest(); + private slots: void newView(); diff --git a/apps/opencs/view/doc/viewmanager.cpp b/apps/opencs/view/doc/viewmanager.cpp index 673afbad82..22847c78b7 100644 --- a/apps/opencs/view/doc/viewmanager.cpp +++ b/apps/opencs/view/doc/viewmanager.cpp @@ -56,6 +56,8 @@ CSVDoc::View *CSVDoc::ViewManager::addView (CSMDoc::Document *document) view->show(); + connect (view, SIGNAL (newDocumentRequest ()), this, SIGNAL (newDocumentRequest())); + updateIndices(); return view; diff --git a/apps/opencs/view/doc/viewmanager.hpp b/apps/opencs/view/doc/viewmanager.hpp index caf75a0cdb..5e4b1be075 100644 --- a/apps/opencs/view/doc/viewmanager.hpp +++ b/apps/opencs/view/doc/viewmanager.hpp @@ -42,6 +42,10 @@ namespace CSVDoc bool closeRequest (View *view); + signals: + + void newDocumentRequest(); + private slots: void documentStateChanged (int state, CSMDoc::Document *document); From 019146756fc0d91ab46b54c696fc33770c0d2f1a Mon Sep 17 00:00:00 2001 From: Marc Zinnschlag Date: Sat, 24 Nov 2012 10:14:43 +0100 Subject: [PATCH 17/49] minor documentation changes regarding future improvements and additions --- apps/opencs/model/doc/document.hpp | 4 +++- apps/opencs/view/doc/operation.cpp | 2 ++ 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/apps/opencs/model/doc/document.hpp b/apps/opencs/model/doc/document.hpp index 0249d8e5ce..1f73b54371 100644 --- a/apps/opencs/model/doc/document.hpp +++ b/apps/opencs/model/doc/document.hpp @@ -20,7 +20,9 @@ namespace CSMDoc State_Modified = 1, State_Locked = 2, State_Saving = 4, - State_Verifying = 8 + State_Verifying = 8, + State_Compiling = 16, // not implemented yet + State_Searching = 32 // not implemented yet }; std::string mName; ///< \todo replace name with ESX list diff --git a/apps/opencs/view/doc/operation.cpp b/apps/opencs/view/doc/operation.cpp index 02a93f9c53..62f006be55 100644 --- a/apps/opencs/view/doc/operation.cpp +++ b/apps/opencs/view/doc/operation.cpp @@ -34,6 +34,8 @@ void CSVDoc::Operation::updateLabel (int threads) CSVDoc::Operation::Operation (int type) : mType (type), mStalling (false) { + /// \todo Add a cancel button or a pop up menu with a cancel item + updateLabel(); /// \todo assign different progress bar colours to allow the user to distinguish easily between operation types From 4c0dcd46a19fea65c1c8bd31f82fbbe9103b7429 Mon Sep 17 00:00:00 2001 From: Marc Zinnschlag Date: Sat, 24 Nov 2012 11:01:53 +0100 Subject: [PATCH 18/49] added UniversalId class --- apps/opencs/CMakeLists.txt | 4 + apps/opencs/model/world/universalid.cpp | 161 ++++++++++++++++++++++++ apps/opencs/model/world/universalid.hpp | 80 ++++++++++++ 3 files changed, 245 insertions(+) create mode 100644 apps/opencs/model/world/universalid.cpp create mode 100644 apps/opencs/model/world/universalid.hpp diff --git a/apps/opencs/CMakeLists.txt b/apps/opencs/CMakeLists.txt index 66b9f4942a..cb721ac54c 100644 --- a/apps/opencs/CMakeLists.txt +++ b/apps/opencs/CMakeLists.txt @@ -4,6 +4,8 @@ set (OPENCS_SRC model/doc/documentmanager.cpp model/doc/document.cpp + model/world/universalid.cpp + view/doc/viewmanager.cpp view/doc/view.cpp view/doc/operations.cpp view/doc/operation.cpp ) @@ -12,6 +14,8 @@ set (OPENCS_HDR model/doc/documentmanager.hpp model/doc/document.hpp + model/world/universalid.hpp + view/doc/viewmanager.hpp view/doc/view.hpp view/doc/operations.hpp view/doc/operation.hpp ) diff --git a/apps/opencs/model/world/universalid.cpp b/apps/opencs/model/world/universalid.cpp new file mode 100644 index 0000000000..b56a336a6e --- /dev/null +++ b/apps/opencs/model/world/universalid.cpp @@ -0,0 +1,161 @@ + +#include "universalid.hpp" + +#include +#include +#include + +namespace +{ + struct TypeData + { + CSMWorld::UniversalId::Class mClass; + CSMWorld::UniversalId::Type mType; + const char *mName; + }; + + static const TypeData sNoArg[] = + { + { CSMWorld::UniversalId::Class_None, CSMWorld::UniversalId::Type_None, "empty" }, + + { CSMWorld::UniversalId::Class_None, CSMWorld::UniversalId::Type_None, 0 } // end marker + }; + + static const TypeData sIdArg[] = + { + + { CSMWorld::UniversalId::Class_None, CSMWorld::UniversalId::Type_None, 0 } // end marker + }; + + static const TypeData sIndexArg[] = + { + + { CSMWorld::UniversalId::Class_None, CSMWorld::UniversalId::Type_None, 0 } // end marker + }; +} + +CSMWorld::UniversalId::UniversalId (Type type) : mArgumentType (ArgumentType_None), mType (type), mIndex (0) +{ + for (int i=0; sNoArg[i].mName; ++i) + if (type==sNoArg[i].mType) + { + mClass = sNoArg[i].mClass; + return; + } + + throw std::logic_error ("invalid argument-less UniversalId type"); +} + +CSMWorld::UniversalId::UniversalId (Type type, const std::string& id) +: mArgumentType (ArgumentType_Id), mType (type), mId (id), mIndex (0) +{ + for (int i=0; sIdArg[i].mName; ++i) + if (type==sIdArg[i].mType) + { + mClass = sIdArg[i].mClass; + return; + } + + throw std::logic_error ("invalid ID argument UniversalId type"); +} + +CSMWorld::UniversalId::UniversalId (Type type, int index) +: mArgumentType (ArgumentType_Index), mType (type), mIndex (index) +{ + for (int i=0; sIndexArg[i].mName; ++i) + if (type==sIndexArg[i].mType) + { + mClass = sIndexArg[i].mClass; + return; + } + + throw std::logic_error ("invalid index argument UniversalId type"); +} + +CSMWorld::UniversalId::Class CSMWorld::UniversalId::getClass() const +{ + return mClass; +} + +CSMWorld::UniversalId::ArgumentType CSMWorld::UniversalId::getArgumentType() const +{ + return mArgumentType; +} + +CSMWorld::UniversalId::Type CSMWorld::UniversalId::getType() const +{ + return mType; +} + +const std::string& CSMWorld::UniversalId::getId() const +{ + if (mArgumentType!=ArgumentType_Id) + throw std::logic_error ("invalid access to ID of non-ID UniversalId"); + + return mId; +} + +int CSMWorld::UniversalId::getIndex() const +{ + if (mArgumentType!=ArgumentType_Index) + throw std::logic_error ("invalid access to index of non-index UniversalId"); + + return mIndex; +} + +bool CSMWorld::UniversalId::isEqual (const UniversalId& universalId) const +{ + if (mClass!=universalId.mClass || mArgumentType!=universalId.mArgumentType || mType!=universalId.mType) + return false; + + switch (mArgumentType) + { + case ArgumentType_Id: return mId==universalId.mId; + case ArgumentType_Index: return mIndex==universalId.mIndex; + + default: return true; + } +} + +std::string CSMWorld::UniversalId::getTypeName() 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].mName; + + throw std::logic_error ("failed to retrieve UniversalId type name"); +} + +std::string CSMWorld::UniversalId::toString() const +{ + std::ostringstream stream; + + stream << getTypeName(); + + switch (mArgumentType) + { + case ArgumentType_None: break; + case ArgumentType_Id: stream << " " << mId; + case ArgumentType_Index: stream << " " << mIndex; + } + + return stream.str(); +} + +bool operator== (const CSMWorld::UniversalId& left, const CSMWorld::UniversalId& right) +{ + return left.isEqual (right); +} + +bool operator!= (const CSMWorld::UniversalId& left, const CSMWorld::UniversalId& right) +{ + return !left.isEqual (right); +} + +std::ostream& operator< (std::ostream& stream, const CSMWorld::UniversalId& universalId) +{ + return stream << universalId.toString(); +} \ No newline at end of file diff --git a/apps/opencs/model/world/universalid.hpp b/apps/opencs/model/world/universalid.hpp new file mode 100644 index 0000000000..6f085cfc29 --- /dev/null +++ b/apps/opencs/model/world/universalid.hpp @@ -0,0 +1,80 @@ +#ifndef CSM_WOLRD_UNIVERSALID_H +#define CSM_WOLRD_UNIVERSALID_H + +#include +#include + +namespace CSMWorld +{ + class UniversalId + { + public: + + 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 + }; + + enum ArgumentType + { + ArgumentType_None, + ArgumentType_Id, + ArgumentType_Index + }; + + enum Type + { + Type_None + }; + + private: + + Class mClass; + ArgumentType mArgumentType; + Type mType; + std::string mId; + int mIndex; + + public: + + UniversalId (Type type = Type_None); + ///< Using a type for a non-argument-less UniversalId will throw an exception. + + UniversalId (Type type, const std::string& id); + ///< Using a type for a non-ID-argument UniversalId will throw an exception. + + UniversalId (Type type, int index); + ///< Using a type for a non-index-argument UniversalId will throw an exception. + + Class getClass() const; + + ArgumentType getArgumentType() const; + + Type getType() const; + + const std::string& getId() const; + ///< Calling this function for a non-ID type will throw an exception. + + int getIndex() const; + ///< Calling this function for a non-index type will throw an exception. + + bool isEqual (const UniversalId& universalId) const; + + std::string getTypeName() const; + + std::string toString() const; + }; + + bool operator== (const UniversalId& left, const UniversalId& right); + bool operator!= (const UniversalId& left, const UniversalId& right); + + std::ostream& operator< (std::ostream& stream, const UniversalId& universalId); +} + +#endif From eece4226c0427ac2cd7ca5e7b621e6bc8799e8e7 Mon Sep 17 00:00:00 2001 From: Marc Zinnschlag Date: Sat, 24 Nov 2012 13:17:21 +0100 Subject: [PATCH 19/49] basic sub view system (very incomplete) --- apps/opencs/CMakeLists.txt | 4 ++++ apps/opencs/view/doc/view.cpp | 32 ++++++++++++++++++++++++++++-- apps/opencs/view/doc/view.hpp | 9 +++++++++ apps/opencs/view/world/subview.cpp | 18 +++++++++++++++++ apps/opencs/view/world/subview.hpp | 28 ++++++++++++++++++++++++++ 5 files changed, 89 insertions(+), 2 deletions(-) create mode 100644 apps/opencs/view/world/subview.cpp create mode 100644 apps/opencs/view/world/subview.hpp diff --git a/apps/opencs/CMakeLists.txt b/apps/opencs/CMakeLists.txt index cb721ac54c..a56e77d089 100644 --- a/apps/opencs/CMakeLists.txt +++ b/apps/opencs/CMakeLists.txt @@ -7,6 +7,8 @@ set (OPENCS_SRC model/world/universalid.cpp view/doc/viewmanager.cpp view/doc/view.cpp view/doc/operations.cpp view/doc/operation.cpp + + view/world/subview.cpp ) set (OPENCS_HDR @@ -17,6 +19,8 @@ set (OPENCS_HDR model/world/universalid.hpp view/doc/viewmanager.hpp view/doc/view.hpp view/doc/operations.hpp view/doc/operation.hpp + + view/world/subview.hpp ) set (OPENCS_US diff --git a/apps/opencs/view/doc/view.cpp b/apps/opencs/view/doc/view.cpp index 5c7199aa4b..9bcb8fc5ab 100644 --- a/apps/opencs/view/doc/view.cpp +++ b/apps/opencs/view/doc/view.cpp @@ -5,9 +5,12 @@ #include #include +#include #include "../../model/doc/document.hpp" +#include "../world/subview.hpp" + #include "viewmanager.hpp" #include "operations.hpp" @@ -56,6 +59,10 @@ void CSVDoc::View::setupViewMenu() QAction *newWindow = new QAction (tr ("&New View"), this); connect (newWindow, SIGNAL (triggered()), this, SLOT (newView())); view->addAction (newWindow); + + QAction *test = new QAction (tr ("Add test Subview"), this); + connect (test, SIGNAL (triggered()), this, SLOT (addTestSubView())); + view->addAction (test); } void CSVDoc::View::setupWorldMenu() @@ -107,8 +114,9 @@ void CSVDoc::View::updateActions() CSVDoc::View::View (ViewManager& viewManager, CSMDoc::Document *document, int totalViews) : mViewManager (viewManager), mDocument (document), mViewIndex (totalViews-1), mViewTotal (totalViews) { - setCentralWidget (new QWidget); - resize (200, 200); /// \todo get default size from settings and set reasonable minimal size + setDockOptions (QMainWindow::AllowNestedDocks); + + resize (300, 300); /// \todo get default size from settings and set reasonable minimal size mOperations = new Operations; addDockWidget (Qt::BottomDockWidgetArea, mOperations); @@ -158,6 +166,21 @@ void CSVDoc::View::updateProgress (int current, int max, int type, int threads) mOperations->setProgress (current, max, type, threads); } +void CSVDoc::View::addSubView (const CSMWorld::UniversalId& id) +{ + /// \todo add an user setting for limiting the number of sub views per top level view. Automatically open a new top level view if this + /// number is exceeded + + /// \todo if the sub view limit setting is one, the sub view title bar should be hidden and the text in the main title bar adjusted + /// accordingly + + /// \todo add an user setting to reuse sub views (on a per document basis or on a per top level view basis) + + CSVWorld::SubView *view = new CSVWorld::SubView (id); + addDockWidget (Qt::RightDockWidgetArea, view); + view->show(); +} + void CSVDoc::View::newView() { mViewManager.addView (mDocument); @@ -176,4 +199,9 @@ void CSVDoc::View::save() void CSVDoc::View::verify() { mDocument->verify(); +} + +void CSVDoc::View::addTestSubView() +{ + addSubView (CSMWorld::UniversalId::Type_None); } \ No newline at end of file diff --git a/apps/opencs/view/doc/view.hpp b/apps/opencs/view/doc/view.hpp index d15d942fc0..7a9164e12f 100644 --- a/apps/opencs/view/doc/view.hpp +++ b/apps/opencs/view/doc/view.hpp @@ -12,6 +12,11 @@ namespace CSMDoc class Document; } +namespace CSMWorld +{ + class UniversalId; +} + namespace CSVDoc { class ViewManager; @@ -69,6 +74,8 @@ namespace CSVDoc void updateProgress (int current, int max, int type, int threads); + void addSubView (const CSMWorld::UniversalId& id); + signals: void newDocumentRequest(); @@ -82,6 +89,8 @@ namespace CSVDoc void save(); void verify(); + + void addTestSubView(); ///< \todo remove }; } diff --git a/apps/opencs/view/world/subview.cpp b/apps/opencs/view/world/subview.cpp new file mode 100644 index 0000000000..23f075980a --- /dev/null +++ b/apps/opencs/view/world/subview.cpp @@ -0,0 +1,18 @@ + +#include "subview.hpp" + +CSVWorld::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 CSVWorld::SubView::getUniversalId() const +{ + return mUniversalId; +} diff --git a/apps/opencs/view/world/subview.hpp b/apps/opencs/view/world/subview.hpp new file mode 100644 index 0000000000..8488690c88 --- /dev/null +++ b/apps/opencs/view/world/subview.hpp @@ -0,0 +1,28 @@ +#ifndef CSV_WORLD_SUBVIEW_H +#define CSV_WORLD_SUBVIEW_H + +#include "../../model/world/universalid.hpp" + +#include + +namespace CSVWorld +{ + class SubView : public QDockWidget + { + Q_OBJECT + + CSMWorld::UniversalId mUniversalId; + + // not implemented + SubView (const SubView&); + SubView& operator= (SubView&); + + public: + + SubView (const CSMWorld::UniversalId& id); + + CSMWorld::UniversalId getUniversalId() const; + }; +} + +#endif \ No newline at end of file From ef9575498f231e50a99a7beadc048e21ce74486d Mon Sep 17 00:00:00 2001 From: Marc Zinnschlag Date: Mon, 26 Nov 2012 12:29:22 +0100 Subject: [PATCH 20/49] basic (non-editable) subview for global variables --- apps/opencs/CMakeLists.txt | 9 +- apps/opencs/editor.cpp | 18 +++ apps/opencs/model/doc/document.cpp | 10 ++ apps/opencs/model/doc/document.hpp | 9 ++ apps/opencs/model/world/columns.hpp | 21 +++ apps/opencs/model/world/data.cpp | 47 +++++++ apps/opencs/model/world/data.hpp | 39 ++++++ apps/opencs/model/world/idcollection.cpp | 6 + apps/opencs/model/world/idcollection.hpp | 158 +++++++++++++++++++++++ apps/opencs/model/world/idtable.cpp | 55 ++++++++ apps/opencs/model/world/idtable.hpp | 37 ++++++ apps/opencs/model/world/record.hpp | 76 +++++++++++ apps/opencs/model/world/universalid.cpp | 29 ++++- apps/opencs/model/world/universalid.hpp | 7 +- apps/opencs/view/doc/view.cpp | 33 +++-- apps/opencs/view/doc/view.hpp | 11 +- apps/opencs/view/world/globals.cpp | 26 ++++ apps/opencs/view/world/globals.hpp | 17 +++ apps/opencs/view/world/subview.hpp | 22 ++++ components/esm/loadglob.hpp | 2 +- 20 files changed, 614 insertions(+), 18 deletions(-) create mode 100644 apps/opencs/model/world/columns.hpp create mode 100644 apps/opencs/model/world/data.cpp create mode 100644 apps/opencs/model/world/data.hpp create mode 100644 apps/opencs/model/world/idcollection.cpp create mode 100644 apps/opencs/model/world/idcollection.hpp create mode 100644 apps/opencs/model/world/idtable.cpp create mode 100644 apps/opencs/model/world/idtable.hpp create mode 100644 apps/opencs/model/world/record.hpp create mode 100644 apps/opencs/view/world/globals.cpp create mode 100644 apps/opencs/view/world/globals.hpp diff --git a/apps/opencs/CMakeLists.txt b/apps/opencs/CMakeLists.txt index a56e77d089..92fd859bed 100644 --- a/apps/opencs/CMakeLists.txt +++ b/apps/opencs/CMakeLists.txt @@ -4,11 +4,11 @@ set (OPENCS_SRC model/doc/documentmanager.cpp model/doc/document.cpp - model/world/universalid.cpp + model/world/universalid.cpp model/world/idcollection.cpp model/world/data.cpp model/world/idtable.cpp view/doc/viewmanager.cpp view/doc/view.cpp view/doc/operations.cpp view/doc/operation.cpp - view/world/subview.cpp + view/world/subview.cpp view/world/globals.cpp ) set (OPENCS_HDR @@ -16,11 +16,12 @@ set (OPENCS_HDR model/doc/documentmanager.hpp model/doc/document.hpp - model/world/universalid.hpp + model/world/universalid.hpp model/world/record.hpp model/world/idcollection.hpp model/world/data.hpp + model/world/idtable.hpp model/world/columns.hpp view/doc/viewmanager.hpp view/doc/view.hpp view/doc/operations.hpp view/doc/operation.hpp - view/world/subview.hpp + view/world/subview.hpp view/world/globals.hpp ) set (OPENCS_US diff --git a/apps/opencs/editor.cpp b/apps/opencs/editor.cpp index c03a1dc5dc..6977a22f02 100644 --- a/apps/opencs/editor.cpp +++ b/apps/opencs/editor.cpp @@ -5,6 +5,9 @@ #include +#include "model/doc/document.hpp" +#include "model/world/data.hpp" + CS::Editor::Editor() : mViewManager (mDocumentManager), mNewDocumentIndex (0) { connect (&mViewManager, SIGNAL (newDocumentRequest ()), this, SLOT (createDocument ())); @@ -17,6 +20,21 @@ void CS::Editor::createDocument() stream << "NewDocument" << (++mNewDocumentIndex); CSMDoc::Document *document = mDocumentManager.addDocument (stream.str()); + + static const char *sGlobals[] = + { + "Day", "DaysPassed", "GameHour", "Month", "PCRace", "PCVampire", "PCWerewolf", "PCYear", 0 + }; + + for (int i=0; sGlobals[i]; ++i) + { + ESM::Global record; + record.mId = sGlobals[i]; + record.mValue = i==0 ? 1 : 0; + record.mType = ESM::VT_Float; + document->getData().getGlobals().add (record); + } + mViewManager.addView (document); } diff --git a/apps/opencs/model/doc/document.cpp b/apps/opencs/model/doc/document.cpp index cd65e83aef..e8091b3e00 100644 --- a/apps/opencs/model/doc/document.cpp +++ b/apps/opencs/model/doc/document.cpp @@ -104,4 +104,14 @@ void CSMDoc::Document::verifying() mVerifyTimer.stop(); emit stateChanged (getState(), this); } +} + +const CSMWorld::Data& CSMDoc::Document::getData() const +{ + return mData; +} + +CSMWorld::Data& CSMDoc::Document::getData() +{ + return mData; } \ No newline at end of file diff --git a/apps/opencs/model/doc/document.hpp b/apps/opencs/model/doc/document.hpp index 1f73b54371..b414bf04d4 100644 --- a/apps/opencs/model/doc/document.hpp +++ b/apps/opencs/model/doc/document.hpp @@ -7,6 +7,8 @@ #include #include +#include "../world/data.hpp" + namespace CSMDoc { class Document : public QObject @@ -25,8 +27,11 @@ namespace CSMDoc State_Searching = 32 // not implemented yet }; + private: + std::string mName; ///< \todo replace name with ESX list QUndoStack mUndoStack; + CSMWorld::Data mData; int mSaveCount; ///< dummy implementation -> remove when proper save is implemented. QTimer mSaveTimer; ///< dummy implementation -> remove when proper save is implemented. @@ -56,6 +61,10 @@ namespace CSMDoc void abortOperation (int type); + const CSMWorld::Data& getData() const; + + CSMWorld::Data& getData(); + signals: void stateChanged (int state, CSMDoc::Document *document); diff --git a/apps/opencs/model/world/columns.hpp b/apps/opencs/model/world/columns.hpp new file mode 100644 index 0000000000..56362e4cdb --- /dev/null +++ b/apps/opencs/model/world/columns.hpp @@ -0,0 +1,21 @@ +#ifndef CSM_WOLRD_COLUMNS_H +#define CSM_WOLRD_COLUMNS_H + +#include "idcollection.hpp" + +namespace CSMWorld +{ + template + struct FloatValueColumn : public Column + { + FloatValueColumn() : Column ("Value") {} + + virtual QVariant get (const Record& record) const + { + return record.get().mValue; + } + }; + +} + +#endif \ No newline at end of file diff --git a/apps/opencs/model/world/data.cpp b/apps/opencs/model/world/data.cpp new file mode 100644 index 0000000000..7fdb149b31 --- /dev/null +++ b/apps/opencs/model/world/data.cpp @@ -0,0 +1,47 @@ + +#include "data.hpp" + +#include + +#include + +#include + +#include "idtable.hpp" +#include "columns.hpp" + +CSMWorld::Data::Data() +{ + mGlobals.addColumn (new FloatValueColumn); + + mModels.insert (std::make_pair ( + UniversalId (UniversalId::Type_Globals), + new IdTable (&mGlobals) + )); +} + +CSMWorld::Data::~Data() +{ + for (std::map::iterator iter (mModels.begin()); iter!=mModels.end(); ++iter) + delete iter->second; +} + +const CSMWorld::IdCollection& CSMWorld::Data::getGlobals() const +{ + return mGlobals; +} + +CSMWorld::IdCollection& CSMWorld::Data::getGlobals() +{ + return mGlobals; +} + +QAbstractTableModel *CSMWorld::Data::getTableModel (const UniversalId& id) +{ + std::map::iterator iter = mModels.find (id); + + if (iter==mModels.end()) + throw std::logic_error ("No table model available for " + id.toString()); + + return iter->second; +} \ No newline at end of file diff --git a/apps/opencs/model/world/data.hpp b/apps/opencs/model/world/data.hpp new file mode 100644 index 0000000000..11073c5e37 --- /dev/null +++ b/apps/opencs/model/world/data.hpp @@ -0,0 +1,39 @@ +#ifndef CSM_WOLRD_IDLIST_H +#define CSM_WOLRD_IDLIST_H + +#include + +#include + +#include "idcollection.hpp" +#include "universalid.hpp" + +class QAbstractTableModel; + +namespace CSMWorld +{ + class Data + { + IdCollection mGlobals; + std::map mModels; + + // not implemented + Data (const Data&); + Data& operator= (const Data&); + + public: + + Data(); + + ~Data(); + + const IdCollection& getGlobals() const; + + IdCollection& getGlobals(); + + QAbstractTableModel *getTableModel (const UniversalId& id); + ///< If no table model is available for \æ id, an exception is thrown. + }; +} + +#endif \ No newline at end of file diff --git a/apps/opencs/model/world/idcollection.cpp b/apps/opencs/model/world/idcollection.cpp new file mode 100644 index 0000000000..fc4bb1ef65 --- /dev/null +++ b/apps/opencs/model/world/idcollection.cpp @@ -0,0 +1,6 @@ + +#include "idcollection.hpp" + +CSMWorld::IdCollectionBase::IdCollectionBase() {} + +CSMWorld::IdCollectionBase::~IdCollectionBase() {} \ No newline at end of file diff --git a/apps/opencs/model/world/idcollection.hpp b/apps/opencs/model/world/idcollection.hpp new file mode 100644 index 0000000000..0bddda1ac9 --- /dev/null +++ b/apps/opencs/model/world/idcollection.hpp @@ -0,0 +1,158 @@ +#ifndef CSM_WOLRD_IDCOLLECTION_H +#define CSM_WOLRD_IDCOLLECTION_H + +#include +#include +#include +#include +#include + +#include + +#include "record.hpp" + +namespace CSMWorld +{ + template + struct Column + { + std::string mTitle; + + Column (const std::string& title) : mTitle (title) {} + + virtual ~Column() {} + + virtual QVariant get (const Record& record) const = 0; + }; + + class IdCollectionBase + { + // not implemented + IdCollectionBase (const IdCollectionBase&); + IdCollectionBase& operator= (const IdCollectionBase&); + + public: + + IdCollectionBase(); + + virtual ~IdCollectionBase(); + + virtual int getSize() const = 0; + + virtual std::string getId (int index) const = 0; + + virtual int getColumns() const = 0; + + virtual std::string getTitle (int column) const = 0; + + virtual QVariant getData (int index, int column) const = 0; + }; + + ///< \brief Collection of ID-based records + template + class IdCollection : public IdCollectionBase + { + std::vector > mRecords; + std::map mIndex; + std::vector *> mColumns; + + // not implemented + IdCollection (const IdCollection&); + IdCollection& operator= (const IdCollection&); + + public: + + IdCollection(); + + virtual ~IdCollection(); + + void add (const ESXRecordT& record); + ///< Add a new record (modified) + + virtual int getSize() const; + + virtual std::string getId (int index) const; + + virtual int getColumns() const; + + virtual QVariant getData (int index, int column) const; + + virtual std::string getTitle (int column) const; + + virtual void addColumn (Column *column); + }; + + template + IdCollection::IdCollection() + {} + + template + IdCollection::~IdCollection() + { + for (typename std::vector *>::iterator iter (mColumns.begin()); iter!=mColumns.end(); ++iter) + delete *iter; + } + + template + void IdCollection::add (const ESXRecordT& record) + { + std::string id; + + std::transform (record.mId.begin(), record.mId.end(), std::back_inserter (id), + (int(*)(int)) std::tolower); + + std::map::iterator iter = mIndex.find (id); + + if (iter==mIndex.end()) + { + Record record2; + record2.mState = Record::State_ModifiedOnly; + record2.mModified = record; + + mRecords.push_back (record2); + mIndex.insert (std::make_pair (id, mRecords.size()-1)); + } + else + { + mRecords[iter->second].setModified (record); + } + } + + template + int IdCollection::getSize() const + { + return mRecords.size(); + } + + template + std::string IdCollection::getId (int index) const + { + return mRecords.at (index).get().mId; + } + + template + int IdCollection::getColumns() const + { + return mColumns.size(); + } + + template + QVariant IdCollection::getData (int index, int column) const + { + return mColumns.at (column)->get (mRecords.at (index)); + } + + template + std::string IdCollection::getTitle (int column) const + { + return mColumns.at (column)->mTitle; + } + + template + void IdCollection::addColumn (Column *column) + { + mColumns.push_back (column); + } +} + +#endif diff --git a/apps/opencs/model/world/idtable.cpp b/apps/opencs/model/world/idtable.cpp new file mode 100644 index 0000000000..f8acd4f9fe --- /dev/null +++ b/apps/opencs/model/world/idtable.cpp @@ -0,0 +1,55 @@ + +#include "idtable.hpp" + +#include "idcollection.hpp" + +CSMWorld::IdTable::IdTable (IdCollectionBase *idCollection) : mIdCollection (idCollection) +{ + +} + +CSMWorld::IdTable::~IdTable() +{ + +} + +int CSMWorld::IdTable::rowCount (const QModelIndex & parent) const +{ + if (parent.isValid()) + return 0; + + return mIdCollection->getSize(); +} + +int CSMWorld::IdTable::columnCount (const QModelIndex & parent) const +{ + if (parent.isValid()) + return 0; + + return 1+mIdCollection->getColumns(); +} + +QVariant CSMWorld::IdTable::data (const QModelIndex & index, int role) const +{ + if (role!=Qt::DisplayRole) + return QVariant(); + + if (index.column()==0) + return QVariant (tr (mIdCollection->getId (index.row()).c_str())); + + return mIdCollection->getData (index.row(), index.column()-1); +} + +QVariant CSMWorld::IdTable::headerData (int section, Qt::Orientation orientation, int role) const +{ + if (role!=Qt::DisplayRole) + return QVariant(); + + if (orientation==Qt::Vertical) + return QVariant(); + + if (section==0) + return QVariant (tr ("ID")); + + return tr (mIdCollection->getTitle (section-1).c_str()); +} \ No newline at end of file diff --git a/apps/opencs/model/world/idtable.hpp b/apps/opencs/model/world/idtable.hpp new file mode 100644 index 0000000000..4fb939fa31 --- /dev/null +++ b/apps/opencs/model/world/idtable.hpp @@ -0,0 +1,37 @@ +#ifndef CSM_WOLRD_IDTABLE_H +#define CSM_WOLRD_IDTABLE_H + +#include + +namespace CSMWorld +{ + class IdCollectionBase; + + class IdTable : public QAbstractTableModel + { + Q_OBJECT + + IdCollectionBase *mIdCollection; + + // not implemented + IdTable (const IdTable&); + IdTable& operator= (const IdTable&); + + public: + + IdTable (IdCollectionBase *idCollection); + ///< The ownership of \a idCollection is not transferred. + + virtual ~IdTable(); + + int rowCount (const QModelIndex & parent = QModelIndex()) const; + + int columnCount (const QModelIndex & parent = QModelIndex()) const; + + QVariant data (const QModelIndex & index, int role = Qt::DisplayRole) const; + + QVariant headerData (int section, Qt::Orientation orientation, int role = Qt::DisplayRole) const; + }; +} + +#endif diff --git a/apps/opencs/model/world/record.hpp b/apps/opencs/model/world/record.hpp new file mode 100644 index 0000000000..230d39eb06 --- /dev/null +++ b/apps/opencs/model/world/record.hpp @@ -0,0 +1,76 @@ +#ifndef CSM_WOLRD_RECORD_H +#define CSM_WOLRD_RECORD_H + +#include + +namespace CSMWorld +{ + template + struct Record + { + enum state + { + State_BaseOnly, // defined in base only + State_Modified, // exists in base, but has been modified + State_ModifiedOnly, // newly created in modified + State_Deleted // exists in base, but has been deleted + }; + + ESXRecordT mBase; + ESXRecordT mModified; + state mState; + + bool isDeleted() const; + + bool isModified() const; + + const ESXRecordT& get() const; + ///< Throws an exception, if the record is deleted. + + ESXRecordT& get(); + ///< Throws an exception, if the record is deleted. + + void setModified (const ESXRecordT& modified); + }; + + template + bool Record::isDeleted() const + { + return mState==State_Deleted; + } + + template + bool Record::isModified() const + { + return mState==State_Modified || mState==State_ModifiedOnly; + } + + template + const ESXRecordT& Record::get() const + { + if (isDeleted()) + throw std::logic_error ("attempt to access a deleted record"); + + return mState==State_BaseOnly ? mBase : mModified; + } + + template + ESXRecordT& Record::get() + { + if (isDeleted()) + throw std::logic_error ("attempt to access a deleted record"); + + return mState==State_BaseOnly ? mBase : mModified; + } + + template + void Record::setModified (const ESXRecordT& modified) + { + mModified = modified; + + if (mState!=State_ModifiedOnly) + mState = State_Modified; + } +} + +#endif diff --git a/apps/opencs/model/world/universalid.cpp b/apps/opencs/model/world/universalid.cpp index b56a336a6e..e2d8d1ffb1 100644 --- a/apps/opencs/model/world/universalid.cpp +++ b/apps/opencs/model/world/universalid.cpp @@ -17,6 +17,7 @@ namespace 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_None, CSMWorld::UniversalId::Type_None, 0 } // end marker }; @@ -117,6 +118,23 @@ bool CSMWorld::UniversalId::isEqual (const UniversalId& universalId) const } } +bool CSMWorld::UniversalId::isLess (const UniversalId& universalId) const +{ + if (mTypeuniversalId.mType) + return false; + + switch (mArgumentType) + { + case ArgumentType_Id: return mId +#include #include #include @@ -10,6 +11,7 @@ #include "../../model/doc/document.hpp" #include "../world/subview.hpp" +#include "../world/globals.hpp" #include "viewmanager.hpp" #include "operations.hpp" @@ -59,16 +61,16 @@ void CSVDoc::View::setupViewMenu() QAction *newWindow = new QAction (tr ("&New View"), this); connect (newWindow, SIGNAL (triggered()), this, SLOT (newView())); view->addAction (newWindow); - - QAction *test = new QAction (tr ("Add test Subview"), this); - connect (test, SIGNAL (triggered()), this, SLOT (addTestSubView())); - view->addAction (test); } void CSVDoc::View::setupWorldMenu() { QMenu *world = menuBar()->addMenu (tr ("&World")); + QAction *globals = new QAction (tr ("Globals"), this); + connect (globals, SIGNAL (triggered()), this, SLOT (addGlobalsSubView())); + world->addAction (globals); + mVerify = new QAction (tr ("&Verify"), this); connect (mVerify, SIGNAL (triggered()), this, SLOT (verify())); world->addAction (mVerify); @@ -124,6 +126,16 @@ CSVDoc::View::View (ViewManager& viewManager, CSMDoc::Document *document, int to updateTitle(); setupUi(); + + mSubViewFactories.insert (std::make_pair (CSMWorld::UniversalId (CSMWorld::UniversalId::Type_Globals), + new CSVWorld::SubViewFactory())); +} + +CSVDoc::View::~View() +{ + for (std::map::iterator iter (mSubViewFactories.begin()); + iter!=mSubViewFactories.end(); ++iter) + delete iter->second; } const CSMDoc::Document *CSVDoc::View::getDocument() const @@ -176,8 +188,13 @@ 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) - CSVWorld::SubView *view = new CSVWorld::SubView (id); - addDockWidget (Qt::RightDockWidgetArea, view); + std::map::iterator iter = mSubViewFactories.find (id); + + if (iter==mSubViewFactories.end()) + throw std::logic_error ("can't create subview for " + id.toString()); + + CSVWorld::SubView *view = iter->second->makeSubView (id, mDocument->getData()); + addDockWidget (Qt::TopDockWidgetArea, view); view->show(); } @@ -201,7 +218,7 @@ void CSVDoc::View::verify() mDocument->verify(); } -void CSVDoc::View::addTestSubView() +void CSVDoc::View::addGlobalsSubView() { - addSubView (CSMWorld::UniversalId::Type_None); + addSubView (CSMWorld::UniversalId::Type_Globals); } \ No newline at end of file diff --git a/apps/opencs/view/doc/view.hpp b/apps/opencs/view/doc/view.hpp index 7a9164e12f..8e2b272930 100644 --- a/apps/opencs/view/doc/view.hpp +++ b/apps/opencs/view/doc/view.hpp @@ -2,6 +2,7 @@ #define CSV_DOC_VIEW_H #include +#include #include @@ -17,6 +18,11 @@ namespace CSMWorld class UniversalId; } +namespace CSVWorld +{ + struct SubViewFactoryBase; +} + namespace CSVDoc { class ViewManager; @@ -36,6 +42,7 @@ namespace CSVDoc QAction *mVerify; std::vector mEditingActions; Operations *mOperations; + std::map mSubViewFactories; // not implemented View (const View&); @@ -64,6 +71,8 @@ namespace CSVDoc View (ViewManager& viewManager, CSMDoc::Document *document, int totalViews); ///< The ownership of \a document is not transferred to *this. + virtual ~View(); + const CSMDoc::Document *getDocument() const; CSMDoc::Document *getDocument(); @@ -90,7 +99,7 @@ namespace CSVDoc void verify(); - void addTestSubView(); ///< \todo remove + void addGlobalsSubView(); }; } diff --git a/apps/opencs/view/world/globals.cpp b/apps/opencs/view/world/globals.cpp new file mode 100644 index 0000000000..1c0faa029e --- /dev/null +++ b/apps/opencs/view/world/globals.cpp @@ -0,0 +1,26 @@ + +#include "globals.hpp" + +#include +#include +#include + +#include "../../model/world/data.hpp" + +CSVWorld::Globals::Globals (const CSMWorld::UniversalId& id, CSMWorld::Data& data) +: SubView (id) +{ + QTableView *table = new QTableView(); + + setWidget (table); + + QSortFilterProxyModel *proxyModel = new QSortFilterProxyModel (this); + proxyModel->setSourceModel (data.getTableModel (id)); + + table->setModel (proxyModel); + table->horizontalHeader()->setResizeMode (QHeaderView::Interactive); + table->verticalHeader()->hide(); + table->setSortingEnabled (true); + + /// \todo make initial layout fill the whole width of the table +} \ No newline at end of file diff --git a/apps/opencs/view/world/globals.hpp b/apps/opencs/view/world/globals.hpp new file mode 100644 index 0000000000..c54716255a --- /dev/null +++ b/apps/opencs/view/world/globals.hpp @@ -0,0 +1,17 @@ +#ifndef CSV_WORLD_GLOBALS_H +#define CSV_WORLD_GLOBALS_H + +#include "subview.hpp" + +namespace CSVWorld +{ + class Globals : public SubView + { + + public: + + Globals (const CSMWorld::UniversalId& id, CSMWorld::Data& data); + }; +} + +#endif \ No newline at end of file diff --git a/apps/opencs/view/world/subview.hpp b/apps/opencs/view/world/subview.hpp index 8488690c88..95cbe4243f 100644 --- a/apps/opencs/view/world/subview.hpp +++ b/apps/opencs/view/world/subview.hpp @@ -5,6 +5,11 @@ #include +namespace CSMWorld +{ + class Data; +} + namespace CSVWorld { class SubView : public QDockWidget @@ -23,6 +28,23 @@ namespace CSVWorld CSMWorld::UniversalId getUniversalId() const; }; + + struct SubViewFactoryBase + { + virtual SubView *makeSubView (const CSMWorld::UniversalId& id, CSMWorld::Data& data) = 0; + }; + + template + struct SubViewFactory : public SubViewFactoryBase + { + virtual SubView *makeSubView (const CSMWorld::UniversalId& id, CSMWorld::Data& data); + }; + + template + SubView *SubViewFactory::makeSubView (const CSMWorld::UniversalId& id, CSMWorld::Data& data) + { + return new SubViewT (id, data); + } } #endif \ No newline at end of file diff --git a/components/esm/loadglob.hpp b/components/esm/loadglob.hpp index 302729d2e6..5cfb3c87b7 100644 --- a/components/esm/loadglob.hpp +++ b/components/esm/loadglob.hpp @@ -18,7 +18,7 @@ class ESMWriter; struct Global { std::string mId; - unsigned mValue; + float mValue; VarType mType; void load(ESMReader &esm); From 92f70635a2bb7d26ffecd3582cfd6c18ae01516b Mon Sep 17 00:00:00 2001 From: Marc Zinnschlag Date: Tue, 27 Nov 2012 10:42:46 +0100 Subject: [PATCH 21/49] improved selection behaviour --- apps/opencs/view/world/globals.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/apps/opencs/view/world/globals.cpp b/apps/opencs/view/world/globals.cpp index 1c0faa029e..1f68a57fe6 100644 --- a/apps/opencs/view/world/globals.cpp +++ b/apps/opencs/view/world/globals.cpp @@ -21,6 +21,8 @@ CSVWorld::Globals::Globals (const CSMWorld::UniversalId& id, CSMWorld::Data& dat table->horizontalHeader()->setResizeMode (QHeaderView::Interactive); table->verticalHeader()->hide(); table->setSortingEnabled (true); + table->setSelectionBehavior (QAbstractItemView::SelectRows); + table->setSelectionMode (QAbstractItemView::ExtendedSelection); /// \todo make initial layout fill the whole width of the table } \ No newline at end of file From 8a09e03d5c6b369bffcac7dbb16916151eb2c548 Mon Sep 17 00:00:00 2001 From: Marc Zinnschlag Date: Thu, 29 Nov 2012 14:45:34 +0100 Subject: [PATCH 22/49] global variable editing (no undo support yet) --- apps/opencs/model/world/columns.hpp | 12 +++++++++ apps/opencs/model/world/idcollection.hpp | 26 ++++++++++++++++++- apps/opencs/model/world/idtable.cpp | 33 +++++++++++++++++++++++- apps/opencs/model/world/idtable.hpp | 4 +++ apps/opencs/model/world/record.hpp | 18 ++++++++----- components/esm/loadglob.cpp | 4 +++ components/esm/loadglob.hpp | 3 +++ 7 files changed, 91 insertions(+), 9 deletions(-) diff --git a/apps/opencs/model/world/columns.hpp b/apps/opencs/model/world/columns.hpp index 56362e4cdb..4d0ecb58eb 100644 --- a/apps/opencs/model/world/columns.hpp +++ b/apps/opencs/model/world/columns.hpp @@ -14,6 +14,18 @@ namespace CSMWorld { return record.get().mValue; } + + virtual void set (Record& record, const QVariant& data) + { + ESXRecordT base = record.getBase(); + base.mValue = data.toFloat(); + record.setModified (base); + } + + virtual bool isEditable() const + { + return true; + } }; } diff --git a/apps/opencs/model/world/idcollection.hpp b/apps/opencs/model/world/idcollection.hpp index 0bddda1ac9..ee6a4b2ce8 100644 --- a/apps/opencs/model/world/idcollection.hpp +++ b/apps/opencs/model/world/idcollection.hpp @@ -23,6 +23,10 @@ namespace CSMWorld virtual ~Column() {} virtual QVariant get (const Record& record) const = 0; + + virtual void set (Record& record, const QVariant& data) = 0; + + virtual bool isEditable() const = 0; }; class IdCollectionBase @@ -46,6 +50,10 @@ namespace CSMWorld virtual std::string getTitle (int column) const = 0; virtual QVariant getData (int index, int column) const = 0; + + virtual void setData (int index, int column, const QVariant& data) = 0; + + virtual bool isEditable (int column) const = 0; }; ///< \brief Collection of ID-based records @@ -77,9 +85,13 @@ namespace CSMWorld virtual QVariant getData (int index, int column) const; + virtual void setData (int index, int column, const QVariant& data); + virtual std::string getTitle (int column) const; - virtual void addColumn (Column *column); + virtual bool isEditable (int column) const; + + void addColumn (Column *column); }; template @@ -142,12 +154,24 @@ namespace CSMWorld return mColumns.at (column)->get (mRecords.at (index)); } + template + void IdCollection::setData (int index, int column, const QVariant& data) + { + return mColumns.at (column)->set (mRecords.at (index), data); + } + template std::string IdCollection::getTitle (int column) const { return mColumns.at (column)->mTitle; } + template + bool IdCollection::isEditable (int column) const + { + return mColumns.at (column)->isEditable(); + } + template void IdCollection::addColumn (Column *column) { diff --git a/apps/opencs/model/world/idtable.cpp b/apps/opencs/model/world/idtable.cpp index f8acd4f9fe..8fdc4fb8ff 100644 --- a/apps/opencs/model/world/idtable.cpp +++ b/apps/opencs/model/world/idtable.cpp @@ -31,9 +31,18 @@ int CSMWorld::IdTable::columnCount (const QModelIndex & parent) const QVariant CSMWorld::IdTable::data (const QModelIndex & index, int role) const { - if (role!=Qt::DisplayRole) + if (role!=Qt::DisplayRole && role!=Qt::EditRole) return QVariant(); + if (role==Qt::EditRole) + { + if (index.column()==0) + return QVariant(); + + if (!mIdCollection->isEditable (index.column()-1)) + return QVariant(); + } + if (index.column()==0) return QVariant (tr (mIdCollection->getId (index.row()).c_str())); @@ -52,4 +61,26 @@ QVariant CSMWorld::IdTable::headerData (int section, Qt::Orientation orientation return QVariant (tr ("ID")); return tr (mIdCollection->getTitle (section-1).c_str()); +} + +bool CSMWorld::IdTable::setData ( const QModelIndex &index, const QVariant &value, int role) +{ + if (index.column()>0 && role==Qt::EditRole) + { + mIdCollection->setData (index.row(), index.column()-1, value); + emit dataChanged (index, index); + return true; + } + + return false; +} + +Qt::ItemFlags CSMWorld::IdTable::flags (const QModelIndex & index) const +{ + Qt::ItemFlags flags = Qt::ItemIsSelectable | Qt::ItemIsEnabled; + + if (index.column()>0) + flags |= Qt::ItemIsEditable; + + return flags; } \ No newline at end of file diff --git a/apps/opencs/model/world/idtable.hpp b/apps/opencs/model/world/idtable.hpp index 4fb939fa31..30af3aaf70 100644 --- a/apps/opencs/model/world/idtable.hpp +++ b/apps/opencs/model/world/idtable.hpp @@ -31,6 +31,10 @@ namespace CSMWorld QVariant data (const QModelIndex & index, int role = Qt::DisplayRole) const; QVariant headerData (int section, Qt::Orientation orientation, int role = Qt::DisplayRole) const; + + bool setData ( const QModelIndex &index, const QVariant &value, int role = Qt::EditRole); + + Qt::ItemFlags flags (const QModelIndex & index) const; }; } diff --git a/apps/opencs/model/world/record.hpp b/apps/opencs/model/world/record.hpp index 230d39eb06..950d7f176e 100644 --- a/apps/opencs/model/world/record.hpp +++ b/apps/opencs/model/world/record.hpp @@ -8,7 +8,7 @@ namespace CSMWorld template struct Record { - enum state + enum State { State_BaseOnly, // defined in base only State_Modified, // exists in base, but has been modified @@ -18,7 +18,7 @@ namespace CSMWorld ESXRecordT mBase; ESXRecordT mModified; - state mState; + State mState; bool isDeleted() const; @@ -27,10 +27,11 @@ namespace CSMWorld const ESXRecordT& get() const; ///< Throws an exception, if the record is deleted. - ESXRecordT& get(); - ///< Throws an exception, if the record is deleted. + const ESXRecordT& getBase() const; + ///< Throws an exception, if the record is deleted. Returns modified, if there is no base. void setModified (const ESXRecordT& modified); + ///< Throws an exception, if the record is deleted. }; template @@ -55,21 +56,24 @@ namespace CSMWorld } template - ESXRecordT& Record::get() + const ESXRecordT& Record::getBase() const { if (isDeleted()) throw std::logic_error ("attempt to access a deleted record"); - return mState==State_BaseOnly ? mBase : mModified; + return mState==State_ModifiedOnly ? mModified : mBase; } template void Record::setModified (const ESXRecordT& modified) { + if (isDeleted()) + throw std::logic_error ("attempt to modify a deleted record"); + mModified = modified; if (mState!=State_ModifiedOnly) - mState = State_Modified; + mState = mBase==mModified ? State_BaseOnly : State_Modified; } } diff --git a/components/esm/loadglob.cpp b/components/esm/loadglob.cpp index 39c07fb310..0335da0df3 100644 --- a/components/esm/loadglob.cpp +++ b/components/esm/loadglob.cpp @@ -44,4 +44,8 @@ void Global::save(ESMWriter &esm) esm.writeHNT("FLTV", mValue); } + bool operator== (const Global& left, const Global& right) + { + return left.mId==right.mId && left.mValue==right.mValue && left.mType==right.mType; + } } diff --git a/components/esm/loadglob.hpp b/components/esm/loadglob.hpp index 5cfb3c87b7..5c5dafaecb 100644 --- a/components/esm/loadglob.hpp +++ b/components/esm/loadglob.hpp @@ -24,5 +24,8 @@ struct Global void load(ESMReader &esm); void save(ESMWriter &esm); }; + +bool operator== (const Global& left, const Global& right); + } #endif From 4086b556d242280d7ad2e8bd030e7118dab5d57d Mon Sep 17 00:00:00 2001 From: Marc Zinnschlag Date: Thu, 29 Nov 2012 16:05:28 +0100 Subject: [PATCH 23/49] use commands for modifying globals --- apps/opencs/CMakeLists.txt | 2 + apps/opencs/model/world/commands.cpp | 23 +++++++++++ apps/opencs/model/world/commands.hpp | 33 ++++++++++++++++ apps/opencs/view/doc/view.cpp | 2 +- apps/opencs/view/world/globals.cpp | 59 +++++++++++++++++++++++++++- apps/opencs/view/world/globals.hpp | 42 +++++++++++++++++++- apps/opencs/view/world/subview.hpp | 12 ++++-- 7 files changed, 164 insertions(+), 9 deletions(-) create mode 100644 apps/opencs/model/world/commands.cpp create mode 100644 apps/opencs/model/world/commands.hpp diff --git a/apps/opencs/CMakeLists.txt b/apps/opencs/CMakeLists.txt index 92fd859bed..61580461fc 100644 --- a/apps/opencs/CMakeLists.txt +++ b/apps/opencs/CMakeLists.txt @@ -5,6 +5,7 @@ set (OPENCS_SRC model/doc/documentmanager.cpp model/doc/document.cpp model/world/universalid.cpp model/world/idcollection.cpp model/world/data.cpp model/world/idtable.cpp + model/world/commands.cpp view/doc/viewmanager.cpp view/doc/view.cpp view/doc/operations.cpp view/doc/operation.cpp @@ -20,6 +21,7 @@ set (OPENCS_HDR model/world/idtable.hpp model/world/columns.hpp view/doc/viewmanager.hpp view/doc/view.hpp view/doc/operations.hpp view/doc/operation.hpp + model/world/commands.hpp view/world/subview.hpp view/world/globals.hpp ) diff --git a/apps/opencs/model/world/commands.cpp b/apps/opencs/model/world/commands.cpp new file mode 100644 index 0000000000..a15d00619f --- /dev/null +++ b/apps/opencs/model/world/commands.cpp @@ -0,0 +1,23 @@ + +#include "commands.hpp" + +#include + +CSMWorld::ModifyCommand::ModifyCommand (QAbstractItemModel& model, const QModelIndex& index, + const QVariant& new_, QUndoCommand *parent) +: QUndoCommand (parent), mModel (model), mIndex (index), mNew (new_) +{ + mOld = mModel.data (mIndex, Qt::EditRole); + + setText ("Modify " + mModel.headerData (mIndex.column(), Qt::Horizontal, Qt::DisplayRole).toString()); +} + +void CSMWorld::ModifyCommand::redo() +{ + mModel.setData (mIndex, mNew); +} + +void CSMWorld::ModifyCommand::undo() +{ + mModel.setData (mIndex, mOld); +} \ No newline at end of file diff --git a/apps/opencs/model/world/commands.hpp b/apps/opencs/model/world/commands.hpp new file mode 100644 index 0000000000..ffaee59ef5 --- /dev/null +++ b/apps/opencs/model/world/commands.hpp @@ -0,0 +1,33 @@ +#ifndef CSM_WOLRD_COMMANDS_H +#define CSM_WOLRD_COMMANDS_H + +#include "record.hpp" + +#include +#include +#include + +class QModelIndex; +class QAbstractItemModel; + +namespace CSMWorld +{ + class ModifyCommand : public QUndoCommand + { + QAbstractItemModel& mModel; + QModelIndex mIndex; + QVariant mNew; + QVariant mOld; + + public: + + ModifyCommand (QAbstractItemModel& model, const QModelIndex& index, const QVariant& new_, + QUndoCommand *parent = 0); + + virtual void redo(); + + virtual void undo(); + }; +} + +#endif \ No newline at end of file diff --git a/apps/opencs/view/doc/view.cpp b/apps/opencs/view/doc/view.cpp index 18d58bbf58..c81ba2ba14 100644 --- a/apps/opencs/view/doc/view.cpp +++ b/apps/opencs/view/doc/view.cpp @@ -193,7 +193,7 @@ void CSVDoc::View::addSubView (const CSMWorld::UniversalId& id) if (iter==mSubViewFactories.end()) throw std::logic_error ("can't create subview for " + id.toString()); - CSVWorld::SubView *view = iter->second->makeSubView (id, mDocument->getData()); + CSVWorld::SubView *view = iter->second->makeSubView (id, mDocument->getData(), mDocument->getUndoStack()); addDockWidget (Qt::TopDockWidgetArea, view); view->show(); } diff --git a/apps/opencs/view/world/globals.cpp b/apps/opencs/view/world/globals.cpp index 1f68a57fe6..a57f63dffe 100644 --- a/apps/opencs/view/world/globals.cpp +++ b/apps/opencs/view/world/globals.cpp @@ -4,18 +4,73 @@ #include #include #include +#include #include "../../model/world/data.hpp" -CSVWorld::Globals::Globals (const CSMWorld::UniversalId& id, CSMWorld::Data& data) +#include "../../model/world/commands.hpp" + +CSVWorld::NastyTableModelHack::NastyTableModelHack (QAbstractItemModel& model) +: mModel (model) +{} + +int CSVWorld::NastyTableModelHack::rowCount (const QModelIndex & parent) const +{ + return mModel.rowCount (parent); +} + +int CSVWorld::NastyTableModelHack::columnCount (const QModelIndex & parent) const +{ + return mModel.columnCount (parent); +} + +QVariant CSVWorld::NastyTableModelHack::data (const QModelIndex & index, int role) const +{ + return mModel.data (index, role); +} + +bool CSVWorld::NastyTableModelHack::setData ( const QModelIndex &index, const QVariant &value, int role) +{ + mData = value; + return true; +} + +QVariant CSVWorld::NastyTableModelHack::getData() const +{ + return mData; +} + +CSVWorld::CommandDelegate::CommandDelegate (QUndoStack& undoStack, QObject *parent) +: QStyledItemDelegate (parent), mUndoStack (undoStack) +{} + +void CSVWorld::CommandDelegate::setModelData (QWidget *editor, QAbstractItemModel *model, + const QModelIndex& index) const +{ + NastyTableModelHack hack (*model); + QStyledItemDelegate::setModelData (editor, &hack, index); + mUndoStack.push (new CSMWorld::ModifyCommand (*model, index, hack.getData())); +} + +CSVWorld::Globals::Globals (const CSMWorld::UniversalId& id, CSMWorld::Data& data, QUndoStack& undoStack) : SubView (id) { QTableView *table = new QTableView(); setWidget (table); + QAbstractTableModel *model = data.getTableModel (id); + + int columns = model->columnCount(); + + for (int i=1; isetItemDelegateForColumn (i, delegate); + } + QSortFilterProxyModel *proxyModel = new QSortFilterProxyModel (this); - proxyModel->setSourceModel (data.getTableModel (id)); + proxyModel->setSourceModel (model); table->setModel (proxyModel); table->horizontalHeader()->setResizeMode (QHeaderView::Interactive); diff --git a/apps/opencs/view/world/globals.hpp b/apps/opencs/view/world/globals.hpp index c54716255a..11ab7b6aa1 100644 --- a/apps/opencs/view/world/globals.hpp +++ b/apps/opencs/view/world/globals.hpp @@ -3,14 +3,52 @@ #include "subview.hpp" +#include + +class QUndoStack; + namespace CSVWorld { - class Globals : public SubView + ///< \brief Getting the data out of an editor widget + /// + /// Really, Qt? Really? + class NastyTableModelHack : public QAbstractTableModel { + QAbstractItemModel& mModel; + QVariant mData; + + public: + + NastyTableModelHack (QAbstractItemModel& model); + int rowCount (const QModelIndex & parent = QModelIndex()) const; + + int columnCount (const QModelIndex & parent = QModelIndex()) const; + + QVariant data (const QModelIndex & index, int role = Qt::DisplayRole) const; + + bool setData (const QModelIndex &index, const QVariant &value, int role = Qt::EditRole); + + QVariant getData() const; + }; + + ///< \brief Use commands instead of manipulating the model directly + class CommandDelegate : public QStyledItemDelegate + { + QUndoStack& mUndoStack; + + public: + + CommandDelegate (QUndoStack& undoStack, QObject *parent); + + void setModelData (QWidget *editor, QAbstractItemModel *model, const QModelIndex& index) const; + }; + + class Globals : public SubView + { public: - Globals (const CSMWorld::UniversalId& id, CSMWorld::Data& data); + Globals (const CSMWorld::UniversalId& id, CSMWorld::Data& data, QUndoStack& undoStack); }; } diff --git a/apps/opencs/view/world/subview.hpp b/apps/opencs/view/world/subview.hpp index 95cbe4243f..fd7a516315 100644 --- a/apps/opencs/view/world/subview.hpp +++ b/apps/opencs/view/world/subview.hpp @@ -5,6 +5,8 @@ #include +class QUndoStack; + namespace CSMWorld { class Data; @@ -31,19 +33,21 @@ namespace CSVWorld struct SubViewFactoryBase { - virtual SubView *makeSubView (const CSMWorld::UniversalId& id, CSMWorld::Data& data) = 0; + virtual SubView *makeSubView (const CSMWorld::UniversalId& id, CSMWorld::Data& data, QUndoStack& undoStack) + = 0; }; template struct SubViewFactory : public SubViewFactoryBase { - virtual SubView *makeSubView (const CSMWorld::UniversalId& id, CSMWorld::Data& data); + virtual SubView *makeSubView (const CSMWorld::UniversalId& id, CSMWorld::Data& data, QUndoStack& undoStack); }; template - SubView *SubViewFactory::makeSubView (const CSMWorld::UniversalId& id, CSMWorld::Data& data) + SubView *SubViewFactory::makeSubView (const CSMWorld::UniversalId& id, CSMWorld::Data& data, + QUndoStack& undoStack) { - return new SubViewT (id, data); + return new SubViewT (id, data, undoStack); } } From fd55c0cae2603562c7a648bf62c70bbbd33976a3 Mon Sep 17 00:00:00 2001 From: Marc Zinnschlag Date: Thu, 29 Nov 2012 18:56:28 +0100 Subject: [PATCH 24/49] record IDs are no longer handled as a special case --- apps/opencs/model/world/columns.hpp | 16 +++++++++++++++ apps/opencs/model/world/data.cpp | 1 + apps/opencs/model/world/idcollection.hpp | 6 +++++- apps/opencs/model/world/idtable.cpp | 26 +++++++----------------- apps/opencs/view/world/globals.cpp | 2 +- 5 files changed, 30 insertions(+), 21 deletions(-) diff --git a/apps/opencs/model/world/columns.hpp b/apps/opencs/model/world/columns.hpp index 4d0ecb58eb..3220b3bba7 100644 --- a/apps/opencs/model/world/columns.hpp +++ b/apps/opencs/model/world/columns.hpp @@ -28,6 +28,22 @@ namespace CSMWorld } }; + template + struct StringIdColumn : public Column + { + StringIdColumn() : Column ("ID") {} + + virtual QVariant get (const Record& record) const + { + return record.get().mId.c_str(); + } + + virtual bool isEditable() const + { + return false; + } + }; + } #endif \ No newline at end of file diff --git a/apps/opencs/model/world/data.cpp b/apps/opencs/model/world/data.cpp index 7fdb149b31..aeafc16761 100644 --- a/apps/opencs/model/world/data.cpp +++ b/apps/opencs/model/world/data.cpp @@ -12,6 +12,7 @@ CSMWorld::Data::Data() { + mGlobals.addColumn (new StringIdColumn); mGlobals.addColumn (new FloatValueColumn); mModels.insert (std::make_pair ( diff --git a/apps/opencs/model/world/idcollection.hpp b/apps/opencs/model/world/idcollection.hpp index ee6a4b2ce8..41cd352ced 100644 --- a/apps/opencs/model/world/idcollection.hpp +++ b/apps/opencs/model/world/idcollection.hpp @@ -6,6 +6,7 @@ #include #include #include +#include #include @@ -24,7 +25,10 @@ namespace CSMWorld virtual QVariant get (const Record& record) const = 0; - virtual void set (Record& record, const QVariant& data) = 0; + virtual void set (Record& record, const QVariant& data) + { + throw std::logic_error ("Column " + mTitle + " is not editable"); + } virtual bool isEditable() const = 0; }; diff --git a/apps/opencs/model/world/idtable.cpp b/apps/opencs/model/world/idtable.cpp index 8fdc4fb8ff..1fc2bfedbe 100644 --- a/apps/opencs/model/world/idtable.cpp +++ b/apps/opencs/model/world/idtable.cpp @@ -26,7 +26,7 @@ int CSMWorld::IdTable::columnCount (const QModelIndex & parent) const if (parent.isValid()) return 0; - return 1+mIdCollection->getColumns(); + return mIdCollection->getColumns(); } QVariant CSMWorld::IdTable::data (const QModelIndex & index, int role) const @@ -34,19 +34,10 @@ QVariant CSMWorld::IdTable::data (const QModelIndex & index, int role) const if (role!=Qt::DisplayRole && role!=Qt::EditRole) return QVariant(); - if (role==Qt::EditRole) - { - if (index.column()==0) - return QVariant(); - - if (!mIdCollection->isEditable (index.column()-1)) + if (role==Qt::EditRole && !mIdCollection->isEditable (index.column())) return QVariant(); - } - - if (index.column()==0) - return QVariant (tr (mIdCollection->getId (index.row()).c_str())); - return mIdCollection->getData (index.row(), index.column()-1); + return mIdCollection->getData (index.row(), index.column()); } QVariant CSMWorld::IdTable::headerData (int section, Qt::Orientation orientation, int role) const @@ -57,17 +48,14 @@ QVariant CSMWorld::IdTable::headerData (int section, Qt::Orientation orientation if (orientation==Qt::Vertical) return QVariant(); - if (section==0) - return QVariant (tr ("ID")); - - return tr (mIdCollection->getTitle (section-1).c_str()); + return tr (mIdCollection->getTitle (section).c_str()); } bool CSMWorld::IdTable::setData ( const QModelIndex &index, const QVariant &value, int role) { - if (index.column()>0 && role==Qt::EditRole) + if (mIdCollection->isEditable (index.column()) && role==Qt::EditRole) { - mIdCollection->setData (index.row(), index.column()-1, value); + mIdCollection->setData (index.row(), index.column(), value); emit dataChanged (index, index); return true; } @@ -79,7 +67,7 @@ Qt::ItemFlags CSMWorld::IdTable::flags (const QModelIndex & index) const { Qt::ItemFlags flags = Qt::ItemIsSelectable | Qt::ItemIsEnabled; - if (index.column()>0) + if (mIdCollection->isEditable (index.column())) flags |= Qt::ItemIsEditable; return flags; diff --git a/apps/opencs/view/world/globals.cpp b/apps/opencs/view/world/globals.cpp index a57f63dffe..459b8c3579 100644 --- a/apps/opencs/view/world/globals.cpp +++ b/apps/opencs/view/world/globals.cpp @@ -63,7 +63,7 @@ CSVWorld::Globals::Globals (const CSMWorld::UniversalId& id, CSMWorld::Data& dat int columns = model->columnCount(); - for (int i=1; isetItemDelegateForColumn (i, delegate); From 8dd76b49af58ee7822fd11145cf0694a11ca51b1 Mon Sep 17 00:00:00 2001 From: Marc Zinnschlag Date: Thu, 29 Nov 2012 19:09:06 +0100 Subject: [PATCH 25/49] factored out table widget from globals sub view --- apps/opencs/CMakeLists.txt | 4 +- apps/opencs/view/doc/view.cpp | 11 --- apps/opencs/view/doc/view.hpp | 2 - apps/opencs/view/world/globals.cpp | 75 +----------------- apps/opencs/view/world/globals.hpp | 37 --------- apps/opencs/view/world/table.cpp | 118 +++++++++++++++++++++++++++++ apps/opencs/view/world/table.hpp | 25 ++++++ 7 files changed, 147 insertions(+), 125 deletions(-) create mode 100644 apps/opencs/view/world/table.cpp create mode 100644 apps/opencs/view/world/table.hpp diff --git a/apps/opencs/CMakeLists.txt b/apps/opencs/CMakeLists.txt index 61580461fc..dfd9873450 100644 --- a/apps/opencs/CMakeLists.txt +++ b/apps/opencs/CMakeLists.txt @@ -9,7 +9,7 @@ set (OPENCS_SRC view/doc/viewmanager.cpp view/doc/view.cpp view/doc/operations.cpp view/doc/operation.cpp - view/world/subview.cpp view/world/globals.cpp + view/world/subview.cpp view/world/table.cpp view/world/globals.cpp ) set (OPENCS_HDR @@ -23,7 +23,7 @@ set (OPENCS_HDR view/doc/viewmanager.hpp view/doc/view.hpp view/doc/operations.hpp view/doc/operation.hpp model/world/commands.hpp - view/world/subview.hpp view/world/globals.hpp + view/world/subview.hpp view/world/table.hpp view/world/globals.hpp ) set (OPENCS_US diff --git a/apps/opencs/view/doc/view.cpp b/apps/opencs/view/doc/view.cpp index c81ba2ba14..0c336376b8 100644 --- a/apps/opencs/view/doc/view.cpp +++ b/apps/opencs/view/doc/view.cpp @@ -46,12 +46,6 @@ void CSVDoc::View::setupEditMenu() mRedo= mDocument->getUndoStack().createRedoAction (this, tr("&Redo")); mRedo->setShortcuts (QKeySequence::Redo); edit->addAction (mRedo); - - // test - QAction *test = new QAction (tr ("&Test Command"), this); - connect (test, SIGNAL (triggered()), this, SLOT (test())); - edit->addAction (test); - mEditingActions.push_back (test); } void CSVDoc::View::setupViewMenu() @@ -203,11 +197,6 @@ void CSVDoc::View::newView() mViewManager.addView (mDocument); } -void CSVDoc::View::test() -{ - mDocument->getUndoStack().push (new QUndoCommand()); -} - void CSVDoc::View::save() { mDocument->save(); diff --git a/apps/opencs/view/doc/view.hpp b/apps/opencs/view/doc/view.hpp index 8e2b272930..c86c3b3625 100644 --- a/apps/opencs/view/doc/view.hpp +++ b/apps/opencs/view/doc/view.hpp @@ -93,8 +93,6 @@ namespace CSVDoc void newView(); - void test(); - void save(); void verify(); diff --git a/apps/opencs/view/world/globals.cpp b/apps/opencs/view/world/globals.cpp index 459b8c3579..a8b6497db0 100644 --- a/apps/opencs/view/world/globals.cpp +++ b/apps/opencs/view/world/globals.cpp @@ -1,83 +1,12 @@ #include "globals.hpp" -#include -#include -#include -#include - -#include "../../model/world/data.hpp" - -#include "../../model/world/commands.hpp" - -CSVWorld::NastyTableModelHack::NastyTableModelHack (QAbstractItemModel& model) -: mModel (model) -{} - -int CSVWorld::NastyTableModelHack::rowCount (const QModelIndex & parent) const -{ - return mModel.rowCount (parent); -} - -int CSVWorld::NastyTableModelHack::columnCount (const QModelIndex & parent) const -{ - return mModel.columnCount (parent); -} - -QVariant CSVWorld::NastyTableModelHack::data (const QModelIndex & index, int role) const -{ - return mModel.data (index, role); -} - -bool CSVWorld::NastyTableModelHack::setData ( const QModelIndex &index, const QVariant &value, int role) -{ - mData = value; - return true; -} - -QVariant CSVWorld::NastyTableModelHack::getData() const -{ - return mData; -} - -CSVWorld::CommandDelegate::CommandDelegate (QUndoStack& undoStack, QObject *parent) -: QStyledItemDelegate (parent), mUndoStack (undoStack) -{} - -void CSVWorld::CommandDelegate::setModelData (QWidget *editor, QAbstractItemModel *model, - const QModelIndex& index) const -{ - NastyTableModelHack hack (*model); - QStyledItemDelegate::setModelData (editor, &hack, index); - mUndoStack.push (new CSMWorld::ModifyCommand (*model, index, hack.getData())); -} +#include "table.hpp" CSVWorld::Globals::Globals (const CSMWorld::UniversalId& id, CSMWorld::Data& data, QUndoStack& undoStack) : SubView (id) { - QTableView *table = new QTableView(); + QTableView *table = new Table (id, data, undoStack); setWidget (table); - - QAbstractTableModel *model = data.getTableModel (id); - - int columns = model->columnCount(); - - for (int i=0; isetItemDelegateForColumn (i, delegate); - } - - QSortFilterProxyModel *proxyModel = new QSortFilterProxyModel (this); - proxyModel->setSourceModel (model); - - table->setModel (proxyModel); - table->horizontalHeader()->setResizeMode (QHeaderView::Interactive); - table->verticalHeader()->hide(); - table->setSortingEnabled (true); - table->setSelectionBehavior (QAbstractItemView::SelectRows); - table->setSelectionMode (QAbstractItemView::ExtendedSelection); - - /// \todo make initial layout fill the whole width of the table } \ No newline at end of file diff --git a/apps/opencs/view/world/globals.hpp b/apps/opencs/view/world/globals.hpp index 11ab7b6aa1..c4a9fd402f 100644 --- a/apps/opencs/view/world/globals.hpp +++ b/apps/opencs/view/world/globals.hpp @@ -3,47 +3,10 @@ #include "subview.hpp" -#include - class QUndoStack; namespace CSVWorld { - ///< \brief Getting the data out of an editor widget - /// - /// Really, Qt? Really? - class NastyTableModelHack : public QAbstractTableModel - { - QAbstractItemModel& mModel; - QVariant mData; - - public: - - NastyTableModelHack (QAbstractItemModel& model); - - int rowCount (const QModelIndex & parent = QModelIndex()) const; - - int columnCount (const QModelIndex & parent = QModelIndex()) const; - - QVariant data (const QModelIndex & index, int role = Qt::DisplayRole) const; - - bool setData (const QModelIndex &index, const QVariant &value, int role = Qt::EditRole); - - QVariant getData() const; - }; - - ///< \brief Use commands instead of manipulating the model directly - class CommandDelegate : public QStyledItemDelegate - { - QUndoStack& mUndoStack; - - public: - - CommandDelegate (QUndoStack& undoStack, QObject *parent); - - void setModelData (QWidget *editor, QAbstractItemModel *model, const QModelIndex& index) const; - }; - class Globals : public SubView { public: diff --git a/apps/opencs/view/world/table.cpp b/apps/opencs/view/world/table.cpp new file mode 100644 index 0000000000..2c9aa431fc --- /dev/null +++ b/apps/opencs/view/world/table.cpp @@ -0,0 +1,118 @@ + +#include "table.hpp" + +#include +#include +#include +#include + +#include "../../model/world/data.hpp" + +#include "../../model/world/commands.hpp" + +namespace CSVWorld +{ + ///< \brief Getting the data out of an editor widget + /// + /// Really, Qt? Really? + class NastyTableModelHack : public QAbstractTableModel + { + QAbstractItemModel& mModel; + QVariant mData; + + public: + + NastyTableModelHack (QAbstractItemModel& model); + + int rowCount (const QModelIndex & parent = QModelIndex()) const; + + int columnCount (const QModelIndex & parent = QModelIndex()) const; + + QVariant data (const QModelIndex & index, int role = Qt::DisplayRole) const; + + bool setData (const QModelIndex &index, const QVariant &value, int role = Qt::EditRole); + + QVariant getData() const; + }; + + ///< \brief Use commands instead of manipulating the model directly + class CommandDelegate : public QStyledItemDelegate + { + QUndoStack& mUndoStack; + + public: + + CommandDelegate (QUndoStack& undoStack, QObject *parent); + + void setModelData (QWidget *editor, QAbstractItemModel *model, const QModelIndex& index) const; + }; + +} + +CSVWorld::NastyTableModelHack::NastyTableModelHack (QAbstractItemModel& model) +: mModel (model) +{} + +int CSVWorld::NastyTableModelHack::rowCount (const QModelIndex & parent) const +{ + return mModel.rowCount (parent); +} + +int CSVWorld::NastyTableModelHack::columnCount (const QModelIndex & parent) const +{ + return mModel.columnCount (parent); +} + +QVariant CSVWorld::NastyTableModelHack::data (const QModelIndex & index, int role) const +{ + return mModel.data (index, role); +} + +bool CSVWorld::NastyTableModelHack::setData ( const QModelIndex &index, const QVariant &value, int role) +{ + mData = value; + return true; +} + +QVariant CSVWorld::NastyTableModelHack::getData() const +{ + return mData; +} + +CSVWorld::CommandDelegate::CommandDelegate (QUndoStack& undoStack, QObject *parent) +: QStyledItemDelegate (parent), mUndoStack (undoStack) +{} + +void CSVWorld::CommandDelegate::setModelData (QWidget *editor, QAbstractItemModel *model, + const QModelIndex& index) const +{ + NastyTableModelHack hack (*model); + QStyledItemDelegate::setModelData (editor, &hack, index); + mUndoStack.push (new CSMWorld::ModifyCommand (*model, index, hack.getData())); +} + + +CSVWorld::Table::Table (const CSMWorld::UniversalId& id, CSMWorld::Data& data, QUndoStack& undoStack) +{ + QAbstractTableModel *model = data.getTableModel (id); + + int columns = model->columnCount(); + + for (int i=0; isetSourceModel (model); + + setModel (proxyModel); + horizontalHeader()->setResizeMode (QHeaderView::Interactive); + verticalHeader()->hide(); + setSortingEnabled (true); + setSelectionBehavior (QAbstractItemView::SelectRows); + setSelectionMode (QAbstractItemView::ExtendedSelection); + + /// \todo make initial layout fill the whole width of the table +} \ No newline at end of file diff --git a/apps/opencs/view/world/table.hpp b/apps/opencs/view/world/table.hpp new file mode 100644 index 0000000000..dbb3c34431 --- /dev/null +++ b/apps/opencs/view/world/table.hpp @@ -0,0 +1,25 @@ +#ifndef CSV_WORLD_TABLE_H +#define CSV_WORLD_TABLE_H + +#include + +class QUndoStack; + +namespace CSMWorld +{ + class Data; + class UniversalId; +} + +namespace CSVWorld +{ + ///< Table widget + class Table : public QTableView + { + public: + + Table (const CSMWorld::UniversalId& id, CSMWorld::Data& data, QUndoStack& undoStack); + }; +} + +#endif From ec1f957e54887dcb153d4ab07c51348373f65bb7 Mon Sep 17 00:00:00 2001 From: Marc Zinnschlag Date: Fri, 30 Nov 2012 13:58:10 +0100 Subject: [PATCH 26/49] edit lock for sub views --- apps/opencs/view/doc/view.cpp | 5 +++++ apps/opencs/view/world/globals.cpp | 7 +++++-- apps/opencs/view/world/globals.hpp | 6 ++++++ apps/opencs/view/world/subview.hpp | 2 ++ apps/opencs/view/world/table.cpp | 27 +++++++++++++++++++++++---- apps/opencs/view/world/table.hpp | 8 ++++++++ 6 files changed, 49 insertions(+), 6 deletions(-) diff --git a/apps/opencs/view/doc/view.cpp b/apps/opencs/view/doc/view.cpp index 0c336376b8..3d5ebc84bc 100644 --- a/apps/opencs/view/doc/view.cpp +++ b/apps/opencs/view/doc/view.cpp @@ -165,6 +165,11 @@ void CSVDoc::View::updateDocumentState() for (int i=0; operations[i]!=-1; ++i) if (!(state & operations[i])) mOperations->quitOperation (operations[i]); + + QList subViews = findChildren(); + + for (QList::iterator iter (subViews.begin()); iter!=subViews.end(); ++iter) + (*iter)->setEditLock (state && CSMDoc::Document::State_Locked); } void CSVDoc::View::updateProgress (int current, int max, int type, int threads) diff --git a/apps/opencs/view/world/globals.cpp b/apps/opencs/view/world/globals.cpp index a8b6497db0..68c9012aa9 100644 --- a/apps/opencs/view/world/globals.cpp +++ b/apps/opencs/view/world/globals.cpp @@ -6,7 +6,10 @@ CSVWorld::Globals::Globals (const CSMWorld::UniversalId& id, CSMWorld::Data& data, QUndoStack& undoStack) : SubView (id) { - QTableView *table = new Table (id, data, undoStack); + setWidget (mTable = new Table (id, data, undoStack)); +} - setWidget (table); +void CSVWorld::Globals::setEditLock (bool locked) +{ + mTable->setEditLock (locked); } \ No newline at end of file diff --git a/apps/opencs/view/world/globals.hpp b/apps/opencs/view/world/globals.hpp index c4a9fd402f..33cbce47f6 100644 --- a/apps/opencs/view/world/globals.hpp +++ b/apps/opencs/view/world/globals.hpp @@ -7,11 +7,17 @@ class QUndoStack; namespace CSVWorld { + class Table; + class Globals : public SubView { + Table *mTable; + public: Globals (const CSMWorld::UniversalId& id, CSMWorld::Data& data, QUndoStack& undoStack); + + virtual void setEditLock (bool locked); }; } diff --git a/apps/opencs/view/world/subview.hpp b/apps/opencs/view/world/subview.hpp index fd7a516315..543a9b2a1e 100644 --- a/apps/opencs/view/world/subview.hpp +++ b/apps/opencs/view/world/subview.hpp @@ -29,6 +29,8 @@ namespace CSVWorld SubView (const CSMWorld::UniversalId& id); CSMWorld::UniversalId getUniversalId() const; + + virtual void setEditLock (bool locked) = 0; }; struct SubViewFactoryBase diff --git a/apps/opencs/view/world/table.cpp b/apps/opencs/view/world/table.cpp index 2c9aa431fc..590f7ea982 100644 --- a/apps/opencs/view/world/table.cpp +++ b/apps/opencs/view/world/table.cpp @@ -39,12 +39,15 @@ namespace CSVWorld class CommandDelegate : public QStyledItemDelegate { QUndoStack& mUndoStack; + bool mEditLock; public: CommandDelegate (QUndoStack& undoStack, QObject *parent); void setModelData (QWidget *editor, QAbstractItemModel *model, const QModelIndex& index) const; + + void setEditLock (bool locked); }; } @@ -80,15 +83,24 @@ QVariant CSVWorld::NastyTableModelHack::getData() const } CSVWorld::CommandDelegate::CommandDelegate (QUndoStack& undoStack, QObject *parent) -: QStyledItemDelegate (parent), mUndoStack (undoStack) +: QStyledItemDelegate (parent), mUndoStack (undoStack), mEditLock (false) {} void CSVWorld::CommandDelegate::setModelData (QWidget *editor, QAbstractItemModel *model, const QModelIndex& index) const { - NastyTableModelHack hack (*model); - QStyledItemDelegate::setModelData (editor, &hack, index); - mUndoStack.push (new CSMWorld::ModifyCommand (*model, index, hack.getData())); + if (!mEditLock) + { + NastyTableModelHack hack (*model); + QStyledItemDelegate::setModelData (editor, &hack, index); + mUndoStack.push (new CSMWorld::ModifyCommand (*model, index, hack.getData())); + } + ///< \todo provide some kind of feedback to the user, indicating that editing is currently not possible. +} + +void CSVWorld::CommandDelegate::setEditLock (bool locked) +{ + mEditLock = locked; } @@ -101,6 +113,7 @@ CSVWorld::Table::Table (const CSMWorld::UniversalId& id, CSMWorld::Data& data, Q for (int i=0; i::iterator iter (mDelegates.begin()); iter!=mDelegates.end(); ++iter) + (*iter)->setEditLock (locked); } \ No newline at end of file diff --git a/apps/opencs/view/world/table.hpp b/apps/opencs/view/world/table.hpp index dbb3c34431..ae203f5161 100644 --- a/apps/opencs/view/world/table.hpp +++ b/apps/opencs/view/world/table.hpp @@ -1,6 +1,8 @@ #ifndef CSV_WORLD_TABLE_H #define CSV_WORLD_TABLE_H +#include + #include class QUndoStack; @@ -13,12 +15,18 @@ namespace CSMWorld namespace CSVWorld { + class CommandDelegate; + ///< Table widget class Table : public QTableView { + std::vector mDelegates; + public: Table (const CSMWorld::UniversalId& id, CSMWorld::Data& data, QUndoStack& undoStack); + + void setEditLock (bool locked); }; } From bd5e364ac1e29667e789d026360170f8a66734dc Mon Sep 17 00:00:00 2001 From: Marc Zinnschlag Date: Sat, 1 Dec 2012 13:42:12 +0100 Subject: [PATCH 27/49] display record state in table --- apps/opencs/model/world/columns.hpp | 15 +++++++++++++++ apps/opencs/model/world/data.cpp | 1 + 2 files changed, 16 insertions(+) diff --git a/apps/opencs/model/world/columns.hpp b/apps/opencs/model/world/columns.hpp index 3220b3bba7..e81780ceee 100644 --- a/apps/opencs/model/world/columns.hpp +++ b/apps/opencs/model/world/columns.hpp @@ -44,6 +44,21 @@ namespace CSMWorld } }; + template + struct RecordStateColumn : public Column + { + RecordStateColumn() : Column ("*") {} + + virtual QVariant get (const Record& record) const + { + return static_cast (record.mState); + } + + virtual bool isEditable() const + { + return false; + } + }; } #endif \ No newline at end of file diff --git a/apps/opencs/model/world/data.cpp b/apps/opencs/model/world/data.cpp index aeafc16761..c0df54c103 100644 --- a/apps/opencs/model/world/data.cpp +++ b/apps/opencs/model/world/data.cpp @@ -13,6 +13,7 @@ CSMWorld::Data::Data() { mGlobals.addColumn (new StringIdColumn); + mGlobals.addColumn (new RecordStateColumn); mGlobals.addColumn (new FloatValueColumn); mModels.insert (std::make_pair ( From db29e411c4a28805611ce7d90e0ee8294af09cb8 Mon Sep 17 00:00:00 2001 From: Marc Zinnschlag Date: Mon, 3 Dec 2012 13:56:02 +0100 Subject: [PATCH 28/49] added merge functions; temporarily merge on document creation --- apps/opencs/editor.cpp | 2 ++ apps/opencs/model/world/columns.hpp | 3 +++ apps/opencs/model/world/data.cpp | 5 ++++ apps/opencs/model/world/data.hpp | 3 +++ apps/opencs/model/world/idcollection.hpp | 30 ++++++++++++++++++++++++ apps/opencs/model/world/record.hpp | 30 ++++++++++++++++++++++-- 6 files changed, 71 insertions(+), 2 deletions(-) diff --git a/apps/opencs/editor.cpp b/apps/opencs/editor.cpp index 6977a22f02..1632ed220d 100644 --- a/apps/opencs/editor.cpp +++ b/apps/opencs/editor.cpp @@ -35,6 +35,8 @@ void CS::Editor::createDocument() document->getData().getGlobals().add (record); } + document->getData().merge(); /// \todo remove once proper ESX loading is implemented + mViewManager.addView (document); } diff --git a/apps/opencs/model/world/columns.hpp b/apps/opencs/model/world/columns.hpp index e81780ceee..483ce929d7 100644 --- a/apps/opencs/model/world/columns.hpp +++ b/apps/opencs/model/world/columns.hpp @@ -51,6 +51,9 @@ namespace CSMWorld virtual QVariant get (const Record& record) const { + if (record.mState==Record::State_Erased) + return static_cast (Record::State_Deleted); + return static_cast (record.mState); } diff --git a/apps/opencs/model/world/data.cpp b/apps/opencs/model/world/data.cpp index c0df54c103..f350299ec7 100644 --- a/apps/opencs/model/world/data.cpp +++ b/apps/opencs/model/world/data.cpp @@ -46,4 +46,9 @@ QAbstractTableModel *CSMWorld::Data::getTableModel (const UniversalId& id) throw std::logic_error ("No table model available for " + id.toString()); return iter->second; +} + +void CSMWorld::Data::merge() +{ + mGlobals.merge(); } \ No newline at end of file diff --git a/apps/opencs/model/world/data.hpp b/apps/opencs/model/world/data.hpp index 11073c5e37..a8a21e2054 100644 --- a/apps/opencs/model/world/data.hpp +++ b/apps/opencs/model/world/data.hpp @@ -33,6 +33,9 @@ namespace CSMWorld QAbstractTableModel *getTableModel (const UniversalId& id); ///< If no table model is available for \æ id, an exception is thrown. + + void merge(); + ///< Merge modified into base. }; } diff --git a/apps/opencs/model/world/idcollection.hpp b/apps/opencs/model/world/idcollection.hpp index 41cd352ced..d9ab167470 100644 --- a/apps/opencs/model/world/idcollection.hpp +++ b/apps/opencs/model/world/idcollection.hpp @@ -7,6 +7,7 @@ #include #include #include +#include #include @@ -58,6 +59,12 @@ namespace CSMWorld virtual void setData (int index, int column, const QVariant& data) = 0; virtual bool isEditable (int column) const = 0; + + virtual void merge() = 0; + ///< Merge modified into base. + + virtual void purge() = 0; + ///< Remove records that are flagged as erased. }; ///< \brief Collection of ID-based records @@ -95,6 +102,12 @@ namespace CSMWorld virtual bool isEditable (int column) const; + virtual void merge(); + ///< Merge modified into base. + + virtual void purge(); + ///< Remove records that are flagged as erased. + void addColumn (Column *column); }; @@ -181,6 +194,23 @@ namespace CSMWorld { mColumns.push_back (column); } + + template + void IdCollection::merge() + { + for (typename std::vector >::iterator iter (mRecords.begin()); iter!=mRecords.end(); ++iter) + iter->merge(); + + purge(); + } + + template + void IdCollection::purge() + { + mRecords.erase (std::remove_if (mRecords.begin(), mRecords.end(), + std::mem_fun_ref (&Record::isErased) // I want lambda :( + ), mRecords.end()); + } } #endif diff --git a/apps/opencs/model/world/record.hpp b/apps/opencs/model/world/record.hpp index 950d7f176e..c08d2e0d1f 100644 --- a/apps/opencs/model/world/record.hpp +++ b/apps/opencs/model/world/record.hpp @@ -13,7 +13,8 @@ namespace CSMWorld State_BaseOnly, // defined in base only State_Modified, // exists in base, but has been modified State_ModifiedOnly, // newly created in modified - State_Deleted // exists in base, but has been deleted + State_Deleted, // exists in base, but has been deleted + State_Erased // does not exist at all (we mostly treat that the same way as deleted) }; ESXRecordT mBase; @@ -22,6 +23,8 @@ namespace CSMWorld bool isDeleted() const; + bool isErased() const; + bool isModified() const; const ESXRecordT& get() const; @@ -32,12 +35,21 @@ namespace CSMWorld void setModified (const ESXRecordT& modified); ///< Throws an exception, if the record is deleted. + + void merge(); + ///< Merge modified into base. }; template bool Record::isDeleted() const { - return mState==State_Deleted; + return mState==State_Deleted || mState==State_Erased; + } + + template + bool Record::isErased() const + { + return mState==State_Erased; } template @@ -75,6 +87,20 @@ namespace CSMWorld if (mState!=State_ModifiedOnly) mState = mBase==mModified ? State_BaseOnly : State_Modified; } + + template + void Record::merge() + { + if (isModified()) + { + mBase = mModified; + mState = State_BaseOnly; + } + else if (mState==State_Deleted) + { + mState = State_Erased; + } + } } #endif From 49d62390045bfc3794f98da72fee9ce0351415fd Mon Sep 17 00:00:00 2001 From: Marc Zinnschlag Date: Mon, 3 Dec 2012 21:44:16 +0100 Subject: [PATCH 29/49] added pop-up menu with create record action --- apps/opencs/CMakeLists.txt | 6 +- apps/opencs/model/world/commands.cpp | 18 ++++++ apps/opencs/model/world/commands.hpp | 18 ++++++ apps/opencs/model/world/idcollection.hpp | 56 +++++++++++++++++++ apps/opencs/model/world/idtable.cpp | 30 ++++++++++ apps/opencs/model/world/idtable.hpp | 18 ++++-- apps/opencs/model/world/idtableproxymodel.cpp | 18 ++++++ apps/opencs/model/world/idtableproxymodel.hpp | 24 ++++++++ apps/opencs/model/world/record.hpp | 17 +++--- apps/opencs/view/world/globals.cpp | 2 +- apps/opencs/view/world/table.cpp | 45 +++++++++++++-- apps/opencs/view/world/table.hpp | 18 +++++- 12 files changed, 246 insertions(+), 24 deletions(-) create mode 100644 apps/opencs/model/world/idtableproxymodel.cpp create mode 100644 apps/opencs/model/world/idtableproxymodel.hpp diff --git a/apps/opencs/CMakeLists.txt b/apps/opencs/CMakeLists.txt index dfd9873450..6d18a1811a 100644 --- a/apps/opencs/CMakeLists.txt +++ b/apps/opencs/CMakeLists.txt @@ -5,7 +5,7 @@ set (OPENCS_SRC model/doc/documentmanager.cpp model/doc/document.cpp model/world/universalid.cpp model/world/idcollection.cpp model/world/data.cpp model/world/idtable.cpp - model/world/commands.cpp + model/world/commands.cpp model/world/idtableproxymodel.cpp view/doc/viewmanager.cpp view/doc/view.cpp view/doc/operations.cpp view/doc/operation.cpp @@ -18,10 +18,10 @@ set (OPENCS_HDR model/doc/documentmanager.hpp model/doc/document.hpp model/world/universalid.hpp model/world/record.hpp model/world/idcollection.hpp model/world/data.hpp - model/world/idtable.hpp model/world/columns.hpp + model/world/idtable.hpp model/world/columns.hpp model/world/idtableproxymodel.hpp + model/world/commands.hpp view/doc/viewmanager.hpp view/doc/view.hpp view/doc/operations.hpp view/doc/operation.hpp - model/world/commands.hpp view/world/subview.hpp view/world/table.hpp view/world/globals.hpp ) diff --git a/apps/opencs/model/world/commands.cpp b/apps/opencs/model/world/commands.cpp index a15d00619f..7bb76acd0a 100644 --- a/apps/opencs/model/world/commands.cpp +++ b/apps/opencs/model/world/commands.cpp @@ -3,6 +3,8 @@ #include +#include "idtableproxymodel.hpp" + CSMWorld::ModifyCommand::ModifyCommand (QAbstractItemModel& model, const QModelIndex& index, const QVariant& new_, QUndoCommand *parent) : QUndoCommand (parent), mModel (model), mIndex (index), mNew (new_) @@ -20,4 +22,20 @@ void CSMWorld::ModifyCommand::redo() void CSMWorld::ModifyCommand::undo() { mModel.setData (mIndex, mOld); +} + +CSMWorld::CreateCommand::CreateCommand (IdTableProxyModel& model, const std::string& id, QUndoCommand *parent) +: QUndoCommand (parent), mModel (model), mId (id) +{ + setText (("Create record " + id).c_str()); +} + +void CSMWorld::CreateCommand::redo() +{ + mModel.addRecord (mId); +} + +void CSMWorld::CreateCommand::undo() +{ + mModel.removeRow (mModel.getModelIndex (mId, 0).row()); } \ No newline at end of file diff --git a/apps/opencs/model/world/commands.hpp b/apps/opencs/model/world/commands.hpp index ffaee59ef5..50b9045c61 100644 --- a/apps/opencs/model/world/commands.hpp +++ b/apps/opencs/model/world/commands.hpp @@ -3,6 +3,8 @@ #include "record.hpp" +#include + #include #include #include @@ -12,6 +14,8 @@ class QAbstractItemModel; namespace CSMWorld { + class IdTableProxyModel; + class ModifyCommand : public QUndoCommand { QAbstractItemModel& mModel; @@ -28,6 +32,20 @@ namespace CSMWorld virtual void undo(); }; + + class CreateCommand : public QUndoCommand + { + IdTableProxyModel& mModel; + std::string mId; + + public: + + CreateCommand (IdTableProxyModel& model, const std::string& id, QUndoCommand *parent = 0); + + virtual void redo(); + + virtual void undo(); + }; } #endif \ No newline at end of file diff --git a/apps/opencs/model/world/idcollection.hpp b/apps/opencs/model/world/idcollection.hpp index d9ab167470..be7891bd29 100644 --- a/apps/opencs/model/world/idcollection.hpp +++ b/apps/opencs/model/world/idcollection.hpp @@ -50,6 +50,8 @@ namespace CSMWorld virtual std::string getId (int index) const = 0; + virtual int getIndex (const std::string& id) const = 0; + virtual int getColumns() const = 0; virtual std::string getTitle (int column) const = 0; @@ -65,6 +67,10 @@ namespace CSMWorld virtual void purge() = 0; ///< Remove records that are flagged as erased. + + virtual void removeRows (int index, int count) = 0; + + virtual void appendBlankRecord (const std::string& id) = 0; }; ///< \brief Collection of ID-based records @@ -92,6 +98,8 @@ namespace CSMWorld virtual std::string getId (int index) const; + virtual int getIndex (const std::string& id) const; + virtual int getColumns() const; virtual QVariant getData (int index, int column) const; @@ -108,6 +116,10 @@ namespace CSMWorld virtual void purge(); ///< Remove records that are flagged as erased. + virtual void removeRows (int index, int count) ; + + virtual void appendBlankRecord (const std::string& id); + void addColumn (Column *column); }; @@ -159,6 +171,17 @@ namespace CSMWorld return mRecords.at (index).get().mId; } + template + int IdCollection::getIndex (const std::string& id) const + { + std::map::const_iterator iter = mIndex.find (id); + + if (iter==mIndex.end()) + throw std::runtime_error ("invalid ID: " + id); + + return iter->second; + } + template int IdCollection::getColumns() const { @@ -211,6 +234,39 @@ namespace CSMWorld std::mem_fun_ref (&Record::isErased) // I want lambda :( ), mRecords.end()); } + + template + void IdCollection::removeRows (int index, int count) + { + mRecords.erase (mRecords.begin()+index, mRecords.begin()+index+count); + + typename std::map::iterator iter = mIndex.begin(); + + while (iter!=mIndex.end()) + { + if (iter->second>=index) + { + if (iter->second>=index+count) + { + iter->second -= count; + } + else + { + mIndex.erase (iter++); + } + } + + ++iter; + } + } + + template + void IdCollection::appendBlankRecord (const std::string& id) + { + ESXRecordT record; + record.mId = id; + add (record); + } } #endif diff --git a/apps/opencs/model/world/idtable.cpp b/apps/opencs/model/world/idtable.cpp index 1fc2bfedbe..50a6953d60 100644 --- a/apps/opencs/model/world/idtable.cpp +++ b/apps/opencs/model/world/idtable.cpp @@ -71,4 +71,34 @@ Qt::ItemFlags CSMWorld::IdTable::flags (const QModelIndex & index) const flags |= Qt::ItemIsEditable; return flags; +} + +bool CSMWorld::IdTable::removeRows (int row, int count, const QModelIndex& parent) +{ + if (parent.isValid()) + return false; + + beginRemoveRows (parent, row, row+count-1); + + mIdCollection->removeRows (row, count); + + endRemoveRows(); + + return true; +} + +void CSMWorld::IdTable::addRecord (const std::string& id) +{ + int index = mIdCollection->getSize(); + + beginInsertRows (QModelIndex(), index, index); + + mIdCollection->appendBlankRecord (id); + + endInsertRows(); +} + +QModelIndex CSMWorld::IdTable::getModelIndex (const std::string& id, int column) const +{ + return index (mIdCollection->getIndex (id), column); } \ No newline at end of file diff --git a/apps/opencs/model/world/idtable.hpp b/apps/opencs/model/world/idtable.hpp index 30af3aaf70..f95873c7a4 100644 --- a/apps/opencs/model/world/idtable.hpp +++ b/apps/opencs/model/world/idtable.hpp @@ -24,17 +24,23 @@ namespace CSMWorld virtual ~IdTable(); - int rowCount (const QModelIndex & parent = QModelIndex()) const; + virtual int rowCount (const QModelIndex & parent = QModelIndex()) const; - int columnCount (const QModelIndex & parent = QModelIndex()) const; + virtual int columnCount (const QModelIndex & parent = QModelIndex()) const; - QVariant data (const QModelIndex & index, int role = Qt::DisplayRole) const; + virtual QVariant data (const QModelIndex & index, int role = Qt::DisplayRole) const; - QVariant headerData (int section, Qt::Orientation orientation, int role = Qt::DisplayRole) const; + virtual QVariant headerData (int section, Qt::Orientation orientation, int role = Qt::DisplayRole) const; - bool setData ( const QModelIndex &index, const QVariant &value, int role = Qt::EditRole); + virtual bool setData ( const QModelIndex &index, const QVariant &value, int role = Qt::EditRole); - Qt::ItemFlags flags (const QModelIndex & index) const; + virtual Qt::ItemFlags flags (const QModelIndex & index) const; + + virtual bool removeRows (int row, int count, const QModelIndex& parent = QModelIndex()); + + void addRecord (const std::string& id); + + QModelIndex getModelIndex (const std::string& id, int column) const; }; } diff --git a/apps/opencs/model/world/idtableproxymodel.cpp b/apps/opencs/model/world/idtableproxymodel.cpp new file mode 100644 index 0000000000..78995f60bc --- /dev/null +++ b/apps/opencs/model/world/idtableproxymodel.cpp @@ -0,0 +1,18 @@ + +#include "idtableproxymodel.hpp" + +#include "idtable.hpp" + +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)); +} \ No newline at end of file diff --git a/apps/opencs/model/world/idtableproxymodel.hpp b/apps/opencs/model/world/idtableproxymodel.hpp new file mode 100644 index 0000000000..3f1537cce6 --- /dev/null +++ b/apps/opencs/model/world/idtableproxymodel.hpp @@ -0,0 +1,24 @@ +#ifndef CSM_WOLRD_IDTABLEPROXYMODEL_H +#define CSM_WOLRD_IDTABLEPROXYMODEL_H + +#include + +#include + +namespace CSMWorld +{ + class IdTableProxyModel : public QSortFilterProxyModel + { + Q_OBJECT + + public: + + IdTableProxyModel (QObject *parent = 0); + + virtual void addRecord (const std::string& id); + + virtual QModelIndex getModelIndex (const std::string& id, int column) const; + }; +} + +#endif \ No newline at end of file diff --git a/apps/opencs/model/world/record.hpp b/apps/opencs/model/world/record.hpp index c08d2e0d1f..df93501f3e 100644 --- a/apps/opencs/model/world/record.hpp +++ b/apps/opencs/model/world/record.hpp @@ -5,18 +5,21 @@ namespace CSMWorld { - template - struct Record + struct RecordBase { enum State { - State_BaseOnly, // defined in base only - State_Modified, // exists in base, but has been modified - State_ModifiedOnly, // newly created in modified - State_Deleted, // exists in base, but has been deleted - State_Erased // does not exist at all (we mostly treat that the same way as deleted) + State_BaseOnly = 0, // defined in base only + State_Modified = 1, // exists in base, but has been modified + State_ModifiedOnly = 2, // newly created in modified + State_Deleted = 3, // exists in base, but has been deleted + State_Erased = 4 // does not exist at all (we mostly treat that the same way as deleted) }; + }; + template + struct Record : public RecordBase + { ESXRecordT mBase; ESXRecordT mModified; State mState; diff --git a/apps/opencs/view/world/globals.cpp b/apps/opencs/view/world/globals.cpp index 68c9012aa9..20cdb80f4d 100644 --- a/apps/opencs/view/world/globals.cpp +++ b/apps/opencs/view/world/globals.cpp @@ -6,7 +6,7 @@ CSVWorld::Globals::Globals (const CSMWorld::UniversalId& id, CSMWorld::Data& data, QUndoStack& undoStack) : SubView (id) { - setWidget (mTable = new Table (id, data, undoStack)); + setWidget (mTable = new Table (id, data, undoStack, true)); } void CSVWorld::Globals::setEditLock (bool locked) diff --git a/apps/opencs/view/world/table.cpp b/apps/opencs/view/world/table.cpp index 590f7ea982..862ebdc79d 100644 --- a/apps/opencs/view/world/table.cpp +++ b/apps/opencs/view/world/table.cpp @@ -3,12 +3,14 @@ #include #include -#include #include +#include +#include +#include #include "../../model/world/data.hpp" - #include "../../model/world/commands.hpp" +#include "../../model/world/idtableproxymodel.hpp" namespace CSVWorld { @@ -104,7 +106,19 @@ void CSVWorld::CommandDelegate::setEditLock (bool locked) } -CSVWorld::Table::Table (const CSMWorld::UniversalId& id, CSMWorld::Data& data, QUndoStack& undoStack) + void CSVWorld::Table::contextMenuEvent (QContextMenuEvent *event) +{ + QMenu menu (this); + + if (mCreateAction) + menu.addAction (mCreateAction); + + menu.exec (event->globalPos()); +} + +CSVWorld::Table::Table (const CSMWorld::UniversalId& id, CSMWorld::Data& data, QUndoStack& undoStack, + bool createAndDelete) +: mUndoStack (undoStack), mCreateAction (0) { QAbstractTableModel *model = data.getTableModel (id); @@ -117,10 +131,10 @@ CSVWorld::Table::Table (const CSMWorld::UniversalId& id, CSMWorld::Data& data, Q setItemDelegateForColumn (i, delegate); } - QSortFilterProxyModel *proxyModel = new QSortFilterProxyModel (this); - proxyModel->setSourceModel (model); + mModel = new CSMWorld::IdTableProxyModel (this); + mModel->setSourceModel (model); - setModel (proxyModel); + setModel (mModel); horizontalHeader()->setResizeMode (QHeaderView::Interactive); verticalHeader()->hide(); setSortingEnabled (true); @@ -128,10 +142,29 @@ CSVWorld::Table::Table (const CSMWorld::UniversalId& id, CSMWorld::Data& data, Q setSelectionMode (QAbstractItemView::ExtendedSelection); /// \todo make initial layout fill the whole width of the table + + if (createAndDelete) + { + mCreateAction = new QAction (tr ("CreateRecord"), this); + connect (mCreateAction, SIGNAL (triggered()), this, SLOT (createRecord())); + addAction (mCreateAction); + } } void CSVWorld::Table::setEditLock (bool locked) { for (std::vector::iterator iter (mDelegates.begin()); iter!=mDelegates.end(); ++iter) (*iter)->setEditLock (locked); +} + +#include /// \todo remove +void CSVWorld::Table::createRecord() +{ + /// \todo ask the user for an ID instead. + static int index = 0; + + std::ostringstream stream; + stream << "id" << index++; + + mUndoStack.push (new CSMWorld::CreateCommand (*mModel, stream.str())); } \ No newline at end of file diff --git a/apps/opencs/view/world/table.hpp b/apps/opencs/view/world/table.hpp index ae203f5161..f07f3ff24b 100644 --- a/apps/opencs/view/world/table.hpp +++ b/apps/opencs/view/world/table.hpp @@ -6,11 +6,13 @@ #include class QUndoStack; +class QAction; namespace CSMWorld { class Data; class UniversalId; + class IdTableProxyModel; } namespace CSVWorld @@ -20,13 +22,27 @@ namespace CSVWorld ///< Table widget class Table : public QTableView { + Q_OBJECT + std::vector mDelegates; + QUndoStack& mUndoStack; + QAction *mCreateAction; + CSMWorld::IdTableProxyModel *mModel; + + private: + + void contextMenuEvent (QContextMenuEvent *event); public: - Table (const CSMWorld::UniversalId& id, CSMWorld::Data& data, QUndoStack& undoStack); + Table (const CSMWorld::UniversalId& id, CSMWorld::Data& data, QUndoStack& undoStack, bool createAndDelete); + ///< \param createAndDelete Allow creation and deletion of records. void setEditLock (bool locked); + + private slots: + + void createRecord(); }; } From 0a8b7602d316c63d2909270be035d2137a6551a3 Mon Sep 17 00:00:00 2001 From: Marc Zinnschlag Date: Mon, 3 Dec 2012 21:51:42 +0100 Subject: [PATCH 30/49] fixed edit lock --- apps/opencs/view/doc/view.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/opencs/view/doc/view.cpp b/apps/opencs/view/doc/view.cpp index 3d5ebc84bc..1a8d568787 100644 --- a/apps/opencs/view/doc/view.cpp +++ b/apps/opencs/view/doc/view.cpp @@ -169,7 +169,7 @@ void CSVDoc::View::updateDocumentState() QList subViews = findChildren(); for (QList::iterator iter (subViews.begin()); iter!=subViews.end(); ++iter) - (*iter)->setEditLock (state && CSMDoc::Document::State_Locked); + (*iter)->setEditLock (state & CSMDoc::Document::State_Locked); } void CSVDoc::View::updateProgress (int current, int max, int type, int threads) From 8e93bfa607ba7e38a507e7ffe346df0f5c9ecaec Mon Sep 17 00:00:00 2001 From: Marc Zinnschlag Date: Mon, 3 Dec 2012 22:03:02 +0100 Subject: [PATCH 31/49] turned the global class into a general purpose table subview class --- apps/opencs/CMakeLists.txt | 4 ++-- apps/opencs/view/doc/view.cpp | 5 ++--- apps/opencs/view/world/globals.cpp | 15 --------------- apps/opencs/view/world/globals.hpp | 24 ------------------------ apps/opencs/view/world/subview.hpp | 23 +++++++++++++++++++++++ apps/opencs/view/world/table.cpp | 2 +- apps/opencs/view/world/tablesubview.cpp | 16 ++++++++++++++++ apps/opencs/view/world/tablesubview.hpp | 25 +++++++++++++++++++++++++ 8 files changed, 69 insertions(+), 45 deletions(-) delete mode 100644 apps/opencs/view/world/globals.cpp delete mode 100644 apps/opencs/view/world/globals.hpp create mode 100644 apps/opencs/view/world/tablesubview.cpp create mode 100644 apps/opencs/view/world/tablesubview.hpp diff --git a/apps/opencs/CMakeLists.txt b/apps/opencs/CMakeLists.txt index 6d18a1811a..4ef4f93c7a 100644 --- a/apps/opencs/CMakeLists.txt +++ b/apps/opencs/CMakeLists.txt @@ -9,7 +9,7 @@ set (OPENCS_SRC view/doc/viewmanager.cpp view/doc/view.cpp view/doc/operations.cpp view/doc/operation.cpp - view/world/subview.cpp view/world/table.cpp view/world/globals.cpp + view/world/subview.cpp view/world/table.cpp view/world/tablesubview.cpp ) set (OPENCS_HDR @@ -23,7 +23,7 @@ set (OPENCS_HDR view/doc/viewmanager.hpp view/doc/view.hpp view/doc/operations.hpp view/doc/operation.hpp - view/world/subview.hpp view/world/table.hpp view/world/globals.hpp + view/world/subview.hpp view/world/table.hpp view/world/tablesubview.hpp ) set (OPENCS_US diff --git a/apps/opencs/view/doc/view.cpp b/apps/opencs/view/doc/view.cpp index 1a8d568787..65ec103a21 100644 --- a/apps/opencs/view/doc/view.cpp +++ b/apps/opencs/view/doc/view.cpp @@ -10,8 +10,7 @@ #include "../../model/doc/document.hpp" -#include "../world/subview.hpp" -#include "../world/globals.hpp" +#include "../world/tablesubview.hpp" #include "viewmanager.hpp" #include "operations.hpp" @@ -122,7 +121,7 @@ CSVDoc::View::View (ViewManager& viewManager, CSMDoc::Document *document, int to setupUi(); mSubViewFactories.insert (std::make_pair (CSMWorld::UniversalId (CSMWorld::UniversalId::Type_Globals), - new CSVWorld::SubViewFactory())); + new CSVWorld::SubViewFactoryWithCreateFlag (true))); } CSVDoc::View::~View() diff --git a/apps/opencs/view/world/globals.cpp b/apps/opencs/view/world/globals.cpp deleted file mode 100644 index 20cdb80f4d..0000000000 --- a/apps/opencs/view/world/globals.cpp +++ /dev/null @@ -1,15 +0,0 @@ - -#include "globals.hpp" - -#include "table.hpp" - -CSVWorld::Globals::Globals (const CSMWorld::UniversalId& id, CSMWorld::Data& data, QUndoStack& undoStack) -: SubView (id) -{ - setWidget (mTable = new Table (id, data, undoStack, true)); -} - -void CSVWorld::Globals::setEditLock (bool locked) -{ - mTable->setEditLock (locked); -} \ No newline at end of file diff --git a/apps/opencs/view/world/globals.hpp b/apps/opencs/view/world/globals.hpp deleted file mode 100644 index 33cbce47f6..0000000000 --- a/apps/opencs/view/world/globals.hpp +++ /dev/null @@ -1,24 +0,0 @@ -#ifndef CSV_WORLD_GLOBALS_H -#define CSV_WORLD_GLOBALS_H - -#include "subview.hpp" - -class QUndoStack; - -namespace CSVWorld -{ - class Table; - - class Globals : public SubView - { - Table *mTable; - - public: - - Globals (const CSMWorld::UniversalId& id, CSMWorld::Data& data, QUndoStack& undoStack); - - virtual void setEditLock (bool locked); - }; -} - -#endif \ No newline at end of file diff --git a/apps/opencs/view/world/subview.hpp b/apps/opencs/view/world/subview.hpp index 543a9b2a1e..95448cb47b 100644 --- a/apps/opencs/view/world/subview.hpp +++ b/apps/opencs/view/world/subview.hpp @@ -51,6 +51,29 @@ namespace CSVWorld { return new SubViewT (id, data, undoStack); } + + template + struct SubViewFactoryWithCreateFlag : public SubViewFactoryBase + { + bool mCreateAndDelete; + + SubViewFactoryWithCreateFlag (bool createAndDelete); + + virtual SubView *makeSubView (const CSMWorld::UniversalId& id, CSMWorld::Data& data, QUndoStack& undoStack); + }; + + template + SubViewFactoryWithCreateFlag::SubViewFactoryWithCreateFlag (bool createAndDelete) + : mCreateAndDelete (createAndDelete) + {} + + template + SubView *SubViewFactoryWithCreateFlag::makeSubView (const CSMWorld::UniversalId& id, + CSMWorld::Data& data, + QUndoStack& undoStack) + { + return new SubViewT (id, data, undoStack, mCreateAndDelete); + } } #endif \ No newline at end of file diff --git a/apps/opencs/view/world/table.cpp b/apps/opencs/view/world/table.cpp index 862ebdc79d..4f20d9fd26 100644 --- a/apps/opencs/view/world/table.cpp +++ b/apps/opencs/view/world/table.cpp @@ -145,7 +145,7 @@ CSVWorld::Table::Table (const CSMWorld::UniversalId& id, CSMWorld::Data& data, Q if (createAndDelete) { - mCreateAction = new QAction (tr ("CreateRecord"), this); + mCreateAction = new QAction (tr ("Add Record"), this); connect (mCreateAction, SIGNAL (triggered()), this, SLOT (createRecord())); addAction (mCreateAction); } diff --git a/apps/opencs/view/world/tablesubview.cpp b/apps/opencs/view/world/tablesubview.cpp new file mode 100644 index 0000000000..3bc555a2d0 --- /dev/null +++ b/apps/opencs/view/world/tablesubview.cpp @@ -0,0 +1,16 @@ + +#include "tablesubview.hpp" + +#include "table.hpp" + +CSVWorld::TableSubView::TableSubView (const CSMWorld::UniversalId& id, CSMWorld::Data& data, QUndoStack& undoStack, + bool createAndDelete) +: SubView (id) +{ + setWidget (mTable = new Table (id, data, undoStack, createAndDelete)); +} + +void CSVWorld::TableSubView::setEditLock (bool locked) +{ + mTable->setEditLock (locked); +} \ No newline at end of file diff --git a/apps/opencs/view/world/tablesubview.hpp b/apps/opencs/view/world/tablesubview.hpp new file mode 100644 index 0000000000..b45b3c2796 --- /dev/null +++ b/apps/opencs/view/world/tablesubview.hpp @@ -0,0 +1,25 @@ +#ifndef CSV_WORLD_TABLESUBVIEW_H +#define CSV_WORLD_TABLESUBVIEW_H + +#include "subview.hpp" + +class QUndoStack; + +namespace CSVWorld +{ + class Table; + + class TableSubView : public SubView + { + Table *mTable; + + public: + + TableSubView (const CSMWorld::UniversalId& id, CSMWorld::Data& data, QUndoStack& undoStack, + bool createAndDelete); + + virtual void setEditLock (bool locked); + }; +} + +#endif \ No newline at end of file From 5cd2fe00ab41eaef4618e017061fd86630987338 Mon Sep 17 00:00:00 2001 From: Marc Zinnschlag Date: Mon, 3 Dec 2012 22:16:02 +0100 Subject: [PATCH 32/49] initialise blank global records --- apps/opencs/model/world/idcollection.hpp | 1 + components/esm/loadglob.cpp | 6 ++++++ components/esm/loadglob.hpp | 3 +++ 3 files changed, 10 insertions(+) diff --git a/apps/opencs/model/world/idcollection.hpp b/apps/opencs/model/world/idcollection.hpp index be7891bd29..e4bb31dbeb 100644 --- a/apps/opencs/model/world/idcollection.hpp +++ b/apps/opencs/model/world/idcollection.hpp @@ -265,6 +265,7 @@ namespace CSMWorld { ESXRecordT record; record.mId = id; + record.blank(); add (record); } } diff --git a/components/esm/loadglob.cpp b/components/esm/loadglob.cpp index 0335da0df3..ceaa869489 100644 --- a/components/esm/loadglob.cpp +++ b/components/esm/loadglob.cpp @@ -44,6 +44,12 @@ void Global::save(ESMWriter &esm) esm.writeHNT("FLTV", mValue); } + void Global::blank() + { + mValue = 0; + mType = VT_Float; + } + bool operator== (const Global& left, const Global& right) { return left.mId==right.mId && left.mValue==right.mValue && left.mType==right.mType; diff --git a/components/esm/loadglob.hpp b/components/esm/loadglob.hpp index 5c5dafaecb..6111648a63 100644 --- a/components/esm/loadglob.hpp +++ b/components/esm/loadglob.hpp @@ -23,6 +23,9 @@ struct Global void load(ESMReader &esm); void save(ESMWriter &esm); + + void blank(); + ///< Set record to default state (does not touch the ID). }; bool operator== (const Global& left, const Global& right); From f07b7d17cdb1e07d907fe1518bd7249b695e64f3 Mon Sep 17 00:00:00 2001 From: Marc Zinnschlag Date: Tue, 4 Dec 2012 20:43:47 +0100 Subject: [PATCH 33/49] improved exception handling --- apps/opencs/main.cpp | 28 +++++++++++++++++++++++++++- 1 file changed, 27 insertions(+), 1 deletion(-) diff --git a/apps/opencs/main.cpp b/apps/opencs/main.cpp index 15772eba0e..4b1a688c26 100644 --- a/apps/opencs/main.cpp +++ b/apps/opencs/main.cpp @@ -1,11 +1,37 @@ #include "editor.hpp" +#include +#include + #include +class Application : public QApplication +{ + private: + + bool notify (QObject *receiver, QEvent *event) + { + try + { + return QApplication::notify (receiver, event); + } + catch (const std::exception& exception) + { + std::cerr << "An exception has been caught: " << exception.what() << std::endl; + } + + return false; + } + + public: + + Application (int& argc, char *argv[]) : QApplication (argc, argv) {} +}; + int main(int argc, char *argv[]) { - QApplication mApplication (argc, argv); + Application mApplication (argc, argv); CS::Editor editor; From b41cc5e9e943580281b7be67262de633c41f8404 Mon Sep 17 00:00:00 2001 From: Marc Zinnschlag Date: Thu, 6 Dec 2012 14:56:04 +0100 Subject: [PATCH 34/49] added revert command --- apps/opencs/CMakeLists.txt | 2 +- apps/opencs/model/world/columns.hpp | 7 +- apps/opencs/model/world/commands.cpp | 34 +++++++++ apps/opencs/model/world/commands.hpp | 23 +++++++ apps/opencs/model/world/idcollection.hpp | 87 +++++++++++++++++++++++- apps/opencs/model/world/idtable.cpp | 32 ++++++++- apps/opencs/model/world/idtable.hpp | 6 ++ apps/opencs/model/world/record.cpp | 21 ++++++ apps/opencs/model/world/record.hpp | 35 ++++------ apps/opencs/view/world/table.cpp | 55 +++++++++++++-- apps/opencs/view/world/table.hpp | 7 +- 11 files changed, 275 insertions(+), 34 deletions(-) create mode 100644 apps/opencs/model/world/record.cpp diff --git a/apps/opencs/CMakeLists.txt b/apps/opencs/CMakeLists.txt index 4ef4f93c7a..5a9e1e99cc 100644 --- a/apps/opencs/CMakeLists.txt +++ b/apps/opencs/CMakeLists.txt @@ -5,7 +5,7 @@ set (OPENCS_SRC model/doc/documentmanager.cpp model/doc/document.cpp model/world/universalid.cpp model/world/idcollection.cpp model/world/data.cpp model/world/idtable.cpp - model/world/commands.cpp model/world/idtableproxymodel.cpp + model/world/commands.cpp model/world/idtableproxymodel.cpp model/world/record.cpp view/doc/viewmanager.cpp view/doc/view.cpp view/doc/operations.cpp view/doc/operation.cpp diff --git a/apps/opencs/model/world/columns.hpp b/apps/opencs/model/world/columns.hpp index 483ce929d7..188d3a2ac5 100644 --- a/apps/opencs/model/world/columns.hpp +++ b/apps/opencs/model/world/columns.hpp @@ -57,9 +57,14 @@ namespace CSMWorld return static_cast (record.mState); } + virtual void set (Record& record, const QVariant& data) + { + record.mState = static_cast (data.toInt()); + } + virtual bool isEditable() const { - return false; + return true; } }; } diff --git a/apps/opencs/model/world/commands.cpp b/apps/opencs/model/world/commands.cpp index 7bb76acd0a..96a1b639cf 100644 --- a/apps/opencs/model/world/commands.cpp +++ b/apps/opencs/model/world/commands.cpp @@ -4,6 +4,7 @@ #include #include "idtableproxymodel.hpp" +#include "idtable.hpp" CSMWorld::ModifyCommand::ModifyCommand (QAbstractItemModel& model, const QModelIndex& index, const QVariant& new_, QUndoCommand *parent) @@ -38,4 +39,37 @@ void CSMWorld::CreateCommand::redo() void CSMWorld::CreateCommand::undo() { mModel.removeRow (mModel.getModelIndex (mId, 0).row()); +} + +CSMWorld::RevertCommand::RevertCommand (IdTable& model, const std::string& id, QUndoCommand *parent) +: QUndoCommand (parent), mModel (model), mId (id), mOld (0) +{ + setText (("Revert record " + id).c_str()); + + mOld = model.getRecord (id).clone(); +} + +CSMWorld::RevertCommand::~RevertCommand() +{ + delete mOld; +} + +void CSMWorld::RevertCommand::redo() +{ + QModelIndex index = mModel.getModelIndex (mId, 1); + RecordBase::State state = static_cast (mModel.data (index).toInt()); + + if (state==RecordBase::State_ModifiedOnly) + { + mModel.removeRows (index.row(), 1); + } + else + { + mModel.setData (index, static_cast (RecordBase::State_BaseOnly)); + } +} + +void CSMWorld::RevertCommand::undo() +{ + mModel.setRecord (*mOld); } \ No newline at end of file diff --git a/apps/opencs/model/world/commands.hpp b/apps/opencs/model/world/commands.hpp index 50b9045c61..e916d05c9e 100644 --- a/apps/opencs/model/world/commands.hpp +++ b/apps/opencs/model/world/commands.hpp @@ -15,6 +15,8 @@ class QAbstractItemModel; namespace CSMWorld { class IdTableProxyModel; + class IdTable; + class RecordBase; class ModifyCommand : public QUndoCommand { @@ -46,6 +48,27 @@ namespace CSMWorld virtual void undo(); }; + + class RevertCommand : public QUndoCommand + { + IdTable& mModel; + std::string mId; + RecordBase *mOld; + + // not implemented + RevertCommand (const RevertCommand&); + RevertCommand& operator= (const RevertCommand&); + + public: + + RevertCommand (IdTable& model, const std::string& id, QUndoCommand *parent = 0); + + virtual ~RevertCommand(); + + virtual void redo(); + + virtual void undo(); + }; } #endif \ No newline at end of file diff --git a/apps/opencs/model/world/idcollection.hpp b/apps/opencs/model/world/idcollection.hpp index e4bb31dbeb..50afa715eb 100644 --- a/apps/opencs/model/world/idcollection.hpp +++ b/apps/opencs/model/world/idcollection.hpp @@ -71,6 +71,25 @@ namespace CSMWorld virtual void removeRows (int index, int count) = 0; virtual void appendBlankRecord (const std::string& id) = 0; + + virtual int searchId (const std::string& id) const = 0; + ////< Search record with \a id. + /// \return index of record (if found) or -1 (not found) + + virtual void replace (int index, const RecordBase& record) = 0; + ///< If the record type does not match, an exception is thrown. + /// + /// \attention \a record must not change the ID. + + virtual void appendRecord (const RecordBase& record) = 0; + ///< If the record type does not match, an exception is thrown. + + virtual std::string getId (const RecordBase& record) const = 0; + ///< Return ID for \a record. + /// + /// \attention Throw san exception, if the type of \a record does not match. + + virtual const RecordBase& getRecord (const std::string& id) const = 0; }; ///< \brief Collection of ID-based records @@ -120,6 +139,25 @@ namespace CSMWorld virtual void appendBlankRecord (const std::string& id); + virtual int searchId (const std::string& id) const; + ////< Search record with \a id. + /// \return index of record (if found) or -1 (not found) + + virtual void replace (int index, const RecordBase& record); + ///< If the record type does not match, an exception is thrown. + /// + /// \attention \a record must not change the ID. + + virtual void appendRecord (const RecordBase& record); + ///< If the record type does not match, an exception is thrown. + + virtual std::string getId (const RecordBase& record) const; + ///< Return ID for \a record. + /// + /// \attention Throw san exception, if the type of \a record does not match. + + virtual const RecordBase& getRecord (const std::string& id) const; + void addColumn (Column *column); }; @@ -174,12 +212,12 @@ namespace CSMWorld template int IdCollection::getIndex (const std::string& id) const { - std::map::const_iterator iter = mIndex.find (id); + int index = searchId (id); - if (iter==mIndex.end()) + if (index==-1) throw std::runtime_error ("invalid ID: " + id); - return iter->second; + return index; } template @@ -268,6 +306,49 @@ namespace CSMWorld record.blank(); add (record); } + + template + int IdCollection::searchId (const std::string& id) const + { + std::string id2; + + std::transform (id.begin(), id.end(), std::back_inserter (id2), + (int(*)(int)) std::tolower); + + std::map::const_iterator iter = mIndex.find (id2); + + if (iter==mIndex.end()) + return -1; + + return iter->second; + } + + template + void IdCollection::replace (int index, const RecordBase& record) + { + mRecords.at (index) = dynamic_cast&> (record); + } + + template + void IdCollection::appendRecord (const RecordBase& record) + { + mRecords.push_back (dynamic_cast&> (record)); + mIndex.insert (std::make_pair (getId (record), mRecords.size()-1)); + } + + template + std::string IdCollection::getId (const RecordBase& record) const + { + const Record& record2 = dynamic_cast&> (record); + return (record2.isModified() ? record2.mModified : record2.mBase).mId; + } + + template + const RecordBase& IdCollection::getRecord (const std::string& id) const + { + int index = getIndex (id); + return mRecords.at (index); + } } #endif diff --git a/apps/opencs/model/world/idtable.cpp b/apps/opencs/model/world/idtable.cpp index 50a6953d60..a2b0a3c1f5 100644 --- a/apps/opencs/model/world/idtable.cpp +++ b/apps/opencs/model/world/idtable.cpp @@ -56,7 +56,10 @@ bool CSMWorld::IdTable::setData ( const QModelIndex &index, const QVariant &valu if (mIdCollection->isEditable (index.column()) && role==Qt::EditRole) { mIdCollection->setData (index.row(), index.column(), value); - emit dataChanged (index, index); + + emit dataChanged (CSMWorld::IdTable::index (index.row(), 0), + CSMWorld::IdTable::index (index.row(), mIdCollection->getColumns()-1)); + return true; } @@ -101,4 +104,31 @@ void CSMWorld::IdTable::addRecord (const std::string& id) QModelIndex CSMWorld::IdTable::getModelIndex (const std::string& id, int column) const { return index (mIdCollection->getIndex (id), column); +} + +void CSMWorld::IdTable::setRecord (const RecordBase& record) +{ + int index = mIdCollection->searchId (mIdCollection->getId (record)); + + if (index==-1) + { + int index = mIdCollection->getSize(); + + beginInsertRows (QModelIndex(), index, index); + + mIdCollection->appendRecord (record); + + endInsertRows(); + } + else + { + mIdCollection->replace (index, record); + emit dataChanged (CSMWorld::IdTable::index (index, 0), + CSMWorld::IdTable::index (index, mIdCollection->getColumns()-1)); + } +} + +const CSMWorld::RecordBase& CSMWorld::IdTable::getRecord (const std::string& id) const +{ + return mIdCollection->getRecord (id); } \ No newline at end of file diff --git a/apps/opencs/model/world/idtable.hpp b/apps/opencs/model/world/idtable.hpp index f95873c7a4..deaebaa38a 100644 --- a/apps/opencs/model/world/idtable.hpp +++ b/apps/opencs/model/world/idtable.hpp @@ -6,6 +6,7 @@ namespace CSMWorld { class IdCollectionBase; + class RecordBase; class IdTable : public QAbstractTableModel { @@ -41,6 +42,11 @@ namespace CSMWorld void addRecord (const std::string& id); QModelIndex getModelIndex (const std::string& id, int column) const; + + void setRecord (const RecordBase& record); + ///< Add record or overwrite existing recrod. + + const RecordBase& getRecord (const std::string& id) const; }; } diff --git a/apps/opencs/model/world/record.cpp b/apps/opencs/model/world/record.cpp new file mode 100644 index 0000000000..229985a8a2 --- /dev/null +++ b/apps/opencs/model/world/record.cpp @@ -0,0 +1,21 @@ + +#include "record.hpp" + +CSMWorld::RecordBase::~RecordBase() {} + +bool CSMWorld::RecordBase::RecordBase::isDeleted() const +{ + return mState==State_Deleted || mState==State_Erased; +} + + +bool CSMWorld::RecordBase::RecordBase::isErased() const +{ + return mState==State_Erased; +} + + +bool CSMWorld::RecordBase::RecordBase::isModified() const +{ + return mState==State_Modified || mState==State_ModifiedOnly; +} \ No newline at end of file diff --git a/apps/opencs/model/world/record.hpp b/apps/opencs/model/world/record.hpp index df93501f3e..3b83836aba 100644 --- a/apps/opencs/model/world/record.hpp +++ b/apps/opencs/model/world/record.hpp @@ -15,20 +15,27 @@ namespace CSMWorld State_Deleted = 3, // exists in base, but has been deleted State_Erased = 4 // does not exist at all (we mostly treat that the same way as deleted) }; - }; - template - struct Record : public RecordBase - { - ESXRecordT mBase; - ESXRecordT mModified; State mState; + virtual ~RecordBase(); + + virtual RecordBase *clone() const = 0; + bool isDeleted() const; bool isErased() const; bool isModified() const; + }; + + template + struct Record : public RecordBase + { + ESXRecordT mBase; + ESXRecordT mModified; + + virtual RecordBase *clone() const; const ESXRecordT& get() const; ///< Throws an exception, if the record is deleted. @@ -44,21 +51,9 @@ namespace CSMWorld }; template - bool Record::isDeleted() const - { - return mState==State_Deleted || mState==State_Erased; - } - - template - bool Record::isErased() const - { - return mState==State_Erased; - } - - template - bool Record::isModified() const + RecordBase *Record::clone() const { - return mState==State_Modified || mState==State_ModifiedOnly; + return new Record (*this); } template diff --git a/apps/opencs/view/world/table.cpp b/apps/opencs/view/world/table.cpp index 4f20d9fd26..dafcb95c08 100644 --- a/apps/opencs/view/world/table.cpp +++ b/apps/opencs/view/world/table.cpp @@ -11,6 +11,8 @@ #include "../../model/world/data.hpp" #include "../../model/world/commands.hpp" #include "../../model/world/idtableproxymodel.hpp" +#include "../../model/world/idtable.hpp" +#include "../../model/world/record.hpp" namespace CSVWorld { @@ -108,11 +110,16 @@ void CSVWorld::CommandDelegate::setEditLock (bool locked) void CSVWorld::Table::contextMenuEvent (QContextMenuEvent *event) { - QMenu menu (this); + QModelIndexList selectedRows = selectionModel()->selectedRows(); + + QMenu menu (this); if (mCreateAction) menu.addAction (mCreateAction); + if (selectedRows.size()>0) + menu.addAction (mRevertAction); + menu.exec (event->globalPos()); } @@ -120,9 +127,9 @@ CSVWorld::Table::Table (const CSMWorld::UniversalId& id, CSMWorld::Data& data, Q bool createAndDelete) : mUndoStack (undoStack), mCreateAction (0) { - QAbstractTableModel *model = data.getTableModel (id); + mModel = &dynamic_cast (*data.getTableModel (id)); - int columns = model->columnCount(); + int columns = mModel->columnCount(); for (int i=0; isetSourceModel (model); + mProxyModel = new CSMWorld::IdTableProxyModel (this); + mProxyModel->setSourceModel (mModel); - setModel (mModel); + setModel (mProxyModel); horizontalHeader()->setResizeMode (QHeaderView::Interactive); verticalHeader()->hide(); setSortingEnabled (true); @@ -149,6 +156,10 @@ CSVWorld::Table::Table (const CSMWorld::UniversalId& id, CSMWorld::Data& data, Q connect (mCreateAction, SIGNAL (triggered()), this, SLOT (createRecord())); addAction (mCreateAction); } + + mRevertAction = new QAction (tr ("Revert Record"), this); + connect (mRevertAction, SIGNAL (triggered()), this, SLOT (revertRecord())); + addAction (mRevertAction); } void CSVWorld::Table::setEditLock (bool locked) @@ -166,5 +177,35 @@ void CSVWorld::Table::createRecord() std::ostringstream stream; stream << "id" << index++; - mUndoStack.push (new CSMWorld::CreateCommand (*mModel, stream.str())); + mUndoStack.push (new CSMWorld::CreateCommand (*mProxyModel, stream.str())); +} + +void CSVWorld::Table::revertRecord() +{ + QModelIndexList selectedRows = selectionModel()->selectedRows(); + + std::vector revertableIds; + + for (QModelIndexList::const_iterator iter (selectedRows.begin()); iter!=selectedRows.end(); ++iter) + { + std::string id = mProxyModel->data (*iter).toString().toStdString(); + + CSMWorld::RecordBase::State state = + static_cast (mModel->data (mModel->getModelIndex (id, 1)).toInt()); + + if (state!=CSMWorld::RecordBase::State_BaseOnly) + revertableIds.push_back (id); + } + + if (revertableIds.size()>0) + { + if (revertableIds.size()>1) + mUndoStack.beginMacro (tr ("Revert multiple records")); + + for (std::vector::const_iterator iter (revertableIds.begin()); iter!=revertableIds.end(); ++iter) + mUndoStack.push (new CSMWorld::RevertCommand (*mModel, *iter)); + + if (revertableIds.size()>1) + mUndoStack.endMacro(); + } } \ No newline at end of file diff --git a/apps/opencs/view/world/table.hpp b/apps/opencs/view/world/table.hpp index f07f3ff24b..022d4f12a6 100644 --- a/apps/opencs/view/world/table.hpp +++ b/apps/opencs/view/world/table.hpp @@ -13,6 +13,7 @@ namespace CSMWorld class Data; class UniversalId; class IdTableProxyModel; + class IdTable; } namespace CSVWorld @@ -27,7 +28,9 @@ namespace CSVWorld std::vector mDelegates; QUndoStack& mUndoStack; QAction *mCreateAction; - CSMWorld::IdTableProxyModel *mModel; + QAction *mRevertAction; + CSMWorld::IdTableProxyModel *mProxyModel; + CSMWorld::IdTable *mModel; private: @@ -43,6 +46,8 @@ namespace CSVWorld private slots: void createRecord(); + + void revertRecord(); }; } From c12ee129f7019f5664f3a25b28e8f8961b5121bb Mon Sep 17 00:00:00 2001 From: Marc Zinnschlag Date: Thu, 6 Dec 2012 15:18:41 +0100 Subject: [PATCH 35/49] added delete command --- apps/opencs/model/world/commands.cpp | 33 +++++++++++++++++++++++++ apps/opencs/model/world/commands.hpp | 21 ++++++++++++++++ apps/opencs/model/world/record.hpp | 6 ++--- apps/opencs/view/world/table.cpp | 37 ++++++++++++++++++++++++++++ apps/opencs/view/world/table.hpp | 3 +++ 5 files changed, 97 insertions(+), 3 deletions(-) diff --git a/apps/opencs/model/world/commands.cpp b/apps/opencs/model/world/commands.cpp index 96a1b639cf..e22ecf9921 100644 --- a/apps/opencs/model/world/commands.cpp +++ b/apps/opencs/model/world/commands.cpp @@ -70,6 +70,39 @@ void CSMWorld::RevertCommand::redo() } void CSMWorld::RevertCommand::undo() +{ + mModel.setRecord (*mOld); +} + +CSMWorld::DeleteCommand::DeleteCommand (IdTable& model, const std::string& id, QUndoCommand *parent) +: QUndoCommand (parent), mModel (model), mId (id), mOld (0) +{ + setText (("Delete record " + id).c_str()); + + mOld = model.getRecord (id).clone(); +} + +CSMWorld::DeleteCommand::~DeleteCommand() +{ + delete mOld; +} + +void CSMWorld::DeleteCommand::redo() +{ + QModelIndex index = mModel.getModelIndex (mId, 1); + RecordBase::State state = static_cast (mModel.data (index).toInt()); + + if (state==RecordBase::State_ModifiedOnly) + { + mModel.removeRows (index.row(), 1); + } + else + { + mModel.setData (index, static_cast (RecordBase::State_Deleted)); + } +} + +void CSMWorld::DeleteCommand::undo() { mModel.setRecord (*mOld); } \ No newline at end of file diff --git a/apps/opencs/model/world/commands.hpp b/apps/opencs/model/world/commands.hpp index e916d05c9e..af419215dc 100644 --- a/apps/opencs/model/world/commands.hpp +++ b/apps/opencs/model/world/commands.hpp @@ -69,6 +69,27 @@ namespace CSMWorld virtual void undo(); }; + + class DeleteCommand : public QUndoCommand + { + IdTable& mModel; + std::string mId; + RecordBase *mOld; + + // not implemented + DeleteCommand (const DeleteCommand&); + DeleteCommand& operator= (const DeleteCommand&); + + public: + + DeleteCommand (IdTable& model, const std::string& id, QUndoCommand *parent = 0); + + virtual ~DeleteCommand(); + + virtual void redo(); + + virtual void undo(); + }; } #endif \ No newline at end of file diff --git a/apps/opencs/model/world/record.hpp b/apps/opencs/model/world/record.hpp index 3b83836aba..53bb7ea2ce 100644 --- a/apps/opencs/model/world/record.hpp +++ b/apps/opencs/model/world/record.hpp @@ -59,7 +59,7 @@ namespace CSMWorld template const ESXRecordT& Record::get() const { - if (isDeleted()) + if (mState==State_Erased) throw std::logic_error ("attempt to access a deleted record"); return mState==State_BaseOnly ? mBase : mModified; @@ -68,7 +68,7 @@ namespace CSMWorld template const ESXRecordT& Record::getBase() const { - if (isDeleted()) + if (mState==State_Erased) throw std::logic_error ("attempt to access a deleted record"); return mState==State_ModifiedOnly ? mModified : mBase; @@ -77,7 +77,7 @@ namespace CSMWorld template void Record::setModified (const ESXRecordT& modified) { - if (isDeleted()) + if (mState==State_Erased) throw std::logic_error ("attempt to modify a deleted record"); mModified = modified; diff --git a/apps/opencs/view/world/table.cpp b/apps/opencs/view/world/table.cpp index dafcb95c08..1595b6926a 100644 --- a/apps/opencs/view/world/table.cpp +++ b/apps/opencs/view/world/table.cpp @@ -120,6 +120,9 @@ void CSVWorld::CommandDelegate::setEditLock (bool locked) if (selectedRows.size()>0) menu.addAction (mRevertAction); + if (selectedRows.size()>0) + menu.addAction (mDeleteAction); + menu.exec (event->globalPos()); } @@ -160,6 +163,10 @@ CSVWorld::Table::Table (const CSMWorld::UniversalId& id, CSMWorld::Data& data, Q mRevertAction = new QAction (tr ("Revert Record"), this); connect (mRevertAction, SIGNAL (triggered()), this, SLOT (revertRecord())); addAction (mRevertAction); + + mDeleteAction = new QAction (tr ("Delete Record"), this); + connect (mDeleteAction, SIGNAL (triggered()), this, SLOT (deleteRecord())); + addAction (mDeleteAction); } void CSVWorld::Table::setEditLock (bool locked) @@ -205,6 +212,36 @@ void CSVWorld::Table::revertRecord() for (std::vector::const_iterator iter (revertableIds.begin()); iter!=revertableIds.end(); ++iter) mUndoStack.push (new CSMWorld::RevertCommand (*mModel, *iter)); + if (revertableIds.size()>1) + mUndoStack.endMacro(); + } +} + +void CSVWorld::Table::deleteRecord() +{ + QModelIndexList selectedRows = selectionModel()->selectedRows(); + + std::vector revertableIds; + + for (QModelIndexList::const_iterator iter (selectedRows.begin()); iter!=selectedRows.end(); ++iter) + { + std::string id = mProxyModel->data (*iter).toString().toStdString(); + + CSMWorld::RecordBase::State state = + static_cast (mModel->data (mModel->getModelIndex (id, 1)).toInt()); + + if (state!=CSMWorld::RecordBase::State_Deleted) + revertableIds.push_back (id); + } + + if (revertableIds.size()>0) + { + if (revertableIds.size()>1) + mUndoStack.beginMacro (tr ("Delete multiple records")); + + for (std::vector::const_iterator iter (revertableIds.begin()); iter!=revertableIds.end(); ++iter) + mUndoStack.push (new CSMWorld::DeleteCommand (*mModel, *iter)); + if (revertableIds.size()>1) mUndoStack.endMacro(); } diff --git a/apps/opencs/view/world/table.hpp b/apps/opencs/view/world/table.hpp index 022d4f12a6..555dc8e1fb 100644 --- a/apps/opencs/view/world/table.hpp +++ b/apps/opencs/view/world/table.hpp @@ -29,6 +29,7 @@ namespace CSVWorld QUndoStack& mUndoStack; QAction *mCreateAction; QAction *mRevertAction; + QAction *mDeleteAction; CSMWorld::IdTableProxyModel *mProxyModel; CSMWorld::IdTable *mModel; @@ -48,6 +49,8 @@ namespace CSVWorld void createRecord(); void revertRecord(); + + void deleteRecord(); }; } From 2b53cf6547f9611be8e4c6508865437a331f373c Mon Sep 17 00:00:00 2001 From: Marc Zinnschlag Date: Thu, 6 Dec 2012 15:25:31 +0100 Subject: [PATCH 36/49] do not list actions in the pop up menu that do not apply to any of the selected records --- apps/opencs/view/world/table.cpp | 85 ++++++++++++++++++-------------- apps/opencs/view/world/table.hpp | 5 ++ 2 files changed, 54 insertions(+), 36 deletions(-) diff --git a/apps/opencs/view/world/table.cpp b/apps/opencs/view/world/table.cpp index 1595b6926a..31f7d22eda 100644 --- a/apps/opencs/view/world/table.cpp +++ b/apps/opencs/view/world/table.cpp @@ -107,8 +107,7 @@ void CSVWorld::CommandDelegate::setEditLock (bool locked) mEditLock = locked; } - - void CSVWorld::Table::contextMenuEvent (QContextMenuEvent *event) +void CSVWorld::Table::contextMenuEvent (QContextMenuEvent *event) { QModelIndexList selectedRows = selectionModel()->selectedRows(); @@ -117,15 +116,55 @@ void CSVWorld::CommandDelegate::setEditLock (bool locked) if (mCreateAction) menu.addAction (mCreateAction); - if (selectedRows.size()>0) + if (listRevertableSelectedIds().size()>0) menu.addAction (mRevertAction); - if (selectedRows.size()>0) + if (listDeletableSelectedIds().size()>0) menu.addAction (mDeleteAction); menu.exec (event->globalPos()); } +std::vector CSVWorld::Table::listRevertableSelectedIds() const +{ + QModelIndexList selectedRows = selectionModel()->selectedRows(); + + std::vector revertableIds; + + for (QModelIndexList::const_iterator iter (selectedRows.begin()); iter!=selectedRows.end(); ++iter) + { + std::string id = mProxyModel->data (*iter).toString().toStdString(); + + CSMWorld::RecordBase::State state = + static_cast (mModel->data (mModel->getModelIndex (id, 1)).toInt()); + + if (state!=CSMWorld::RecordBase::State_BaseOnly) + revertableIds.push_back (id); + } + + return revertableIds; +} + +std::vector CSVWorld::Table::listDeletableSelectedIds() const +{ + QModelIndexList selectedRows = selectionModel()->selectedRows(); + + std::vector deletableIds; + + for (QModelIndexList::const_iterator iter (selectedRows.begin()); iter!=selectedRows.end(); ++iter) + { + std::string id = mProxyModel->data (*iter).toString().toStdString(); + + CSMWorld::RecordBase::State state = + static_cast (mModel->data (mModel->getModelIndex (id, 1)).toInt()); + + if (state!=CSMWorld::RecordBase::State_Deleted) + deletableIds.push_back (id); + } + + return deletableIds; +} + CSVWorld::Table::Table (const CSMWorld::UniversalId& id, CSMWorld::Data& data, QUndoStack& undoStack, bool createAndDelete) : mUndoStack (undoStack), mCreateAction (0) @@ -189,20 +228,7 @@ void CSVWorld::Table::createRecord() void CSVWorld::Table::revertRecord() { - QModelIndexList selectedRows = selectionModel()->selectedRows(); - - std::vector revertableIds; - - for (QModelIndexList::const_iterator iter (selectedRows.begin()); iter!=selectedRows.end(); ++iter) - { - std::string id = mProxyModel->data (*iter).toString().toStdString(); - - CSMWorld::RecordBase::State state = - static_cast (mModel->data (mModel->getModelIndex (id, 1)).toInt()); - - if (state!=CSMWorld::RecordBase::State_BaseOnly) - revertableIds.push_back (id); - } + std::vector revertableIds = listRevertableSelectedIds(); if (revertableIds.size()>0) { @@ -219,30 +245,17 @@ void CSVWorld::Table::revertRecord() void CSVWorld::Table::deleteRecord() { - QModelIndexList selectedRows = selectionModel()->selectedRows(); + std::vector deletableIds = listDeletableSelectedIds(); - std::vector revertableIds; - - for (QModelIndexList::const_iterator iter (selectedRows.begin()); iter!=selectedRows.end(); ++iter) - { - std::string id = mProxyModel->data (*iter).toString().toStdString(); - - CSMWorld::RecordBase::State state = - static_cast (mModel->data (mModel->getModelIndex (id, 1)).toInt()); - - if (state!=CSMWorld::RecordBase::State_Deleted) - revertableIds.push_back (id); - } - - if (revertableIds.size()>0) + if (deletableIds.size()>0) { - if (revertableIds.size()>1) + if (deletableIds.size()>1) mUndoStack.beginMacro (tr ("Delete multiple records")); - for (std::vector::const_iterator iter (revertableIds.begin()); iter!=revertableIds.end(); ++iter) + for (std::vector::const_iterator iter (deletableIds.begin()); iter!=deletableIds.end(); ++iter) mUndoStack.push (new CSMWorld::DeleteCommand (*mModel, *iter)); - if (revertableIds.size()>1) + if (deletableIds.size()>1) mUndoStack.endMacro(); } } \ No newline at end of file diff --git a/apps/opencs/view/world/table.hpp b/apps/opencs/view/world/table.hpp index 555dc8e1fb..264d2bc5c2 100644 --- a/apps/opencs/view/world/table.hpp +++ b/apps/opencs/view/world/table.hpp @@ -2,6 +2,7 @@ #define CSV_WORLD_TABLE_H #include +#include #include @@ -37,6 +38,10 @@ namespace CSVWorld void contextMenuEvent (QContextMenuEvent *event); + std::vector listRevertableSelectedIds() const; + + std::vector listDeletableSelectedIds() const; + public: Table (const CSMWorld::UniversalId& id, CSMWorld::Data& data, QUndoStack& undoStack, bool createAndDelete); From fdc7e93835defe57d5fca0e47515ec3aba01fda6 Mon Sep 17 00:00:00 2001 From: Marc Zinnschlag Date: Sat, 8 Dec 2012 11:59:13 +0100 Subject: [PATCH 37/49] preliminary multi-threaded verify implementation (does not actually perfom any document verification yet) --- apps/opencs/CMakeLists.txt | 4 +++ apps/opencs/model/doc/document.cpp | 42 ++++++++++++------------- apps/opencs/model/doc/document.hpp | 11 +++++-- apps/opencs/model/tools/tools.cpp | 46 ++++++++++++++++++++++++++++ apps/opencs/model/tools/tools.hpp | 45 +++++++++++++++++++++++++++ apps/opencs/model/tools/verifier.cpp | 33 ++++++++++++++++++++ apps/opencs/model/tools/verifier.hpp | 33 ++++++++++++++++++++ 7 files changed, 189 insertions(+), 25 deletions(-) create mode 100644 apps/opencs/model/tools/tools.cpp create mode 100644 apps/opencs/model/tools/tools.hpp create mode 100644 apps/opencs/model/tools/verifier.cpp create mode 100644 apps/opencs/model/tools/verifier.hpp diff --git a/apps/opencs/CMakeLists.txt b/apps/opencs/CMakeLists.txt index 5a9e1e99cc..ca235042a6 100644 --- a/apps/opencs/CMakeLists.txt +++ b/apps/opencs/CMakeLists.txt @@ -7,6 +7,8 @@ set (OPENCS_SRC model/world/universalid.cpp model/world/idcollection.cpp model/world/data.cpp model/world/idtable.cpp model/world/commands.cpp model/world/idtableproxymodel.cpp model/world/record.cpp + model/tools/tools.cpp model/tools/verifier.cpp + view/doc/viewmanager.cpp view/doc/view.cpp view/doc/operations.cpp view/doc/operation.cpp view/world/subview.cpp view/world/table.cpp view/world/tablesubview.cpp @@ -21,6 +23,8 @@ set (OPENCS_HDR model/world/idtable.hpp model/world/columns.hpp model/world/idtableproxymodel.hpp model/world/commands.hpp + model/tools/tools.hpp model/tools/verifier.hpp + view/doc/viewmanager.hpp view/doc/view.hpp view/doc/operations.hpp view/doc/operation.hpp view/world/subview.hpp view/world/table.hpp view/world/tablesubview.hpp diff --git a/apps/opencs/model/doc/document.cpp b/apps/opencs/model/doc/document.cpp index e8091b3e00..f85fde0382 100644 --- a/apps/opencs/model/doc/document.cpp +++ b/apps/opencs/model/doc/document.cpp @@ -7,13 +7,16 @@ CSMDoc::Document::Document (const std::string& name) connect (&mUndoStack, SIGNAL (cleanChanged (bool)), this, SLOT (modificationStateChanged (bool))); + connect (&mTools, SIGNAL (progress (int, int, int)), this, SLOT (progress (int, int, int))); + connect (&mTools, SIGNAL (done (int)), this, SLOT (operationDone (int))); + // dummy implementation -> remove when proper save is implemented. mSaveCount = 0; connect (&mSaveTimer, SIGNAL(timeout()), this, SLOT (saving())); // dummy implementation -> remove when proper verify is implemented. mVerifyCount = 0; - connect (&mVerifyTimer, SIGNAL(timeout()), this, SLOT (verifying())); + } QUndoStack& CSMDoc::Document::getUndoStack() @@ -53,23 +56,19 @@ void CSMDoc::Document::save() void CSMDoc::Document::verify() { mVerifyCount = 1; - mVerifyTimer.start (500); emit stateChanged (getState(), this); - emit progress (1, 20, State_Verifying, 1, this); + mTools.runVerifier(); } void CSMDoc::Document::abortOperation (int type) { + mTools.abortOperation (type); + if (type==State_Saving) { mSaveTimer.stop(); emit stateChanged (getState(), this); } - else if (type==State_Verifying) - { - mVerifyTimer.stop(); - emit stateChanged (getState(), this); - } } void CSMDoc::Document::modificationStateChanged (bool clean) @@ -77,6 +76,14 @@ void CSMDoc::Document::modificationStateChanged (bool clean) emit stateChanged (getState(), this); } +void CSMDoc::Document::operationDone (int type) +{ + if (type==State_Verifying) + mVerifyCount = 0; + + emit stateChanged (getState(), this); +} + void CSMDoc::Document::saving() { ++mSaveCount; @@ -92,20 +99,6 @@ void CSMDoc::Document::saving() } } -void CSMDoc::Document::verifying() -{ - ++mVerifyCount; - - emit progress (mVerifyCount, 20, State_Verifying, 1, this); - - if (mVerifyCount>19) - { - mVerifyCount = 0; - mVerifyTimer.stop(); - emit stateChanged (getState(), this); - } -} - const CSMWorld::Data& CSMDoc::Document::getData() const { return mData; @@ -114,4 +107,9 @@ const CSMWorld::Data& CSMDoc::Document::getData() const CSMWorld::Data& CSMDoc::Document::getData() { return mData; +} + +void CSMDoc::Document::progress (int current, int max, int type) +{ + emit progress (current, max, type, 1, this); } \ No newline at end of file diff --git a/apps/opencs/model/doc/document.hpp b/apps/opencs/model/doc/document.hpp index b414bf04d4..3fe20bc80e 100644 --- a/apps/opencs/model/doc/document.hpp +++ b/apps/opencs/model/doc/document.hpp @@ -9,6 +9,8 @@ #include "../world/data.hpp" +#include "../tools/tools.hpp" + namespace CSMDoc { class Document : public QObject @@ -32,12 +34,12 @@ namespace CSMDoc std::string mName; ///< \todo replace name with ESX list QUndoStack mUndoStack; CSMWorld::Data mData; + CSMTools::Tools mTools; int mSaveCount; ///< dummy implementation -> remove when proper save is implemented. QTimer mSaveTimer; ///< dummy implementation -> remove when proper save is implemented. int mVerifyCount; ///< dummy implementation -> remove when proper verify is implemented. - QTimer mVerifyTimer; ///< dummy implementation -> remove when proper verify is implemented. // not implemented Document (const Document&); @@ -75,11 +77,14 @@ namespace CSMDoc void modificationStateChanged (bool clean); + void operationDone (int type); + void saving(); ///< dummy implementation -> remove when proper save is implemented. - void verifying(); - ///< dummy implementation -> remove when proper verify is implemented. + public slots: + + void progress (int current, int max, int type); }; } diff --git a/apps/opencs/model/tools/tools.cpp b/apps/opencs/model/tools/tools.cpp new file mode 100644 index 0000000000..941a22cfff --- /dev/null +++ b/apps/opencs/model/tools/tools.cpp @@ -0,0 +1,46 @@ + +#include "tools.hpp" + +#include + +#include "verifier.hpp" + +#include "../doc/document.hpp" + +CSMTools::Verifier *CSMTools::Tools::getVerifier() +{ + if (!mVerifier) + { + mVerifier = new Verifier; + + connect (mVerifier, SIGNAL (progress (int, int, int)), this, SIGNAL (progress (int, int, int))); + connect (mVerifier, SIGNAL (finished()), this, SLOT (verifierDone())); + } + + return mVerifier; +} + +CSMTools::Tools::Tools() : mVerifier (0) +{ + +} + +CSMTools::Tools::~Tools() +{ + delete mVerifier; +} + +void CSMTools::Tools::runVerifier() +{ + getVerifier()->start(); +} + +void CSMTools::Tools::abortOperation (int type) +{ + +} + +void CSMTools::Tools::verifierDone() +{ + emit done (CSMDoc::Document::State_Verifying); +} \ No newline at end of file diff --git a/apps/opencs/model/tools/tools.hpp b/apps/opencs/model/tools/tools.hpp new file mode 100644 index 0000000000..65b1d16840 --- /dev/null +++ b/apps/opencs/model/tools/tools.hpp @@ -0,0 +1,45 @@ +#ifndef CSM_TOOLS_TOOLS_H +#define CSM_TOOLS_TOOLS_H + +#include + +namespace CSMTools +{ + class Verifier; + + class Tools : public QObject + { + Q_OBJECT + + Verifier *mVerifier; + + // not implemented + Tools (const Tools&); + Tools& operator= (const Tools&); + + Verifier *getVerifier(); + + public: + + Tools(); + + virtual ~Tools(); + + void runVerifier(); + + void abortOperation (int type); + ///< \attention The operation is not aborted immediately. + + private slots: + + void verifierDone(); + + signals: + + void progress (int current, int max, int type); + + void done (int type); + }; +} + +#endif diff --git a/apps/opencs/model/tools/verifier.cpp b/apps/opencs/model/tools/verifier.cpp new file mode 100644 index 0000000000..43a864289f --- /dev/null +++ b/apps/opencs/model/tools/verifier.cpp @@ -0,0 +1,33 @@ + +#include "verifier.hpp" + +#include + +#include "../doc/document.hpp" + +void CSMTools::Verifier::run() +{ + mStep = 0; + + QTimer timer; + + timer.connect (&timer, SIGNAL (timeout()), this, SLOT (verify())); + + timer.start (0); + + exec(); +} + +void CSMTools::Verifier::abort() +{ + exit(); +} + +void CSMTools::Verifier::verify() +{ + ++mStep; + emit progress (mStep, 1000, CSMDoc::Document::State_Verifying); + + if (mStep>=1000) + exit(); +} \ No newline at end of file diff --git a/apps/opencs/model/tools/verifier.hpp b/apps/opencs/model/tools/verifier.hpp new file mode 100644 index 0000000000..0e7fae19c4 --- /dev/null +++ b/apps/opencs/model/tools/verifier.hpp @@ -0,0 +1,33 @@ +#ifndef CSM_TOOLS_VERIFIER_H +#define CSM_TOOLS_VERIFIER_H + +#include + +namespace CSMTools +{ + class Verifier : public QThread + { + Q_OBJECT + + int mStep; + + public: + + virtual void run(); + + signals: + + void progress (int current, int max, int type); + + public slots: + + void abort(); + + private slots: + + void verify(); + }; + +} + +#endif From a2b4f431760d0fcae95c1774ae7f6913acb1b0af Mon Sep 17 00:00:00 2001 From: Marc Zinnschlag Date: Sat, 8 Dec 2012 14:44:03 +0100 Subject: [PATCH 38/49] moved document state enum to a separate file --- apps/opencs/CMakeLists.txt | 2 +- apps/opencs/model/doc/document.cpp | 5 ++--- apps/opencs/model/doc/document.hpp | 14 ++------------ apps/opencs/model/doc/state.hpp | 19 +++++++++++++++++++ apps/opencs/model/tools/tools.cpp | 4 ++-- apps/opencs/model/tools/verifier.cpp | 4 ++-- apps/opencs/view/doc/operation.cpp | 4 ++-- apps/opencs/view/doc/view.cpp | 12 ++++++------ 8 files changed, 36 insertions(+), 28 deletions(-) create mode 100644 apps/opencs/model/doc/state.hpp diff --git a/apps/opencs/CMakeLists.txt b/apps/opencs/CMakeLists.txt index ca235042a6..ce83e4ea60 100644 --- a/apps/opencs/CMakeLists.txt +++ b/apps/opencs/CMakeLists.txt @@ -17,7 +17,7 @@ set (OPENCS_SRC set (OPENCS_HDR editor.hpp - model/doc/documentmanager.hpp model/doc/document.hpp + model/doc/documentmanager.hpp model/doc/document.hpp model/doc/state.hpp model/world/universalid.hpp model/world/record.hpp model/world/idcollection.hpp model/world/data.hpp model/world/idtable.hpp model/world/columns.hpp model/world/idtableproxymodel.hpp diff --git a/apps/opencs/model/doc/document.cpp b/apps/opencs/model/doc/document.cpp index f85fde0382..2bd0f2e3e0 100644 --- a/apps/opencs/model/doc/document.cpp +++ b/apps/opencs/model/doc/document.cpp @@ -16,7 +16,6 @@ CSMDoc::Document::Document (const std::string& name) // dummy implementation -> remove when proper verify is implemented. mVerifyCount = 0; - } QUndoStack& CSMDoc::Document::getUndoStack() @@ -32,10 +31,10 @@ int CSMDoc::Document::getState() const state |= State_Modified; if (mSaveCount) - state |= State_Locked | State_Saving; + state |= State_Locked | State_Saving | State_Operation; if (mVerifyCount) - state |= State_Locked | State_Verifying; + state |= State_Locked | State_Verifying | State_Operation; return state; } diff --git a/apps/opencs/model/doc/document.hpp b/apps/opencs/model/doc/document.hpp index 3fe20bc80e..6226e31655 100644 --- a/apps/opencs/model/doc/document.hpp +++ b/apps/opencs/model/doc/document.hpp @@ -11,24 +11,14 @@ #include "../tools/tools.hpp" +#include "state.hpp" + namespace CSMDoc { class Document : public QObject { Q_OBJECT - public: - - enum State - { - State_Modified = 1, - State_Locked = 2, - State_Saving = 4, - State_Verifying = 8, - State_Compiling = 16, // not implemented yet - State_Searching = 32 // not implemented yet - }; - private: std::string mName; ///< \todo replace name with ESX list diff --git a/apps/opencs/model/doc/state.hpp b/apps/opencs/model/doc/state.hpp new file mode 100644 index 0000000000..04e6fae899 --- /dev/null +++ b/apps/opencs/model/doc/state.hpp @@ -0,0 +1,19 @@ +#ifndef CSM_DOC_STATE_H +#define CSM_DOC_STATE_H + +namespace CSMDoc +{ + enum State + { + State_Modified = 1, + State_Locked = 2, + State_Operation = 4, + + State_Saving = 8, + State_Verifying = 16, + State_Compiling = 32, // not implemented yet + State_Searching = 64 // not implemented yet + }; +} + +#endif diff --git a/apps/opencs/model/tools/tools.cpp b/apps/opencs/model/tools/tools.cpp index 941a22cfff..95375332cb 100644 --- a/apps/opencs/model/tools/tools.cpp +++ b/apps/opencs/model/tools/tools.cpp @@ -5,7 +5,7 @@ #include "verifier.hpp" -#include "../doc/document.hpp" +#include "../doc/state.hpp" CSMTools::Verifier *CSMTools::Tools::getVerifier() { @@ -42,5 +42,5 @@ void CSMTools::Tools::abortOperation (int type) void CSMTools::Tools::verifierDone() { - emit done (CSMDoc::Document::State_Verifying); + emit done (CSMDoc::State_Verifying); } \ No newline at end of file diff --git a/apps/opencs/model/tools/verifier.cpp b/apps/opencs/model/tools/verifier.cpp index 43a864289f..14cb692e98 100644 --- a/apps/opencs/model/tools/verifier.cpp +++ b/apps/opencs/model/tools/verifier.cpp @@ -3,7 +3,7 @@ #include -#include "../doc/document.hpp" +#include "../doc/state.hpp" void CSMTools::Verifier::run() { @@ -26,7 +26,7 @@ void CSMTools::Verifier::abort() void CSMTools::Verifier::verify() { ++mStep; - emit progress (mStep, 1000, CSMDoc::Document::State_Verifying); + emit progress (mStep, 1000, CSMDoc::State_Verifying); if (mStep>=1000) exit(); diff --git a/apps/opencs/view/doc/operation.cpp b/apps/opencs/view/doc/operation.cpp index 62f006be55..3f415da032 100644 --- a/apps/opencs/view/doc/operation.cpp +++ b/apps/opencs/view/doc/operation.cpp @@ -13,8 +13,8 @@ void CSVDoc::Operation::updateLabel (int threads) switch (mType) { - case CSMDoc::Document::State_Saving: name = "saving"; break; - case CSMDoc::Document::State_Verifying: name = "verifying"; break; + case CSMDoc::State_Saving: name = "saving"; break; + case CSMDoc::State_Verifying: name = "verifying"; break; } std::ostringstream stream; diff --git a/apps/opencs/view/doc/view.cpp b/apps/opencs/view/doc/view.cpp index 65ec103a21..539b149cb2 100644 --- a/apps/opencs/view/doc/view.cpp +++ b/apps/opencs/view/doc/view.cpp @@ -83,7 +83,7 @@ void CSVDoc::View::updateTitle() stream << mDocument->getName(); - if (mDocument->getState() & CSMDoc::Document::State_Modified) + if (mDocument->getState() & CSMDoc::State_Modified) stream << " *"; if (mViewTotal>1) @@ -94,7 +94,7 @@ void CSVDoc::View::updateTitle() void CSVDoc::View::updateActions() { - bool editing = !(mDocument->getState() & CSMDoc::Document::State_Locked); + bool editing = !(mDocument->getState() & CSMDoc::State_Locked); for (std::vector::iterator iter (mEditingActions.begin()); iter!=mEditingActions.end(); ++iter) (*iter)->setEnabled (editing); @@ -102,8 +102,8 @@ void CSVDoc::View::updateActions() mUndo->setEnabled (editing & mDocument->getUndoStack().canUndo()); mRedo->setEnabled (editing & mDocument->getUndoStack().canRedo()); - mSave->setEnabled (!(mDocument->getState() & CSMDoc::Document::State_Saving)); - mVerify->setEnabled (!(mDocument->getState() & CSMDoc::Document::State_Verifying)); + mSave->setEnabled (!(mDocument->getState() & CSMDoc::State_Saving)); + mVerify->setEnabled (!(mDocument->getState() & CSMDoc::State_Verifying)); } CSVDoc::View::View (ViewManager& viewManager, CSMDoc::Document *document, int totalViews) @@ -155,7 +155,7 @@ void CSVDoc::View::updateDocumentState() static const int operations[] = { - CSMDoc::Document::State_Saving, CSMDoc::Document::State_Verifying, + CSMDoc::State_Saving, CSMDoc::State_Verifying, -1 // end marker }; @@ -168,7 +168,7 @@ void CSVDoc::View::updateDocumentState() QList subViews = findChildren(); for (QList::iterator iter (subViews.begin()); iter!=subViews.end(); ++iter) - (*iter)->setEditLock (state & CSMDoc::Document::State_Locked); + (*iter)->setEditLock (state & CSMDoc::State_Locked); } void CSVDoc::View::updateProgress (int current, int max, int type, int threads) From af9b48f4d333839a66b96cf23e9faa62cbfaa7c8 Mon Sep 17 00:00:00 2001 From: Marc Zinnschlag Date: Sat, 8 Dec 2012 15:25:50 +0100 Subject: [PATCH 39/49] added operations base class --- apps/opencs/CMakeLists.txt | 4 +-- apps/opencs/model/tools/operation.cpp | 35 +++++++++++++++++++++++++++ apps/opencs/model/tools/operation.hpp | 35 +++++++++++++++++++++++++++ apps/opencs/model/tools/verifier.cpp | 30 ++--------------------- apps/opencs/model/tools/verifier.hpp | 22 +++-------------- 5 files changed, 77 insertions(+), 49 deletions(-) create mode 100644 apps/opencs/model/tools/operation.cpp create mode 100644 apps/opencs/model/tools/operation.hpp diff --git a/apps/opencs/CMakeLists.txt b/apps/opencs/CMakeLists.txt index ce83e4ea60..d2b87be516 100644 --- a/apps/opencs/CMakeLists.txt +++ b/apps/opencs/CMakeLists.txt @@ -7,7 +7,7 @@ set (OPENCS_SRC model/world/universalid.cpp model/world/idcollection.cpp model/world/data.cpp model/world/idtable.cpp model/world/commands.cpp model/world/idtableproxymodel.cpp model/world/record.cpp - model/tools/tools.cpp model/tools/verifier.cpp + model/tools/tools.cpp model/tools/operation.cpp model/tools/verifier.cpp view/doc/viewmanager.cpp view/doc/view.cpp view/doc/operations.cpp view/doc/operation.cpp @@ -23,7 +23,7 @@ set (OPENCS_HDR model/world/idtable.hpp model/world/columns.hpp model/world/idtableproxymodel.hpp model/world/commands.hpp - model/tools/tools.hpp model/tools/verifier.hpp + model/tools/tools.hpp model/tools/operation.hpp model/tools/verifier.hpp view/doc/viewmanager.hpp view/doc/view.hpp view/doc/operations.hpp view/doc/operation.hpp diff --git a/apps/opencs/model/tools/operation.cpp b/apps/opencs/model/tools/operation.cpp new file mode 100644 index 0000000000..ba58661688 --- /dev/null +++ b/apps/opencs/model/tools/operation.cpp @@ -0,0 +1,35 @@ + +#include "operation.hpp" + +#include + +#include "../doc/state.hpp" + +CSMTools::Operation::Operation (int type) : mType (type) {} + +void CSMTools::Operation::run() +{ + mStep = 0; + + QTimer timer; + + timer.connect (&timer, SIGNAL (timeout()), this, SLOT (verify())); + + timer.start (0); + + exec(); +} + +void CSMTools::Operation::abort() +{ + exit(); +} + +void CSMTools::Operation::verify() +{ + ++mStep; + emit progress (mStep, 1000, mType); + + if (mStep>=1000) + exit(); +} \ No newline at end of file diff --git a/apps/opencs/model/tools/operation.hpp b/apps/opencs/model/tools/operation.hpp new file mode 100644 index 0000000000..b75e2898ff --- /dev/null +++ b/apps/opencs/model/tools/operation.hpp @@ -0,0 +1,35 @@ +#ifndef CSM_TOOLS_OPERATION_H +#define CSM_TOOLS_OPERATION_H + +#include + +namespace CSMTools +{ + class Operation : public QThread + { + Q_OBJECT + + int mType; + int mStep; + + public: + + Operation (int type); + + virtual void run(); + + signals: + + void progress (int current, int max, int type); + + public slots: + + void abort(); + + private slots: + + void verify(); + }; +} + +#endif \ No newline at end of file diff --git a/apps/opencs/model/tools/verifier.cpp b/apps/opencs/model/tools/verifier.cpp index 14cb692e98..9c00d4ea7e 100644 --- a/apps/opencs/model/tools/verifier.cpp +++ b/apps/opencs/model/tools/verifier.cpp @@ -1,33 +1,7 @@ #include "verifier.hpp" -#include - #include "../doc/state.hpp" -void CSMTools::Verifier::run() -{ - mStep = 0; - - QTimer timer; - - timer.connect (&timer, SIGNAL (timeout()), this, SLOT (verify())); - - timer.start (0); - - exec(); -} - -void CSMTools::Verifier::abort() -{ - exit(); -} - -void CSMTools::Verifier::verify() -{ - ++mStep; - emit progress (mStep, 1000, CSMDoc::State_Verifying); - - if (mStep>=1000) - exit(); -} \ No newline at end of file +CSMTools::Verifier::Verifier() : Operation (CSMDoc::State_Verifying) +{} diff --git a/apps/opencs/model/tools/verifier.hpp b/apps/opencs/model/tools/verifier.hpp index 0e7fae19c4..054f87169c 100644 --- a/apps/opencs/model/tools/verifier.hpp +++ b/apps/opencs/model/tools/verifier.hpp @@ -1,33 +1,17 @@ #ifndef CSM_TOOLS_VERIFIER_H #define CSM_TOOLS_VERIFIER_H -#include +#include "operation.hpp" namespace CSMTools { - class Verifier : public QThread + class Verifier : public Operation { - Q_OBJECT - - int mStep; - public: - virtual void run(); - - signals: - - void progress (int current, int max, int type); + Verifier(); - public slots: - - void abort(); - - private slots: - - void verify(); }; - } #endif From 8b7f342641b38c740cb78bc0f137b22f2f94ba6e Mon Sep 17 00:00:00 2001 From: Marc Zinnschlag Date: Sat, 8 Dec 2012 17:00:58 +0100 Subject: [PATCH 40/49] removed last remains of old verify implementation --- apps/opencs/model/doc/document.cpp | 13 +++--------- apps/opencs/model/doc/document.hpp | 2 -- apps/opencs/model/tools/tools.cpp | 34 ++++++++++++++++++++++++++++++ apps/opencs/model/tools/tools.hpp | 9 ++++++++ 4 files changed, 46 insertions(+), 12 deletions(-) diff --git a/apps/opencs/model/doc/document.cpp b/apps/opencs/model/doc/document.cpp index 2bd0f2e3e0..d8ad5ff01d 100644 --- a/apps/opencs/model/doc/document.cpp +++ b/apps/opencs/model/doc/document.cpp @@ -13,9 +13,6 @@ CSMDoc::Document::Document (const std::string& name) // dummy implementation -> remove when proper save is implemented. mSaveCount = 0; connect (&mSaveTimer, SIGNAL(timeout()), this, SLOT (saving())); - - // dummy implementation -> remove when proper verify is implemented. - mVerifyCount = 0; } QUndoStack& CSMDoc::Document::getUndoStack() @@ -33,8 +30,8 @@ int CSMDoc::Document::getState() const if (mSaveCount) state |= State_Locked | State_Saving | State_Operation; - if (mVerifyCount) - state |= State_Locked | State_Verifying | State_Operation; + if (int operations = mTools.getRunningOperations()) + state |= State_Locked | State_Operation | operations; return state; } @@ -54,9 +51,8 @@ void CSMDoc::Document::save() void CSMDoc::Document::verify() { - mVerifyCount = 1; - emit stateChanged (getState(), this); mTools.runVerifier(); + emit stateChanged (getState(), this); } void CSMDoc::Document::abortOperation (int type) @@ -77,9 +73,6 @@ void CSMDoc::Document::modificationStateChanged (bool clean) void CSMDoc::Document::operationDone (int type) { - if (type==State_Verifying) - mVerifyCount = 0; - emit stateChanged (getState(), this); } diff --git a/apps/opencs/model/doc/document.hpp b/apps/opencs/model/doc/document.hpp index 6226e31655..40f8c0ea11 100644 --- a/apps/opencs/model/doc/document.hpp +++ b/apps/opencs/model/doc/document.hpp @@ -29,8 +29,6 @@ namespace CSMDoc int mSaveCount; ///< dummy implementation -> remove when proper save is implemented. QTimer mSaveTimer; ///< dummy implementation -> remove when proper save is implemented. - int mVerifyCount; ///< dummy implementation -> remove when proper verify is implemented. - // not implemented Document (const Document&); Document& operator= (const Document&); diff --git a/apps/opencs/model/tools/tools.cpp b/apps/opencs/model/tools/tools.cpp index 95375332cb..608244a3ca 100644 --- a/apps/opencs/model/tools/tools.cpp +++ b/apps/opencs/model/tools/tools.cpp @@ -7,6 +7,21 @@ #include "../doc/state.hpp" +CSMTools::Operation *CSMTools::Tools::get (int type) +{ + switch (type) + { + case CSMDoc::State_Verifying: return mVerifier; + } + + return 0; +} + +const CSMTools::Operation *CSMTools::Tools::get (int type) const +{ + return const_cast (this)->get (type); +} + CSMTools::Verifier *CSMTools::Tools::getVerifier() { if (!mVerifier) @@ -37,7 +52,26 @@ void CSMTools::Tools::runVerifier() void CSMTools::Tools::abortOperation (int type) { + if (Operation *operation = get (type)) + operation->abort(); +} + +int CSMTools::Tools::getRunningOperations() const +{ + static const int sOperations[] = + { + CSMDoc::State_Verifying, + -1 + }; + + int result = 0; + + for (int i=0; sOperations[i]!=-1; ++i) + if (const Operation *operation = get (sOperations[i])) + if (operation->isRunning()) + result |= sOperations[i]; + return result; } void CSMTools::Tools::verifierDone() diff --git a/apps/opencs/model/tools/tools.hpp b/apps/opencs/model/tools/tools.hpp index 65b1d16840..ab18637387 100644 --- a/apps/opencs/model/tools/tools.hpp +++ b/apps/opencs/model/tools/tools.hpp @@ -6,6 +6,7 @@ namespace CSMTools { class Verifier; + class Operation; class Tools : public QObject { @@ -19,6 +20,12 @@ namespace CSMTools Verifier *getVerifier(); + Operation *get (int type); + ///< Returns a 0-pointer, if operation hasn't been used yet. + + const Operation *get (int type) const; + ///< Returns a 0-pointer, if operation hasn't been used yet. + public: Tools(); @@ -30,6 +37,8 @@ namespace CSMTools void abortOperation (int type); ///< \attention The operation is not aborted immediately. + int getRunningOperations() const; + private slots: void verifierDone(); From 6c18be39f0e10b43163de194fe93d0714df40eef Mon Sep 17 00:00:00 2001 From: Marc Zinnschlag Date: Sat, 8 Dec 2012 17:53:45 +0100 Subject: [PATCH 41/49] added stage class --- apps/opencs/CMakeLists.txt | 4 +-- apps/opencs/model/tools/operation.cpp | 49 ++++++++++++++++++++++++--- apps/opencs/model/tools/operation.hpp | 19 ++++++++++- apps/opencs/model/tools/stage.cpp | 4 +++ apps/opencs/model/tools/stage.hpp | 20 +++++++++++ 5 files changed, 89 insertions(+), 7 deletions(-) create mode 100644 apps/opencs/model/tools/stage.cpp create mode 100644 apps/opencs/model/tools/stage.hpp diff --git a/apps/opencs/CMakeLists.txt b/apps/opencs/CMakeLists.txt index d2b87be516..381ce51cfe 100644 --- a/apps/opencs/CMakeLists.txt +++ b/apps/opencs/CMakeLists.txt @@ -7,7 +7,7 @@ set (OPENCS_SRC model/world/universalid.cpp model/world/idcollection.cpp model/world/data.cpp model/world/idtable.cpp model/world/commands.cpp model/world/idtableproxymodel.cpp model/world/record.cpp - model/tools/tools.cpp model/tools/operation.cpp model/tools/verifier.cpp + model/tools/tools.cpp model/tools/operation.cpp model/tools/stage.cpp model/tools/verifier.cpp view/doc/viewmanager.cpp view/doc/view.cpp view/doc/operations.cpp view/doc/operation.cpp @@ -23,7 +23,7 @@ set (OPENCS_HDR model/world/idtable.hpp model/world/columns.hpp model/world/idtableproxymodel.hpp model/world/commands.hpp - model/tools/tools.hpp model/tools/operation.hpp model/tools/verifier.hpp + model/tools/tools.hpp model/tools/operation.hpp model/tools/stage.hpp model/tools/verifier.hpp view/doc/viewmanager.hpp view/doc/view.hpp view/doc/operations.hpp view/doc/operation.hpp diff --git a/apps/opencs/model/tools/operation.cpp b/apps/opencs/model/tools/operation.cpp index ba58661688..12c4a8108c 100644 --- a/apps/opencs/model/tools/operation.cpp +++ b/apps/opencs/model/tools/operation.cpp @@ -5,11 +5,33 @@ #include "../doc/state.hpp" +#include "stage.hpp" + +void CSMTools::Operation::prepareStages() +{ + mCurrentStage = mStages.begin(); + mCurrentStep = 0; + mCurrentStepTotal = 0; + mTotalSteps = 0; + + for (std::vector >::iterator iter (mStages.begin()); iter!=mStages.end(); ++iter) + { + iter->second = mTotalSteps; + mTotalSteps += iter->first->setup(); + } +} + CSMTools::Operation::Operation (int type) : mType (type) {} +CSMTools::Operation::~Operation() +{ + for (std::vector >::iterator iter (mStages.begin()); iter!=mStages.end(); ++iter) + delete iter->first; +} + void CSMTools::Operation::run() { - mStep = 0; + prepareStages(); QTimer timer; @@ -20,6 +42,11 @@ void CSMTools::Operation::run() exec(); } +void CSMTools::Operation::appendStage (Stage *stage) +{ + mStages.push_back (std::make_pair (stage, 0)); +} + void CSMTools::Operation::abort() { exit(); @@ -27,9 +54,23 @@ void CSMTools::Operation::abort() void CSMTools::Operation::verify() { - ++mStep; - emit progress (mStep, 1000, mType); + while (mCurrentStage!=mStages.end()) + { + if (mCurrentStep>=mCurrentStage->second) + { + mCurrentStep = 0; + ++mCurrentStage; + } + else + { + mCurrentStage->first->perform (mCurrentStep++); + ++mCurrentStepTotal; + break; + } + } + + emit progress (mCurrentStepTotal, mTotalSteps ? mTotalSteps : 1, mType); - if (mStep>=1000) + if (mCurrentStage==mStages.end()) exit(); } \ No newline at end of file diff --git a/apps/opencs/model/tools/operation.hpp b/apps/opencs/model/tools/operation.hpp index b75e2898ff..72419e00a3 100644 --- a/apps/opencs/model/tools/operation.hpp +++ b/apps/opencs/model/tools/operation.hpp @@ -1,23 +1,40 @@ #ifndef CSM_TOOLS_OPERATION_H #define CSM_TOOLS_OPERATION_H +#include + #include namespace CSMTools { + class Stage; + class Operation : public QThread { Q_OBJECT int mType; - int mStep; + std::vector > mStages; // stage, number of steps + std::vector >::iterator mCurrentStage; + int mCurrentStep; + int mCurrentStepTotal; + int mTotalSteps; + + void prepareStages(); public: Operation (int type); + virtual ~Operation(); + virtual void run(); + void appendStage (Stage *stage); + ///< The ownership of \a stage is transferred to *this. + /// + /// \attention Do no call this function while this Operation is running. + signals: void progress (int current, int max, int type); diff --git a/apps/opencs/model/tools/stage.cpp b/apps/opencs/model/tools/stage.cpp new file mode 100644 index 0000000000..6f4567e579 --- /dev/null +++ b/apps/opencs/model/tools/stage.cpp @@ -0,0 +1,4 @@ + +#include "stage.hpp" + +CSMTools::Stage::~Stage() {} \ No newline at end of file diff --git a/apps/opencs/model/tools/stage.hpp b/apps/opencs/model/tools/stage.hpp new file mode 100644 index 0000000000..9125594104 --- /dev/null +++ b/apps/opencs/model/tools/stage.hpp @@ -0,0 +1,20 @@ +#ifndef CSM_TOOLS_STAGE_H +#define CSM_TOOLS_STAGE_H + +namespace CSMTools +{ + class Stage + { + public: + + virtual ~Stage(); + + virtual int setup() = 0; + ///< \return number of steps + + virtual void perform (int stage) = 0; + }; +} + +#endif + From 89b449733128f2967cecfe47c7c15d1890e023de Mon Sep 17 00:00:00 2001 From: Marc Zinnschlag Date: Sat, 8 Dec 2012 18:15:00 +0100 Subject: [PATCH 42/49] added missing edit locks for create/revert/delete --- apps/opencs/view/world/table.cpp | 76 +++++++++++++++++++------------- apps/opencs/view/world/table.hpp | 1 + 2 files changed, 47 insertions(+), 30 deletions(-) diff --git a/apps/opencs/view/world/table.cpp b/apps/opencs/view/world/table.cpp index 31f7d22eda..593dc85633 100644 --- a/apps/opencs/view/world/table.cpp +++ b/apps/opencs/view/world/table.cpp @@ -113,14 +113,19 @@ void CSVWorld::Table::contextMenuEvent (QContextMenuEvent *event) QMenu menu (this); - if (mCreateAction) - menu.addAction (mCreateAction); + /// \todo add menu items for select all and clear selection - if (listRevertableSelectedIds().size()>0) - menu.addAction (mRevertAction); + if (!mEditLock) + { + if (mCreateAction) + menu.addAction (mCreateAction); - if (listDeletableSelectedIds().size()>0) - menu.addAction (mDeleteAction); + if (listRevertableSelectedIds().size()>0) + menu.addAction (mRevertAction); + + if (listDeletableSelectedIds().size()>0) + menu.addAction (mDeleteAction); + } menu.exec (event->globalPos()); } @@ -167,7 +172,7 @@ std::vector CSVWorld::Table::listDeletableSelectedIds() const CSVWorld::Table::Table (const CSMWorld::UniversalId& id, CSMWorld::Data& data, QUndoStack& undoStack, bool createAndDelete) -: mUndoStack (undoStack), mCreateAction (0) +: mUndoStack (undoStack), mCreateAction (0), mEditLock (false) { mModel = &dynamic_cast (*data.getTableModel (id)); @@ -212,50 +217,61 @@ void CSVWorld::Table::setEditLock (bool locked) { for (std::vector::iterator iter (mDelegates.begin()); iter!=mDelegates.end(); ++iter) (*iter)->setEditLock (locked); + + mEditLock = locked; } #include /// \todo remove void CSVWorld::Table::createRecord() { - /// \todo ask the user for an ID instead. - static int index = 0; + if (!mEditLock) + { + /// \todo ask the user for an ID instead. + static int index = 0; - std::ostringstream stream; - stream << "id" << index++; + std::ostringstream stream; + stream << "id" << index++; - mUndoStack.push (new CSMWorld::CreateCommand (*mProxyModel, stream.str())); + mUndoStack.push (new CSMWorld::CreateCommand (*mProxyModel, stream.str())); + } } void CSVWorld::Table::revertRecord() { - std::vector revertableIds = listRevertableSelectedIds(); - - if (revertableIds.size()>0) + if (!mEditLock) { - if (revertableIds.size()>1) - mUndoStack.beginMacro (tr ("Revert multiple records")); + std::vector revertableIds = listRevertableSelectedIds(); + + if (revertableIds.size()>0) + { + if (revertableIds.size()>1) + mUndoStack.beginMacro (tr ("Revert multiple records")); - for (std::vector::const_iterator iter (revertableIds.begin()); iter!=revertableIds.end(); ++iter) - mUndoStack.push (new CSMWorld::RevertCommand (*mModel, *iter)); + for (std::vector::const_iterator iter (revertableIds.begin()); iter!=revertableIds.end(); ++iter) + mUndoStack.push (new CSMWorld::RevertCommand (*mModel, *iter)); - if (revertableIds.size()>1) - mUndoStack.endMacro(); + if (revertableIds.size()>1) + mUndoStack.endMacro(); + } } } void CSVWorld::Table::deleteRecord() { - std::vector deletableIds = listDeletableSelectedIds(); - - if (deletableIds.size()>0) + if (!mEditLock) { - if (deletableIds.size()>1) - mUndoStack.beginMacro (tr ("Delete multiple records")); + std::vector deletableIds = listDeletableSelectedIds(); + + if (deletableIds.size()>0) + { + if (deletableIds.size()>1) + mUndoStack.beginMacro (tr ("Delete multiple records")); - for (std::vector::const_iterator iter (deletableIds.begin()); iter!=deletableIds.end(); ++iter) - mUndoStack.push (new CSMWorld::DeleteCommand (*mModel, *iter)); + for (std::vector::const_iterator iter (deletableIds.begin()); iter!=deletableIds.end(); ++iter) + mUndoStack.push (new CSMWorld::DeleteCommand (*mModel, *iter)); - if (deletableIds.size()>1) - mUndoStack.endMacro(); + if (deletableIds.size()>1) + mUndoStack.endMacro(); + } } } \ No newline at end of file diff --git a/apps/opencs/view/world/table.hpp b/apps/opencs/view/world/table.hpp index 264d2bc5c2..b58ba8328a 100644 --- a/apps/opencs/view/world/table.hpp +++ b/apps/opencs/view/world/table.hpp @@ -33,6 +33,7 @@ namespace CSVWorld QAction *mDeleteAction; CSMWorld::IdTableProxyModel *mProxyModel; CSMWorld::IdTable *mModel; + bool mEditLock; private: From 72623652e46dd5ce94b4e1b4f2593cb889db23b1 Mon Sep 17 00:00:00 2001 From: Marc Zinnschlag Date: Sat, 8 Dec 2012 18:38:36 +0100 Subject: [PATCH 43/49] addded messages interface for operations/stages --- apps/opencs/model/tools/operation.cpp | 10 +++++++++- apps/opencs/model/tools/operation.hpp | 2 ++ apps/opencs/model/tools/stage.hpp | 6 +++++- apps/opencs/model/tools/tools.cpp | 10 ++++++++++ apps/opencs/model/tools/tools.hpp | 2 ++ 5 files changed, 28 insertions(+), 2 deletions(-) diff --git a/apps/opencs/model/tools/operation.cpp b/apps/opencs/model/tools/operation.cpp index 12c4a8108c..b68f79ca45 100644 --- a/apps/opencs/model/tools/operation.cpp +++ b/apps/opencs/model/tools/operation.cpp @@ -1,6 +1,9 @@ #include "operation.hpp" +#include +#include + #include #include "../doc/state.hpp" @@ -54,6 +57,8 @@ void CSMTools::Operation::abort() void CSMTools::Operation::verify() { + std::vector messages; + while (mCurrentStage!=mStages.end()) { if (mCurrentStep>=mCurrentStage->second) @@ -63,7 +68,7 @@ void CSMTools::Operation::verify() } else { - mCurrentStage->first->perform (mCurrentStep++); + mCurrentStage->first->perform (mCurrentStep++, messages); ++mCurrentStepTotal; break; } @@ -71,6 +76,9 @@ void CSMTools::Operation::verify() emit progress (mCurrentStepTotal, mTotalSteps ? mTotalSteps : 1, mType); + for (std::vector::const_iterator iter (messages.begin()); iter!=messages.end(); ++iter) + emit reportMessage (iter->c_str(), mType); + if (mCurrentStage==mStages.end()) exit(); } \ No newline at end of file diff --git a/apps/opencs/model/tools/operation.hpp b/apps/opencs/model/tools/operation.hpp index 72419e00a3..4731c58fa8 100644 --- a/apps/opencs/model/tools/operation.hpp +++ b/apps/opencs/model/tools/operation.hpp @@ -39,6 +39,8 @@ namespace CSMTools void progress (int current, int max, int type); + void reportMessage (const QString& message, int type); + public slots: void abort(); diff --git a/apps/opencs/model/tools/stage.hpp b/apps/opencs/model/tools/stage.hpp index 9125594104..1ad61960ae 100644 --- a/apps/opencs/model/tools/stage.hpp +++ b/apps/opencs/model/tools/stage.hpp @@ -1,6 +1,9 @@ #ifndef CSM_TOOLS_STAGE_H #define CSM_TOOLS_STAGE_H +#include +#include + namespace CSMTools { class Stage @@ -12,7 +15,8 @@ namespace CSMTools virtual int setup() = 0; ///< \return number of steps - virtual void perform (int stage) = 0; + virtual void perform (int stage, std::vector& messages) = 0; + ///< Messages resulting from this tage will be appended to \a messages. }; } diff --git a/apps/opencs/model/tools/tools.cpp b/apps/opencs/model/tools/tools.cpp index 608244a3ca..8293b72916 100644 --- a/apps/opencs/model/tools/tools.cpp +++ b/apps/opencs/model/tools/tools.cpp @@ -30,6 +30,8 @@ CSMTools::Verifier *CSMTools::Tools::getVerifier() connect (mVerifier, SIGNAL (progress (int, int, int)), this, SIGNAL (progress (int, int, int))); connect (mVerifier, SIGNAL (finished()), this, SLOT (verifierDone())); + connect (mVerifier, SIGNAL (reportMessage (const QString&, int)), + this, SLOT (verifierMessage (const QString&, int))); } return mVerifier; @@ -77,4 +79,12 @@ int CSMTools::Tools::getRunningOperations() const void CSMTools::Tools::verifierDone() { emit done (CSMDoc::State_Verifying); +} + +#include +void CSMTools::Tools::verifierMessage (const QString& message, int type) +{ + /// \todo store it in a result model instead + + std::cout << message.toStdString() << std::endl; } \ No newline at end of file diff --git a/apps/opencs/model/tools/tools.hpp b/apps/opencs/model/tools/tools.hpp index ab18637387..04140bb91f 100644 --- a/apps/opencs/model/tools/tools.hpp +++ b/apps/opencs/model/tools/tools.hpp @@ -43,6 +43,8 @@ namespace CSMTools void verifierDone(); + void verifierMessage (const QString& message, int type); + signals: void progress (int current, int max, int type); From 9fe7ff969047df565bae6b39045b6fb52fcf8b50 Mon Sep 17 00:00:00 2001 From: Marc Zinnschlag Date: Sat, 8 Dec 2012 23:27:59 +0100 Subject: [PATCH 44/49] added mandatory ID check stage --- apps/opencs/CMakeLists.txt | 2 ++ apps/opencs/model/doc/document.cpp | 1 + apps/opencs/model/doc/document.hpp | 5 ++- apps/opencs/model/tools/mandatoryid.cpp | 21 +++++++++++ apps/opencs/model/tools/mandatoryid.hpp | 38 ++++++++++++++++++++ apps/opencs/model/tools/operation.cpp | 4 +-- apps/opencs/model/tools/stage.hpp | 12 +++---- apps/opencs/model/tools/tools.cpp | 19 +++++++++- apps/opencs/model/tools/tools.hpp | 8 ++++- apps/opencs/model/world/universalid.cpp | 48 ++++++++++++++++++++++++- apps/opencs/model/world/universalid.hpp | 2 ++ 11 files changed, 148 insertions(+), 12 deletions(-) create mode 100644 apps/opencs/model/tools/mandatoryid.cpp create mode 100644 apps/opencs/model/tools/mandatoryid.hpp diff --git a/apps/opencs/CMakeLists.txt b/apps/opencs/CMakeLists.txt index 381ce51cfe..bad1e13762 100644 --- a/apps/opencs/CMakeLists.txt +++ b/apps/opencs/CMakeLists.txt @@ -8,6 +8,7 @@ set (OPENCS_SRC model/world/commands.cpp model/world/idtableproxymodel.cpp model/world/record.cpp model/tools/tools.cpp model/tools/operation.cpp model/tools/stage.cpp model/tools/verifier.cpp + model/tools/mandatoryid.cpp view/doc/viewmanager.cpp view/doc/view.cpp view/doc/operations.cpp view/doc/operation.cpp @@ -24,6 +25,7 @@ set (OPENCS_HDR model/world/commands.hpp model/tools/tools.hpp model/tools/operation.hpp model/tools/stage.hpp model/tools/verifier.hpp + model/tools/mandatoryid.hpp view/doc/viewmanager.hpp view/doc/view.hpp view/doc/operations.hpp view/doc/operation.hpp diff --git a/apps/opencs/model/doc/document.cpp b/apps/opencs/model/doc/document.cpp index d8ad5ff01d..f03344e08a 100644 --- a/apps/opencs/model/doc/document.cpp +++ b/apps/opencs/model/doc/document.cpp @@ -2,6 +2,7 @@ #include "document.hpp" CSMDoc::Document::Document (const std::string& name) +: mTools (mData) { mName = name; ///< \todo replace with ESX list diff --git a/apps/opencs/model/doc/document.hpp b/apps/opencs/model/doc/document.hpp index 40f8c0ea11..f9d0a232ce 100644 --- a/apps/opencs/model/doc/document.hpp +++ b/apps/opencs/model/doc/document.hpp @@ -22,10 +22,13 @@ namespace CSMDoc private: std::string mName; ///< \todo replace name with ESX list - QUndoStack mUndoStack; CSMWorld::Data mData; CSMTools::Tools mTools; + // It is important that the undo stack is declared last, because on desctruction it fires a signal, that is connected to a slot, that is + // using other member variables. Unfortunately this connection is cut only in the QObject destructor, which is way too late. + QUndoStack mUndoStack; + int mSaveCount; ///< dummy implementation -> remove when proper save is implemented. QTimer mSaveTimer; ///< dummy implementation -> remove when proper save is implemented. diff --git a/apps/opencs/model/tools/mandatoryid.cpp b/apps/opencs/model/tools/mandatoryid.cpp new file mode 100644 index 0000000000..87ac77e675 --- /dev/null +++ b/apps/opencs/model/tools/mandatoryid.cpp @@ -0,0 +1,21 @@ + +#include "mandatoryid.hpp" + +#include "../world/idcollection.hpp" + +CSMTools::MandatoryIdStage::MandatoryIdStage (const CSMWorld::IdCollectionBase& idCollection, + const CSMWorld::UniversalId& collectionId, const std::vector& ids) +: mIdCollection (idCollection), mCollectionId (collectionId), mIds (ids) +{} + +int CSMTools::MandatoryIdStage::setup() +{ + return mIds.size(); +} + +void CSMTools::MandatoryIdStage::perform (int stage, std::vector& messages) +{ + if (mIdCollection.searchId (mIds.at (stage))==-1 || + mIdCollection.getRecord (mIds.at (stage)).isDeleted()) + messages.push_back (mCollectionId.toString() + " Missing mandatory record: " + mIds.at (stage)); +} \ No newline at end of file diff --git a/apps/opencs/model/tools/mandatoryid.hpp b/apps/opencs/model/tools/mandatoryid.hpp new file mode 100644 index 0000000000..14fcec2048 --- /dev/null +++ b/apps/opencs/model/tools/mandatoryid.hpp @@ -0,0 +1,38 @@ +#ifndef CSM_TOOLS_MANDATORYID_H +#define CSM_TOOLS_MANDATORYID_H + +#include +#include + +#include "../world/universalid.hpp" + +#include "stage.hpp" + +namespace CSMWorld +{ + class IdCollectionBase; +} + +namespace CSMTools +{ + /// \brief Verify stage: make sure that records with specific IDs exist. + class MandatoryIdStage : public Stage + { + const CSMWorld::IdCollectionBase& mIdCollection; + CSMWorld::UniversalId mCollectionId; + std::vector mIds; + + public: + + MandatoryIdStage (const CSMWorld::IdCollectionBase& idCollection, const CSMWorld::UniversalId& collectionId, + const std::vector& ids); + + virtual int setup(); + ///< \return number of steps + + virtual void perform (int stage, std::vector& messages); + ///< Messages resulting from this tage will be appended to \a messages. + }; +} + +#endif diff --git a/apps/opencs/model/tools/operation.cpp b/apps/opencs/model/tools/operation.cpp index b68f79ca45..71761cdaea 100644 --- a/apps/opencs/model/tools/operation.cpp +++ b/apps/opencs/model/tools/operation.cpp @@ -19,8 +19,8 @@ void CSMTools::Operation::prepareStages() for (std::vector >::iterator iter (mStages.begin()); iter!=mStages.end(); ++iter) { - iter->second = mTotalSteps; - mTotalSteps += iter->first->setup(); + iter->second = iter->first->setup(); + mTotalSteps += iter->second; } } diff --git a/apps/opencs/model/tools/stage.hpp b/apps/opencs/model/tools/stage.hpp index 1ad61960ae..3020936f32 100644 --- a/apps/opencs/model/tools/stage.hpp +++ b/apps/opencs/model/tools/stage.hpp @@ -8,15 +8,15 @@ namespace CSMTools { class Stage { - public: + public: - virtual ~Stage(); + virtual ~Stage(); - virtual int setup() = 0; - ///< \return number of steps + virtual int setup() = 0; + ///< \return number of steps - virtual void perform (int stage, std::vector& messages) = 0; - ///< Messages resulting from this tage will be appended to \a messages. + virtual void perform (int stage, std::vector& messages) = 0; + ///< Messages resulting from this tage will be appended to \a messages. }; } diff --git a/apps/opencs/model/tools/tools.cpp b/apps/opencs/model/tools/tools.cpp index 8293b72916..a3cdb78220 100644 --- a/apps/opencs/model/tools/tools.cpp +++ b/apps/opencs/model/tools/tools.cpp @@ -7,6 +7,10 @@ #include "../doc/state.hpp" +#include "../world/data.hpp" + +#include "mandatoryid.hpp" + CSMTools::Operation *CSMTools::Tools::get (int type) { switch (type) @@ -32,12 +36,25 @@ CSMTools::Verifier *CSMTools::Tools::getVerifier() connect (mVerifier, SIGNAL (finished()), this, SLOT (verifierDone())); connect (mVerifier, SIGNAL (reportMessage (const QString&, int)), this, SLOT (verifierMessage (const QString&, int))); + + std::vector mandatoryIds; // I want C++11, damn it! + mandatoryIds.push_back ("Day"); + mandatoryIds.push_back ("DaysPassed"); + mandatoryIds.push_back ("GameHour"); + mandatoryIds.push_back ("Month"); + mandatoryIds.push_back ("PCRace"); + mandatoryIds.push_back ("PCVampire"); + mandatoryIds.push_back ("PCWerewolf"); + mandatoryIds.push_back ("PCYear"); + + mVerifier->appendStage (new MandatoryIdStage (mData.getGlobals(), + CSMWorld::UniversalId (CSMWorld::UniversalId::Type_Globals), mandatoryIds)); } return mVerifier; } -CSMTools::Tools::Tools() : mVerifier (0) +CSMTools::Tools::Tools (CSMWorld::Data& data) : mData (data), mVerifier (0) { } diff --git a/apps/opencs/model/tools/tools.hpp b/apps/opencs/model/tools/tools.hpp index 04140bb91f..da49fd8b8d 100644 --- a/apps/opencs/model/tools/tools.hpp +++ b/apps/opencs/model/tools/tools.hpp @@ -3,6 +3,11 @@ #include +namespace CSMWorld +{ + class Data; +} + namespace CSMTools { class Verifier; @@ -12,6 +17,7 @@ namespace CSMTools { Q_OBJECT + CSMWorld::Data& mData; Verifier *mVerifier; // not implemented @@ -28,7 +34,7 @@ namespace CSMTools public: - Tools(); + Tools (CSMWorld::Data& data); virtual ~Tools(); diff --git a/apps/opencs/model/world/universalid.cpp b/apps/opencs/model/world/universalid.cpp index e2d8d1ffb1..229779f5ac 100644 --- a/apps/opencs/model/world/universalid.cpp +++ b/apps/opencs/model/world/universalid.cpp @@ -35,6 +35,52 @@ namespace }; } +CSMWorld::UniversalId::UniversalId (const std::string& universalId) +{ + std::string::size_type index = universalId.find (':'); + + if (index!=std::string::npos) + { + std::string type = universalId.substr (0, index); + + for (int i=0; sNoArg[i].mName; ++i) + if (type==sNoArg[i].mName) + { + mArgumentType = ArgumentType_None; + mType = sNoArg[i].mType; + mClass = sNoArg[i].mClass; + return; + } + + for (int i=0; sIdArg[i].mName; ++i) + if (type==sIdArg[i].mName) + { + mArgumentType = ArgumentType_Id; + mType = sIdArg[i].mType; + mClass = sIdArg[i].mClass; + mId = universalId.substr (0, index); + return; + } + + for (int i=0; sIndexArg[i].mName; ++i) + if (type==sIndexArg[i].mName) + { + mArgumentType = ArgumentType_Index; + mType = sIndexArg[i].mType; + mClass = sIndexArg[i].mClass; + + std::istringstream stream (universalId.substr (0, index)); + + if (stream >> mIndex) + return; + + break; + } + } + + throw std::runtime_error ("invalid UniversalId: " + universalId); +} + CSMWorld::UniversalId::UniversalId (Type type) : mArgumentType (ArgumentType_None), mType (type), mIndex (0) { for (int i=0; sNoArg[i].mName; ++i) @@ -151,7 +197,7 @@ std::string CSMWorld::UniversalId::toString() const { std::ostringstream stream; - stream << getTypeName(); + stream << getTypeName() << ":"; switch (mArgumentType) { diff --git a/apps/opencs/model/world/universalid.hpp b/apps/opencs/model/world/universalid.hpp index 6dc0eda1e0..7b630ebc7a 100644 --- a/apps/opencs/model/world/universalid.hpp +++ b/apps/opencs/model/world/universalid.hpp @@ -44,6 +44,8 @@ namespace CSMWorld public: + UniversalId (const std::string& universalId); + UniversalId (Type type = Type_None); ///< Using a type for a non-argument-less UniversalId will throw an exception. From 832fc56d34d06092bd6fc4344ca6fe71399b2205 Mon Sep 17 00:00:00 2001 From: Marc Zinnschlag Date: Sun, 9 Dec 2012 11:10:35 +0100 Subject: [PATCH 45/49] changed UniversalId to string conversion --- apps/opencs/model/tools/mandatoryid.cpp | 2 +- apps/opencs/model/world/universalid.cpp | 73 +++++++++++++------------ 2 files changed, 40 insertions(+), 35 deletions(-) diff --git a/apps/opencs/model/tools/mandatoryid.cpp b/apps/opencs/model/tools/mandatoryid.cpp index 87ac77e675..f9f2ca378a 100644 --- a/apps/opencs/model/tools/mandatoryid.cpp +++ b/apps/opencs/model/tools/mandatoryid.cpp @@ -17,5 +17,5 @@ void CSMTools::MandatoryIdStage::perform (int stage, std::vector& m { if (mIdCollection.searchId (mIds.at (stage))==-1 || mIdCollection.getRecord (mIds.at (stage)).isDeleted()) - messages.push_back (mCollectionId.toString() + " Missing mandatory record: " + mIds.at (stage)); + messages.push_back (mCollectionId.toString() + "|Missing mandatory record: " + mIds.at (stage)); } \ No newline at end of file diff --git a/apps/opencs/model/world/universalid.cpp b/apps/opencs/model/world/universalid.cpp index 229779f5ac..98fb1d0b94 100644 --- a/apps/opencs/model/world/universalid.cpp +++ b/apps/opencs/model/world/universalid.cpp @@ -43,39 +43,44 @@ CSMWorld::UniversalId::UniversalId (const std::string& universalId) { std::string type = universalId.substr (0, index); - for (int i=0; sNoArg[i].mName; ++i) - if (type==sNoArg[i].mName) - { - mArgumentType = ArgumentType_None; - mType = sNoArg[i].mType; - mClass = sNoArg[i].mClass; - return; - } - - for (int i=0; sIdArg[i].mName; ++i) - if (type==sIdArg[i].mName) - { - mArgumentType = ArgumentType_Id; - mType = sIdArg[i].mType; - mClass = sIdArg[i].mClass; - mId = universalId.substr (0, index); - return; - } - - for (int i=0; sIndexArg[i].mName; ++i) - if (type==sIndexArg[i].mName) - { - mArgumentType = ArgumentType_Index; - mType = sIndexArg[i].mType; - mClass = sIndexArg[i].mClass; - - std::istringstream stream (universalId.substr (0, index)); - - if (stream >> mIndex) + if (index==std::string::npos) + { + for (int i=0; sNoArg[i].mName; ++i) + if (type==sNoArg[i].mName) + { + mArgumentType = ArgumentType_None; + mType = sNoArg[i].mType; + mClass = sNoArg[i].mClass; + return; + } + } + else + { + for (int i=0; sIdArg[i].mName; ++i) + if (type==sIdArg[i].mName) + { + mArgumentType = ArgumentType_Id; + mType = sIdArg[i].mType; + mClass = sIdArg[i].mClass; + mId = universalId.substr (0, index); return; + } - break; - } + for (int i=0; sIndexArg[i].mName; ++i) + if (type==sIndexArg[i].mName) + { + mArgumentType = ArgumentType_Index; + mType = sIndexArg[i].mType; + mClass = sIndexArg[i].mClass; + + std::istringstream stream (universalId.substr (0, index)); + + if (stream >> mIndex) + return; + + break; + } + } } throw std::runtime_error ("invalid UniversalId: " + universalId); @@ -197,13 +202,13 @@ std::string CSMWorld::UniversalId::toString() const { std::ostringstream stream; - stream << getTypeName() << ":"; + stream << getTypeName(); switch (mArgumentType) { case ArgumentType_None: break; - case ArgumentType_Id: stream << " " << mId; - case ArgumentType_Index: stream << " " << mIndex; + case ArgumentType_Id: stream << ": " << mId; + case ArgumentType_Index: stream << ": " << mIndex; } return stream.str(); From 0ed378dfb21fd3796f44a5ee0cd5542ca88e7af6 Mon Sep 17 00:00:00 2001 From: Marc Zinnschlag Date: Tue, 11 Dec 2012 11:24:30 +0100 Subject: [PATCH 46/49] changed sub view factory method signature --- apps/opencs/view/doc/view.cpp | 2 +- apps/opencs/view/world/subview.hpp | 18 +++++++++--------- 2 files changed, 10 insertions(+), 10 deletions(-) diff --git a/apps/opencs/view/doc/view.cpp b/apps/opencs/view/doc/view.cpp index 539b149cb2..c1659b388e 100644 --- a/apps/opencs/view/doc/view.cpp +++ b/apps/opencs/view/doc/view.cpp @@ -191,7 +191,7 @@ void CSVDoc::View::addSubView (const CSMWorld::UniversalId& id) if (iter==mSubViewFactories.end()) throw std::logic_error ("can't create subview for " + id.toString()); - CSVWorld::SubView *view = iter->second->makeSubView (id, mDocument->getData(), mDocument->getUndoStack()); + CSVWorld::SubView *view = iter->second->makeSubView (id, *mDocument); addDockWidget (Qt::TopDockWidgetArea, view); view->show(); } diff --git a/apps/opencs/view/world/subview.hpp b/apps/opencs/view/world/subview.hpp index 95448cb47b..ff130828b6 100644 --- a/apps/opencs/view/world/subview.hpp +++ b/apps/opencs/view/world/subview.hpp @@ -1,6 +1,8 @@ #ifndef CSV_WORLD_SUBVIEW_H #define CSV_WORLD_SUBVIEW_H +#include "../../model/doc/document.hpp" + #include "../../model/world/universalid.hpp" #include @@ -35,21 +37,20 @@ namespace CSVWorld struct SubViewFactoryBase { - virtual SubView *makeSubView (const CSMWorld::UniversalId& id, CSMWorld::Data& data, QUndoStack& undoStack) + virtual SubView *makeSubView (const CSMWorld::UniversalId& id, CSMDoc::Document& document) = 0; }; template struct SubViewFactory : public SubViewFactoryBase { - virtual SubView *makeSubView (const CSMWorld::UniversalId& id, CSMWorld::Data& data, QUndoStack& undoStack); + virtual SubView *makeSubView (const CSMWorld::UniversalId& id, CSMDoc::Document& document); }; template - SubView *SubViewFactory::makeSubView (const CSMWorld::UniversalId& id, CSMWorld::Data& data, - QUndoStack& undoStack) + SubView *SubViewFactory::makeSubView (const CSMWorld::UniversalId& id, CSMDoc::Document& document) { - return new SubViewT (id, data, undoStack); + return new SubViewT (id, document.getData(), document.getUndoStack()); } template @@ -59,7 +60,7 @@ namespace CSVWorld SubViewFactoryWithCreateFlag (bool createAndDelete); - virtual SubView *makeSubView (const CSMWorld::UniversalId& id, CSMWorld::Data& data, QUndoStack& undoStack); + virtual SubView *makeSubView (const CSMWorld::UniversalId& id, CSMDoc::Document& document); }; template @@ -69,10 +70,9 @@ namespace CSVWorld template SubView *SubViewFactoryWithCreateFlag::makeSubView (const CSMWorld::UniversalId& id, - CSMWorld::Data& data, - QUndoStack& undoStack) + CSMDoc::Document& document) { - return new SubViewT (id, data, undoStack, mCreateAndDelete); + return new SubViewT (id, document.getData(), document.getUndoStack(), mCreateAndDelete); } } From 2db930a5cf36f19b174b8a1c8e1cdb6789ba6a14 Mon Sep 17 00:00:00 2001 From: Marc Zinnschlag Date: Tue, 11 Dec 2012 13:22:43 +0100 Subject: [PATCH 47/49] rewrote subview factory system --- apps/opencs/CMakeLists.txt | 10 +-- apps/opencs/view/{world => doc}/subview.cpp | 4 +- apps/opencs/view/doc/subview.hpp | 41 +++++++++++ apps/opencs/view/doc/subviewfactory.cpp | 38 ++++++++++ apps/opencs/view/doc/subviewfactory.hpp | 55 ++++++++++++++ apps/opencs/view/doc/subviewfactoryimp.hpp | 50 +++++++++++++ apps/opencs/view/doc/view.cpp | 20 ++---- apps/opencs/view/doc/view.hpp | 9 +-- apps/opencs/view/world/subview.hpp | 79 --------------------- apps/opencs/view/world/subviews.cpp | 12 ++++ apps/opencs/view/world/subviews.hpp | 14 ++++ apps/opencs/view/world/tablesubview.cpp | 6 +- apps/opencs/view/world/tablesubview.hpp | 12 ++-- 13 files changed, 239 insertions(+), 111 deletions(-) rename apps/opencs/view/{world => doc}/subview.cpp (65%) create mode 100644 apps/opencs/view/doc/subview.hpp create mode 100644 apps/opencs/view/doc/subviewfactory.cpp create mode 100644 apps/opencs/view/doc/subviewfactory.hpp create mode 100644 apps/opencs/view/doc/subviewfactoryimp.hpp delete mode 100644 apps/opencs/view/world/subview.hpp create mode 100644 apps/opencs/view/world/subviews.cpp create mode 100644 apps/opencs/view/world/subviews.hpp diff --git a/apps/opencs/CMakeLists.txt b/apps/opencs/CMakeLists.txt index bad1e13762..67cbcc772a 100644 --- a/apps/opencs/CMakeLists.txt +++ b/apps/opencs/CMakeLists.txt @@ -10,9 +10,10 @@ set (OPENCS_SRC model/tools/tools.cpp model/tools/operation.cpp model/tools/stage.cpp model/tools/verifier.cpp model/tools/mandatoryid.cpp - view/doc/viewmanager.cpp view/doc/view.cpp view/doc/operations.cpp view/doc/operation.cpp + view/doc/viewmanager.cpp view/doc/view.cpp view/doc/operations.cpp view/doc/operation.cpp view/doc/subviewfactory.cpp + view/doc/subview.cpp - view/world/subview.cpp view/world/table.cpp view/world/tablesubview.cpp + view/world/table.cpp view/world/tablesubview.cpp view/world/subviews.cpp ) set (OPENCS_HDR @@ -27,9 +28,10 @@ set (OPENCS_HDR model/tools/tools.hpp model/tools/operation.hpp model/tools/stage.hpp model/tools/verifier.hpp model/tools/mandatoryid.hpp - view/doc/viewmanager.hpp view/doc/view.hpp view/doc/operations.hpp view/doc/operation.hpp + view/doc/viewmanager.hpp view/doc/view.hpp view/doc/operations.hpp view/doc/operation.hpp view/doc/subviewfactory.hpp + view/doc/subview.hpp view/doc/subviewfactoryimp.hpp - view/world/subview.hpp view/world/table.hpp view/world/tablesubview.hpp + view/world/table.hpp view/world/tablesubview.hpp view/world/subviews.hpp ) set (OPENCS_US diff --git a/apps/opencs/view/world/subview.cpp b/apps/opencs/view/doc/subview.cpp similarity index 65% rename from apps/opencs/view/world/subview.cpp rename to apps/opencs/view/doc/subview.cpp index 23f075980a..1c356fa736 100644 --- a/apps/opencs/view/world/subview.cpp +++ b/apps/opencs/view/doc/subview.cpp @@ -1,7 +1,7 @@ #include "subview.hpp" -CSVWorld::SubView::SubView (const CSMWorld::UniversalId& id) : mUniversalId (id) +CSVDoc::SubView::SubView (const CSMWorld::UniversalId& id) : mUniversalId (id) { /// \todo add a button to the title bar that clones this sub view @@ -12,7 +12,7 @@ CSVWorld::SubView::SubView (const CSMWorld::UniversalId& id) : mUniversalId (id) setMinimumHeight (60); } -CSMWorld::UniversalId CSVWorld::SubView::getUniversalId() const +CSMWorld::UniversalId CSVDoc::SubView::getUniversalId() const { return mUniversalId; } diff --git a/apps/opencs/view/doc/subview.hpp b/apps/opencs/view/doc/subview.hpp new file mode 100644 index 0000000000..50ec511ab1 --- /dev/null +++ b/apps/opencs/view/doc/subview.hpp @@ -0,0 +1,41 @@ +#ifndef CSV_DOC_SUBVIEW_H +#define CSV_DOC_SUBVIEW_H + +#include "../../model/doc/document.hpp" + +#include "../../model/world/universalid.hpp" + +#include "subviewfactory.hpp" + +#include + +class QUndoStack; + +namespace CSMWorld +{ + class Data; +} + +namespace CSVDoc +{ + class SubView : public QDockWidget + { + Q_OBJECT + + CSMWorld::UniversalId mUniversalId; + + // not implemented + SubView (const SubView&); + SubView& operator= (SubView&); + + public: + + SubView (const CSMWorld::UniversalId& id); + + CSMWorld::UniversalId getUniversalId() const; + + virtual void setEditLock (bool locked) = 0; + }; +} + +#endif \ No newline at end of file diff --git a/apps/opencs/view/doc/subviewfactory.cpp b/apps/opencs/view/doc/subviewfactory.cpp new file mode 100644 index 0000000000..8576f6b1d1 --- /dev/null +++ b/apps/opencs/view/doc/subviewfactory.cpp @@ -0,0 +1,38 @@ + +#include "subviewfactory.hpp" + +#include + +#include + +CSVDoc::SubViewFactoryBase::SubViewFactoryBase() {} + +CSVDoc::SubViewFactoryBase::~SubViewFactoryBase() {} + + +CSVDoc::SubViewFactoryManager::SubViewFactoryManager() {} + +CSVDoc::SubViewFactoryManager::~SubViewFactoryManager() +{ + for (std::map::iterator iter (mSubViewFactories.begin()); + iter!=mSubViewFactories.end(); ++iter) + delete iter->second; +} + +void CSVDoc::SubViewFactoryManager::add (const CSMWorld::UniversalId::Type& id, SubViewFactoryBase *factory) +{ + assert (mSubViewFactories.find (id)==mSubViewFactories.end()); + + mSubViewFactories.insert (std::make_pair (id, factory)); +} + +CSVDoc::SubView *CSVDoc::SubViewFactoryManager::makeSubView (const CSMWorld::UniversalId& id, + CSMDoc::Document& document) +{ + std::map::iterator iter = mSubViewFactories.find (id.getType()); + + if (iter==mSubViewFactories.end()) + throw std::runtime_error ("Failed to create a sub view for: " + id.toString()); + + return iter->second->makeSubView (id, document); +} \ No newline at end of file diff --git a/apps/opencs/view/doc/subviewfactory.hpp b/apps/opencs/view/doc/subviewfactory.hpp new file mode 100644 index 0000000000..1f7c154806 --- /dev/null +++ b/apps/opencs/view/doc/subviewfactory.hpp @@ -0,0 +1,55 @@ +#ifndef CSV_DOC_SUBVIEWFACTORY_H +#define CSV_DOC_SUBVIEWFACTORY_H + +#include + +#include "../../model/world/universalid.hpp" + +namespace CSMDoc +{ + class Document; +} + +namespace CSVDoc +{ + class SubView; + + class SubViewFactoryBase + { + // not implemented + SubViewFactoryBase (const SubViewFactoryBase&); + SubViewFactoryBase& operator= (const SubViewFactoryBase&); + + public: + + SubViewFactoryBase(); + + virtual ~SubViewFactoryBase(); + + virtual SubView *makeSubView (const CSMWorld::UniversalId& id, CSMDoc::Document& document) = 0; + ///< The ownership of the returned sub view is not transferred. + }; + + class SubViewFactoryManager + { + std::map mSubViewFactories; + + // not implemented + SubViewFactoryManager (const SubViewFactoryManager&); + SubViewFactoryManager& operator= (const SubViewFactoryManager&); + + public: + + SubViewFactoryManager(); + + ~SubViewFactoryManager(); + + void add (const CSMWorld::UniversalId::Type& id, SubViewFactoryBase *factory); + ///< The ownership of \a factory is transferred to this. + + SubView *makeSubView (const CSMWorld::UniversalId& id, CSMDoc::Document& document); + ///< The ownership of the returned sub view is not transferred. + }; +} + +#endif diff --git a/apps/opencs/view/doc/subviewfactoryimp.hpp b/apps/opencs/view/doc/subviewfactoryimp.hpp new file mode 100644 index 0000000000..d16e0b2b7b --- /dev/null +++ b/apps/opencs/view/doc/subviewfactoryimp.hpp @@ -0,0 +1,50 @@ +#ifndef CSV_DOC_SUBVIEWFACTORYIMP_H +#define CSV_DOC_SUBVIEWFACTORYIMP_H + +#include "../../model/doc/document.hpp" + +#include "subviewfactory.hpp" + +namespace CSVDoc +{ + template + class SubViewFactory : public SubViewFactoryBase + { + public: + + virtual CSVDoc::SubView *makeSubView (const CSMWorld::UniversalId& id, CSMDoc::Document& document); + }; + + template + CSVDoc::SubView *SubViewFactory::makeSubView (const CSMWorld::UniversalId& id, + CSMDoc::Document& document) + { + return new SubViewT (id, document); + } + + template + class SubViewFactoryWithCreateFlag : 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) + { + return new SubViewT (id, document, mCreateAndDelete); + } +} + +#endif \ No newline at end of file diff --git a/apps/opencs/view/doc/view.cpp b/apps/opencs/view/doc/view.cpp index c1659b388e..47053192b0 100644 --- a/apps/opencs/view/doc/view.cpp +++ b/apps/opencs/view/doc/view.cpp @@ -10,10 +10,11 @@ #include "../../model/doc/document.hpp" -#include "../world/tablesubview.hpp" +#include "../world/subviews.hpp" #include "viewmanager.hpp" #include "operations.hpp" +#include "subview.hpp" void CSVDoc::View::closeEvent (QCloseEvent *event) { @@ -120,15 +121,11 @@ CSVDoc::View::View (ViewManager& viewManager, CSMDoc::Document *document, int to setupUi(); - mSubViewFactories.insert (std::make_pair (CSMWorld::UniversalId (CSMWorld::UniversalId::Type_Globals), - new CSVWorld::SubViewFactoryWithCreateFlag (true))); + CSVWorld::addSubViewFactories (mSubViewFactory); } CSVDoc::View::~View() { - for (std::map::iterator iter (mSubViewFactories.begin()); - iter!=mSubViewFactories.end(); ++iter) - delete iter->second; } const CSMDoc::Document *CSVDoc::View::getDocument() const @@ -165,9 +162,9 @@ void CSVDoc::View::updateDocumentState() if (!(state & operations[i])) mOperations->quitOperation (operations[i]); - QList subViews = findChildren(); + QList subViews = findChildren(); - for (QList::iterator iter (subViews.begin()); iter!=subViews.end(); ++iter) + for (QList::iterator iter (subViews.begin()); iter!=subViews.end(); ++iter) (*iter)->setEditLock (state & CSMDoc::State_Locked); } @@ -186,12 +183,7 @@ 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) - std::map::iterator iter = mSubViewFactories.find (id); - - if (iter==mSubViewFactories.end()) - throw std::logic_error ("can't create subview for " + id.toString()); - - CSVWorld::SubView *view = iter->second->makeSubView (id, *mDocument); + SubView *view = mSubViewFactory.makeSubView (id, *mDocument); addDockWidget (Qt::TopDockWidgetArea, view); view->show(); } diff --git a/apps/opencs/view/doc/view.hpp b/apps/opencs/view/doc/view.hpp index c86c3b3625..f7d4dd3732 100644 --- a/apps/opencs/view/doc/view.hpp +++ b/apps/opencs/view/doc/view.hpp @@ -6,6 +6,8 @@ #include +#include "subviewfactory.hpp" + class QAction; namespace CSMDoc @@ -18,11 +20,6 @@ namespace CSMWorld class UniversalId; } -namespace CSVWorld -{ - struct SubViewFactoryBase; -} - namespace CSVDoc { class ViewManager; @@ -42,7 +39,7 @@ namespace CSVDoc QAction *mVerify; std::vector mEditingActions; Operations *mOperations; - std::map mSubViewFactories; + SubViewFactoryManager mSubViewFactory; // not implemented View (const View&); diff --git a/apps/opencs/view/world/subview.hpp b/apps/opencs/view/world/subview.hpp deleted file mode 100644 index ff130828b6..0000000000 --- a/apps/opencs/view/world/subview.hpp +++ /dev/null @@ -1,79 +0,0 @@ -#ifndef CSV_WORLD_SUBVIEW_H -#define CSV_WORLD_SUBVIEW_H - -#include "../../model/doc/document.hpp" - -#include "../../model/world/universalid.hpp" - -#include - -class QUndoStack; - -namespace CSMWorld -{ - class Data; -} - -namespace CSVWorld -{ - class SubView : public QDockWidget - { - Q_OBJECT - - CSMWorld::UniversalId mUniversalId; - - // not implemented - SubView (const SubView&); - SubView& operator= (SubView&); - - public: - - SubView (const CSMWorld::UniversalId& id); - - CSMWorld::UniversalId getUniversalId() const; - - virtual void setEditLock (bool locked) = 0; - }; - - struct SubViewFactoryBase - { - virtual SubView *makeSubView (const CSMWorld::UniversalId& id, CSMDoc::Document& document) - = 0; - }; - - template - struct SubViewFactory : public SubViewFactoryBase - { - virtual SubView *makeSubView (const CSMWorld::UniversalId& id, CSMDoc::Document& document); - }; - - template - SubView *SubViewFactory::makeSubView (const CSMWorld::UniversalId& id, CSMDoc::Document& document) - { - return new SubViewT (id, document.getData(), document.getUndoStack()); - } - - template - struct SubViewFactoryWithCreateFlag : public SubViewFactoryBase - { - bool mCreateAndDelete; - - SubViewFactoryWithCreateFlag (bool createAndDelete); - - virtual SubView *makeSubView (const CSMWorld::UniversalId& id, CSMDoc::Document& document); - }; - - template - SubViewFactoryWithCreateFlag::SubViewFactoryWithCreateFlag (bool createAndDelete) - : mCreateAndDelete (createAndDelete) - {} - - template - SubView *SubViewFactoryWithCreateFlag::makeSubView (const CSMWorld::UniversalId& id, - CSMDoc::Document& document) - { - return new SubViewT (id, document.getData(), document.getUndoStack(), mCreateAndDelete); - } -} - -#endif \ No newline at end of file diff --git a/apps/opencs/view/world/subviews.cpp b/apps/opencs/view/world/subviews.cpp new file mode 100644 index 0000000000..fdc0cb31d1 --- /dev/null +++ b/apps/opencs/view/world/subviews.cpp @@ -0,0 +1,12 @@ + +#include "subviews.hpp" + +#include "../doc/subviewfactoryimp.hpp" + +#include "tablesubview.hpp" + +void CSVWorld::addSubViewFactories (CSVDoc::SubViewFactoryManager& manager) +{ + manager.add (CSMWorld::UniversalId::Type_Globals, + new CSVDoc::SubViewFactoryWithCreateFlag (true)); +} \ No newline at end of file diff --git a/apps/opencs/view/world/subviews.hpp b/apps/opencs/view/world/subviews.hpp new file mode 100644 index 0000000000..51e4cb0830 --- /dev/null +++ b/apps/opencs/view/world/subviews.hpp @@ -0,0 +1,14 @@ +#ifndef CSV_WORLD_SUBVIEWS_H +#define CSV_WORLD_SUBVIEWS_H + +namespace CSVDoc +{ + class SubViewFactoryManager; +} + +namespace CSVWorld +{ + void addSubViewFactories (CSVDoc::SubViewFactoryManager& manager); +} + +#endif diff --git a/apps/opencs/view/world/tablesubview.cpp b/apps/opencs/view/world/tablesubview.cpp index 3bc555a2d0..4abd531d01 100644 --- a/apps/opencs/view/world/tablesubview.cpp +++ b/apps/opencs/view/world/tablesubview.cpp @@ -1,13 +1,15 @@ #include "tablesubview.hpp" +#include "../../model/doc/document.hpp" + #include "table.hpp" -CSVWorld::TableSubView::TableSubView (const CSMWorld::UniversalId& id, CSMWorld::Data& data, QUndoStack& undoStack, +CSVWorld::TableSubView::TableSubView (const CSMWorld::UniversalId& id, CSMDoc::Document& document, bool createAndDelete) : SubView (id) { - setWidget (mTable = new Table (id, data, undoStack, createAndDelete)); + setWidget (mTable = new Table (id, document.getData(), document.getUndoStack(), createAndDelete)); } void CSVWorld::TableSubView::setEditLock (bool locked) diff --git a/apps/opencs/view/world/tablesubview.hpp b/apps/opencs/view/world/tablesubview.hpp index b45b3c2796..9b0785c470 100644 --- a/apps/opencs/view/world/tablesubview.hpp +++ b/apps/opencs/view/world/tablesubview.hpp @@ -1,22 +1,26 @@ #ifndef CSV_WORLD_TABLESUBVIEW_H #define CSV_WORLD_TABLESUBVIEW_H -#include "subview.hpp" +#include "../doc/subview.hpp" class QUndoStack; +namespace CSMDoc +{ + class Document; +} + namespace CSVWorld { class Table; - class TableSubView : public SubView + class TableSubView : public CSVDoc::SubView { Table *mTable; public: - TableSubView (const CSMWorld::UniversalId& id, CSMWorld::Data& data, QUndoStack& undoStack, - bool createAndDelete); + TableSubView (const CSMWorld::UniversalId& id, CSMDoc::Document& document, bool createAndDelete); virtual void setEditLock (bool locked); }; From c75563c184de28aca46ae2cfb52a4318771cfa1e Mon Sep 17 00:00:00 2001 From: Marc Zinnschlag Date: Tue, 11 Dec 2012 15:35:47 +0100 Subject: [PATCH 48/49] report model and view --- apps/opencs/CMakeLists.txt | 8 ++- apps/opencs/model/doc/document.cpp | 10 +++- apps/opencs/model/doc/document.hpp | 7 ++- apps/opencs/model/tools/reportmodel.cpp | 66 ++++++++++++++++++++++++ apps/opencs/model/tools/reportmodel.hpp | 35 +++++++++++++ apps/opencs/model/tools/tools.cpp | 28 +++++++--- apps/opencs/model/tools/tools.hpp | 13 ++++- apps/opencs/model/world/idtable.cpp | 2 +- apps/opencs/model/world/universalid.cpp | 3 +- apps/opencs/model/world/universalid.hpp | 5 +- apps/opencs/view/doc/view.cpp | 5 +- apps/opencs/view/tools/reportsubview.cpp | 25 +++++++++ apps/opencs/view/tools/reportsubview.hpp | 29 +++++++++++ apps/opencs/view/tools/subviews.cpp | 12 +++++ apps/opencs/view/tools/subviews.hpp | 14 +++++ 15 files changed, 246 insertions(+), 16 deletions(-) create mode 100644 apps/opencs/model/tools/reportmodel.cpp create mode 100644 apps/opencs/model/tools/reportmodel.hpp create mode 100644 apps/opencs/view/tools/reportsubview.cpp create mode 100644 apps/opencs/view/tools/reportsubview.hpp create mode 100644 apps/opencs/view/tools/subviews.cpp create mode 100644 apps/opencs/view/tools/subviews.hpp diff --git a/apps/opencs/CMakeLists.txt b/apps/opencs/CMakeLists.txt index 67cbcc772a..1f9fe85a24 100644 --- a/apps/opencs/CMakeLists.txt +++ b/apps/opencs/CMakeLists.txt @@ -8,12 +8,14 @@ set (OPENCS_SRC model/world/commands.cpp model/world/idtableproxymodel.cpp model/world/record.cpp model/tools/tools.cpp model/tools/operation.cpp model/tools/stage.cpp model/tools/verifier.cpp - model/tools/mandatoryid.cpp + model/tools/mandatoryid.cpp model/tools/reportmodel.cpp view/doc/viewmanager.cpp view/doc/view.cpp view/doc/operations.cpp view/doc/operation.cpp view/doc/subviewfactory.cpp view/doc/subview.cpp view/world/table.cpp view/world/tablesubview.cpp view/world/subviews.cpp + + view/tools/reportsubview.cpp view/tools/subviews.cpp ) set (OPENCS_HDR @@ -26,12 +28,14 @@ set (OPENCS_HDR model/world/commands.hpp model/tools/tools.hpp model/tools/operation.hpp model/tools/stage.hpp model/tools/verifier.hpp - model/tools/mandatoryid.hpp + model/tools/mandatoryid.hpp model/tools/reportmodel.hpp view/doc/viewmanager.hpp view/doc/view.hpp view/doc/operations.hpp view/doc/operation.hpp view/doc/subviewfactory.hpp view/doc/subview.hpp view/doc/subviewfactoryimp.hpp view/world/table.hpp view/world/tablesubview.hpp view/world/subviews.hpp + + view/tools/reportsubview.hpp view/tools/subviews.hpp ) set (OPENCS_US diff --git a/apps/opencs/model/doc/document.cpp b/apps/opencs/model/doc/document.cpp index f03344e08a..9d26944832 100644 --- a/apps/opencs/model/doc/document.cpp +++ b/apps/opencs/model/doc/document.cpp @@ -50,10 +50,11 @@ void CSMDoc::Document::save() emit progress (1, 16, State_Saving, 1, this); } -void CSMDoc::Document::verify() +CSMWorld::UniversalId CSMDoc::Document::verify() { - mTools.runVerifier(); + CSMWorld::UniversalId id = mTools.runVerifier(); emit stateChanged (getState(), this); + return id; } void CSMDoc::Document::abortOperation (int type) @@ -102,6 +103,11 @@ CSMWorld::Data& CSMDoc::Document::getData() return mData; } +CSMTools::ReportModel *CSMDoc::Document::getReport (const CSMWorld::UniversalId& id) +{ + return mTools.getReport (id); +} + void CSMDoc::Document::progress (int current, int max, int type) { emit progress (current, max, type, 1, this); diff --git a/apps/opencs/model/doc/document.hpp b/apps/opencs/model/doc/document.hpp index f9d0a232ce..43e8bba37b 100644 --- a/apps/opencs/model/doc/document.hpp +++ b/apps/opencs/model/doc/document.hpp @@ -13,6 +13,8 @@ #include "state.hpp" +class QAbstractItemModel; + namespace CSMDoc { class Document : public QObject @@ -50,7 +52,7 @@ namespace CSMDoc void save(); - void verify(); + CSMWorld::UniversalId verify(); void abortOperation (int type); @@ -58,6 +60,9 @@ namespace CSMDoc CSMWorld::Data& getData(); + CSMTools::ReportModel *getReport (const CSMWorld::UniversalId& id); + ///< The ownership of the returned report is not transferred. + signals: void stateChanged (int state, CSMDoc::Document *document); diff --git a/apps/opencs/model/tools/reportmodel.cpp b/apps/opencs/model/tools/reportmodel.cpp new file mode 100644 index 0000000000..f142d76697 --- /dev/null +++ b/apps/opencs/model/tools/reportmodel.cpp @@ -0,0 +1,66 @@ + +#include "reportmodel.hpp" + +#include + +int CSMTools::ReportModel::rowCount (const QModelIndex & parent) const +{ + if (parent.isValid()) + return 0; + + return mRows.size(); +} + +int CSMTools::ReportModel::columnCount (const QModelIndex & parent) const +{ + if (parent.isValid()) + return 0; + + return 2; +} + +QVariant CSMTools::ReportModel::data (const QModelIndex & index, int role) const +{ + if (role!=Qt::DisplayRole) + return QVariant(); + + if (index.column()==0) + return static_cast (mRows.at (index.row()).first.getType()); + else + return mRows.at (index.row()).second.c_str(); +} + +QVariant CSMTools::ReportModel::headerData (int section, Qt::Orientation orientation, int role) const +{ + if (role!=Qt::DisplayRole) + return QVariant(); + + if (orientation==Qt::Vertical) + return QVariant(); + + return tr (section==0 ? "Type" : "Description"); +} + +bool CSMTools::ReportModel::removeRows (int row, int count, const QModelIndex& parent) +{ + if (parent.isValid()) + return false; + + mRows.erase (mRows.begin()+row, mRows.begin()+row+count); + + return true; +} + +void CSMTools::ReportModel::add (const std::string& row) +{ + std::string::size_type index = row.find ('|'); + + if (index==std::string::npos) + throw std::logic_error ("invalid report message"); + + beginInsertRows (QModelIndex(), mRows.size(), mRows.size()); + + mRows.push_back (std::make_pair (row.substr (0, index), row.substr (index+1))); + + endInsertRows(); +} \ No newline at end of file diff --git a/apps/opencs/model/tools/reportmodel.hpp b/apps/opencs/model/tools/reportmodel.hpp new file mode 100644 index 0000000000..8814b6d497 --- /dev/null +++ b/apps/opencs/model/tools/reportmodel.hpp @@ -0,0 +1,35 @@ +#ifndef CSM_TOOLS_REPORTMODEL_H +#define CSM_TOOLS_REPORTMODEL_H + +#include +#include + +#include + +#include "../world/universalid.hpp" + +namespace CSMTools +{ + class ReportModel : public QAbstractTableModel + { + Q_OBJECT + + std::vector > mRows; + + public: + + virtual int rowCount (const QModelIndex & parent = QModelIndex()) const; + + virtual int columnCount (const QModelIndex & parent = QModelIndex()) const; + + virtual QVariant data (const QModelIndex & index, int role = Qt::DisplayRole) const; + + virtual QVariant headerData (int section, Qt::Orientation orientation, int role = Qt::DisplayRole) const; + + virtual bool removeRows (int row, int count, const QModelIndex& parent = QModelIndex()); + + void add (const std::string& row); + }; +} + +#endif diff --git a/apps/opencs/model/tools/tools.cpp b/apps/opencs/model/tools/tools.cpp index a3cdb78220..8dd1c0fe6f 100644 --- a/apps/opencs/model/tools/tools.cpp +++ b/apps/opencs/model/tools/tools.cpp @@ -8,7 +8,9 @@ #include "../doc/state.hpp" #include "../world/data.hpp" +#include "../world/universalid.hpp" +#include "reportmodel.hpp" #include "mandatoryid.hpp" CSMTools::Operation *CSMTools::Tools::get (int type) @@ -54,9 +56,10 @@ CSMTools::Verifier *CSMTools::Tools::getVerifier() return mVerifier; } -CSMTools::Tools::Tools (CSMWorld::Data& data) : mData (data), mVerifier (0) +CSMTools::Tools::Tools (CSMWorld::Data& data) : mData (data), mVerifier (0), mNextReportNumber (0) { - + for (std::map::iterator iter (mReports.begin()); iter!=mReports.end(); ++iter) + delete iter->second; } CSMTools::Tools::~Tools() @@ -64,9 +67,14 @@ CSMTools::Tools::~Tools() delete mVerifier; } -void CSMTools::Tools::runVerifier() +CSMWorld::UniversalId CSMTools::Tools::runVerifier() { + mReports.insert (std::make_pair (mNextReportNumber++, new ReportModel)); + mActiveReports[CSMDoc::State_Verifying] = mNextReportNumber-1; + getVerifier()->start(); + + return CSMWorld::UniversalId (CSMWorld::UniversalId::Type_VerificationResults, mNextReportNumber-1); } void CSMTools::Tools::abortOperation (int type) @@ -93,15 +101,23 @@ int CSMTools::Tools::getRunningOperations() const return result; } +CSMTools::ReportModel *CSMTools::Tools::getReport (const CSMWorld::UniversalId& id) +{ + if (id.getType()!=CSMWorld::UniversalId::Type_VerificationResults) + throw std::logic_error ("invalid request for report model: " + id.toString()); + + return mReports.at (id.getIndex()); +} + void CSMTools::Tools::verifierDone() { emit done (CSMDoc::State_Verifying); } -#include void CSMTools::Tools::verifierMessage (const QString& message, int type) { - /// \todo store it in a result model instead + std::map::iterator iter = mActiveReports.find (type); - std::cout << message.toStdString() << std::endl; + if (iter!=mActiveReports.end()) + mReports[iter->second]->add (message.toStdString()); } \ No newline at end of file diff --git a/apps/opencs/model/tools/tools.hpp b/apps/opencs/model/tools/tools.hpp index da49fd8b8d..652345c6da 100644 --- a/apps/opencs/model/tools/tools.hpp +++ b/apps/opencs/model/tools/tools.hpp @@ -3,15 +3,19 @@ #include +#include + namespace CSMWorld { class Data; + class UniversalId; } namespace CSMTools { class Verifier; class Operation; + class ReportModel; class Tools : public QObject { @@ -19,6 +23,9 @@ namespace CSMTools CSMWorld::Data& mData; Verifier *mVerifier; + std::map mReports; + int mNextReportNumber; + std::map mActiveReports; // type, report number // not implemented Tools (const Tools&); @@ -38,13 +45,17 @@ namespace CSMTools virtual ~Tools(); - void runVerifier(); + CSMWorld::UniversalId runVerifier(); + ///< \return ID of the report for this verification run void abortOperation (int type); ///< \attention The operation is not aborted immediately. int getRunningOperations() const; + ReportModel *getReport (const CSMWorld::UniversalId& id); + ///< The ownership of the returned report is not transferred. + private slots: void verifierDone(); diff --git a/apps/opencs/model/world/idtable.cpp b/apps/opencs/model/world/idtable.cpp index a2b0a3c1f5..3fe1fadfef 100644 --- a/apps/opencs/model/world/idtable.cpp +++ b/apps/opencs/model/world/idtable.cpp @@ -35,7 +35,7 @@ QVariant CSMWorld::IdTable::data (const QModelIndex & index, int role) const return QVariant(); if (role==Qt::EditRole && !mIdCollection->isEditable (index.column())) - return QVariant(); + return QVariant(); return mIdCollection->getData (index.row(), index.column()); } diff --git a/apps/opencs/model/world/universalid.cpp b/apps/opencs/model/world/universalid.cpp index 98fb1d0b94..81561bcf42 100644 --- a/apps/opencs/model/world/universalid.cpp +++ b/apps/opencs/model/world/universalid.cpp @@ -30,6 +30,7 @@ namespace static const TypeData sIndexArg[] = { + { CSMWorld::UniversalId::Class_Transient, CSMWorld::UniversalId::Type_VerificationResults, "Verification Results" }, { CSMWorld::UniversalId::Class_None, CSMWorld::UniversalId::Type_None, 0 } // end marker }; @@ -39,7 +40,7 @@ CSMWorld::UniversalId::UniversalId (const std::string& universalId) { std::string::size_type index = universalId.find (':'); - if (index!=std::string::npos) + if (index==std::string::npos) { std::string type = universalId.substr (0, index); diff --git a/apps/opencs/model/world/universalid.hpp b/apps/opencs/model/world/universalid.hpp index 7b630ebc7a..14c0865105 100644 --- a/apps/opencs/model/world/universalid.hpp +++ b/apps/opencs/model/world/universalid.hpp @@ -31,7 +31,10 @@ namespace CSMWorld enum Type { Type_None, - Type_Globals + + Type_Globals, + + Type_VerificationResults }; private: diff --git a/apps/opencs/view/doc/view.cpp b/apps/opencs/view/doc/view.cpp index 47053192b0..4ffd9d7491 100644 --- a/apps/opencs/view/doc/view.cpp +++ b/apps/opencs/view/doc/view.cpp @@ -12,6 +12,8 @@ #include "../world/subviews.hpp" +#include "../tools/subviews.hpp" + #include "viewmanager.hpp" #include "operations.hpp" #include "subview.hpp" @@ -122,6 +124,7 @@ CSVDoc::View::View (ViewManager& viewManager, CSMDoc::Document *document, int to setupUi(); CSVWorld::addSubViewFactories (mSubViewFactory); + CSVTools::addSubViewFactories (mSubViewFactory); } CSVDoc::View::~View() @@ -200,7 +203,7 @@ void CSVDoc::View::save() void CSVDoc::View::verify() { - mDocument->verify(); + addSubView (mDocument->verify()); } void CSVDoc::View::addGlobalsSubView() diff --git a/apps/opencs/view/tools/reportsubview.cpp b/apps/opencs/view/tools/reportsubview.cpp new file mode 100644 index 0000000000..3c92836842 --- /dev/null +++ b/apps/opencs/view/tools/reportsubview.cpp @@ -0,0 +1,25 @@ + +#include "reportsubview.hpp" + +#include +#include + +#include "../../model/tools/reportmodel.hpp" + +CSVTools::ReportSubView::ReportSubView (const CSMWorld::UniversalId& id, CSMDoc::Document& document) +: CSVDoc::SubView (id) +{ + setWidget (mTable = new QTableView (this)); + mTable->setModel (document.getReport (id)); + + mTable->horizontalHeader()->setResizeMode (QHeaderView::Interactive); + mTable->verticalHeader()->hide(); + mTable->setSortingEnabled (true); + mTable->setSelectionBehavior (QAbstractItemView::SelectRows); + mTable->setSelectionMode (QAbstractItemView::ExtendedSelection); +} + +void CSVTools::ReportSubView::setEditLock (bool locked) +{ + // ignored. We don't change document state anyway. +} \ No newline at end of file diff --git a/apps/opencs/view/tools/reportsubview.hpp b/apps/opencs/view/tools/reportsubview.hpp new file mode 100644 index 0000000000..f81f3c386f --- /dev/null +++ b/apps/opencs/view/tools/reportsubview.hpp @@ -0,0 +1,29 @@ +#ifndef CSV_TOOLS_REPORTSUBVIEW_H +#define CSV_TOOLS_REPORTSUBVIEW_H + +#include "../doc/subview.hpp" + +class QTableView; + +namespace CSMDoc +{ + class Document; +} + +namespace CSVTools +{ + class Table; + + class ReportSubView : public CSVDoc::SubView + { + QTableView *mTable; + + public: + + ReportSubView (const CSMWorld::UniversalId& id, CSMDoc::Document& document); + + virtual void setEditLock (bool locked); + }; +} + +#endif \ No newline at end of file diff --git a/apps/opencs/view/tools/subviews.cpp b/apps/opencs/view/tools/subviews.cpp new file mode 100644 index 0000000000..781cf602e3 --- /dev/null +++ b/apps/opencs/view/tools/subviews.cpp @@ -0,0 +1,12 @@ + +#include "subviews.hpp" + +#include "../doc/subviewfactoryimp.hpp" + +#include "reportsubview.hpp" + +void CSVTools::addSubViewFactories (CSVDoc::SubViewFactoryManager& manager) +{ + manager.add (CSMWorld::UniversalId::Type_VerificationResults, + new CSVDoc::SubViewFactory); +} \ No newline at end of file diff --git a/apps/opencs/view/tools/subviews.hpp b/apps/opencs/view/tools/subviews.hpp new file mode 100644 index 0000000000..1bac322282 --- /dev/null +++ b/apps/opencs/view/tools/subviews.hpp @@ -0,0 +1,14 @@ +#ifndef CSV_TOOLS_SUBVIEWS_H +#define CSV_TOOLS_SUBVIEWS_H + +namespace CSVDoc +{ + class SubViewFactoryManager; +} + +namespace CSVTools +{ + void addSubViewFactories (CSVDoc::SubViewFactoryManager& manager); +} + +#endif From cc18b30e17fe054b4c7b6bd41baafe3aeaa8799a Mon Sep 17 00:00:00 2001 From: Marc Zinnschlag Date: Wed, 12 Dec 2012 22:36:20 +0100 Subject: [PATCH 49/49] open sub view on double click in report view --- apps/opencs/model/tools/reportmodel.cpp | 5 +++++ apps/opencs/model/tools/reportmodel.hpp | 2 ++ apps/opencs/model/world/universalid.hpp | 4 ++++ apps/opencs/view/doc/subview.hpp | 4 ++++ apps/opencs/view/doc/view.cpp | 4 ++++ apps/opencs/view/doc/view.hpp | 6 ++++-- apps/opencs/view/tools/reportsubview.cpp | 11 +++++++++-- apps/opencs/view/tools/reportsubview.hpp | 13 +++++++++++++ 8 files changed, 45 insertions(+), 4 deletions(-) diff --git a/apps/opencs/model/tools/reportmodel.cpp b/apps/opencs/model/tools/reportmodel.cpp index f142d76697..b125318755 100644 --- a/apps/opencs/model/tools/reportmodel.cpp +++ b/apps/opencs/model/tools/reportmodel.cpp @@ -63,4 +63,9 @@ void CSMTools::ReportModel::add (const std::string& row) mRows.push_back (std::make_pair (row.substr (0, index), row.substr (index+1))); endInsertRows(); +} + +const CSMWorld::UniversalId& CSMTools::ReportModel::getUniversalId (int row) const +{ + return mRows.at (row).first; } \ No newline at end of file diff --git a/apps/opencs/model/tools/reportmodel.hpp b/apps/opencs/model/tools/reportmodel.hpp index 8814b6d497..55c25d9078 100644 --- a/apps/opencs/model/tools/reportmodel.hpp +++ b/apps/opencs/model/tools/reportmodel.hpp @@ -29,6 +29,8 @@ namespace CSMTools virtual bool removeRows (int row, int count, const QModelIndex& parent = QModelIndex()); void add (const std::string& row); + + const CSMWorld::UniversalId& getUniversalId (int row) const; }; } diff --git a/apps/opencs/model/world/universalid.hpp b/apps/opencs/model/world/universalid.hpp index 14c0865105..8f43bf0838 100644 --- a/apps/opencs/model/world/universalid.hpp +++ b/apps/opencs/model/world/universalid.hpp @@ -4,6 +4,8 @@ #include #include +#include + namespace CSMWorld { class UniversalId @@ -87,4 +89,6 @@ namespace CSMWorld std::ostream& operator< (std::ostream& stream, const UniversalId& universalId); } +Q_DECLARE_METATYPE (CSMWorld::UniversalId) + #endif diff --git a/apps/opencs/view/doc/subview.hpp b/apps/opencs/view/doc/subview.hpp index 50ec511ab1..985c5eb3ca 100644 --- a/apps/opencs/view/doc/subview.hpp +++ b/apps/opencs/view/doc/subview.hpp @@ -35,6 +35,10 @@ namespace CSVDoc CSMWorld::UniversalId getUniversalId() const; virtual void setEditLock (bool locked) = 0; + + signals: + + void focusId (const CSMWorld::UniversalId& universalId); }; } diff --git a/apps/opencs/view/doc/view.cpp b/apps/opencs/view/doc/view.cpp index 4ffd9d7491..13edb6e749 100644 --- a/apps/opencs/view/doc/view.cpp +++ b/apps/opencs/view/doc/view.cpp @@ -188,6 +188,10 @@ void CSVDoc::View::addSubView (const CSMWorld::UniversalId& id) SubView *view = mSubViewFactory.makeSubView (id, *mDocument); addDockWidget (Qt::TopDockWidgetArea, view); + + connect (view, SIGNAL (focusId (const CSMWorld::UniversalId&)), this, + SLOT (addSubView (const CSMWorld::UniversalId&))); + view->show(); } diff --git a/apps/opencs/view/doc/view.hpp b/apps/opencs/view/doc/view.hpp index f7d4dd3732..b1dedafe92 100644 --- a/apps/opencs/view/doc/view.hpp +++ b/apps/opencs/view/doc/view.hpp @@ -80,12 +80,14 @@ namespace CSVDoc void updateProgress (int current, int max, int type, int threads); - void addSubView (const CSMWorld::UniversalId& id); - signals: void newDocumentRequest(); + public slots: + + void addSubView (const CSMWorld::UniversalId& id); + private slots: void newView(); diff --git a/apps/opencs/view/tools/reportsubview.cpp b/apps/opencs/view/tools/reportsubview.cpp index 3c92836842..fe1be85d79 100644 --- a/apps/opencs/view/tools/reportsubview.cpp +++ b/apps/opencs/view/tools/reportsubview.cpp @@ -7,19 +7,26 @@ #include "../../model/tools/reportmodel.hpp" CSVTools::ReportSubView::ReportSubView (const CSMWorld::UniversalId& id, CSMDoc::Document& document) -: CSVDoc::SubView (id) +: CSVDoc::SubView (id), mModel (document.getReport (id)) { setWidget (mTable = new QTableView (this)); - mTable->setModel (document.getReport (id)); + mTable->setModel (mModel); mTable->horizontalHeader()->setResizeMode (QHeaderView::Interactive); mTable->verticalHeader()->hide(); mTable->setSortingEnabled (true); mTable->setSelectionBehavior (QAbstractItemView::SelectRows); mTable->setSelectionMode (QAbstractItemView::ExtendedSelection); + + connect (mTable, SIGNAL (doubleClicked (const QModelIndex&)), this, SLOT (show (const QModelIndex&))); } void CSVTools::ReportSubView::setEditLock (bool locked) { // ignored. We don't change document state anyway. +} + +void CSVTools::ReportSubView::show (const QModelIndex& index) +{ + focusId (mModel->getUniversalId (index.row())); } \ No newline at end of file diff --git a/apps/opencs/view/tools/reportsubview.hpp b/apps/opencs/view/tools/reportsubview.hpp index f81f3c386f..626ceb663d 100644 --- a/apps/opencs/view/tools/reportsubview.hpp +++ b/apps/opencs/view/tools/reportsubview.hpp @@ -4,18 +4,27 @@ #include "../doc/subview.hpp" class QTableView; +class QModelIndex; namespace CSMDoc { class Document; } +namespace CSMTools +{ + class ReportModel; +} + namespace CSVTools { class Table; class ReportSubView : public CSVDoc::SubView { + Q_OBJECT + + CSMTools::ReportModel *mModel; QTableView *mTable; public: @@ -23,6 +32,10 @@ namespace CSVTools ReportSubView (const CSMWorld::UniversalId& id, CSMDoc::Document& document); virtual void setEditLock (bool locked); + + private slots: + + void show (const QModelIndex& index); }; }