cutter/src/widgets/AddressableItemList.h
Florian Märkl 1f133741ab
Make ClassesWidget a ListDockWidget (#3152)
Adds Quick Filter and generic address-based context menu entries to the
existing ClassesWidget. The original ClassesWidget.ui is not used
anymore as the layout is provided by ListDockWidget and only adjusted.
The AddressableItemContextMenu may now also optionally be shown when
there no currently selected item by using
setShowItemContextMenuWithoutAddress(). This is used e.g. to display the
"Create Class" option when nothing is present in the list.

Fixes #2237

Co-authored-by: Tristan Crawford <tristanthtcrawford@gmail.com>
2023-03-30 19:33:31 +02:00

114 lines
3.7 KiB
C++

#ifndef ADDRESSABLE_ITEM_LIST_H
#define ADDRESSABLE_ITEM_LIST_H
#include <memory>
#include <QAbstractItemModel>
#include <QSortFilterProxyModel>
#include <QAbstractItemView>
#include <QMenu>
#include "core/Cutter.h"
#include "common/AddressableItemModel.h"
#include "CutterDockWidget.h"
#include "CutterTreeWidget.h"
#include "menus/AddressableItemContextMenu.h"
#include "CutterTreeView.h"
class MainWindow;
template<class BaseListWidget = CutterTreeView>
class AddressableItemList : public BaseListWidget
{
static_assert(std::is_base_of<QAbstractItemView, BaseListWidget>::value,
"ParentModel needs to inherit from QAbstractItemModel");
public:
explicit AddressableItemList(QWidget *parent = nullptr) : BaseListWidget(parent)
{
this->connect(this, &QWidget::customContextMenuRequested, this,
&AddressableItemList<BaseListWidget>::showItemContextMenu);
this->setContextMenuPolicy(Qt::CustomContextMenu);
this->connect(this, &QAbstractItemView::activated, this,
&AddressableItemList<BaseListWidget>::onItemActivated);
}
void setModel(AddressableItemModelI *addressableItemModel)
{
this->addressableModel = addressableItemModel;
BaseListWidget::setModel(this->addressableModel->asItemModel());
this->connect(this->selectionModel(), &QItemSelectionModel::currentChanged, this,
&AddressableItemList<BaseListWidget>::onSelectedItemChanged);
}
void setMainWindow(MainWindow *mainWindow)
{
this->mainWindow = mainWindow;
setItemContextMenu(new AddressableItemContextMenu(this, mainWindow));
this->addActions(this->getItemContextMenu()->actions());
}
AddressableItemContextMenu *getItemContextMenu() { return itemContextMenu; }
void setItemContextMenu(AddressableItemContextMenu *menu)
{
if (itemContextMenu != menu && itemContextMenu) {
itemContextMenu->deleteLater();
}
itemContextMenu = menu;
}
/**
* If this is set to true, the context menu will also be shown if no item
* is currently selected.
*/
void setShowItemContextMenuWithoutAddress(bool val) { showItemContextMenuWithoutAddress = val; }
protected:
virtual void showItemContextMenu(const QPoint &pt)
{
if (!itemContextMenu) {
return;
}
auto index = this->currentIndex();
if (index.isValid()) {
auto offset = addressableModel->address(index);
auto name = addressableModel->name(index);
itemContextMenu->setTarget(offset, name);
} else {
if (!showItemContextMenuWithoutAddress) {
return;
}
itemContextMenu->clearTarget();
}
itemContextMenu->exec(this->mapToGlobal(pt));
}
virtual void onItemActivated(const QModelIndex &index)
{
if (!index.isValid())
return;
auto offset = addressableModel->address(index);
Core()->seekAndShow(offset);
}
virtual void onSelectedItemChanged(const QModelIndex &index) { updateMenuFromItem(index); }
void updateMenuFromItem(const QModelIndex &index)
{
if (index.isValid()) {
auto offset = addressableModel->address(index);
auto name = addressableModel->name(index);
itemContextMenu->setTarget(offset, name);
} else {
itemContextMenu->clearTarget();
}
}
private:
bool showItemContextMenuWithoutAddress = false;
AddressableItemModelI *addressableModel = nullptr;
AddressableItemContextMenu *itemContextMenu = nullptr;
MainWindow *mainWindow = nullptr;
};
#endif // ADDRESSABLE_ITEM_LIST_H