diff --git a/apps/opencs/CMakeLists.txt b/apps/opencs/CMakeLists.txt index 66c446bae..d2568ce02 100644 --- a/apps/opencs/CMakeLists.txt +++ b/apps/opencs/CMakeLists.txt @@ -57,7 +57,7 @@ opencs_hdrs_noqt (view/doc opencs_units (view/world - table tablesubview scriptsubview util regionmapsubview + table tablesubview scriptsubview util regionmapsubview tablebottombox ) opencs_units_noqt (view/world diff --git a/apps/opencs/view/doc/subview.cpp b/apps/opencs/view/doc/subview.cpp index 153700d32..09361a1c0 100644 --- a/apps/opencs/view/doc/subview.cpp +++ b/apps/opencs/view/doc/subview.cpp @@ -15,3 +15,5 @@ CSMWorld::UniversalId CSVDoc::SubView::getUniversalId() const void CSVDoc::SubView::updateEditorSetting (const QString &settingName, const QString &settingValue) { } + +void CSVDoc::SubView::setStatusBar (bool show) {} \ No newline at end of file diff --git a/apps/opencs/view/doc/subview.hpp b/apps/opencs/view/doc/subview.hpp index 280a2a487..aa073f81d 100644 --- a/apps/opencs/view/doc/subview.hpp +++ b/apps/opencs/view/doc/subview.hpp @@ -37,6 +37,9 @@ namespace CSVDoc virtual void setEditLock (bool locked) = 0; virtual void updateEditorSetting (const QString &, const QString &); + virtual void setStatusBar (bool show); + ///< Default implementation: ignored + signals: void focusId (const CSMWorld::UniversalId& universalId); diff --git a/apps/opencs/view/doc/view.cpp b/apps/opencs/view/doc/view.cpp index 63fab56db..b3374c4a5 100644 --- a/apps/opencs/view/doc/view.cpp +++ b/apps/opencs/view/doc/view.cpp @@ -78,6 +78,11 @@ void CSVDoc::View::setupViewMenu() QAction *newWindow = new QAction (tr ("&New View"), this); connect (newWindow, SIGNAL (triggered()), this, SLOT (newView())); view->addAction (newWindow); + + mShowStatusBar = new QAction (tr ("Show Status Bar"), this); + mShowStatusBar->setCheckable (true); + connect (mShowStatusBar, SIGNAL (toggled (bool)), this, SLOT (toggleShowStatusBar (bool))); + view->addAction (mShowStatusBar); } void CSVDoc::View::setupWorldMenu() @@ -282,6 +287,9 @@ void CSVDoc::View::addSubView (const CSMWorld::UniversalId& id) /// \todo add an user setting to reuse sub views (on a per document basis or on a per top level view basis) SubView *view = mSubViewFactory.makeSubView (id, *mDocument); + + view->setStatusBar (mShowStatusBar->isChecked()); + mSubViewWindow.addDockWidget (Qt::TopDockWidgetArea, view); connect (view, SIGNAL (focusId (const CSMWorld::UniversalId&)), this, @@ -436,3 +444,12 @@ void CSVDoc::View::updateEditorSetting (const QString &settingName, const QStrin else if (settingName == "Height") resizeViewHeight (settingValue.toInt()); } + +void CSVDoc::View::toggleShowStatusBar (bool show) +{ + foreach (QObject *view, mSubViewWindow.children()) + { + if (CSVDoc::SubView *subView = dynamic_cast (view)) + subView->setStatusBar (show); + } +} diff --git a/apps/opencs/view/doc/view.hpp b/apps/opencs/view/doc/view.hpp index 4e6b216a1..c0163ce61 100644 --- a/apps/opencs/view/doc/view.hpp +++ b/apps/opencs/view/doc/view.hpp @@ -38,6 +38,7 @@ namespace CSVDoc QAction *mRedo; QAction *mSave; QAction *mVerify; + QAction *mShowStatusBar; std::vector mEditingActions; Operations *mOperations; SubViewFactoryManager mSubViewFactory; @@ -158,6 +159,8 @@ namespace CSVDoc void addRegionMapSubView(); void showUserSettings(); + + void toggleShowStatusBar (bool show); }; } diff --git a/apps/opencs/view/world/table.cpp b/apps/opencs/view/world/table.cpp index 90ce42b34..9085592df 100644 --- a/apps/opencs/view/world/table.cpp +++ b/apps/opencs/view/world/table.cpp @@ -44,6 +44,7 @@ void CSVWorld::Table::contextMenuEvent (QContextMenuEvent *event) std::vector CSVWorld::Table::listRevertableSelectedIds() const { + /// \todo columns filtering fixes QModelIndexList selectedRows = selectionModel()->selectedRows(); std::vector revertableIds; @@ -64,6 +65,7 @@ std::vector CSVWorld::Table::listRevertableSelectedIds() const std::vector CSVWorld::Table::listDeletableSelectedIds() const { + /// \todo columns filtering fixes QModelIndexList selectedRows = selectionModel()->selectedRows(); std::vector deletableIds; @@ -137,6 +139,17 @@ CSVWorld::Table::Table (const CSMWorld::UniversalId& id, CSMWorld::Data& data, Q mDeleteAction = new QAction (tr ("Delete Record"), this); connect (mDeleteAction, SIGNAL (triggered()), this, SLOT (deleteRecord())); addAction (mDeleteAction); + + connect (mProxyModel, SIGNAL (rowsInserted (const QModelIndex&, int, int)), + this, SLOT (tableSizeUpdate())); + + /// \note This signal could instead be connected to a slot that filters out changes not affecting + /// the records status column (for permanence reasons) + connect (mProxyModel, SIGNAL (dataChanged (const QModelIndex&, const QModelIndex&)), + this, SLOT (tableSizeUpdate())); + + connect (selectionModel(), SIGNAL (selectionChanged (const QItemSelection&, const QItemSelection&)), + this, SLOT (selectionSizeUpdate ())); } void CSVWorld::Table::setEditLock (bool locked) @@ -231,3 +244,38 @@ void CSVWorld::Table::updateEditorSetting (const QString &settingName, const QSt updateEditorSetting (settingName, settingValue)) emit dataChanged (mModel->index (0, i), mModel->index (mModel->rowCount()-1, i)); } + +void CSVWorld::Table::tableSizeUpdate() +{ + int size = 0; + int deleted = 0; + int modified = 0; + + if (mModel->columnCount()>0) + { + int rows = mModel->rowCount(); + + for (int i=0; imapToSource (mProxyModel->index (i, 0)); + + /// \todo Do not use hardcoded column numbers + int state = mModel->data (mModel->index (index.row(), 1)).toInt(); + + switch (state) + { + case CSMWorld::RecordBase::State_BaseOnly: ++size; break; + case CSMWorld::RecordBase::State_Modified: ++size; ++modified; break; + case CSMWorld::RecordBase::State_ModifiedOnly: ++size; ++modified; break; + case CSMWorld::RecordBase:: State_Deleted: ++deleted; ++modified; break; + } + } + } + + tableSizeChanged (size, deleted, modified); +} + +void CSVWorld::Table::selectionSizeUpdate() +{ + selectionSizeChanged (selectionModel()->selectedRows().size()); +} \ No newline at end of file diff --git a/apps/opencs/view/world/table.hpp b/apps/opencs/view/world/table.hpp index eedfeb8a1..dd8e82ed7 100644 --- a/apps/opencs/view/world/table.hpp +++ b/apps/opencs/view/world/table.hpp @@ -60,6 +60,13 @@ namespace CSVWorld void editRequest (int row); + void selectionSizeChanged (int size); + + void tableSizeChanged (int size, int deleted, int modified); + ///< \param size Number of not deleted records + /// \param deleted Number of deleted records + /// \param modified Number of added and modified records + private slots: void createRecord(); @@ -69,6 +76,12 @@ namespace CSVWorld void deleteRecord(); void editRecord(); + + public slots: + + void tableSizeUpdate(); + + void selectionSizeUpdate(); }; } diff --git a/apps/opencs/view/world/tablebottombox.cpp b/apps/opencs/view/world/tablebottombox.cpp new file mode 100644 index 000000000..c8ddb662c --- /dev/null +++ b/apps/opencs/view/world/tablebottombox.cpp @@ -0,0 +1,111 @@ + +#include "tablebottombox.hpp" + +#include + +#include +#include +#include + +void CSVWorld::TableBottomBox::updateStatus() +{ + if (mShowStatusBar) + { + static const char *sLabels[4] = { "record", "deleted", "touched", "selected" }; + static const char *sLabelsPlural[4] = { "records", "deleted", "touched", "selected" }; + + std::ostringstream stream; + + bool first = true; + + for (int i=0; i<4; ++i) + { + if (mStatusCount[i]>0) + { + if (first) + first = false; + else + stream << ", "; + + stream + << mStatusCount[i] << ' ' + << (mStatusCount[i]==1 ? sLabels[i] : sLabelsPlural[i]); + } + } + + mStatus->setText (QString::fromUtf8 (stream.str().c_str())); + } +} + +CSVWorld::TableBottomBox::TableBottomBox (QWidget *parent) +: QWidget (parent), mShowStatusBar (false) +{ + for (int i=0; i<4; ++i) + mStatusCount[i] = 0; + + setVisible (false); + + QStackedLayout *layout = new QStackedLayout; + + mStatus = new QLabel; + + QStatusBar *statusBar = new QStatusBar; + + statusBar->addWidget (mStatus); + + layout->addWidget (statusBar); + + QStatusBar *statusBar2 = new QStatusBar; + + layout->addWidget (statusBar2); + + setLayout (layout); +} + +void CSVWorld::TableBottomBox::setStatusBar (bool show) +{ + if (show!=mShowStatusBar) + { + setVisible (show); + + mShowStatusBar = show; + + if (show) + updateStatus(); + } +} + +void CSVWorld::TableBottomBox::selectionSizeChanged (int size) +{ + if (mStatusCount[3]!=size) + { + mStatusCount[3] = size; + updateStatus(); + } +} + +void CSVWorld::TableBottomBox::tableSizeChanged (int size, int deleted, int modified) +{ + bool changed = false; + + if (mStatusCount[0]!=size) + { + mStatusCount[0] = size; + changed = true; + } + + if (mStatusCount[1]!=deleted) + { + mStatusCount[1] = deleted; + changed = true; + } + + if (mStatusCount[2]!=modified) + { + mStatusCount[2] = modified; + changed = true; + } + + if (changed) + updateStatus(); +} \ No newline at end of file diff --git a/apps/opencs/view/world/tablebottombox.hpp b/apps/opencs/view/world/tablebottombox.hpp new file mode 100644 index 000000000..2663da855 --- /dev/null +++ b/apps/opencs/view/world/tablebottombox.hpp @@ -0,0 +1,39 @@ +#ifndef CSV_WORLD_BOTTOMBOX_H +#define CSV_WORLD_BOTTOMBOX_H + +#include + +class QLabel; + +namespace CSVWorld +{ + class TableBottomBox : public QWidget + { + Q_OBJECT + + bool mShowStatusBar; + QLabel *mStatus; + int mStatusCount[4]; + + private: + + void updateStatus(); + + public: + + TableBottomBox (QWidget *parent = 0); + + void setStatusBar (bool show); + + public slots: + + void selectionSizeChanged (int size); + + void tableSizeChanged (int size, int deleted, int modified); + ///< \param size Number of not deleted records + /// \param deleted Number of deleted records + /// \param modified Number of added and modified records + }; +} + +#endif diff --git a/apps/opencs/view/world/tablesubview.cpp b/apps/opencs/view/world/tablesubview.cpp index 502dcc292..7f9c671c0 100644 --- a/apps/opencs/view/world/tablesubview.cpp +++ b/apps/opencs/view/world/tablesubview.cpp @@ -6,6 +6,7 @@ #include "../../model/doc/document.hpp" #include "table.hpp" +#include "tablebottombox.hpp" CSVWorld::TableSubView::TableSubView (const CSMWorld::UniversalId& id, CSMDoc::Document& document, bool createAndDelete) @@ -18,6 +19,8 @@ CSVWorld::TableSubView::TableSubView (const CSMWorld::UniversalId& id, CSMDoc::D layout->addWidget ( mTable = new Table (id, document.getData(), document.getUndoStack(), createAndDelete), 2); + layout->addWidget (mBottom = new TableBottomBox (this), 0); + QWidget *widget = new QWidget; widget->setLayout (layout); @@ -25,6 +28,14 @@ CSVWorld::TableSubView::TableSubView (const CSMWorld::UniversalId& id, CSMDoc::D setWidget (widget); connect (mTable, SIGNAL (editRequest (int)), this, SLOT (editRequest (int))); + + connect (mTable, SIGNAL (selectionSizeChanged (int)), + mBottom, SLOT (selectionSizeChanged (int))); + connect (mTable, SIGNAL (tableSizeChanged (int, int, int)), + mBottom, SLOT (tableSizeChanged (int, int, int))); + + mTable->tableSizeUpdate(); + mTable->selectionSizeUpdate(); } void CSVWorld::TableSubView::setEditLock (bool locked) @@ -41,3 +52,8 @@ void CSVWorld::TableSubView::updateEditorSetting(const QString &settingName, con { mTable->updateEditorSetting(settingName, settingValue); } + +void CSVWorld::TableSubView::setStatusBar (bool show) +{ + mBottom->setStatusBar (show); +} \ No newline at end of file diff --git a/apps/opencs/view/world/tablesubview.hpp b/apps/opencs/view/world/tablesubview.hpp index ccee50dbc..79450ecce 100644 --- a/apps/opencs/view/world/tablesubview.hpp +++ b/apps/opencs/view/world/tablesubview.hpp @@ -13,18 +13,24 @@ namespace CSMDoc namespace CSVWorld { class Table; + class TableBottomBox; class TableSubView : public CSVDoc::SubView { Q_OBJECT Table *mTable; + TableBottomBox *mBottom; public: TableSubView (const CSMWorld::UniversalId& id, CSMDoc::Document& document, bool createAndDelete); + virtual void setEditLock (bool locked); - void updateEditorSetting (const QString &, const QString &); + + virtual void updateEditorSetting (const QString& key, const QString& value); + + virtual void setStatusBar (bool show); private slots: