Hello all,
I again need help.
I have app written in c/c++ in gtk4. In App is list box with quite a lot rows and I would like that app after pressing some letter (e.g. a) move to first row which start with this letter.
In my code I have function “keyPress” where I can recognize what letter was pressed (switch will be enhanced in real app). I can find index of row which starts with pressed letter.
But I can not find any gtk function which moves me to this row. Exists this function?
Thanks for any advice!
my testing code:
#include <gtk/gtk.h>
#include <iostream>
#include <string>
#include <vector>
#include <algorithm> //to make string lowercases
using namespace std;
GtkWidget *lBox;
gboolean
keyPress (GtkWidget *drawing_area,
guint keyval,
guint keycode,
GdkModifierType state,
GtkEventControllerKey *event_controller)
{
string comparedString;
switch (keyval)
{
case GDK_KEY_a:
std::cout << "Pressed - a" << std::endl;
comparedString = "a";
break;
case GDK_KEY_b:
std::cout << "Pressed - b" << std::endl;
comparedString = "b";
break;
case GDK_KEY_c:
std::cout << "Pressed - c" << std::endl;
comparedString = "c";
break;
case GDK_KEY_d:
std::cout << "Pressed - d" << std::endl;
comparedString = "d";
break;
case GDK_KEY_e:
std::cout << "Pressed - e" << std::endl;
comparedString = "e";
break;
}
int index = 0;
GtkListBoxRow* testedRow;
string rowText;
//loop for finding row begining with pressed letter
while ( (testedRow = gtk_list_box_get_row_at_index (GTK_LIST_BOX(lBox),index++)) != NULL ) {
rowText = gtk_label_get_text(GTK_LABEL(gtk_list_box_row_get_child (GTK_LIST_BOX_ROW(testedRow))));
transform(rowText.begin(), rowText.end(), rowText.begin(),[](unsigned char c){ return tolower(c); });
//cout << "row" << index << ": " << rowText << " -find result=" << rowText.find(comparedString) << endl;
if (rowText.find(comparedString) == 0)
{
break;
}
}
if (testedRow == NULL)
{
cout << "this letter is not in listbox" << endl;
}
else
{
cout << "fist row with letter " << comparedString << " is at row " << index << endl;
//FOCUS at row index
}
return TRUE;
}
static void appActivate (GApplication *app, gpointer user_data) {
GtkWidget *win = gtk_application_window_new (GTK_APPLICATION (app));
gtk_window_set_default_size (GTK_WINDOW (win), 400, 300);
GtkWidget *hBox = gtk_box_new (GTK_ORIENTATION_HORIZONTAL,10);
gtk_box_set_homogeneous(GTK_BOX(hBox),true);
gtk_window_set_child (GTK_WINDOW (win), hBox);
GtkWidget *skrollBox = gtk_scrolled_window_new();
gtk_box_append (GTK_BOX (hBox), skrollBox);
lBox = gtk_list_box_new();
gtk_scrolled_window_set_child(GTK_SCROLLED_WINDOW (skrollBox), lBox);
gtk_list_box_set_selection_mode (GTK_LIST_BOX(lBox), GTK_SELECTION_MULTIPLE);
//prepare many rows in list box
vector<string> startLetter = {"x", "a", "r" ,"B", "g", "c"};
for ( unsigned int x =0; x < startLetter.size(); ++x )
{
for (int i = 0; i < 40; i++) {
string jmeno = startLetter.at(x) + "test " + to_string(i);
GtkWidget* lab = gtk_label_new(jmeno.c_str());
gtk_list_box_append(GTK_LIST_BOX(lBox), lab);
}
}
//key shortcut
GtkEventController *event_controller = gtk_event_controller_key_new ();
g_signal_connect_object (event_controller, "key-pressed", G_CALLBACK (keyPress), NULL, G_CONNECT_SWAPPED);
gtk_widget_add_controller (GTK_WIDGET (win), event_controller);
//end - key shortcut
gtk_widget_show (win);
}
int main(int argc, char **argv) {
GtkApplication *app;
app = gtk_application_new ("testing.app", G_APPLICATION_FLAGS_NONE);
g_signal_connect (app, "activate", G_CALLBACK (appActivate), NULL);
return g_application_run (G_APPLICATION (app), NULL, NULL);
g_object_unref (app);
return 0;
}