Skip to content

Commit

Permalink
Merge branch 'master' into feature/plugin_description_markdown
Browse files Browse the repository at this point in the history
  • Loading branch information
ThomasKroes committed Dec 10, 2024
2 parents eade633 + 1e5509d commit 8487367
Show file tree
Hide file tree
Showing 12 changed files with 213 additions and 24 deletions.
2 changes: 2 additions & 0 deletions ManiVault/cmake/CMakeMvSourcesPublic.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -427,6 +427,7 @@ set(PUBLIC_WIDGETS_INTERNAL_HEADERS
src/widgets/ViewPluginShortcutsDialog.h
src/widgets/ViewPluginLearningCenterOverlayWidget.h
src/widgets/IconLabel.h
src/widgets/MultiSelectComboBox.h
)

set(PUBLIC_WIDGETS_INTERNAL_SOURCES
Expand All @@ -446,6 +447,7 @@ set(PUBLIC_WIDGETS_INTERNAL_SOURCES
src/widgets/ViewPluginShortcutsDialog.cpp
src/widgets/ViewPluginLearningCenterOverlayWidget.cpp
src/widgets/IconLabel.cpp
src/widgets/MultiSelectComboBox.cpp
)

set(PUBLIC_WIDGETS_INTERNAL_FILES
Expand Down
1 change: 1 addition & 0 deletions ManiVault/src/MiscellaneousSettingsAction.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ MiscellaneousSettingsAction::MiscellaneousSettingsAction(QObject* parent) :
addAction(&_keepDescendantsAfterRemovalAction);
addAction(&_statusBarVisibleAction);
addAction(&_statusBarOptionsAction);
addAction(&_showSimplifiedGuidsAction);
}

void MiscellaneousSettingsAction::updateStatusBarOptionsAction()
Expand Down
5 changes: 4 additions & 1 deletion ManiVault/src/actions/OptionsAction.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -277,7 +277,8 @@ QVariantMap OptionsAction::toVariantMap() const

OptionsAction::ComboBoxWidget::ComboBoxWidget(QWidget* parent, OptionsAction* optionsAction, const std::int32_t& widgetFlags) :
QWidget(parent),
_optionsAction(optionsAction)
_optionsAction(optionsAction),
_preventPopupClose(false)
{
auto comboBoxCheckableTableView = new CheckableTableView(this);

Expand All @@ -303,6 +304,8 @@ OptionsAction::ComboBoxWidget::ComboBoxWidget(QWidget* parent, OptionsAction* op
_comboBox.installEventFilter(this);
_comboBox.lineEdit()->installEventFilter(this);

_comboBox.init();

_layout.setContentsMargins(0, 0, 0, 0);

_layout.addWidget(&_comboBox);
Expand Down
12 changes: 7 additions & 5 deletions ManiVault/src/actions/OptionsAction.h
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
#include "models/CheckableStringListModel.h"

#include "widgets/FlowLayout.h"
#include "widgets/MultiSelectComboBox.h"

#include <QComboBox>
#include <QCompleter>
Expand Down Expand Up @@ -128,11 +129,12 @@ class CORE_EXPORT OptionsAction : public WidgetAction
void updateCurrentText() const;

protected:
OptionsAction* _optionsAction; /** Pointer to owning options action */
QHBoxLayout _layout; /** Horizontal layout */
QComboBox _comboBox; /** Combobox for selecting options */
QCompleter _completer; /** For inline searching */

OptionsAction* _optionsAction; /** Pointer to owning options action */
QHBoxLayout _layout; /** Horizontal layout */
MultiSelectComboBox _comboBox; /** Combobox for selecting options */
QCompleter _completer; /** For inline searching */
bool _preventPopupClose; /** Prevent the popup from closing when we do not want it */

friend class OptionsAction;
};

Expand Down
3 changes: 0 additions & 3 deletions ManiVault/src/actions/RecentFilesAction.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -18,9 +18,6 @@ namespace mv::gui {

RecentFilesAction::RecentFilesAction(QObject* parent, const QString& settingsKey /*= ""*/, const QString& fileType /*= ""*/, const QString& shortcutPrefix /*= ""*/, const QIcon& icon /*= QIcon()*/) :
WidgetAction(parent, "Recent Files"),
_settingsKey(),
_fileType(),
_icon(),
_model(this),
_filterModel(this),
_editAction(this, "Edit...")
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
#include <QVBoxLayout>
#include <QStyledItemDelegate>
#include <QStyleOptionViewItem>
#include <QClipboard>

#include <stdexcept>

Expand Down Expand Up @@ -70,7 +71,7 @@ class ProgressItemDelegateEditorWidget : public QWidget
private:

/** Updates the editor widget visibility based on the dataset task status */
void updateEditorWidgetVisibility() {
void updateEditorWidgetVisibility() const {
const auto datasetTaskStatus = _progressItem->getDatasetTask().getStatus();

if (datasetTaskStatus == Task::Status::Running || datasetTaskStatus == Task::Status::RunningIndeterminate || datasetTaskStatus == Task::Status::Finished)
Expand All @@ -80,7 +81,7 @@ class ProgressItemDelegateEditorWidget : public QWidget
}

/** Updates the editor widget read-only state based on the dataset task status */
void updateEditorWidgetReadOnly() {
void updateEditorWidgetReadOnly() const {
_progressEditorWidget->setEnabled(!_progressItem->getDataset()->isLocked());
}

Expand All @@ -102,7 +103,7 @@ class ItemDelegate : public QStyledItemDelegate {

/**
* Construct with owning parent \p dataHierarchyWidget
* @param parent Pointer to owning parent data hierarchy widget
* @param dataHierarchyWidget Pointer to owning parent data hierarchy widget
*/
explicit ItemDelegate(DataHierarchyWidget* dataHierarchyWidget) :
QStyledItemDelegate(dataHierarchyWidget),
Expand All @@ -121,12 +122,12 @@ class ItemDelegate : public QStyledItemDelegate {
* @param index Model index to create the editor for
* @return Pointer to widget if progress column, nullptr otherwise
*/
QWidget* createEditor(QWidget* parent, const QStyleOptionViewItem& option, const QModelIndex& index) const {
QWidget* createEditor(QWidget* parent, const QStyleOptionViewItem& option, const QModelIndex& index) const override {
if (static_cast<AbstractDataHierarchyModel::Column>(index.column()) != AbstractDataHierarchyModel::Column::Progress)
return QStyledItemDelegate::createEditor(parent, option, index);

const auto sourceModelIndex = _dataHierarchyWidget->getFilterModel().mapToSource(index);
const auto progressItem = static_cast<AbstractDataHierarchyModel::ProgressItem*>(_dataHierarchyWidget->getTreeModel().itemFromIndex(sourceModelIndex));
const auto progressItem = dynamic_cast<AbstractDataHierarchyModel::ProgressItem*>(_dataHierarchyWidget->getTreeModel().itemFromIndex(sourceModelIndex));

return new ProgressItemDelegateEditorWidget(progressItem, parent);
}
Expand All @@ -136,7 +137,7 @@ class ItemDelegate : public QStyledItemDelegate {
* @param option Style option
* @param index Model index of the cell for which the geometry changed
*/
void updateEditorGeometry(QWidget* editor, const QStyleOptionViewItem& option, const QModelIndex& index) const {
void updateEditorGeometry(QWidget* editor, const QStyleOptionViewItem& option, const QModelIndex& index) const override {
Q_UNUSED(index)

if (editor == nullptr)
Expand All @@ -156,7 +157,7 @@ class ItemDelegate : public QStyledItemDelegate {
{
QStyledItemDelegate::initStyleOption(option, index);

auto item = static_cast<AbstractDataHierarchyModel::Item*>(_dataHierarchyWidget->getTreeModel().itemFromIndex(_dataHierarchyWidget->getFilterModel().mapToSource(index)));
auto item = dynamic_cast<AbstractDataHierarchyModel::Item*>(_dataHierarchyWidget->getTreeModel().itemFromIndex(_dataHierarchyWidget->getFilterModel().mapToSource(index)));

if (item->getDataset()->isLocked())// || index.column() >= static_cast<int>(AbstractDataHierarchyModel::Column::IsGroup))
option->state &= ~QStyle::State_Enabled;
Expand Down Expand Up @@ -230,7 +231,7 @@ DataHierarchyWidget::DataHierarchyWidget(QWidget* parent) :

connect(expandAllAction, &TriggerAction::triggered, this, [this]() -> void {
_hierarchyWidget.getExpandAllAction().trigger();
});
});

auto& treeView = _hierarchyWidget.getTreeView();

Expand Down Expand Up @@ -427,14 +428,25 @@ DataHierarchyWidget::DataHierarchyWidget(QWidget* parent) :
});
}

connect(&_hierarchyWidget.getTreeView(), &QTreeView::clicked, this, [this](const QModelIndex& index) -> void {
if (index.column() != static_cast<int>(AbstractDataHierarchyModel::Column::DatasetId))
return;

const auto datasetId = _treeModel.getItem(_filterModel.mapToSource(index))->getDataset()->getId();
const auto datasetIdLog = _treeModel.getItem(_filterModel.mapToSource(index))->getDataset()->getId(mv::settings().getMiscellaneousSettings().getShowSimplifiedGuidsAction().isChecked());

QGuiApplication::clipboard()->setText(datasetId);

qDebug() << "Dataset identifier" << datasetIdLog << "copied to clipboard";
});
}

QModelIndex DataHierarchyWidget::getModelIndexByDataset(const Dataset<DatasetImpl>& dataset) const
{
const auto modelIndices = _treeModel.match(_treeModel.index(0, static_cast<int>(AbstractDataHierarchyModel::Column::DatasetId), QModelIndex()), Qt::EditRole, dataset->getId(), 1, Qt::MatchFlag::MatchRecursive);

if (modelIndices.isEmpty())
throw new std::runtime_error(QString("'%1' not found in the data hierarchy model").arg(dataset->text()).toLatin1());
throw std::runtime_error(QString("'%1' not found in the data hierarchy model").arg(dataset->text()).toLatin1());

return modelIndices.first();
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,7 @@
#include <QDebug>
#include <QMenu>
#include <QAction>

#include <stdexcept>
#include <QClipboard>

using namespace mv;
using namespace mv::util;
Expand Down Expand Up @@ -72,13 +71,41 @@ DataHierarchyWidgetContextMenu::DataHierarchyWidgetContextMenu(QWidget* parent,

addAction(removeDatasetsAction);
}

if (!_selectedDatasets.isEmpty()) {
addSeparator();

const auto copySelectedDatasetIdsToClipboard = [this]() -> void {
QStringList datasetIds, datasetIdsLog;

for (const auto& selectedDataset : _selectedDatasets) {
datasetIds << selectedDataset->getId();
datasetIdsLog << selectedDataset->getId(mv::settings().getMiscellaneousSettings().getShowSimplifiedGuidsAction().isChecked());
}

QGuiApplication::clipboard()->setText(datasetIds.join("\n"));

if (datasetIdsLog.count() > 1)
qDebug() << "Dataset identifiers" << datasetIdsLog.join(", ") << "copied to clipboard";
else
qDebug() << "Dataset identifier" << datasetIdsLog.join(", ") << "copied to clipboard";
};

auto copyAction = new QAction(QString("Copy dataset ID%1").arg(_selectedDatasets.count() > 1 ? "'s" : ""));

copyAction->setIcon(Application::getIconFont("FontAwesome").getIcon("barcode"));

connect(copyAction, &QAction::triggered, copyAction, copySelectedDatasetIdsToClipboard);

addAction(copyAction);
}
}

void DataHierarchyWidgetContextMenu::addMenusForPluginType(plugin::Type pluginType)
{
QMap<QString, QMenu*> menus;

for (auto pluginTriggerAction : Application::core()->getPluginManager().getPluginTriggerActions(pluginType, _selectedDatasets)) {
for (const auto& pluginTriggerAction : Application::core()->getPluginManager().getPluginTriggerActions(pluginType, _selectedDatasets)) {
const auto titleSegments = pluginTriggerAction->getMenuLocation().split("/");

QString menuPath, previousMenuPath = titleSegments.first();
Expand Down Expand Up @@ -311,3 +338,4 @@ QMenu* DataHierarchyWidgetContextMenu::getUnhideMenu()

return unhideMenu;
}

10 changes: 9 additions & 1 deletion ManiVault/src/private/FileMenu.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ FileMenu::FileMenu(QWidget* parent /*= nullptr*/) :
setToolTip("File operations");

// Quit is by default in the app menu on macOS
if(QOperatingSystemVersion::currentType() != QOperatingSystemVersion::MacOS) {
if (QOperatingSystemVersion::currentType() != QOperatingSystemVersion::MacOS) {

_exitApplictionAction.setShortcut(QKeySequence("Alt+F4"));
_exitApplictionAction.setShortcutContext(Qt::ApplicationShortcut);
Expand All @@ -38,6 +38,14 @@ FileMenu::FileMenu(QWidget* parent /*= nullptr*/) :
populate();
}

void FileMenu::showEvent(QShowEvent* event)
{
QMenu::showEvent(event);

if (QOperatingSystemVersion::currentType() == QOperatingSystemVersion::Windows)
populate();
}

void FileMenu::populate()
{
clear();
Expand Down
8 changes: 7 additions & 1 deletion ManiVault/src/private/FileMenu.h
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,13 @@ class FileMenu : public QMenu
* @param parent Pointer to parent widget
*/
FileMenu(QWidget *parent = nullptr);


/**
*
* @param event
*/
void showEvent(QShowEvent* event) override;

private:

/**
Expand Down
2 changes: 1 addition & 1 deletion ManiVault/src/util/Serializable.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ Serializable::Serializable(const QString& name /*= ""*/) :
QString Serializable::getId(bool truncated /*= false*/) const
{
if (truncated)
return _id.left(8);
return _id.right(8);

return _id;
}
Expand Down
67 changes: 67 additions & 0 deletions ManiVault/src/widgets/MultiSelectComboBox.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
// SPDX-License-Identifier: LGPL-3.0-or-later
// A corresponding LICENSE file is located in the root directory of this source tree
// Copyright (C) 2023 BioVault (Biomedical Visual Analytics Unit LUMC - TU Delft)

#include "MultiSelectComboBox.h"

#include <QAbstractItemView>
#include <QMouseEvent>

namespace mv::gui {

MultiSelectComboBox::MultiSelectComboBox(QWidget* parent) :
QComboBox(parent),
_preventHidePopup(true)
{
setEditable(true);
}

void MultiSelectComboBox::init()
{
// Install an event filter to prevent automated popup hide
view()->installEventFilter(this);

// Install an event filter to hide the popup when clicked outside of it
view()->parentWidget()->installEventFilter(this);
}

void MultiSelectComboBox::hidePopup()
{
if (_preventHidePopup)
return;

QComboBox::hidePopup();

_preventHidePopup = true;
}

bool MultiSelectComboBox::eventFilter(QObject* watched, QEvent* event)
{
if (event->type() == QEvent::MouseButtonPress) {
const auto mouseEvent = dynamic_cast<QMouseEvent*>(event);

if (watched == view()) {
const auto index = view()->indexAt(mouseEvent->pos());

if (index.isValid()) {
toggleItemCheckState(index);
return true;
}
}

if (watched == view()->parentWidget()) {
_preventHidePopup = false;
hidePopup();
}
}

return QComboBox::eventFilter(watched, event);
}

void MultiSelectComboBox::toggleItemCheckState(const QModelIndex& index) const
{
if (index.isValid())
model()->setData(index, !model()->data(index, Qt::CheckStateRole).toBool(), Qt::CheckStateRole);
}

}
Loading

0 comments on commit 8487367

Please sign in to comment.