Skip to content

GTK file-open case-insensitive filters #157

@inflex

Description

@inflex

Good day, many thanks for NFD-extended, it has been a great replacement for my project, thank you so much.

One thing I had to tackle was implementing GTK/linux case-insensitive filters, and I honestly don't know if I missed something obvious, in which case I duly apologise, but I ended up butchering your good work to drop in a piece of my old code from my prior file-picking.

I did see that gtkmm has implemented in case insensitive suffix matching with;

void Gtk::FileFilter::add_suffix

( https://gnome.pages.gitlab.gnome.org/gtkmm/classGtk_1_1FileFilter.html )

but I'm not sure how that aligns with the API/lib utilised here.

For the interim, and I apologise for the code to follow, I've created this Frankenstein's monster of a blob ( nfd_gtk.cpp );

I did also clobber the building of the filter name as I was passing many extensions ( 22 ).

(EDIT: Converted to use std::string so as to provide memory safety)

void AddFiltersToDialog(GtkFileChooser* chooser,
		const nfdnfilteritem_t* filterList,
		nfdfiltersize_t filterCount) {
	if (filterCount) {
		assert(filterList);

		// we have filters to add ... format and add them
		for (nfdfiltersize_t index = 0; index != filterCount; ++index) {
			GtkFileFilter* filter = gtk_file_filter_new();
			const nfdnchar_t *p_spec = filterList[index].spec;

			while (p_spec && *p_spec) {

				// Using std::string for easy memory-safe usage ( requires <string> )
				std::string cis_filter = std::string("*."); 

				// For each character in the individual file extension, expand out to [aA] if isalpha()
				while (*p_spec != '\0' && *p_spec != ',') {
					char tmp[5];
					if (isalpha(*p_spec)) {
						snprintf(tmp, sizeof(tmp), "[%c%c]", tolower(*p_spec), toupper(*p_spec));
					} else {
						snprintf(tmp, sizeof(tmp), "%c", *p_spec);
					}
					cis_filter += std::string(tmp);
					p_spec++;
				}

				// Add the case-insensitive variant to the filter
				gtk_file_filter_add_pattern(filter, cis_filter.c_str());

				// Jump to the next pspec char if there's one so that the while loop starts with a new glob filter
				if (*p_spec == ',') p_spec++;

			} // for each char in the filter spec

			// add to the filter set
			gtk_file_filter_set_name(filter, filterList[index].name);

			// add filter to chooser
			gtk_file_chooser_add_filter(chooser, filter);
		} // for each filter 
	} // if there's filters

	/* always append a wildcard option to the end*/

	GtkFileFilter* filter = gtk_file_filter_new();
	gtk_file_filter_set_name(filter, "All files");
	gtk_file_filter_add_pattern(filter, "*");
	gtk_file_chooser_add_filter(chooser, filter);
}

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions