Reputation: 501
I have Qt application with splitter based view: on the left side is QListWidget containing files that can be selected; selected file's contents are displayed in an appropriate format on the right side of the splitter. This part works fine.
I now need to add compare functionality: if one item is selected in QListWidget then its contents are displayed on the right side; if another item is selected than I would like to display diff result instead. (Things are a bit more complicated than that because not all items can be diff’ed.)
What I would like to do is have a single selection capability intact but then also enable only CTRL + mouse click for second selection. I tried using QAbstractItemView::ExtendedSelection and then filtering out Shift and mouse drag but had no luck with that approach: while I could capture Shift key with keyPressEvent() I couldn't prevent selection (I hoped just dropping the event would suffice); as for drag I used mouseMoveEvent() hoping to drop event when state changes to DragSelectingState but that didn't work either.
I then considered sticking with single selection but opening context menu on right click on the second item -- while right click does emit itemSelectionChanged() signal, I haven't figured out yet what to do with this since I don't know which item was right-clicked.
Open to any other creative suggestions that do not involve adding additional UI elements – I can’t have any extra buttons, combo boxes etc.
Upvotes: 1
Views: 2072
Reputation: 501
Still haven't figured out how to limit selections in QListWidget to just one or two, but got context menu on right click on the second item working.
Just set selection mode to QAbstractItemView::SingleSelection then reimplemented mousePressEvent() and contextMenuEvent().
class MyListView : public QListWidget
{
Q_OBJECT
public:
ListView();
virtual ~ListView() {}
/** Add item to the list.
@param itemName Item's display name.
@param itemHandle Value to return if item selected.
*/
void AddItem(const QString itemName, const quint32 itemHandle);
private slots:
void slot_ItemSelectionChanged(void);
void slot_Option1(void);
void slot_Option1(void);
signals:
void signal_ItemSelectionChanged(const qint32 itemHandle);
private:
void mousePressEvent(QMouseEvent* mousePressEvent);
void contextMenuEvent(QContextMenuEvent* menuEvent);
QListWidgetItem *m_selectedItem; ///< Pointer to the currently selected item.
QListWidgetItem *m_rightClickedItem; ///< Pointer to right-clicked item in the list.
QAction* m_menuOption1; ///< Menu option 1.
QAction* m_menuOption2; ///< Menu option 2.
QMenu* m_myListContextMenu; ///< Menu with all List View menu actions.
};
MyListView::MyListView()
{
setSelectionMode(QAbstractItemView::SingleSelection);
// create my context menu with 2 options
m_menuOption1 = new QAction(tr("option 1"), this);
m_menuOption1 ->setEnabled(true);
m_menuOption2 = new QAction(tr("option 2"), this);
m_menuOption2 ->setEnabled(true);
m_myListContextMenu = new QMenu(this);
m_myListContextMenu ->addAction(m_menuOption1);
m_myListContextMenu ->addAction(m_menuOption2);
bool allConnected = true;
// process primary selection
allConnected &= connect(this, SIGNAL(itemSelectionChanged(void)), this, SLOT(slot_ItemSelectionChanged(void)));
// process menu option 1
allConnected &= connect(m_menuOption1, SIGNAL(triggered()), this, SLOT(slot_Option1()));
// process menu option 2
allConnected &= connect(m_menuOption2, SIGNAL(triggered()), this, SLOT(slot_Option2()));
if (!allConnected )
{
assert(0);
}
}
void ListView::slot_ItemSelectionChanged(void)
{
if (currentItem() != m_selectedItem)
{
m_selectedItem = currentItem();
emit signal_ItemSelectionChanged(m_selectedItem->type());
}
} // end of method slot_ItemSelectionChanged()
void MyListView::contextMenuEvent(QContextMenuEvent* menuEvent)
{
m_rightClickedItem = itemAt(menuEvent->pos());
// do my prep stuff here specific to right-clicked item
// in case one of menu options gets selected
m_listMenu->exec(menuEvent->globalPos());
} // end of method contextMenuEvent()
void MyListView::mousePressEvent(QMouseEvent* mousePressEvent)
{
// drop right mouse button event as it would otherwise cause a change of selection
if (!(mousePressEvent->buttons() & Qt::RightButton))
{
QListWidget::mousePressEvent(mousePressEvent);
}
} // end of method mousePressEvent()
Upvotes: 0