7 #include <QApplication>
19 #include "gui/menus/fontmenus.h"
20 #include "gui/menus/menudelegate.h"
25 using namespace swift::config;
28 using namespace swift::gui::menus;
31 using namespace swift::gui::settings;
38 this->setContextMenuPolicy(Qt::CustomContextMenu);
39 connect(
this, &QWidget::customContextMenuRequested,
this, &CViewBaseNonTemplate::customMenuRequested);
42 this->horizontalHeader()->setSortIndicatorShown(
true);
48 this->setVerticalScrollMode(QAbstractItemView::ScrollPerPixel);
49 this->setHorizontalScrollMode(QAbstractItemView::ScrollPerPixel);
50 this->setWordWrap(
false);
51 this->setTextElideMode(Qt::ElideNone);
56 Q_ASSERT_X(s, Q_FUNC_INFO,
"Shortcut");
57 filter->setObjectName(
"Filter shortcut for " + this->objectName());
58 filter->setContext(Qt::WidgetShortcut);
61 s = connect(clearSelection, &QShortcut::activated,
this, &CViewBaseNonTemplate::clearSelection);
62 Q_ASSERT_X(s, Q_FUNC_INFO,
"Shortcut");
63 clearSelection->setObjectName(
"Clear selection shortcut for " + this->objectName());
64 clearSelection->setContext(Qt::WidgetShortcut);
68 Q_ASSERT_X(s, Q_FUNC_INFO,
"Shortcut");
69 saveJson->setObjectName(
"Save JSON for " + this->objectName());
70 saveJson->setContext(Qt::WidgetShortcut);
73 s = connect(deleteRow, &QShortcut::activated,
this, &CViewBaseNonTemplate::removeSelectedRowsChecked);
74 Q_ASSERT_X(s, Q_FUNC_INFO,
"Shortcut");
75 deleteRow->setObjectName(
"Remove selected rows for " + this->objectName());
76 deleteRow->setContext(Qt::WidgetShortcut);
80 Q_ASSERT_X(s, Q_FUNC_INFO,
"Shortcut");
81 copy->setObjectName(
"Copy selection shortcut for " + this->objectName());
82 copy->setContext(Qt::WidgetShortcut);
86 Q_ASSERT_X(s, Q_FUNC_INFO,
"Shortcut");
87 resize->setObjectName(
"Resize view shortcut for " + this->objectName());
88 resize->setContext(Qt::WidgetShortcut);
105 void CViewBaseNonTemplate::setFilterWidgetImpl(QWidget *filterWidget)
128 this->setFilterWidgetImpl(filterDialog);
133 Q_ASSERT_X(s, Q_FUNC_INFO,
"filter dialog connect");
141 this->setFilterWidgetImpl(filterWidget);
144 bool s = connect(filterWidget, &CFilterWidget::changeFilter,
this,
146 Q_ASSERT_X(s, Q_FUNC_INFO,
"filter connect changeFilter");
148 Qt::QueuedConnection);
149 Q_ASSERT_X(s, Q_FUNC_INFO,
"filter connect modelDataChanged");
163 if (this->selectionModel()) { disconnect(this->selectionModel()); }
164 QTableView::setSelectionModel(model);
165 if (this->selectionModel())
167 connect(this->selectionModel(), &QItemSelectionModel::currentRowChanged,
this,
181 return this->
saveJson(selectedOnly, directory);
186 this->horizontalHeader()->setSectionResizeMode(mode);
191 if (menu && nestPreviousMenu)
197 else if (!menu && nestPreviousMenu)
220 if (!this->isSignalConnected(requestSignal))
break;
221 ma.
addAction(CIcons::refresh16(),
"Update", CMenuAction::pathViewUpdates(),
227 static const QMetaMethod requestSignal =
229 if (!this->isSignalConnected(requestSignal))
break;
230 ma.
addAction(CIcons::refresh16(),
"Reload from backend", CMenuAction::pathViewUpdates(),
237 ma.
addAction(CIcons::appMappings16(),
"Automatically display (when loaded)",
238 CMenuAction::pathViewUpdates(), {
this, &CViewBaseNonTemplate::toggleAutoDisplay });
239 a->setCheckable(
true);
245 ma.
addAction(CIcons::delete16(),
"Remove selected rows", CMenuAction::pathViewAddRemove(),
251 ma.
addAction(CIcons::delete16(),
"Clear", CMenuAction::pathViewAddRemove(),
265 ma.
addAction(CIcons::filter16(),
"Remove Filter", CMenuAction::pathViewFilter(),
272 ma.
addAction(CIcons::tableRelationship16(),
"Materialize filtered data", CMenuAction::pathViewFilter(),
278 ma.
addAction(CIcons::disk16(),
"Load from file ", CMenuAction::pathViewLoadSave(),
290 ma.
addAction(CIcons::disk16(),
"Save selected data in file", CMenuAction::pathViewLoadSave(),
298 if (!QApplication::clipboard())
break;
300 QKeySequence(QKeySequence::Paste));
305 if (!QApplication::clipboard())
break;
306 ma.
addAction(CIcons::paste16(),
"Paste", CMenuAction::pathViewCutPaste(),
312 if (!QApplication::clipboard())
break;
313 ma.
addAction(CIcons::copy16(),
"Copy", CMenuAction::pathViewCutPaste(),
336 if (selectedFileOrDir.isEmpty()) {
return; }
337 const QString dir = CDirectories::fileNameToDirectory(selectedFileOrDir);
339 if (!d.exists()) {
return; }
345 CLogMessage::preformatted(msg);
399 const SelectionMode sm = this->selectionMode();
400 if (sm == MultiSelection || sm == ExtendedSelection)
402 menuActions.
addAction(
"Select all", CMenuAction::pathViewSelection(),
nullptr,
405 if (sm != NoSelection)
408 CMenuAction::pathViewSelection(),
nullptr,
414 if (sm != MultiSelection)
416 menuActions.
addAction(
"Switch to multi selection", CMenuAction::pathViewSelection(),
nullptr,
420 if (sm != ExtendedSelection)
422 menuActions.
addAction(
"Switch to extended selection", CMenuAction::pathViewSelection(),
nullptr,
426 if (sm != SingleSelection)
428 menuActions.
addAction(
"Switch to single selection", CMenuAction::pathViewSelection(),
nullptr,
445 const bool enabled =
true;
451 QAction *resizeRowsAction =
452 menuActions.
addAction(CIcons::resizeVertical16(),
"Resize rows to content", CMenuAction::pathViewResize(),
453 nullptr, {
this, &CViewBaseNonTemplate::resizeRowsToContents });
467 if (CBuildConfig::isLocalDeveloperDebugBuild())
469 menuActions.
addAction(CIcons::tableSheet16(),
"Display as JSON", CMenuAction::pathViewLoadSave(),
473 menuActions.
addAction(CIcons::tableSheet16(),
"Display selected as JSON",
474 CMenuAction::pathViewLoadSave(),
480 QAction *actionInteractiveResize =
481 menuActions.
addAction(CIcons::viewTile(),
"Resize (auto)", CMenuAction::pathViewResize(),
nullptr);
482 actionInteractiveResize->setObjectName(this->objectName().append(
"ActionResizing"));
483 actionInteractiveResize->setCheckable(
true);
484 actionInteractiveResize->setChecked(autoResize);
486 connect(actionInteractiveResize, &QAction::toggled,
this, &CViewBaseNonTemplate::toggleResizeMode);
488 QAction *actionWordWrap = menuActions.
addAction(CIcons::viewMultiColumn(),
"Word wrap (multiline)",
489 CMenuAction::pathViewResize(),
nullptr);
490 actionWordWrap->setObjectName(this->objectName().append(
"ActionResizing"));
491 actionWordWrap->setCheckable(
true);
492 actionWordWrap->setChecked(this->wordWrap());
494 connect(actionWordWrap, &QAction::toggled,
this, &CViewBaseNonTemplate::toggleWordWrap);
504 QTableView::resizeEvent(event);
510 const int h = m.height();
522 QModelIndexList indexes = this->selectionModel()->selectedRows();
523 std::sort(indexes.begin(), indexes.end());
530 QModelIndexList unselected;
532 for (
int r = 0; r < rows; r++)
534 const QModelIndex mi = this->model()->index(r, 0);
535 if (selected.contains(mi)) {
continue; }
536 unselected.push_back(mi);
543 if (!this->selectionModel()) {
return 0; }
546 this->clearSelection();
547 QItemSelection selectedItems;
548 const int columns = this->model()->columnCount() - 1;
549 for (
int r : rows) { selectedItems.select(this->model()->index(r, 0), this->model()->index(r, columns)); }
550 this->selectionModel()->select(selectedItems, QItemSelectionModel::Select);
551 return selectedItems.size();
573 QAbstractItemView::SelectionMode m = this->selectionMode();
574 return m == QAbstractItemView::MultiSelection || m == QAbstractItemView::ExtendedSelection;
579 this->horizontalHeader()->setSectionResizeMode(QHeaderView::Interactive);
580 this->horizontalHeader()->setStretchLastSection(
true);
582 this->verticalHeader()->setDefaultSectionSize(fh);
583 this->verticalHeader()->setMinimumSectionSize(fh);
589 default: Q_ASSERT_X(
false, Q_FUNC_INFO,
"wrong resize mode");
break;
594 const QPointer<CViewBaseNonTemplate> guard(
this);
596 if (!guard) {
return; }
607 CFileUtils::jsonWildcardAppendix());
617 else { name = this->metaObject()->className(); }
619 if (!name.endsWith(CFileUtils::jsonAppendix(), Qt::CaseInsensitive)) { name += CFileUtils::jsonAppendix(); }
620 return CFileUtils::appendFilePaths(dir, name);
642 if (!m.
isEmpty()) { CLogMessage::preformatted(m); }
647 if (this->
isEmpty()) {
return; }
650 if (!m.
isEmpty()) { CLogMessage::preformatted(m); }
655 if (this->
isEmpty()) {
return; }
658 if (!m.
isEmpty()) { CLogMessage::preformatted(m); }
677 const int height = this->verticalHeader()->minimumSectionSize();
678 QHeaderView *verticalHeader = this->verticalHeader();
679 Q_ASSERT_X(verticalHeader, Q_FUNC_INFO,
"Missing vertical header");
680 verticalHeader->setSectionResizeMode(QHeaderView::Interactive);
681 verticalHeader->setDefaultSectionSize(height);
688 QHeaderView *verticalHeader = this->verticalHeader();
690 verticalHeader->setFixedWidth(16);
695 QHeaderView *verticalHeader = this->verticalHeader();
696 Q_ASSERT(verticalHeader);
697 verticalHeader->setSectionResizeMode(QHeaderView::ResizeToContents);
711 using namespace std::chrono_literals;
720 if (containerSizeDependent >= 0)
745 const QPoint middle = this->viewport()->geometry().center();
795 this->resizeRowsToContents();
803 this->horizontalHeader()->setStretchLastSection(
false);
804 this->horizontalHeader()->setStretchLastSection(
true);
811 this->resizeColumnsToContents();
821 void CViewBaseNonTemplate::customMenuRequested(
const QPoint &pos)
826 if (menuActions.
isEmpty()) {
return; }
827 menuActions.
toQMenu(menu,
true);
833 if (!menu.isEmpty()) { menu.addSeparator(); }
834 const QString mm = QStringLiteral(
"Dock widget '%1'").arg(dockWidget->
windowTitleOrBackup());
835 QMenu *dockWidgetSubMenu = menu.addMenu(CIcons::text16(), mm);
839 const QPoint globalPos = this->mapToGlobal(pos);
840 menu.exec(globalPos);
845 void CViewBaseNonTemplate::toggleResizeMode(
bool checked)
856 void CViewBaseNonTemplate::toggleWordWrap(
bool checked)
858 if (this->wordWrap() == checked) {
return; }
863 this->setWordWrap(checked);
867 void CViewBaseNonTemplate::toggleAutoDisplay()
869 const QAction *a = qobject_cast<const QAction *>(QObject::sender());
871 Q_ASSERT_X(a->isCheckable(), Q_FUNC_INFO,
"object not checkable");
879 this->clearSelection();
880 QItemSelection selectedItems;
881 const int columns = this->model()->columnCount() - 1;
882 const int rows = this->model()->rowCount() - 1;
883 selectedItems.select(this->model()->index(0, 0), this->model()->index(rows, columns));
884 this->selectionModel()->select(selectedItems, QItemSelectionModel::Select);
899 void CViewBaseNonTemplate::removeSelectedRowsChecked()
907 if (!event || !this->
acceptDrop(event->mimeData())) {
return; }
908 this->setBackgroundRole(QPalette::Highlight);
909 event->acceptProposedAction();
914 if (!event || !this->
acceptDrop(event->mimeData())) {
return; }
915 event->acceptProposedAction();
920 if (!event) {
return; }
926 if (!event) {
return; }
927 QTableView::dropEvent(event);
932 containerSize = containerSize >= 0 ? containerSize : this->
rowCount();
933 const int presizeRandomElements = containerSize > 1000 ? containerSize / 100 : containerSize / 40;
934 return presizeRandomElements;
static QWidget * mainApplicationWidget()
Main application window widget.
The QProgressIndicator class lets an application display a progress indicator to show that a lengthy ...
void centerLoadIndicator(const QPoint &middle)
Center this load indicator.
int startAnimation(std::chrono::milliseconds timeout=std::chrono::milliseconds(0), bool processEvents=false)
Starts the spin animation.
void timedOut()
Timed out.
void stopAnimation(int indicatorId=-1)
Stops the spin animation.
Using this class provides a QTableView with the overlay functionality already integrated.
static const QKeySequence & keyDelete()
Delete, e.g. selected rows.
static const QKeySequence & keySelectAll()
For selecting all.
static const QKeySequence & keyResizeView()
Resize view.
static const QKeySequence & keyDisplayFilter()
Display filter.
static const QKeySequence & keyClearSelection()
For deselecting all.
static const QKeySequence & keyCopy()
Copy.
static QString toParenthesisString(const QKeySequence &sequence)
As string for menus etc. Looks like "(CTRL + R)".
static const QKeySequence & keySaveViews()
Save in views.
QAbstractItemView::SelectionMode getPreferredSelection() const
Preferred selection.
virtual bool filterWidgetChangedFilter(bool enabled)=0
Filter changed in filter widget.
QString getFileDialogFileName(bool load) const
Default file for load/save operations.
QWidget * m_filterWidget
filter widget or dialog
void menuAddItems(Menu menusToAdd)
Add given menu items.
virtual void setSelectionModel(QItemSelectionModel *model)
components::CTextEditDialog * textEditDialog()
Init text edit dialog if required and return pointer to it.
static constexpr int ResizeSubsetThreshold
When to use pre-sizing with random elements.
void rowsResizeModeToInteractive()
Init as interactive, as this allows manually resizing.
bool m_forceStretchLastColumnWhenResized
a small table might (few columns) fail stretching, force again
void hideLoadIndicator(int loadingId=-1)
Hide loading indicator.
void setHorizontalHeaderSectionResizeMode(QHeaderView::ResizeMode mode)
Resize mode.
virtual bool reachedResizeThreshold(int containerSize=-1) const =0
Skip resizing because of size?
swift::misc::CDirectories::ColumnIndex m_dirSettingsIndex
allows to set more specialized directories //!< remember last JSON directory, having this member allo...
menus::IMenuDelegate * setCustomMenu(menus::IMenuDelegate *menu, bool nestPreviousMenu=true)
Set custom menu if applicable.
Menu m_menus
Default menu settings.
@ PresizeSubset
use a subset of the data to resize
@ ResizingAlways
always resize
@ ResizingOnce
only one time
@ ResizingAuto
resizing when below threshold,
int selectedRowCount() const
Number of selected rows.
virtual void resizeToContents()
Resize to contents, strategy depends on container size.
SelectionMode m_originalSelectionMode
Selection mode set.
void triggerReload()
Trigger reload from backend by signal requestUpdate();.
bool isCurrentlyAllowingMultipleRowSelections() const
Is the current selection mode allow multiple selection.
virtual int removeSelectedRows()=0
Remove selected rows.
int getPresizeRandomElementsSize(int containerSize=-1) const
Calculate presize count.
bool allowsMultipleSelectedRows() const
Allows to select multiple rows.
void requestNewBackendData()
Load data from backend (where it makes sense)
ResizeMode m_resizeMode
mode
virtual void removeFilter()=0
Remove filter.
virtual QString getRememberedLastJsonDirectory() const
JSON directory.
virtual void onDoubleClicked(const QModelIndex &index)=0
Index double clicked.
void showVerticalHeader()
Vertical header.
virtual void displaySelectedJsonPopup()=0
Display JSON data.
virtual void onClicked(const QModelIndex &index)=0
Index clicked.
virtual bool acceptDrop(const QMimeData *mimeData) const =0
Accept drop data?
void loadIndicatorVisibilityChanged(bool visible)
Load indicator's visibility has been changed.
int getHorizontalHeaderFontHeight() const
Horizontal font height.
bool m_displayAutomatically
display directly when loaded
QModelIndexList selectedRows() const
Selected rows if any.
void loadJsonAction()
Load JSON for action/menu, void return signatur.
void menuRemoveItems(Menu menusToRemove)
Remove given menu items.
virtual void rememberLastJsonDirectory(const QString &selectedFileOrDir)
JSON directory.
virtual swift::misc::CStatusMessage loadJson(const QString &directory={})=0
Load JSON.
CLoadIndicator * m_loadIndicator
load indicator if needed
virtual QModelIndexList unselectedRows() const
Unselected (not selected) rows if any.
RowsResizeMode m_rowResizeMode
row resize mode for row height
void requestUpdate()
Ask for new data from currently loaded data.
bool m_enabledLoadIndicator
loading indicator enabled/disabled
int showLoadIndicatorWithTimeout(std::chrono::milliseconds timeout=std::chrono::milliseconds { 0 }, bool processEvents=true)
Show loading indicator which can time out.
void saveJsonAction()
Save JSON for action/menu, void return signatur.
void saveSelectedJsonAction()
Save JSON for action/menu, void return signatur.
virtual void resizeEvent(QResizeEvent *event)
QWidget * mainApplicationWindowWidget() const
Main application window widget if any.
virtual void displayJsonPopup()=0
Display JSON data.
virtual void performModeBasedResizeToContent()=0
Perform resizing (no presizing) / non slot method for template.
virtual void materializeFilter()=0
Materialize filter.
void setFilterWidget(filters::CFilterWidget *filterWidget)
Set filter widget.
virtual void dragEnterEvent(QDragEnterEvent *event)
swift::misc::CStatusMessage showFileLoadDialog(const QString &directory={})
Show file load dialog.
void onModelChanged()
Underlying model changed.
int m_resizeAutoNthTime
with ResizeAuto, resize every n-th time
virtual void fullResizeToContents()
Full resizing to content, might be slow.
void setMultiSelection()
Change selection modes.
QMap< MenuFlag, menus::CMenuActions > m_menuFlagActions
initialized actions for menu flag (enum)
std::chrono::milliseconds m_loadIndicatorTimeoutDefault
default time for timeout
virtual void clear()=0
Clear data.
virtual void onRowSelected(const QModelIndex &index)=0
Row selected.
void rowsResizeModeToContent()
Resize mode to content.
virtual void dropEvent(QDropEvent *event)
virtual bool filterDialogFinished(int status)=0
Filter dialog finished.
QString m_saveFileName
save file name (JSON)
menus::CFontMenu * m_fontMenu
font menu if applicable
void centerLoadIndicator()
Center / re-center load indicator.
virtual bool isResizeConditionMet(int containerSize=-1) const
Resize or skip resize?
bool hasSingleSelectedRow() const
Single selected row.
bool hasMultipleSelectedRows() const
Multiple selected rows.
swift::misc::CSettingReadOnly< settings::TGeneralGui > m_guiSettings
general GUI settings
virtual ~CViewBaseNonTemplate()
Destructor.
virtual bool isEmpty() const =0
Empty?
int showLoadIndicator(int containerSizeDependent=-1, std::chrono::milliseconds timeout=std::chrono::milliseconds { 0 }, bool processEvents=true)
Show loading indicator.
int m_resizeCount
flag / counter, how many resize activities
virtual void presizeOrFullResizeToContents()=0
Depending on CViewBaseNonTemplate::ResizeSubsetThreshold presize or fully resize.
virtual void customMenu(menus::CMenuActions &menuActions)
Method creating the menu.
swift::misc::CStatusMessage showFileSaveDialog(bool selectedOnly, const QString &directory={})
Show file save dialog.
virtual void updateSortIndicator()=0
Set the sort indicator to the current sort column.
virtual swift::misc::CStatusMessage saveJson(bool selectedOnly=false, const QString &directory={})=0
Save JSON.
void rowsResizeModeBasedOnThreshold(int elements)
Set content/interactive mode based on ResizeRowsToContentThreshold.
void enableLoadIndicator(bool enable)
Enable loading indicator.
static constexpr int ResizeRowsToContentThreshold
When to use rows resizing (which is slow)
bool isShowingLoadIndicator
Load indicator property allows using in stylesheet.
void settingsChanged()
Settings have been changed.
void setExtendedSelection()
Change selection modes.
void modelDataChanged(int count, bool withFilter)
Model data changed.
bool m_showingLoadIndicator
showing loading indicator
int selectRows(const QSet< int > &rows)
Select given rows.
virtual bool setParentDockWidgetInfoArea(swift::gui::CDockWidgetInfoArea *parentDockableWidget)
Corresponding dockable widget in info area.
void init()
Init default values.
virtual void paste()=0
Clipboard cut/copy/paste.
void displayFilterDialog()
Display the filter dialog.
menus::IMenuDelegate * m_menu
custom menu if any
void selectAll()
Select all rows.
swift::misc::CSetting< swift::misc::settings::TDirectorySettings > m_dirSettings
directory for load/save
void setSingleSelection()
Change selection modes.
menus::CMenuActions initMenuActions(MenuFlag menu)
Init menu actions.
virtual void copy()=0
Clipboard cut/copy/paste.
void setFilterDialog(filters::CFilterDialog *filterDialog)
Filter dialog.
components::CTextEditDialog * m_textEditDialog
text edit dialog
virtual void dragLeaveEvent(QDragLeaveEvent *event)
void triggerReloadFromBackend()
Trigger reload from backend by signal requestNewBackendData()
int unselectedRowCount() const
Unselected row count.
@ MenuDisplayAutomatically
allow to switch display automatically
@ MenuClear
allow clearing the view via menu
@ MenuFont
font related menu (size)
@ MenuRefresh
allow refreshing the view via menu
@ MenuCut
cut (for copy/paste)
@ MenuCopy
copy (for copy/paste)
@ MenuBackend
allow to request data from backend
@ MenuRemoveSelectedRows
allow to remove selected rows
@ MenuPaste
paste (for copy/paste)
@ MenuMaterializeFilter
materialize filter (filtered data become model data)
@ MenuFilter
filter can be opened
@ MenuToggleSelectionMode
allow to toggle selection mode
bool hasSelection() const
Selection (selected rows)
virtual void dragMoveEvent(QDragMoveEvent *event)
virtual int rowCount() const =0
Elements in container.
bool displayAutomatically() const
Display automatically (when models are loaded)
bool m_enableDeleteSelectedRows
selected rows can be deleted
const QFont & getHorizontalHeaderFont() const
Header (horizontal) font.
virtual void cut()=0
Clipboard cut/copy/paste.
CStatusMessage setAndSave(const T &value, qint64 timestamp=0)
Write and save in the same step. Must be called from the thread in which the owner lives.
T get() const
Get a copy of the current value.
Directories (swift data directories)
void setPropertyByIndex(CPropertyIndexRef index, const QVariant &variant)
Set property by index.
QVariant propertyByIndex(CPropertyIndexRef index) const
Property by index.
bool isEmpty() const
Message empty.
Streamable status message, e.g.
High level reusable GUI components.
Filter to search data sets.
Models to be used with views, mainly QTableView.
Views, mainly QTableView.
Free functions in swift::misc.
auto singleShot(int msec, QObject *target, F &&task)
Starts a single-shot timer which will call a task in the thread of the given object when it times out...