From 9ad5743681cef44a3db1a3f13173cf308269bf21 Mon Sep 17 00:00:00 2001
From: Sebastião Guerra <sebastiao.luiz.guerra@gmail.com>
Date: Wed, 21 Oct 2026 08:23:15 -0300
Subject: TQComboBox: add navigation of popup-backed comboboxes with
 Up/Down/Home/End keys
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

Signed-off-by: Sebastião Guerra <sebastiao.luiz.guerra@gmail.com>
Signed-off-by: Michele Calgaro <michele.calgaro@yahoo.it>
---
 src/widgets/tqcombobox.cpp | 71 ++++++++++++++++++++++++++++++++++++++--------
 src/widgets/tqcombobox.h   |  1 +
 2 files changed, 60 insertions(+), 12 deletions(-)

diff --git a/src/widgets/tqcombobox.cpp b/src/widgets/tqcombobox.cpp
index c918225ad..f23adecb4 100644
--- a/src/widgets/tqcombobox.cpp
+++ b/src/widgets/tqcombobox.cpp
@@ -567,8 +567,7 @@ TQComboBox::TQComboBox( bool rw, TQWidget *parent, const char *name )
     d = new TQComboBoxData( this );
     setUpListBox();
 
-    if(d->popup() && style().styleHint(TQStyle::SH_ComboBox_Popup, this))
-	d->popup()->setItemChecked(d->current, false);
+    setPopupItemChecked( d->current, false );
     d->current = 0;
     d->maxCount = INT_MAX;
     setSizeLimit(10);
@@ -904,8 +903,7 @@ void TQComboBox::clear()
 	d->popup()->clear();
     }
 
-    if(d->popup() && style().styleHint(TQStyle::SH_ComboBox_Popup, this))
-	d->popup()->setItemChecked(d->current, false);
+    setPopupItemChecked( d->current, false );
     d->current = 0;
     if ( d->ed ) {
 	d->ed->setText( TQString::fromLatin1("") );
@@ -1056,9 +1054,9 @@ void TQComboBox::setCurrentItem( int index )
     if ( d->usingListBox() && !( listBox()->item(index) && listBox()->item(index)->isSelectable() ) )
 	return;
 
-    if(d->popup() && style().styleHint(TQStyle::SH_ComboBox_Popup, this))
-	d->popup()->setItemChecked(d->current, false);
+    setPopupItemChecked( d->current, false );
     d->current = index;
+    setPopupItemChecked( d->current, true );
     d->completeAt = 0;
     if ( d->ed ) {
 	d->ed->setText( text( index ) );
@@ -1086,8 +1084,7 @@ void TQComboBox::clearCurrentItem()
     bool hadCurrent = d->current >= 0;
     if ( hadCurrent ) {
 	if ( d->popup() ) {
-	    if ( style().styleHint(TQStyle::SH_ComboBox_Popup, this) )
-		d->popup()->setItemChecked(d->current, false);
+	    setPopupItemChecked( d->current, false );
 	    if ( d->poppedUp )
 		d->popup()->setActiveItem(-1);
 	}
@@ -1169,9 +1166,9 @@ void TQComboBox::internalActivate( int index )
 {
     if ( d->current != index ) {
 	if ( !d->usingListBox() || listBox()->item( index )->isSelectable() ) {
-	    if(d->popup() && style().styleHint(TQStyle::SH_ComboBox_Popup, this))
-		d->popup()->setItemChecked(d->current, false);
+	    setPopupItemChecked( d->current, false );
 	    d->current = index;
+	    setPopupItemChecked( d->current, true );
 	    currentChanged();
 	}
     }
@@ -1474,6 +1471,44 @@ void TQComboBox::keyPressEvent( TQKeyEvent *e )
     } else if ( d->usingListBox() && e->key() == Key_Down ) {
 	if ( ++c < count() )
 	    setCurrentItem( c );
+    } else if ( !d->usingListBox() && !d->ed && !d->poppedUp &&
+			( e->key() == Key_Up || e->key() == Key_Down ||
+			  e->key() == Key_Home || e->key() == Key_End ) ) {
+	int step = 0;
+	int next = 0;
+	switch ( e->key() ) {
+	case Key_Up:
+	    step = -1;
+	    next = c < 0 ? count() - 1 : c - 1;
+	    break;
+	case Key_Down:
+	    step = 1;
+	    next = c < 0 ? 0 : c + 1;
+	    break;
+	case Key_Home:
+	    step = 1;
+	    next = 0;
+	    break;
+	case Key_End:
+	    step = -1;
+	    next = count() - 1;
+	    break;
+	}
+
+	bool found = false;
+	for ( ; next >= 0 && next < count(); next += step ) {
+	    TQMenuItem *item = d->popup()->findItem( next );
+	    if ( item && !item->isSeparator() && item->isEnabled() && item->isVisible() ) {
+		found = true;
+		break;
+	    }
+	}
+	if ( !found || next == c ) {
+	    // Ignore the key press if no selectable item was found or the selection would not change
+	    e->ignore();
+	    return;
+	}
+	setCurrentItem( next );
     } else if ( d->usingListBox() && e->key() == Key_Home && ( !d->ed || !d->ed->hasFocus() ) ) {
 	setCurrentItem( 0 );
     } else if ( d->usingListBox() && e->key() == Key_End && ( !d->ed || !d->ed->hasFocus() ) ) {
@@ -1618,8 +1653,7 @@ void TQComboBox::popup()
 	    }
 	}
 	d->popup()->installEventFilter( this );
-	if(d->popup() && style().styleHint(TQStyle::SH_ComboBox_Popup, this))
-	    d->popup()->setItemChecked(this->d->current, true);
+	setPopupItemChecked( d->current, true );
 	d->popup()->popup( mapToGlobal( TQPoint(0,0) ), this->d->current );
 	update();
     } else {
@@ -1741,6 +1775,19 @@ void TQComboBox::popDownListBox()
 }
 
 
+/*!
+  \internal
+  Sets the checked state of popup item \a index, but only for
+  popup-backed comboboxes whose style uses a checkable popup
+  (SH_ComboBox_Popup). Does nothing otherwise.
+*/
+
+void TQComboBox::setPopupItemChecked( int index, bool checked )
+{
+    if ( d->popup() && style().styleHint( TQStyle::SH_ComboBox_Popup, this ) )
+	d->popup()->setItemChecked( index, checked );
+}
+
 /*!
   \internal
   Re-indexes the identifiers in the popup list.
diff --git a/src/widgets/tqcombobox.h b/src/widgets/tqcombobox.h
index 19fdf90dc..9e3af7d5c 100644
--- a/src/widgets/tqcombobox.h
+++ b/src/widgets/tqcombobox.h
@@ -187,6 +187,7 @@ protected:
 private:
     void	setUpListBox();
     void	setUpLineEdit();
+    void	setPopupItemChecked( int index, bool checked );
     void	popDownListBox();
     void	reIndex();
     void	currentChanged();
-- 
cgit v1.2.3

