Author: jsmeix Date: Fri Dec 11 14:20:38 2009 New Revision: 60068 URL: http://svn.opensuse.org/viewcvs/yast?rev=60068&view=rev Log: Enhanced Printer::DeriveModelName and Printer::DeriveDriverFilterString so that it was possible in basicadd.ycp and basicmodify.ycp to replace all those various explicite code blocks to set driver_filter_input_text and driver_filter_string by only calling Printer::DeriveModelName and Printer::DeriveDriverFilterString respectively. Modified: trunk/printer/VERSION trunk/printer/src/Printer.ycp trunk/printer/src/basicadd.ycp trunk/printer/src/basicmodify.ycp trunk/printer/src/connectionwizard.ycp Modified: trunk/printer/VERSION URL: http://svn.opensuse.org/viewcvs/yast/trunk/printer/VERSION?rev=60068&r1=... ============================================================================== --- trunk/printer/VERSION (original) +++ trunk/printer/VERSION Fri Dec 11 14:20:38 2009 @@ -1 +1 @@ -2.19.1 +2.19.2 Modified: trunk/printer/src/Printer.ycp URL: http://svn.opensuse.org/viewcvs/yast/trunk/printer/src/Printer.ycp?rev=60068... ============================================================================== --- trunk/printer/src/Printer.ycp (original) +++ trunk/printer/src/Printer.ycp Fri Dec 11 14:20:38 2009 @@ -170,11 +170,11 @@ /** * PPD database: - * the database is created anew in Printer::CreateDatabase() which calls + * the database is created anew in CreateDatabase() which calls * the bash script "/usr/lib/YaST2/bin/create_ppd_database" * which outputs on stdout a YCP list of @ref printer_ppd_map * where the last list entry is an emtpy map. - * Printer::CreateDatabase() leaves manufacturer and modelname empty because + * CreateDatabase() leaves manufacturer and modelname empty because * it would take several minutes (instead of a few seconds) to fill them up * (see the comments in create_ppd_database). Both fields can be filled up * during runtime for particular PPDs (e.g. for a more detailed PPD selection @@ -201,7 +201,7 @@ /** * Autodetected printers: - * Determined at runtime via Printer::AutodetectPrinters() which calls the bash script + * Determined at runtime via AutodetectPrinters() which calls the bash script * "/usr/lib/YaST2/bin/autodetect_printers" * which outputs on stdout a YCP list of @ref autodetected_printer_map * where the last list entry is an emtpy map. @@ -239,7 +239,7 @@ /** * Autodetected queues: - * Determined at runtime via Printer::AutodetectQueues() which calls the bash script + * Determined at runtime via AutodetectQueues() which calls the bash script * "/usr/lib/YaST2/bin/autodetect_print_queues" * which outputs on stdout a YCP list of @ref autodetected_queue_map * where the last list entry is an emtpy map. @@ -292,7 +292,7 @@ /** * Driver options (options in the PPD for one specific existing queue): - * Determined at runtime via Printer::DetermineDriverOptions( "queue_name") + * Determined at runtime via DetermineDriverOptions( "queue_name") * which calls the bash script "/usr/lib/YaST2/bin/determine_printer_driver_options" * which outputs on stdout a YCP list of @ref driver_option_map * where the last list entry is an emtpy map. @@ -760,122 +760,191 @@ /** * Derive a reasonable model info from an arbitrary description string. - * @param string from which a model is derived. + * @param string from which a model info is derived. + * @param integer how many words the model info can contain. * @return string (possibly the empty string) */ -global string DeriveModelName( string description ) +global string DeriveModelName( string description, integer max_words ) { string model_info = ""; - list <string> description_words = splitstring( description, " " ); - // Remove empty words because a sequence of spaces results empty words in description_words + list <string> words = splitstring( description, " " ); + // Remove empty words because a sequence of spaces results empty words in the list of words // for example "ACME Funprinter" (two spaces!) results ["ACME","","Funprinter"]. // In Printer.ycp and basicmodify.ycp there are lines like // description = model + " with driver " + description; // new_description = model + " with driver " + new_description; // Avoid having "with" and/or "driver" in the model_info. - description_words = filter( string word, - description_words, - { return( "" != word && "with" != word && "driver" != word ); - } - ); - // Use the description only if its first word is actually a known manufacturer: - boolean description_starts_with_known_manufacturer = false; - foreach( string known_manufacturer, - known_manufacturers, - { if( tolower( description_words[0]:"" ) == tolower( known_manufacturer ) ) - { description_starts_with_known_manufacturer = true; - break; + words = filter( string word, + words, + { return( "" != word && "with" != word && "driver" != word ); + } + ); + if( size( words ) > 0 ) + { boolean words_start_with_known_manufacturer = false; + foreach( string known_manufacturer, + known_manufacturers, + { if( tolower( words[0]:"" ) == tolower( known_manufacturer ) ) + { words_start_with_known_manufacturer = true; + break; + } } - } - ); - if( description_starts_with_known_manufacturer ) - { // After the first word which contains the manufacturer name - // there are none or up to two words which contain only letters and hyphens (the model name) - // and then there is a word which contains at least one number (the model series). - // Therefore the manufacturer and model sub-string can be assumed to be: - // One word which contains the manufacturer name, - // followed by at most two words which contain only letters and perhaps hyphens - // finished by one word which may start with letters and hyphens - // but it must contain at least one number followed by whatever characters. - // It is crucial to take whatever (trailing) character in the model series into account - // to be on the safe side to distinguish different models - // (e.g. "HP LaserJet 4" versus "HP LaserJet 4/4M" or "Kyocera FS-1000" versus "Kyocera FS-1000+"). - // For example as egrep regular expression: - // lpinfo -m | cut -d' ' -f2- - // | egrep -o '^[[:alpha:]]+[[:space:]]+([[:alpha:]-]+[[:space:]]+){0,2}[[:alpha:]-]*[[:digit:]][^[:space:]]*' - // Of course this best-guess is not 100% correct because it would result for example - // that "ACME FunPrinter 1000" and "ACME FunPrinter 1000 XL" - // are considered to be the same model "ACME FunPrinter 1000" - // but "ACME FunPrinter 1000XL" and "ACME FunPrinter 1000 XL" - // are considered to be different models "ACME FunPrinter 1000XL" and "ACME FunPrinter 1000": - boolean skip_the_rest = false; - integer index = -1; - description_words = maplist( string word, - description_words, - { if( ! skip_the_rest ) - { index = index + 1; - if( 0 == index ) - { // Return the manufacturer name: - return word; - } - if( 1 == index || 2 == index ) - { // Check for words which look like the model name: - if( "" == deletechars( word, letter_chars + "-" ) ) - { // Return a word of the model name: - return word; - } - } - if( 1 == index || 2 == index || 3 == index ) - { // Check for a word which looks like the model series: - if( "" != filterchars( word, number_chars ) ) - { // Skip the rest after the first model series word: - skip_the_rest = true; - // Return the model series: - return word; - } - } - } - } - ); - model_info = mergestring( description_words, " " ); + ); + if( 1 == max_words || 2 == max_words ) + { if( words_start_with_known_manufacturer ) + { model_info = words[0]:""; + if( 2 == max_words ) + { // Try to find and append the word which contains a model number. + // This is usually the first word which contains a number. + foreach( string word, + words, + { if( "" != filterchars( word, number_chars ) ) + { model_info = model_info + " " + word; + break; + } + } + ); + } + } + else + { // Try to find the word which contains a model number. + // This is usually the first word which contains a number. + foreach( string word, + words, + { if( "" != filterchars( word, number_chars ) ) + { model_info = word; + break; + } + } + ); + } + } + else + { // Derive a model info only if its first word is actually a known manufacturer: + if( words_start_with_known_manufacturer ) + { // After the first word which contains the manufacturer name + // there are none or up to two words which contain only letters and hyphens (the model name) + // and then there is a word which contains at least one number (the model series). + // Therefore the manufacturer and model sub-string can be assumed to be: + // One word which contains the manufacturer name, + // followed by at most two words which contain only letters and perhaps hyphens + // finished by one word which may start with letters and hyphens + // but it must contain at least one number followed by whatever characters. + // It is crucial to take whatever (trailing) character in the model series into account + // to be on the safe side to distinguish different models + // (e.g. "HP LaserJet 4" versus "HP LaserJet 4/4M" or "Kyocera FS-1000" versus "Kyocera FS-1000+"). + // For example as egrep regular expression: + // lpinfo -m | cut -d' ' -f2- + // | egrep -o '^[[:alpha:]]+[[:space:]]+([[:alpha:]-]+[[:space:]]+){0,2}[[:alpha:]-]*[[:digit:]][^[:space:]]*' + // Of course this best-guess is not 100% correct because it would result for example + // that "ACME FunPrinter 1000" and "ACME FunPrinter 1000 XL" + // are considered to be the same model "ACME FunPrinter 1000" + // but "ACME FunPrinter 1000XL" and "ACME FunPrinter 1000 XL" + // are considered to be different models "ACME FunPrinter 1000XL" and "ACME FunPrinter 1000": + boolean skip_the_rest = false; + integer index = -1; + words = maplist( string word, + words, + { if( ! skip_the_rest ) + { index = index + 1; + if( 0 == index ) + { // Return the manufacturer name: + return word; + } + if( 1 == index || 2 == index ) + { // Check for words which look like the model name: + if( "" == deletechars( word, letter_chars + "-" ) ) + { // Return a word of the model name: + return word; + } + } + if( 1 == index || 2 == index || 3 == index ) + { // Check for a word which looks like the model series: + if( "" != filterchars( word, number_chars ) ) + { // Skip the rest after the first model series word: + skip_the_rest = true; + // Return the model series: + return word; + } + } + } + } + ); + model_info = mergestring( words, " " ); + } + } } - y2milestone("DeriveModelName: derived '%1' from '%2'", model_info, description ); + y2milestone("DeriveModelName: derived '%1' from '%2' (max_words=%3)", model_info, description, max_words ); return model_info; } /** - * Derive a reasonable model info from an arbitrary description string. - * @param string from which a model is derived. + * Derive a reasonable driver_filter_string from an arbitrary driver_filter_input_text. + * @param string from which a driver_filter_string is derived. * @return string (possibly the empty string) */ global string DeriveDriverFilterString( string driver_filter_input_text ) { string driver_filter_string = ""; list <string> words = splitstring( driver_filter_input_text, " " ); - // Remove empty words because a sequence of spaces results empty words in words - // for example "ACME Funprinter" (two spaces!) results ["ACME","","Funprinter"]. + // Remove empty words because a sequence of spaces results empty words in the list of words + // for example "ACME Funprinter" (two spaces!) results ["ACME","","Funprinter"] + // and remove effectively empty words like "-", "/" as a result of e.g. "ACME Funprinter / XL" + // i.e. remove words which do not contain at least one alphanumeric character or '+' + // because '+' is also a meaningful character in model names. + // For example the '+' at the end of a Kyocera model name + // indicates that this model has a built-in PostScript interpreter + // while the model without the '+' understands only PCL. // Avoid having meaningless words like "series" or "Serie" + // or addons to the manufacturer name like "Corp." and "Inc." // and "Mita" (from "Kyocera Mita") in the driver_filter_string // (the driver_filter_string "kyocera.*FS-1000" finds the "Kyocera Mita FS-1000+") + // and remove "Packard" from "Hewlett Packard" (without the '-') as precondition + // to change "Hewlett-Packard", "Hewlett - Packard" and "Hewlett Packard" to "HP". + // The '*Manufacturer' entries in our PPDs contain even more confusing stuff like + // "KONICA MINOLTA", "Minolta", "Minolta QMS", "QMS" + // where no good automated solution is possible. words = filter( string word, words, - { return( "" != word - && ! issubstring( tolower( word ), "serie" ) + { return( "" != filterchars( word, alnum_chars + "+" ) + && "serie" != substring( tolower( word ), 0, size( "serie" ) ) + && "inc" != substring( tolower( word ), 0, size( "inc" ) ) + && "corp" != substring( tolower( word ), 0, size( "corp" ) ) && "mita" != tolower( word ) + && "packard" != tolower( word ) ); } ); if( size( words ) > 0 ) - { // Replace each sequence of spaces in driver_filter_input_text - // by the regular expression '.*' so that the search result - // hopefully fits better to what the user expects to get, + { if( "hewlett" == substring( tolower( words[0]:"" ), 0, size( "hewlett" ) ) ) + { // Let "Hewlett-Packard", "Hewlett", and "HP be the same. + // ("Hewlett - Packard" and "Hewlett Packard" were + // already changed to "Hewlett" via the above filter.) + words[0] = "HP"; + } + if( "oki" == substring( tolower( words[0]:"" ), 0, size( "oki" ) ) ) + { // Let "Oki", "Okidata", and "Okipage" be the same. + words[0] = "Oki"; + } + // Match at the beginning only if the first word + // is actually a known manufacturer name: + boolean words_start_with_known_manufacturer = false; + foreach( string known_manufacturer, + known_manufacturers, + { if( tolower( words[0]:"" ) == tolower( known_manufacturer ) ) + { words_start_with_known_manufacturer = true; + words[0] = "^" + words[0]:""; + break; + } + } + ); + // Concatenate the words by the regular expression '.*' so that the search result + // could hopefully fit better to what the user actually expects to get, // for example searching with "ACME 1000" should work to also - // find "ACME FunPrinter 1000" and "ACME Fancy Printer 1000 XL" - // Besides the regular expression characters '.*' + // find "ACME FunPrinter 1000" and "ACME Fancy Printer 1000 XL": + driver_filter_string = mergestring( words, ".*" ); + // Besides lower alphanumeric characters + // and the characters '.*' and '^' for regular expressions // only the special character '+' is also taken into account - // because this is also a meaningful character in model names - // for example the '+' at the end of a Kyocera model name - // indicates that this model has a built-in PostScript interpreter - // while the model without the '+' understands only PCL. - driver_filter_string = filterchars( tolower( mergestring( words, ".*" ) ), lower_alnum_chars + ".*+" ); + // because this is also a meaningful character in model names. + driver_filter_string = filterchars( tolower( driver_filter_string ), lower_alnum_chars + ".*^+" ); // Replace '+' by '\+' which evaluates to '+' (because of YCP quoting with '\') // to get a '+' character in a word quoted as '+' because otherwise // a '+' character would be interpreded as a special regular expression character @@ -1145,11 +1214,16 @@ { continue; } // Skip duplicate URIs because it does not make sense - // to show more than one entry with the same URI because + // to show more than one connection with the same URI because // for CUPS only different URIs distinguish different devices. // For example two same USB printer models without different serial numbers // are indistinguishable for CUPS so that any printout would be sent only - // to one of both devices (probably the first one in the USB device list): + // to one of both devices, usually the first one which is autodetected + // by the CUPS backend (which is usually the first one in the USB device list). + // Accordingly the first one in the connections list is shown to the user + // (the ordering in the connections list is what "lpinfo -v" results) + // and subsequent entries in the connections list with duplicate URIs + // are hidden from what is shown to the user: if( contains( already_added_uris, uri ) ) { y2milestone( "skipped connection_entry with duplicate DeviceURI: '%1'", connection_entry ); continue; @@ -1440,8 +1514,8 @@ { // If the driver_filter_string is a non-empty string, // test whether nickname or deviceID matches to the driver_filter_string. // Only the special character '+' is also taken into account because - // this is sometimes also a meaningful character in the model name - // for example the '+' at the end of a Kyocera model name + // this is also a meaningful character in the model name. + // For example the '+' at the end of a Kyocera model name // indicates that this model has a built-in PostScript interpreter // while the model without the '+' understands only PCL. string unified_nickname = filterchars( tolower( nickname ), lower_alnum_chars + "+" ); @@ -2115,8 +2189,8 @@ */ global map Export () { Printerlib::DetermineClientOnly(); - Printer::AutodetectQueues(); - list <map> p_queues = filter(map queue, Printer::queues, { return (queue["config"]:""=="local"); }); + AutodetectQueues(); + list <map> p_queues = filter(map queue, queues, { return (queue["config"]:""=="local"); }); map exp = $[ // "queues" : p_queues, // "filters" : Printerlib::ExportFilters( p_queues ), Modified: trunk/printer/src/basicadd.ycp URL: http://svn.opensuse.org/viewcvs/yast/trunk/printer/src/basicadd.ycp?rev=6006... ============================================================================== --- trunk/printer/src/basicadd.ycp (original) +++ trunk/printer/src/basicadd.ycp Fri Dec 11 14:20:38 2009 @@ -45,6 +45,7 @@ */ any BasicAddDialog() { y2milestone( "entering BasicAddDialog" ); + string non_matching_fallback_driver_filter_string = "qqqqqqqqqq"; // Caption for the "Add Printer" dialog (BasicAddDialog): string caption = _("Add New Printer Configuration"); // Clear whatever content of a previous dialog which would show up here for several seconds @@ -65,11 +66,15 @@ && "unknown" != tolower( model ) ) { queue_name_proposal = Printer::NewQueueName( tolower( model ) ); - // Match only at the beginning of the NickName entry in the PPD: - driver_filter_string = "^" + filterchars( tolower( model ), Printer::lower_alnum_chars ); - if( "^" != driver_filter_string ) - { driver_filter_input_text = model; - } + driver_filter_input_text = Printer::DeriveModelName( model, 0 ); + driver_filter_string = Printer::DeriveDriverFilterString( driver_filter_input_text ); + } + if( "" == driver_filter_string ) + { // Set a fallback driver_filter_string which does not match to anything + // to avoid that the full list of thousands of PPDs is shown automatically + // because it can take a very long time until the user can proceed: + driver_filter_input_text = _("Enter your printer model here."); + driver_filter_string = non_matching_fallback_driver_filter_string; } term contents = `VBox ( `VBox @@ -407,40 +412,15 @@ && "unknown" != tolower( model ) ) { queue_name_proposal = Printer::NewQueueName( tolower( model ) ); - driver_filter_input_text = model; + driver_filter_input_text = Printer::DeriveModelName( model, 0 ); driver_filter_string = Printer::DeriveDriverFilterString( driver_filter_input_text ); - // The first word in the driver_filter_string is usually the first word of the manufacturer name. - // This fuzzy match is intended so that e.g. "Kyocera" and "Kyocera Mita" result the same. - // Note that DeriveDriverFilterString joined the words in driver_filter_string with '.*' - // so that the first word in driver_filter_string must be split from the rest at '.': - string manufacturer = splitstring( driver_filter_string, "." )[0]:""; - // Even more fuzziness for very ambiguous manufacturer names: - if( "hewlett" == substring( tolower( manufacturer ), 0, 7 ) ) - { // Let "Hewlett-Packard", "Hewlett Packard", and "HP be the same: - manufacturer = "HP"; - } - if( "oki" == substring( tolower( manufacturer ), 0, 3 ) ) - { // Let "Oki", "Okidata", and "Okipage" be the same: - manufacturer = "Oki"; - } - // Match at the beginning only if the first word in the driver_filter_string - // is actually a known manufacturer name - // (there is only "Kyocera" but not "Kyocera Mita" in the known_manufacturers list). - foreach( string known_manufacturer, - Printer::known_manufacturers, - { if( tolower( manufacturer ) == tolower( known_manufacturer ) ) - { driver_filter_string = "^" + driver_filter_string; - break; - } - } - ); } if( "" == driver_filter_string ) { // Set a fallback driver_filter_string which does not match to anything // to avoid that the full list of thousands of PPDs is shown automatically // because it can take a very long time until the user can proceed: driver_filter_input_text = _("Enter your printer model here."); - driver_filter_string = "qqqqqqqqqq"; + driver_filter_string = non_matching_fallback_driver_filter_string; } UI::ReplaceWidget( `id(`driver_filter_input_replace_point), `InputField @@ -488,10 +468,8 @@ continue; } if( ret == `apply_driver_filter ) - { driver_filter_string = ""; - driver_filter_input_text = (string)UI::QueryWidget( `id(`driver_filter_input), `Value ); + { driver_filter_input_text = (string)UI::QueryWidget( `id(`driver_filter_input), `Value ); y2milestone( "Drivers for '%1'", driver_filter_input_text ); - // Match anywhere in the NickName entry in the PPD (i.e. without leading '^'). driver_filter_string = Printer::DeriveDriverFilterString( driver_filter_input_text ); if( "" == driver_filter_string ) { driver_filter_input_text = _("any model"); @@ -518,7 +496,7 @@ continue; } if( ret == `more_drivers ) - { if( "qqqqqqqqqq" != driver_filter_string ) + { if( non_matching_fallback_driver_filter_string != driver_filter_string ) { driver_filter_string = ""; } boolean valid_driver_found = false; @@ -533,46 +511,30 @@ y2milestone( "More drivers for '%1'", driver_filter_input_text ); if( "" != driver_filter_input_text && "unknown" != tolower( driver_filter_input_text ) - && "qqqqqqqqqq" != driver_filter_string + && non_matching_fallback_driver_filter_string != driver_filter_string ) - { // If the driver_filter_input_text string does not contain a space, - // words is a singleton list which contains only one word. - list <string> words = splitstring( driver_filter_input_text, " " ); - if( size( words ) >= 1 ) - { // Even if it is only one word, the following makes sense - // because the one word could already be the model_number_word. - // Try to find the word which contains a model number. - // This is usually the first word which contains a number. - string model_number_word = ""; - foreach( string word, - words, - { if( "" != filterchars( word, Printer::number_chars ) ) - { model_number_word = word; - break; - } - } - ); - // Provide visible feeback what is going on: + { string manufacturer_and_model_number = Printer::DeriveModelName( driver_filter_input_text, 2 ); + // Note that manufacturer_and_model_number may be the empty string + // (when driver_filter_input_text does not contain word which contains a number) + // or manufacturer_and_model_number may be only one word + // (when driver_filter_input_text starts with a known manufacturer + // but does not contain a word which contains a number + // or when driver_filter_input_text does not start with a known manufacturer + // but contains a word which contains a number). + if( "" != manufacturer_and_model_number + && issubstring( manufacturer_and_model_number, " ") + ) + { // Provide visible feeback what is going on: UI::ReplaceWidget( `id(`driver_filter_input_replace_point), `InputField ( `id(`driver_filter_input), `opt(`hstretch), // No InputField header because there is the "Caption for a printer driver selection": "", - model_number_word + manufacturer_and_model_number ) ); - // Only the special character '+' is also taken into account - // because this is also a meaningful character in model names - // for example the '+' at the end of a Kyocera model name - // indicates that this model has a built-in PostScript interpreter - // while the model without the '+' understands only PCL. - driver_filter_string = filterchars( tolower( model_number_word ), Printer::lower_alnum_chars + "+" ); - // Replace '+' by '\+' which evaluates to '+' (because of YCP quoting with '\') - // to get a '+' character in a word quoted as '+' because otherwise - // a '+' character would be interpreded as a special regular expression character - // when the driver_filter_string is used as pattern for regexpmatch in DriverItems(). - driver_filter_string = mergestring( splitstring( driver_filter_string, "+" ), "\+" ); + driver_filter_string = Printer::DeriveDriverFilterString( manufacturer_and_model_number ); if( "" != driver_filter_string ) { driver_items = Printer::DriverItems( driver_filter_string, true ); // Printer::DriverItems may result a driver_items list with one single element @@ -592,44 +554,23 @@ } } } - // Try to use the manufacturer when nothing was found above: + // Try to use only the manufacturer or only the model number when nothing was found above: if( ! valid_driver_found ) - { driver_filter_string = ""; - // The first word in the driver_filter_input_text is usually the first word of the manufacturer name. - // This fuzzy match is intended so that e.g. "Kyocera" and "Kyocera Mita" are the same. - string manufacturer = splitstring( driver_filter_input_text, " " )[0]:""; - if( "" != manufacturer ) - { // Even more fuzziness for very ambiguous manufacturer names: - if( "hewlett" == substring( tolower( driver_filter_input_text ), 0, 7 ) ) - { // Let "Hewlett-Packard", "Hewlett Packard", and "HP be the same: - manufacturer = "HP"; - } - if( "oki" == substring( tolower( driver_filter_input_text ), 0, 3 ) ) - { // Let "Oki", "Okidata", and "Okipage" be the same: - manufacturer = "Oki"; - } - // Provide visible feeback what is going on: + { string manufacturer_or_model_number = Printer::DeriveModelName( driver_filter_input_text, 1 ); + if( "" != manufacturer_or_model_number ) + { // Provide visible feeback what is going on: UI::ReplaceWidget( `id(`driver_filter_input_replace_point), `InputField ( `id(`driver_filter_input), `opt(`hstretch), // No InputField header because there is the "Caption for a printer driver selection": - "", - manufacturer + "", + manufacturer_or_model_number ) ); - driver_filter_string = filterchars( tolower( manufacturer ), Printer::lower_alnum_chars ); + driver_filter_string = Printer::DeriveDriverFilterString( manufacturer_or_model_number ); if( "" != driver_filter_string ) - { // Match at the beginning only if the driver_filter_string is actually a known manufacturer: - foreach( string known_manufacturer, - Printer::known_manufacturers, - { if( driver_filter_string == tolower( known_manufacturer ) ) - { driver_filter_string = "^" + driver_filter_string; - break; - } - } - ); - driver_items = Printer::DriverItems( driver_filter_string, true ); + { driver_items = Printer::DriverItems( driver_filter_string, true ); // Printer::DriverItems may result a driver_items list with one single element // [ `item( `id( -1 ), _("No matching driver found.") ) ] // to show at least a meaningful text as fallback entry to the user Modified: trunk/printer/src/basicmodify.ycp URL: http://svn.opensuse.org/viewcvs/yast/trunk/printer/src/basicmodify.ycp?rev=6... ============================================================================== --- trunk/printer/src/basicmodify.ycp (original) +++ trunk/printer/src/basicmodify.ycp Fri Dec 11 14:20:38 2009 @@ -45,6 +45,7 @@ */ any BasicModifyDialog() { y2milestone( "entering BasicModifyDialog for queue '%1'", Printer::queues[Printer::selected_queues_index]:$[] ); + string non_matching_fallback_driver_filter_string = "qqqqqqqqqq"; string commandline = ""; string name = Printer::queues[Printer::selected_queues_index,"name"]:""; string uri = Printer::queues[Printer::selected_queues_index,"uri"]:""; @@ -76,10 +77,9 @@ false ); Wizard::HideAbortButton(); - string model = Printer::DeriveModelName( description ); - string driver_filter_input_text = model; - // Match anywhere in the NickName entry in the PPD: - string driver_filter_string = filterchars( tolower( driver_filter_input_text ), Printer::lower_alnum_chars ); + string model = Printer::DeriveModelName( description, 0 ); + string driver_filter_input_text = Printer::DeriveModelName( model, 0 ); + string driver_filter_string = Printer::DeriveDriverFilterString( driver_filter_input_text ); string nick_name = ""; term driver_options_content = `Empty(); term paper_choice_content = `Empty(); @@ -120,9 +120,8 @@ if( Printerlib::ExecuteBashCommand( commandline ) ) { y2milestone( "'%1' stdout (nick_name) is: '%2'", commandline, Printerlib::result["stdout"]:"" ); nick_name = Printerlib::result["stdout"]:""; - driver_filter_input_text = nick_name; - // Match only at the beginning of the NickName entry in the PPD: - driver_filter_string = "^" + filterchars( tolower( nick_name ), Printer::lower_alnum_chars ); + driver_filter_input_text = Printer::DeriveModelName( nick_name, 0 ); + driver_filter_string = Printer::DeriveDriverFilterString( driver_filter_input_text ); } if( ! Printer::DetermineDriverOptions( "" ) ) { // Clear the Printer::driver_options so that no outdated driver options are used @@ -271,7 +270,7 @@ // to avoid that the full list of thousands of PPDs is shown automatically // because it can take a very long time until the user can proceed: driver_filter_input_text = _("Enter your printer model here."); - driver_filter_string = "qqqqqqqqqq"; + driver_filter_string = non_matching_fallback_driver_filter_string; } term contents = `VBox ( `VBox @@ -761,33 +760,8 @@ if( "" != model && "unknown" != tolower( model ) ) - { driver_filter_input_text = model; + { driver_filter_input_text = Printer::DeriveModelName( model, 0 ); driver_filter_string = Printer::DeriveDriverFilterString( driver_filter_input_text ); - // The first word in the driver_filter_string is usually the first word of the manufacturer name. - // This fuzzy match is intended so that e.g. "Kyocera" and "Kyocera Mita" result the same. - // Note that DeriveDriverFilterString joined the words in driver_filter_string with '.*' - // so that the first word in driver_filter_string must be split from the rest at '.': - string manufacturer = splitstring( driver_filter_string, "." )[0]:""; - // Even more fuzziness for very ambiguous manufacturer names: - if( "hewlett" == substring( tolower( manufacturer ), 0, 7 ) ) - { // Let "Hewlett-Packard", "Hewlett Packard", and "HP be the same: - manufacturer = "HP"; - } - if( "oki" == substring( tolower( manufacturer ), 0, 3 ) ) - { // Let "Oki", "Okidata", and "Okipage" be the same: - manufacturer = "Oki"; - } - // Match at the beginning only if the first word in the driver_filter_string - // is actually a known manufacturer name - // (there is only "Kyocera" but not "Kyocera Mita" in the known_manufacturers list). - foreach( string known_manufacturer, - Printer::known_manufacturers, - { if( tolower( manufacturer ) == tolower( known_manufacturer ) ) - { driver_filter_string = "^" + driver_filter_string; - break; - } - } - ); } } else @@ -795,47 +769,20 @@ // derive the driver_filter_string from the NickName of the currently used PPD // or derive the driver_filter_string from the description of the currently used connection: if( "" != nick_name ) - { driver_filter_input_text = nick_name; - // Match only at the beginning of the NickName entry in the PPD: - driver_filter_string = "^" + filterchars( tolower( nick_name ), Printer::lower_alnum_chars ); + { driver_filter_input_text = Printer::DeriveModelName( nick_name, 0 ); } else - { model = Printer::DeriveModelName( description ); - driver_filter_input_text = model; - driver_filter_string = Printer::DeriveDriverFilterString( driver_filter_input_text ); - // The first word in the driver_filter_string is usually the first word of the manufacturer name. - // This fuzzy match is intended so that e.g. "Kyocera" and "Kyocera Mita" result the same. - // Note that DeriveDriverFilterString joined the words in driver_filter_string with '.*' - // so that the first word in driver_filter_string must be split from the rest at '.': - string manufacturer = splitstring( driver_filter_string, "." )[0]:""; - // Even more fuzziness for very ambiguous manufacturer names: - if( "hewlett" == substring( tolower( manufacturer ), 0, 7 ) ) - { // Let "Hewlett-Packard", "Hewlett Packard", and "HP be the same: - manufacturer = "HP"; - } - if( "oki" == substring( tolower( manufacturer ), 0, 3 ) ) - { // Let "Oki", "Okidata", and "Okipage" be the same: - manufacturer = "Oki"; - } - // Match at the beginning only if the first word in the driver_filter_string - // is actually a known manufacturer name - // (there is only "Kyocera" but not "Kyocera Mita" in the known_manufacturers list). - foreach( string known_manufacturer, - Printer::known_manufacturers, - { if( tolower( manufacturer ) == tolower( known_manufacturer ) ) - { driver_filter_string = "^" + driver_filter_string; - break; - } - } - ); + { model = Printer::DeriveModelName( description, 0 ); + driver_filter_input_text = Printer::DeriveModelName( model, 0 ); } + driver_filter_string = Printer::DeriveDriverFilterString( driver_filter_input_text ); } if( "" == driver_filter_string ) { // Set a fallback driver_filter_string which does not match to anything // to avoid that the full list of thousands of PPDs is shown automatically // because it can take a very long time until the user can proceed: driver_filter_input_text = _("Enter your printer model here."); - driver_filter_string = "qqqqqqqqqq"; + driver_filter_string = non_matching_fallback_driver_filter_string; } UI::ReplaceWidget( `id(`driver_filter_input_replace_point), `InputField @@ -965,10 +912,8 @@ continue; } if( ret == `apply_driver_filter ) - { driver_filter_string = ""; - driver_filter_input_text = (string)UI::QueryWidget( `id(`driver_filter_input), `Value ); + { driver_filter_input_text = (string)UI::QueryWidget( `id(`driver_filter_input), `Value ); y2milestone( "Drivers for '%1'", driver_filter_input_text ); - // Match anywhere in the NickName entry in the PPD (i.e. without leading '^'). driver_filter_string = Printer::DeriveDriverFilterString( driver_filter_input_text ); if( "" == driver_filter_string ) { driver_filter_input_text = _("any model"); @@ -998,7 +943,7 @@ continue; } if( ret == `more_drivers ) - { if( "qqqqqqqqqq" != driver_filter_string ) + { if( non_matching_fallback_driver_filter_string != driver_filter_string ) { driver_filter_string = ""; } boolean valid_driver_found = false; @@ -1013,46 +958,30 @@ y2milestone( "More drivers for '%1'", driver_filter_input_text ); if( "" != driver_filter_input_text && "unknown" != tolower( driver_filter_input_text ) - && "qqqqqqqqqq" != driver_filter_string + && non_matching_fallback_driver_filter_string != driver_filter_string ) - { // If the driver_filter_input_text string does not contain a space, - // words is a singleton list which contains only one word. - list <string> words = splitstring( driver_filter_input_text, " " ); - if( size( words ) >= 1 ) - { // Even if it is only one word, the following makes sense - // because the one word could already be the model_number_word. - // Try to find the word which contains a model number. - // This is usually the first word which contains a number. - string model_number_word = ""; - foreach( string word, - words, - { if( "" != filterchars( word, Printer::number_chars ) ) - { model_number_word = word; - break; - } - } - ); - // Provide visible feeback what is going on: + { string manufacturer_and_model_number = Printer::DeriveModelName( driver_filter_input_text, 2 ); + // Note that manufacturer_and_model_number may be the empty string + // (when driver_filter_input_text does not contain word which contains a number) + // or manufacturer_and_model_number may be only one word + // (when driver_filter_input_text starts with a known manufacturer + // but does not contain a word which contains a number + // or when driver_filter_input_text does not start with a known manufacturer + // but contains a word which contains a number). + if( "" != manufacturer_and_model_number + && issubstring( manufacturer_and_model_number, " ") + ) + { // Provide visible feeback what is going on: UI::ReplaceWidget( `id(`driver_filter_input_replace_point), `InputField ( `id(`driver_filter_input), `opt(`hstretch), // No InputField header because there is the "Caption for a printer driver selection": "", - model_number_word + manufacturer_and_model_number ) ); - // Only the special character '+' is also taken into account - // because this is also a meaningful character in model names - // for example the '+' at the end of a Kyocera model name - // indicates that this model has a built-in PostScript interpreter - // while the model without the '+' understands only PCL. - driver_filter_string = filterchars( tolower( model_number_word ), Printer::lower_alnum_chars + "+" ); - // Replace '+' by '\+' which evaluates to '+' (because of YCP quoting with '\') - // to get a '+' character in a word quoted as '+' because otherwise - // a '+' character would be interpreded as a special regular expression character - // when the driver_filter_string is used as pattern for regexpmatch in DriverItems(). - driver_filter_string = mergestring( splitstring( driver_filter_string, "+" ), "\+" ); + driver_filter_string = Printer::DeriveDriverFilterString( manufacturer_and_model_number ); if( "" != driver_filter_string ) { driver_items = Printer::DriverItems( driver_filter_string, true ); // Printer::DriverItems may result a driver_items list with one single element @@ -1072,44 +1001,23 @@ } } } - // Try to use the manufacturer when nothing was found above: + // Try to use only the manufacturer or only the model number when nothing was found above: if( ! valid_driver_found ) - { driver_filter_string = ""; - // The first word in the driver_filter_input_text is usually the first word of the manufacturer name. - // This fuzzy match is intended so that e.g. "Kyocera" and "Kyocera Mita" are the same. - string manufacturer = splitstring( driver_filter_input_text, " " )[0]:""; - if( "" != manufacturer ) - { // Even more fuzziness for very ambiguous manufacturer names: - if( "hewlett" == substring( tolower( driver_filter_input_text ), 0, 7 ) ) - { // Let "Hewlett-Packard", "Hewlett Packard", and "HP be the same: - manufacturer = "HP"; - } - if( "oki" == substring( tolower( driver_filter_input_text ), 0, 3 ) ) - { // Let "Oki", "Okidata", and "Okipage" be the same: - manufacturer = "Oki"; - } - // Provide visible feeback what is going on: + { string manufacturer_or_model_number = Printer::DeriveModelName( driver_filter_input_text, 1 ); + if( "" != manufacturer_or_model_number ) + { // Provide visible feeback what is going on: UI::ReplaceWidget( `id(`driver_filter_input_replace_point), `InputField ( `id(`driver_filter_input), `opt(`hstretch), // No InputField header because there is the "Caption for a printer driver selection": "", - manufacturer + manufacturer_or_model_number ) ); - driver_filter_string = filterchars( tolower( manufacturer ), Printer::lower_alnum_chars ); + driver_filter_string = Printer::DeriveDriverFilterString( manufacturer_or_model_number ); if( "" != driver_filter_string ) - { // Match at the beginning only if the driver_filter_string is actually a known manufacturer: - foreach( string known_manufacturer, - Printer::known_manufacturers, - { if( driver_filter_string == tolower( known_manufacturer ) ) - { driver_filter_string = "^" + driver_filter_string; - break; - } - } - ); - driver_items = Printer::DriverItems( driver_filter_string, true ); + { driver_items = Printer::DriverItems( driver_filter_string, true ); // Printer::DriverItems may result a driver_items list with one single element // [ `item( `id( -1 ), _("No matching driver found.") ) ] // to show at least a meaningful text as fallback entry to the user Modified: trunk/printer/src/connectionwizard.ycp URL: http://svn.opensuse.org/viewcvs/yast/trunk/printer/src/connectionwizard.ycp?... ============================================================================== --- trunk/printer/src/connectionwizard.ycp (original) +++ trunk/printer/src/connectionwizard.ycp Fri Dec 11 14:20:38 2009 @@ -190,7 +190,7 @@ if( "" != current_model_info && "unknown" != tolower( current_model_info ) ) - { current_model_info = Printer::DeriveModelName( current_model_info ); + { current_model_info = Printer::DeriveModelName( current_model_info, 0 ); if( no_default_raw_queue ) { content = `Left ( `ComboBox -- To unsubscribe, e-mail: yast-commit+unsubscribe@opensuse.org For additional commands, e-mail: yast-commit+help@opensuse.org