refs #452, views upgraded

* load indicator when performing long lasting operations
* custom menu can be injected (->menu delegate)
* resizing based on random elements (subset resized only)
This commit is contained in:
Klaus Basan
2015-09-23 20:01:10 +02:00
committed by Mathew Sutcliffe
parent 933ffea201
commit f0fc1cba42
5 changed files with 629 additions and 87 deletions

View File

@@ -12,6 +12,11 @@
#ifndef BLACKGUI_VIEWBASE_H
#define BLACKGUI_VIEWBASE_H
#include "blackgui/filters/filterdialog.h"
#include "blackgui/filters/filterwidget.h"
#include "blackgui/models/modelfilter.h"
#include "blackgui/menudelegate.h"
#include "blackgui/loadindicator.h"
#include "blackgui/blackguiexport.h"
#include "blackmisc/icons.h"
#include "blackmisc/worker.h"
@@ -29,43 +34,51 @@ namespace BlackGui
{
namespace Views
{
//! Non templated base class, allows Q_OBJECT and signals / slots to be used
class BLACKGUI_EXPORT CViewBaseNonTemplate : public QTableView
{
Q_OBJECT
public:
//! Load indicator property allows using in stylesheet
Q_PROPERTY(bool isShowingLoadIndicator READ isShowingLoadIndicator NOTIFY loadIndicatorVisibilityChanged)
//! Resize mode
public:
//! Resize mode, when to resize rows / columns
//! \remarks Using own resizing (other than QHeaderView::ResizeMode)
enum ResizeMode
{
ResizingAuto, //!< always resizing, \sa m_resizeAutoNthTime
ResizingOnce, //!< only one time
ResizingOff //!< never
ResizingAuto, //!< resizing when below threshold, \sa m_resizeAutoNthTime forcing only every n-th update to be resized
ResizingOnce, //!< only one time
ResizingOnceSubset, //!< use a subset of the data to resize
ResizingOff //!< never
};
//! How rows are resizes
//! How rows are resized, makes sense when \sa ResizeMode is \sa ResizingOff
enum RowsResizeMode
{
Interactive,
Content
};
//! When (rows count) to use asynchronous updates
static const int asyncRowsCountThreshold = 50;
//! When (row count) to use asynchronous updates
static const int ASyncRowsCountThreshold = 50;
//! When to use pre-sizing with random elements
static const int ResizeSubsetThreshold = 50;
//! Clear data
virtual void clear() = 0;
//! Allow to drag and/or drop value objects
virtual void allowDragDropValueObjects(bool allowDrag, bool allowDrop);
//! Resize mode
ResizeMode getResizeMode() const { return m_resizeMode; }
//! Set resize mode
void setResizeMode(ResizeMode mode) { m_resizeMode = mode; }
//! In ResizeAuto mode, how often to update. "1" updates every time, "2" every 2nd time, ..
//! In \sa ResizingAuto mode, how often to update. "1" updates every time, "2" every 2nd time, ..
void setAutoResizeFrequency(int updateEveryNthTime) { this->m_resizeAutoNthTime = updateEveryNthTime; }
//! Header (horizontal) font
@@ -81,15 +94,33 @@ namespace BlackGui
QModelIndexList selectedRows() const;
//! Filter dialog
void setFilterDialog(QDialog *filterDialog);
void setFilterDialog(BlackGui::Filters::CFilterDialog *filterDialog);
//! Set filter widget
void setFilterWidget(BlackGui::Filters::CFilterWidget *filterDialog);
//! Set custom menu if applicable
void setCustomMenu(BlackGui::IMenuDelegate *menu);
//! Enable loading indicator
void enableLoadIndicator(bool enable);
//! Showing load indicator
bool isShowingLoadIndicator() const;
//! Main application window widget if any
QWidget *mainApplicationWindowWidget() const;
signals:
//! Ask for new data
//! Ask for new data from currently loaded data
void requestUpdate();
//! Load indicator's visibility has been changed
void loadIndicatorVisibilityChanged(bool visible);
//! Load data from backend (where it makes sense)
void requestNewBackendData();
//! Asynchronous update finished
void asyncUpdateFinished();
@@ -112,6 +143,12 @@ namespace BlackGui
//! Resize mode to content
void rowsResizeModeToContent();
//! Show loading indicator
void showLoadIndicator(int containerSizeDependent = -1);
//! Hide loading indicator
void hideLoadIndicator();
protected:
//! Constructor
CViewBaseNonTemplate(QWidget *parent);
@@ -120,34 +157,42 @@ namespace BlackGui
//! \remarks override this method to contribute to the menu
virtual void customMenu(QMenu &menu) const;
//! \copydoc QTableView::paintEvent
virtual void paintEvent(QPaintEvent *event) override;
//! Perform resizing / non slot method for template
virtual void performResizeToContents() = 0;
virtual void performModeBasedResizeToContent() = 0;
//! Helper method with template free signature
//! \param variant contains the container
//! \param sort
//! \param performResizing
virtual int performUpdateContainer(const BlackMisc::CVariant &variant, bool sort, bool performResizing) = 0;
//! \param resize
virtual int performUpdateContainer(const BlackMisc::CVariant &variant, bool sort, bool resize) = 0;
//! Skip resizing because of size?
virtual bool reachedResizeThreshold() const = 0;
virtual bool reachedResizeThreshold(int containerSize = -1) const = 0;
//! Resize or skip resize?
virtual bool performResizing() const;
virtual bool isResizeConditionMet(int containerSize = -1) const;
//! Init default values
void init();
ResizeMode m_resizeMode = ResizingAuto; //!< mode
RowsResizeMode m_rowResizeMode = Interactive; //!< row resize mode
int m_resizeCount = 0; //!< flag / counter, how many resize activities
int m_skipResizeThreshold = 40; //!< when to skip resize (rows count)
int m_resizeAutoNthTime = 1; //!< with ResizeAuto, resize every n-th time
bool m_forceStretchLastColumnWhenResized = false; //!< a small table might (few columns) might to fail stretching, force again
bool m_withMenuItemClear = false; //!< allow clearing the view via menu
bool m_withMenuItemRefresh = false; //!< allow refreshing the view via menu
bool m_withMenuFilter = false; //!< filter can be opened
QScopedPointer<QDialog> m_filterDialog; //!< filter dialog if any
ResizeMode m_resizeMode = ResizingOnceSubset; //!< mode
RowsResizeMode m_rowResizeMode = Interactive; //!< row resize mode for row height
int m_resizeCount = 0; //!< flag / counter, how many resize activities
int m_skipResizeThreshold = 40; //!< when to skip resize (rows count)
int m_resizeAutoNthTime = 1; //!< with ResizeAuto, resize every n-th time
bool m_forceStretchLastColumnWhenResized = false; //!< a small table might (few columns) might to fail stretching, force again
bool m_withMenuItemClear = false; //!< allow clearing the view via menu
bool m_withMenuItemRefresh = false; //!< allow refreshing the view via menu
bool m_withMenuItemBackend = false; //!< allow to request data from backend
bool m_withMenuFilter = false; //!< filter can be opened
bool m_showingLoadIndicator = false; //!< showing loading indicator
bool m_enabledLoadIndicator = true; //!< loading indicator enabled/disabled
QWidget *m_filterWidget = nullptr; //!< filter widget if any
BlackGui::IMenuDelegate *m_menu = nullptr; //!< custom menu if any
BlackGui::CLoadIndicator *m_loadIndicator = nullptr; //!< load indicator if neeeded
protected slots:
//! Helper method with template free signature serving as callback from threaded worker
@@ -162,6 +207,9 @@ namespace BlackGui
//! Filter dialog finished
virtual bool ps_filterDialogFinished(int status) = 0;
//! Filter changed in filter widget
virtual bool ps_filterWidgetChangedFilter(bool enabled) = 0;
private slots:
//! Custom menu was requested
void ps_customMenuRequested(QPoint pos);
@@ -169,6 +217,9 @@ namespace BlackGui
//! Toggle the resize mode
void ps_toggleResizeMode(bool checked);
//! Indicator has been updated
void ps_updatedIndicator();
//! Clear the model
virtual void ps_clear() { this->clear(); }
};
@@ -176,10 +227,9 @@ namespace BlackGui
//! Base class for views
template <class ModelClass, class ContainerType, class ObjectType> class CViewBase : public CViewBaseNonTemplate
{
public:
//! Destructor
virtual ~CViewBase() {}
virtual ~CViewBase() { if (this->m_model) { this->m_model->markDestroyed(); }}
//! Model
ModelClass *derivedModel() { return this->m_model; }
@@ -191,13 +241,13 @@ namespace BlackGui
virtual void clear() override { Q_ASSERT(this->m_model); this->m_model->clear(); }
//! Update whole container
int updateContainer(const ContainerType &container, bool sort = true, bool performResizing = true);
int updateContainer(const ContainerType &container, bool sort = true, bool resize = true);
//! Update whole container in background
BlackMisc::CWorker *updateContainerAsync(const ContainerType &container, bool sort = true, bool performResizing = true);
BlackMisc::CWorker *updateContainerAsync(const ContainerType &container, bool sort = true, bool resize = true);
//! Based on size call sync / async update
void updateContainerMaybeAsync(const ContainerType &container, bool sort = true, bool performResizing = true);
void updateContainerMaybeAsync(const ContainerType &container, bool sort = true, bool resize = true);
//! Insert
void insert(const ObjectType &value, bool resize = true);
@@ -226,15 +276,20 @@ namespace BlackGui
//! Set own name and the model's name
virtual void setObjectName(const QString &name);
//! Set filter and take ownership, any previously set filter will be destroyed
void takeFilterOwnership(std::unique_ptr<BlackGui::Models::IModelFilter<ContainerType>> &filter);
//! Removes filter and destroys filter object
void removeFilter();
//! Has filter set?
bool hasFilter() const;
protected:
ModelClass *m_model = nullptr; //!< corresponding model
//! Constructor
CViewBase(QWidget *parent, ModelClass *model = nullptr) : CViewBaseNonTemplate(parent), m_model(model)
{
this->setSortingEnabled(true);
if (model) { this->setModel(this->m_model); }
}
CViewBase(QWidget *parent, ModelClass *model = nullptr);
//! Set the search indicator based on model
void setSortIndicator();
@@ -243,18 +298,22 @@ namespace BlackGui
void standardInit(ModelClass *model = nullptr);
//! \copydoc CViewBaseNonTemplate::reachedResizeThreshold
virtual bool reachedResizeThreshold() const override { return this->rowCount() > m_skipResizeThreshold; }
virtual bool reachedResizeThreshold(int containrerSize = -1) const override;
//! \copydoc CViewBaseNonTemplate::performResizing
virtual void performResizeToContents() override;
virtual void performModeBasedResizeToContent() override;
//! \copydoc CViewBaseNonTemplate::performUpdateContainer
virtual int performUpdateContainer(const BlackMisc::CVariant &variant, bool sort, bool performResizing) override;
virtual int performUpdateContainer(const BlackMisc::CVariant &variant, bool sort, bool resize) override;
//! \copydoc CViewBaseNonTemplate::ps_filterDialogFinished
//! \remarks Actually a slot, but not defined as such as the template does not support Q_OBJECT
virtual bool ps_filterDialogFinished(int status) override;
//! \copydoc CViewBaseNonTemplate::ps_FilterWidgetChangedFilter
//! \remarks Actually a slot, but not defined as such as the template does not support Q_OBJECT
virtual bool ps_filterWidgetChangedFilter(bool enabled) override;
//! \copydoc CViewBaseNonTemplate::ps_removeFilter
//! \remarks Actually a slot, but not defined as such as the template does not support Q_OBJECT
virtual void ps_removeFilter() override;