GtkComboBoxText
的完成,同时具有“静态”和“动态”方面? “静态”方面是因为一些条目已知并在构建时使用gtk_combo_box_text_append_text
添加到组合框文本中。 “动态”方面是因为我还需要通过某些回调函数进行补全,即在键入多个字符后动态地完成-在创建GtkComboBoxText
小部件之后。我的应用程序类似于Guile、SCM或Bigloo等,使用Boehm的GC(当然不包括GTK对象)。它可以被视为一个实验性的“持久性”动态类型编程语言实现,具有集成的编辑器,针对Debian/Linux/x86-64编写,使用系统GTK3.21库,它使用C99编写(其中一些是生成的),并使用GCC6编译。 (我不关心非Linux系统,早于GTK3.20的GTK3库,旧于GCC6的GCC编译器) 问题细节
我正在输入(输入到GtkComboBoxText
中)一个名称或一个对象ID。
name的命名方式类似于C标识符,但必须以字母开头且不能以下划线结尾。例如:
comment
、if
、the_GUI
、the_system
、payload_json
或x1
都是有效的名称(但或_a0bcd
是无效的名称,因为它们以下划线开头或结尾)。我目前有很多名称,但可能会有几千个。因此,一旦只输入了一个或两个字母,就提供自动完成功能是合理的,并且名称的完成可以静态进行,因为它们不是很多(所以我认为对于每个名称调用foobar_
gtk_combo_box_append_text
是合理的)。object-id以下划线开头,后跟一个数字,然后具有18个字母数字字符(类似随机的)。例如:
_5Hf0fFKvRVa71ZPM0
、_8261sbF1f9ohzu2Iu
、_0BV96V94PJIn9si1K
可能是object-id。实际上,它是96个几乎随机的位(可能只有2的94次方是可能的)。object-id扮演UUIDs的角色(在这种意义上,它被假定为对于不同的对象是全球唯一的),但具有C友好的语法。我目前有几十个对象ID,但可能会有数十万个(或者甚至可能有一百万个)。但是,假设像_6S3
或_22z
这样的前缀仅存在合理数量的(可能最多只有一打,肯定不超过一千个)object-id,在输入四个字符的前缀后,注册(静态的)所有对象id是不合理的。完成必须在输入四个字符之后动态发生。
因此,我希望有一个自动完成功能,既可以用于名称(例如,键入一个字母,后面可能跟着另一个字母数字字符就足以提供最多一百个选择的完成),也可以用于对象 ID(键入四个字符,如_826
就足以触发最多几十个选择的完成,如果不幸的话,可能会有一千个)。
因此,键入三个键 p a tab 将提供一些名称的完成,例如 payload_json
或 payload_vectval
等等...,而键入五个键 _ 5 H f tab 将提供非常少的对象ID,特别是 _5Hf0fFKvRVa71ZPM0
示例不完整代码
到目前为止,我编写了以下代码:
static GtkWidget *
mom_objectentry (void)
{
GtkWidget *obent = gtk_combo_box_text_new_with_entry ();
gtk_widget_set_size_request (obent, 30, 10);
mo_value_t namsetv = mo_named_objects_set ();
我有使用Boehm垃圾回收的值,并且
mo_value_t
是指向任何这些值的指针。 值可以是标记整数、指向字符串、对象、元组或一组对象的指针。因此,namesetv
现在包含了一组命名对象(可能少于几千个命名对象)。 int nbnam = mo_set_size (namsetv);
MOM_ASSERTPRINTF (nbnam > 0, "bad nbnam");
mo_value_t *namarr = mom_gc_alloc (nbnam * sizeof (mo_value_t));
int cntnam = 0;
for (int ix = 0; ix < nbnam; ix++)
{
mo_objref_t curobr = mo_set_nth (namsetv, ix);
mo_value_t curnamv = mo_objref_namev (curobr);
if (mo_dyncast_string (curnamv))
namarr[cntnam++] = curnamv;
}
qsort (namarr, cntnam, sizeof (mo_value_t), mom_obname_cmp);
for (int ix = 0; ix < cntnam; ix++)
gtk_combo_box_text_append_text (GTK_COMBO_BOX_TEXT (obent),
mo_string_cstr (namarr[ix]));
此时,我已经按名称排序了所有的(最多几千个)并使用gtk_combo_box_text_append_text
“静态”地添加了它们。
GtkWidget *combtextent = gtk_bin_get_child (GTK_BIN (obent));
MOM_ASSERTPRINTF (GTK_IS_ENTRY (combtextent), "bad combtextent");
MOM_ASSERTPRINTF (gtk_entry_get_completion (GTK_ENTRY (combtextent)) ==
NULL, "got completion in combtextent");
我有点惊讶地发现
gtk_entry_get_completion(GTK_ENTRY(combtextent))
为空。但是我卡在这里了。我在思考:
1.编写一些
mom_set_complete_objectid(const char*prefix)
,它会返回一个垃圾回收的mo_value_t
集合,该集合表示具有至少四个字符的前缀(如"_47n"
)的对象。对我来说这非常容易编码,并且几乎完成了。2.制作自己的本地
GtkEntryCompletion* mycompl = ...
,可以按照我的要求进行完成。然后我将使用gtk_entry_set_completion(GTK_ENTRY(combtextent), mycompl);
将其放入我的gtk-combo-box-text的文本输入框combtextent
中。
它应该使用使用gtk_combo_box_text_append_text
添加的条目作为“静态”名称完成角色吗?如何使用从我的mom_set_complete_objectid
返回的动态设置值进行动态完成;给定一些对象指针obr
和一些char bufid [20];
,我可以轻松快速地使用mo_cstring_from_hi_lo_ids(bufid, obr->mo_ob_hid, obr->mo_ob_loid)
填充该对象的对象ID obr
..
我不知道如何编写上述内容。 供参考,我现在只返回组合框文本:
// if the entered text starts with a letter, I want it to be
// completed with the appended text above if the entered text starts
// with an undersore, then a digit, then two alphanum (like _0BV or
// _6S3 for example), I want to call a completion function.
#warning objectentry: what should I code here?
return obent;
} /* end mom_objectentry */
我的方法是否正确?
上面的mom_objectentry
函数用于填充具有短生命周期的模态对话框。
我更喜欢简单的代码而不是效率。实际上,我的代码是临时的(我希望启动我的语言,并生成所有的C代码!)在实践中,我可能只有几百个名称和最多几万个对象ID。因此,性能并不是非常重要,但编写简单的代码(一些概念上的“一次性”代码)更加重要。
如果可能的话,我不想添加自己的GTK类。我更喜欢使用现有的GTK类和小部件,通过GTK信号和回调进行自定义。
上下文
我的应用程序是一种试验性的编程语言和实现,具有接近Scheme或Python(或JavaScript,忽略原型方面...)的语义,但具有大不相同的语法(在GTK小部件中显示和输入),使用Boehm垃圾收集器对值进行垃圾回收(包括对象、集合、元组、字符串...)。通常情况下,值(包括对象)是持久的(除了与GTK相关的数据:应用程序从一个几乎为空的窗口开始)。整个语言堆在某些Sqlite“数据库”中以类似JSON的语法持久化(在应用程序退出时生成),并在启动时重新加载_momstate.sql
。对象ID对于在GTK小部件中向用户显示对象引用、进行持久化以及生成与对象相关的C代码(例如,ID为_76f7e2VcL8IJC1hq6
的对象可能与一些生成的C代码中的mo_76f7e2VcL8IJC1hq6
标识符相关联;这部分原因是我有自己的对象ID格式,而不是使用UUID)。
PS. 我的C代码是GPLv3自由软件,可在github上获得。它是MELT监视器,分支expjs,提交e2b3b99ef66394...。
NB:这里提到的对象是我的语言对象,而不是GTK对象。它们都有唯一的对象ID,其中一些但不是大多数都有名称。
libgtk-3.so.0
的C函数。因此,也许你可以在那里列出一些函数... - Basile StarynkevitchGtkComboBox
中使用GtkListStore
模型来维护匹配关键字的副本列表(让Gtk+根据需要引用计数和垃圾回收它们),并使用“popup”信号触发列表重建。根据我粗略的测试程序,这似乎对大约一千个匹配项有效(尽管它可能只是创建GtkListStore
的愚蠢方式是瓶颈)。我不认为这是一个完整或真正的答案;只是我朝着解决方案的起点。 - Nominal Animal