You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
o3de/Gems/GraphCanvas/Code/Source/Widgets/GraphCanvasComboBox.cpp

919 lines
27 KiB
C++

/*
* Copyright (c) Contributors to the Open 3D Engine Project. For complete copyright and license terms please see the LICENSE at the root of this distribution.
*
* SPDX-License-Identifier: Apache-2.0 OR MIT
*
*/
#include <AzCore/PlatformDef.h>
AZ_PUSH_DISABLE_WARNING(4251 4800 4244, "-Wunknown-warning-option")
#include <QEvent>
#include <QFocusEvent>
#include <QHeaderView>
#include <QScopedValueRollback>
#include <QToolButton>
#include <QVBoxLayout>
#include <QWidgetAction>
AZ_POP_DISABLE_WARNING
#include <Widgets/GraphCanvasComboBox.h>
namespace GraphCanvas
{
////////////////////////////////////////
// GraphCanvasComboBoxFilterProxyModel
////////////////////////////////////////
GraphCanvasComboBoxFilterProxyModel::GraphCanvasComboBoxFilterProxyModel(QObject*)
{
}
bool GraphCanvasComboBoxFilterProxyModel::filterAcceptsRow(int sourceRow, const QModelIndex& sourceParent) const
{
if (m_filter.isEmpty())
{
return true;
}
QAbstractItemModel* model = sourceModel();
if (!model)
{
return false;
}
QModelIndex index = model->index(sourceRow, filterKeyColumn(), sourceParent);
QString test = model->data(index, filterRole()).toString();
return (test.lastIndexOf(m_testRegex) >= 0);
}
void GraphCanvasComboBoxFilterProxyModel::SetFilter(const QString& filter)
{
m_filter = filter;
m_testRegex = QRegExp(m_filter, Qt::CaseInsensitive);
invalidateFilter();
if (m_filter.isEmpty())
{
sort(-1);
}
else
{
sort(filterKeyColumn());
}
}
////////////////////////////
// GraphCanvasComboBoxMenu
////////////////////////////
GraphCanvasComboBoxMenu::GraphCanvasComboBoxMenu(ComboBoxItemModelInterface* model, QWidget* parent)
: QDialog(parent, Qt::FramelessWindowHint | Qt::WindowStaysOnTopHint)
, m_disableHiding(false)
, m_ignoreNextFocusIn(false)
, m_modelInterface(model)
{
setProperty("HasNoWindowDecorations", true);
setAttribute(Qt::WA_ShowWithoutActivating);
m_filterProxyModel.setSourceModel(m_modelInterface->GetDropDownItemModel());
m_filterProxyModel.sort(m_modelInterface->GetSortColumn());
m_filterProxyModel.setFilterKeyColumn(m_modelInterface->GetCompleterColumn());
m_tableView.setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOn);
m_tableView.setSelectionBehavior(QAbstractItemView::SelectRows);
m_tableView.setSelectionMode(QAbstractItemView::SelectionMode::SingleSelection);
m_tableView.setModel(GetProxyModel());
m_tableView.verticalHeader()->hide();
m_tableView.verticalHeader()->setSectionResizeMode(QHeaderView::ResizeMode::ResizeToContents);
m_tableView.horizontalHeader()->hide();
m_tableView.horizontalHeader()->setStretchLastSection(true);
m_tableView.installEventFilter(this);
m_tableView.setFocusPolicy(Qt::FocusPolicy::ClickFocus);
m_tableView.setMinimumWidth(0);
QVBoxLayout* layout = new QVBoxLayout();
layout->addWidget(&m_tableView);
setLayout(layout);
m_disableHidingStateSetter.AddStateController(GetDisableHidingStateController());
QObject::connect(&m_tableView, &QTableView::clicked, this, &GraphCanvasComboBoxMenu::OnTableClicked);
m_closeTimer.setInterval(0);
QAction* escapeAction = new QAction(this);
escapeAction->setShortcut(Qt::Key_Escape);
addAction(escapeAction);
QObject::connect(escapeAction, &QAction::triggered, this, &GraphCanvasComboBoxMenu::CancelMenu);
}
GraphCanvasComboBoxMenu::~GraphCanvasComboBoxMenu()
{
}
ComboBoxItemModelInterface* GraphCanvasComboBoxMenu::GetInterface()
{
return m_modelInterface;
}
const ComboBoxItemModelInterface* GraphCanvasComboBoxMenu::GetInterface() const
{
return m_modelInterface;
}
GraphCanvasComboBoxFilterProxyModel* GraphCanvasComboBoxMenu::GetProxyModel()
{
return &m_filterProxyModel;
}
const GraphCanvasComboBoxFilterProxyModel* GraphCanvasComboBoxMenu::GetProxyModel() const
{
return &m_filterProxyModel;
}
void GraphCanvasComboBoxMenu::ShowMenu()
{
clearFocus();
m_tableView.clearFocus();
m_tableView.selectionModel()->clearSelection();
m_filterProxyModel.BeginModelReset();
m_modelInterface->OnDropDownAboutToShow();
m_filterProxyModel.EndModelReset();
show();
m_disableHidingStateSetter.ReleaseState();
int rowHeight = m_tableView.rowHeight(0);
if (rowHeight > 0)
{
// Generic padding of like 20 pixels.
setMinimumHeight(aznumeric_cast<int>(rowHeight * 4.5 + 20));
setMaximumHeight(aznumeric_cast<int>(rowHeight * 4.5 + 20));
}
}
void GraphCanvasComboBoxMenu::HideMenu()
{
m_disableHidingStateSetter.ReleaseState();
m_tableView.clearFocus();
m_tableView.selectionModel()->clearSelection();
clearFocus();
reject();
m_filterProxyModel.BeginModelReset();
m_modelInterface->OnDropDownHidden();
m_filterProxyModel.EndModelReset();
}
void GraphCanvasComboBoxMenu::reject()
{
if (!m_disableHiding.GetState())
{
QDialog::reject();
}
}
bool GraphCanvasComboBoxMenu::eventFilter(QObject* object, QEvent* event)
{
if (object == &m_tableView)
{
if (event->type() == QEvent::FocusOut)
{
HandleFocusOut();
}
else if (event->type() == QEvent::FocusIn)
{
HandleFocusIn();
}
}
return false;
}
void GraphCanvasComboBoxMenu::focusInEvent(QFocusEvent* focusEvent)
{
QDialog::focusInEvent(focusEvent);
if (focusEvent->isAccepted())
{
if (!m_ignoreNextFocusIn)
{
HandleFocusIn();
}
else
{
m_ignoreNextFocusIn = false;
}
}
}
void GraphCanvasComboBoxMenu::focusOutEvent(QFocusEvent* focusEvent)
{
QDialog::focusOutEvent(focusEvent);
HandleFocusOut();
}
void GraphCanvasComboBoxMenu::showEvent(QShowEvent* showEvent)
{
QDialog::showEvent(showEvent);
// So, despite me telling it to not activate, the window still gets a focus in event.
// But, it doesn't get a focus out event, since it doesn't actually accept the focus in event?
m_ignoreNextFocusIn = true;
m_tableView.selectionModel()->clearSelection();
Q_EMIT VisibilityChanged(true);
}
void GraphCanvasComboBoxMenu::hideEvent(QHideEvent* hideEvent)
{
QDialog::hideEvent(hideEvent);
clearFocus();
Q_EMIT VisibilityChanged(false);
m_tableView.selectionModel()->clearSelection();
m_filterProxyModel.invalidate();
}
GraphCanvas::StateController<bool>* GraphCanvasComboBoxMenu::GetDisableHidingStateController()
{
return &m_disableHiding;
}
void GraphCanvasComboBoxMenu::SetSelectedIndex(QModelIndex index)
{
m_tableView.selectionModel()->clear();
if (index.isValid()
&& index.row() >= 0
&& index.row() < m_filterProxyModel.rowCount())
{
QItemSelection rowSelection(m_filterProxyModel.index(index.row(), 0, index.parent()), m_filterProxyModel.index(index.row(), m_filterProxyModel.columnCount() - 1, index.parent()));
m_tableView.selectionModel()->select(rowSelection, QItemSelectionModel::Select);
m_tableView.scrollTo(m_filterProxyModel.index(index.row(), 0, index.parent()));
}
}
QModelIndex GraphCanvasComboBoxMenu::GetSelectedIndex() const
{
if (m_tableView.selectionModel()->hasSelection())
{
QModelIndexList selectedIndexes = m_tableView.selectionModel()->selectedIndexes();
if (!selectedIndexes.empty())
{
return selectedIndexes.front();
}
}
return QModelIndex();
}
QModelIndex GraphCanvasComboBoxMenu::GetSelectedSourceIndex() const
{
if (m_tableView.selectionModel()->hasSelection())
{
QModelIndexList selectedIndexes = m_tableView.selectionModel()->selectedIndexes();
if (!selectedIndexes.empty())
{
return m_filterProxyModel.mapToSource(selectedIndexes.front());
}
}
return QModelIndex();
}
void GraphCanvasComboBoxMenu::OnTableClicked(const QModelIndex& modelIndex)
{
if (modelIndex.isValid())
{
QModelIndex sourceIndex = m_filterProxyModel.mapToSource(modelIndex);
if (sourceIndex.isValid())
{
Q_EMIT OnIndexSelected(sourceIndex);
QObject::disconnect(m_closeConnection);
m_closeConnection = QObject::connect(&m_closeTimer, &QTimer::timeout, this, &QDialog::accept);
m_closeTimer.start();
}
}
}
void GraphCanvasComboBoxMenu::HandleFocusIn()
{
m_disableHidingStateSetter.SetState(true);
emit OnFocusIn();
}
void GraphCanvasComboBoxMenu::HandleFocusOut()
{
m_disableHidingStateSetter.ReleaseState();
QObject::disconnect(m_closeConnection);
m_closeConnection = QObject::connect(&m_closeTimer, &QTimer::timeout, this, &QDialog::reject);
m_closeTimer.start();
emit OnFocusOut();
}
////////////////////////
// GraphCanvasComboBox
////////////////////////
GraphCanvasComboBox::GraphCanvasComboBox(ComboBoxItemModelInterface* modelInterface, QWidget* parent)
: QLineEdit(parent)
, m_lineEditInFocus(false)
, m_popUpMenuInFocus(false)
, m_hasFocus(false)
, m_ignoreNextComplete(false)
, m_recursionBlocker(false)
, m_comboBoxMenu(modelInterface)
, m_modelInterface(modelInterface)
{
setObjectName("ComboBoxLineEdit");
setProperty("HasNoWindowDecorations", true);
setProperty("DisableFocusWindowFix", true);
QAction* action = addAction(QIcon(":/GraphCanvasEditorResources/settings_icon.png"), QLineEdit::ActionPosition::TrailingPosition);
QObject::connect(action, &QAction::triggered, this, &GraphCanvasComboBox::OnOptionsClicked);
QAction* escapeAction = new QAction(this);
escapeAction->setShortcut(Qt::Key_Escape);
addAction(escapeAction);
QObject::connect(escapeAction, &QAction::triggered, this, &GraphCanvasComboBox::ResetComboBox);
m_completer.setModel(m_modelInterface->GetCompleterItemModel());
m_completer.setCompletionColumn(m_modelInterface->GetCompleterColumn());
m_completer.setCompletionMode(QCompleter::CompletionMode::InlineCompletion);
m_completer.setCaseSensitivity(Qt::CaseSensitivity::CaseInsensitive);
QObject::connect(this, &QLineEdit::textEdited, this, &GraphCanvasComboBox::OnTextChanged);
QObject::connect(this, &QLineEdit::returnPressed, this, &GraphCanvasComboBox::OnReturnPressed);
QObject::connect(this, &QLineEdit::editingFinished, this, &GraphCanvasComboBox::OnEditComplete);
m_filterTimer.setInterval(500);
QObject::connect(&m_filterTimer, &QTimer::timeout, this, &GraphCanvasComboBox::UpdateFilter);
m_closeTimer.setInterval(0);
QObject::connect(&m_closeTimer, &QTimer::timeout, this, &GraphCanvasComboBox::CloseMenu);
m_focusTimer.setInterval(0);
QObject::connect(&m_focusTimer, &QTimer::timeout, this, &GraphCanvasComboBox::HandleFocusState);
QObject::connect(&m_comboBoxMenu, &GraphCanvasComboBoxMenu::OnIndexSelected, this, &GraphCanvasComboBox::UserSelectedIndex);
QObject::connect(&m_comboBoxMenu, &GraphCanvasComboBoxMenu::OnFocusIn, this, &GraphCanvasComboBox::OnMenuFocusIn);
QObject::connect(&m_comboBoxMenu, &GraphCanvasComboBoxMenu::OnFocusOut, this, &GraphCanvasComboBox::OnMenuFocusOut);
QObject::connect(&m_comboBoxMenu, &GraphCanvasComboBoxMenu::CancelMenu, this, &GraphCanvasComboBox::ResetComboBox);
m_comboBoxMenu.accept();
m_disableHidingStateSetter.AddStateController(m_comboBoxMenu.GetDisableHidingStateController());
}
GraphCanvasComboBox::~GraphCanvasComboBox()
{
}
void GraphCanvasComboBox::RegisterViewId(const ViewId& viewId)
{
m_viewId = viewId;
}
void GraphCanvasComboBox::SetAnchorPoint(QPoint globalPoint)
{
m_anchorPoint = globalPoint;
UpdateMenuPosition();
}
void GraphCanvasComboBox::SetMenuWidth(qreal width)
{
m_displayWidth = width;
UpdateMenuPosition();
}
void GraphCanvasComboBox::SetSelectedIndex(const QModelIndex& selectedIndex)
{
QModelIndex previousIndex = m_modelInterface->FindIndexForName(m_selectedName);
if (previousIndex != selectedIndex)
{
m_selectedName = m_modelInterface->GetNameForIndex(selectedIndex);
if (DisplayIndex(selectedIndex))
{
Q_EMIT SelectedIndexChanged(selectedIndex);
}
}
}
QModelIndex GraphCanvasComboBox::GetSelectedIndex() const
{
return m_modelInterface->FindIndexForName(m_selectedName);
}
void GraphCanvasComboBox::SetOutlineColor(const QColor& outlineColor, const QColor& backgroundColor)
{
QString styleString = QString("QLineEdit#ComboBoxLineEdit { border: 1px solid %1; background-color: %2; }").arg(outlineColor.name()).arg(backgroundColor.name());
AZ_UNUSED(styleString);
//setStyleSheet(styleString);
}
void GraphCanvasComboBox::SetOutlineColor(const QGradient& gradient, const QColor& backgroundColor)
{
QString stops;
for (auto currentStop : gradient.stops())
{
if (!stops.isEmpty())
{
stops.append(", ");
}
QString currentStopStyle = QString("stop: %1 %2").arg(currentStop.first).arg(currentStop.second.name());
stops.append(currentStopStyle);
}
QString styleString = QString("QLineEdit#ComboBoxLineEdit { border: 1px solid qlineargradient(x1: 0, y1: 0, x2: 1, y2: 0 %1); background-color: %2; }").arg(stops).arg(backgroundColor.name());
AZ_UNUSED(styleString);
//setStyleSheet(styleString);
}
void GraphCanvasComboBox::SetOutline(const QBrush& brush, const QColor& backgroundColor)
{
if (brush.gradient() != nullptr)
{
SetOutlineColor((*brush.gradient()), backgroundColor);
}
else
{
SetOutlineColor(brush.color(), backgroundColor);
}
}
void GraphCanvasComboBox::ClearOutlineColor()
{
setStyleSheet("");
}
void GraphCanvasComboBox::ResetComboBox()
{
HideMenu();
QModelIndex selectedIndex = m_modelInterface->FindIndexForName(m_selectedName);
DisplayIndex(selectedIndex);
m_selectedName.clear();
}
void GraphCanvasComboBox::CancelInput()
{
QModelIndex selectedIndex = m_modelInterface->FindIndexForName(m_selectedName);
DisplayIndex(selectedIndex);
HideMenu();
}
void GraphCanvasComboBox::HideMenu()
{
m_disableHidingStateSetter.ReleaseState();
m_comboBoxMenu.HideMenu();
ViewNotificationBus::Handler::BusDisconnect(m_viewId);
}
bool GraphCanvasComboBox::IsMenuVisible() const
{
return !m_comboBoxMenu.isHidden();
}
void GraphCanvasComboBox::focusInEvent(QFocusEvent* focusEvent)
{
QLineEdit::focusInEvent(focusEvent);
m_lineEditInFocus = true;
m_focusTimer.start();
grabKeyboard();
}
void GraphCanvasComboBox::focusOutEvent(QFocusEvent* focusEvent)
{
QLineEdit::focusOutEvent(focusEvent);
m_lineEditInFocus = false;
m_focusTimer.start();
releaseKeyboard();
}
void GraphCanvasComboBox::keyPressEvent(QKeyEvent* keyEvent)
{
QLineEdit::keyPressEvent(keyEvent);
if (keyEvent->key() == Qt::Key_Down)
{
if (m_comboBoxMenu.isHidden())
{
ClearFilter();
DisplayMenu();
}
QModelIndex selectedIndex = m_comboBoxMenu.GetSelectedSourceIndex();
if (!selectedIndex.isValid())
{
selectedIndex = m_modelInterface->FindIndexForName(m_selectedName);
}
QModelIndex mappedIndex;
QModelIndex sourceIndex;
if (selectedIndex.isValid())
{
sourceIndex = m_modelInterface->GetNextIndex(selectedIndex);
}
else
{
sourceIndex = m_modelInterface->GetDefaultIndex();
}
while (sourceIndex != selectedIndex)
{
mappedIndex = m_comboBoxMenu.GetProxyModel()->mapFromSource(sourceIndex);
if (mappedIndex.isValid())
{
break;
}
sourceIndex = m_modelInterface->GetNextIndex(sourceIndex);
}
selectedIndex = sourceIndex;
m_comboBoxMenu.SetSelectedIndex(mappedIndex);
QString typeName = m_modelInterface->GetNameForIndex(selectedIndex);
if (!typeName.isEmpty())
{
setText(typeName);
setSelection(0, static_cast<int>(typeName.size()));
m_completer.setCompletionPrefix(typeName);
}
keyEvent->accept();
}
else if (keyEvent->key() == Qt::Key_Up)
{
if (m_comboBoxMenu.isHidden())
{
m_comboBoxMenu.GetProxyModel()->SetFilter("");
DisplayMenu();
}
QModelIndex selectedIndex = m_comboBoxMenu.GetSelectedSourceIndex();
if (!selectedIndex.isValid())
{
selectedIndex = m_modelInterface->FindIndexForName(m_selectedName);
}
QModelIndex mappedIndex;
QModelIndex sourceIndex;
if (selectedIndex.isValid())
{
sourceIndex = m_modelInterface->GetPreviousIndex(selectedIndex);
}
else
{
sourceIndex = m_modelInterface->GetPreviousIndex(m_modelInterface->GetDefaultIndex());
}
while (sourceIndex != selectedIndex)
{
mappedIndex = m_comboBoxMenu.GetProxyModel()->mapFromSource(sourceIndex);
if (mappedIndex.isValid())
{
break;
}
sourceIndex = m_modelInterface->GetPreviousIndex(sourceIndex);
}
selectedIndex = sourceIndex;
m_comboBoxMenu.SetSelectedIndex(mappedIndex);
QString typeName = m_comboBoxMenu.GetInterface()->GetNameForIndex(sourceIndex);
if (!typeName.isEmpty())
{
setText(typeName);
setSelection(0, static_cast<int>(typeName.size()));
m_completer.setCompletionPrefix(typeName);
}
keyEvent->accept();
}
else if (keyEvent->key() == Qt::Key_Escape)
{
ResetComboBox();
keyEvent->accept();
}
}
void GraphCanvasComboBox::OnViewScrolled()
{
ResetComboBox();
}
void GraphCanvasComboBox::OnViewCenteredOnArea()
{
ResetComboBox();
}
void GraphCanvasComboBox::OnZoomChanged(qreal /*zoomLevel*/)
{
}
void GraphCanvasComboBox::UserSelectedIndex(const QModelIndex& selectedIndex)
{
QModelIndex previousIndex = m_modelInterface->FindIndexForName(m_selectedName);
if (previousIndex != selectedIndex)
{
SetSelectedIndex(selectedIndex);
Q_EMIT OnUserActionComplete();
}
}
void GraphCanvasComboBox::OnTextChanged()
{
DisplayMenu();
UpdateFilter();
}
void GraphCanvasComboBox::OnOptionsClicked()
{
if (m_comboBoxMenu.isHidden())
{
m_comboBoxMenu.GetProxyModel()->SetFilter("");
DisplayMenu();
}
else
{
m_comboBoxMenu.accept();
}
}
void GraphCanvasComboBox::OnReturnPressed()
{
const bool allowReset = false;
if (SubmitData(allowReset))
{
m_comboBoxMenu.accept();
}
else
{
setText("");
UpdateFilter();
}
Q_EMIT OnUserActionComplete();
// When we press enter, we will also get an editing complete signal. We want to ignore that since we handled it here.
m_ignoreNextComplete = true;
}
void GraphCanvasComboBox::OnEditComplete()
{
if (m_ignoreNextComplete)
{
m_ignoreNextComplete = false;
return;
}
SubmitData(false);
m_closeState = CloseMenuState::Reject;
m_closeTimer.start();
}
void GraphCanvasComboBox::ClearFilter()
{
m_comboBoxMenu.GetProxyModel()->SetFilter("");
}
void GraphCanvasComboBox::UpdateFilter()
{
m_comboBoxMenu.GetProxyModel()->SetFilter(GetUserInputText());
}
void GraphCanvasComboBox::CloseMenu()
{
switch (m_closeState)
{
case CloseMenuState::Accept:
m_comboBoxMenu.accept();
default:
m_comboBoxMenu.reject();
}
m_closeState = CloseMenuState::Reject;
}
void GraphCanvasComboBox::OnMenuFocusIn()
{
m_popUpMenuInFocus = true;
m_focusTimer.start();
}
void GraphCanvasComboBox::OnMenuFocusOut()
{
m_popUpMenuInFocus = false;
m_focusTimer.start();
}
void GraphCanvasComboBox::HandleFocusState()
{
bool focusState = m_lineEditInFocus || m_popUpMenuInFocus;
if (focusState != m_hasFocus)
{
m_hasFocus = focusState;
if (m_hasFocus)
{
Q_EMIT OnFocusIn();
}
else
{
Q_EMIT OnFocusOut();
HideMenu();
}
}
}
bool GraphCanvasComboBox::DisplayIndex(const QModelIndex& index)
{
QSignalBlocker signalBlocker(this);
QString name = m_modelInterface->GetNameForIndex(index);
if (!name.isEmpty())
{
m_completer.setCompletionPrefix(name);
setText(name);
ClearFilter();
}
else
{
if (!m_selectedName.isEmpty())
{
QModelIndex currentIndex = m_modelInterface->FindIndexForName(m_selectedName);
if (currentIndex != index)
{
DisplayIndex(currentIndex);
}
}
else
{
m_completer.setCompletionPrefix("");
setText("");
UpdateFilter();
}
}
return !m_selectedName.isEmpty();
}
bool GraphCanvasComboBox::SubmitData(bool allowReset)
{
QString inputName = text();
QModelIndex inputIndex = m_modelInterface->FindIndexForName(inputName);
// We didn't input a valid type. So default to our last previously known value.
if (!inputIndex.isValid())
{
if (allowReset)
{
QModelIndex lastIndex = m_modelInterface->FindIndexForName(m_selectedName);
DisplayIndex(lastIndex);
inputIndex = lastIndex;
}
}
else
{
SetSelectedIndex(inputIndex);
}
return inputIndex.isValid();
}
void GraphCanvasComboBox::DisplayMenu()
{
if (!m_recursionBlocker)
{
QScopedValueRollback<bool> valueRollback(m_recursionBlocker, true);
if (m_comboBoxMenu.isHidden())
{
Q_EMIT OnMenuAboutToDisplay();
ViewNotificationBus::Handler::BusConnect(m_viewId);
qreal zoomLevel = 1.0;
ViewRequestBus::EventResult(zoomLevel, m_viewId, &ViewRequests::GetZoomLevel);
if (zoomLevel < 1.0)
{
zoomLevel = 1.0;
}
m_comboBoxMenu.GetInterface()->SetFontScale(zoomLevel);
m_comboBoxMenu.ShowMenu();
UpdateMenuPosition();
}
}
if (!m_disableHidingStateSetter.HasState())
{
m_disableHidingStateSetter.SetState(true);
}
}
QString GraphCanvasComboBox::GetUserInputText()
{
QString lineEditText = text();
// The QCompleter doesn't seem to update the completion prefix when you delete anything, only when things are added.
// To get it to update correctly when the user deletes something, I'm using the combination of things:
//
// 1) If we have a completion, that text will be auto filled into the quick filter because of the completion model.
// So, we will compare those two values, and if they match, we know we want to search using the completion prefix.
//
// 2) If they don't match, it means that user deleted something, and the Completer didn't update it's internal state, so we'll just
// use whatever is in the text box.
//
// 3) When the text field is set to empty, the current completion gets invalidated, but the prefix doesn't, so that gets special cased out.
//
// Extra fun: If you type in something, "Like" then delete a middle character, "Lie", and then put the k back in. It will auto complete the E
// visually but the completion prefix will be the entire word.
if (completer()
&& completer()->currentCompletion().compare(lineEditText, Qt::CaseInsensitive) == 0
&& !lineEditText.isEmpty())
{
lineEditText = completer()->completionPrefix();
}
return lineEditText;
}
void GraphCanvasComboBox::UpdateMenuPosition()
{
if (!m_comboBoxMenu.isHidden())
{
QRect dialogGeometry = m_comboBoxMenu.geometry();
dialogGeometry.moveTopLeft(m_anchorPoint);
dialogGeometry.setWidth(aznumeric_cast<int>(m_displayWidth));
m_comboBoxMenu.setGeometry(dialogGeometry);
}
}
}
#include <Source/Widgets/moc_GraphCanvasComboBox.cpp>