Author: jsmeix Date: Thu Dec 3 17:09:38 2009 New Revision: 59942 URL: http://svn.opensuse.org/viewcvs/yast?rev=59942&view=rev Log: Replaced several duplicated code blocks in basicmodify.ycp basicadd.ycp connectionwizard.ycp by calling the new added DeriveModelName and DeriveDriverFilterString functions in Printer.ycp. Modified: trunk/printer/src/Printer.ycp trunk/printer/src/basicadd.ycp trunk/printer/src/basicmodify.ycp trunk/printer/src/connectionwizard.ycp Modified: trunk/printer/src/Printer.ycp URL: http://svn.opensuse.org/viewcvs/yast/trunk/printer/src/Printer.ycp?rev=59942&r1=59941&r2=59942&view=diff ============================================================================== --- trunk/printer/src/Printer.ycp (original) +++ trunk/printer/src/Printer.ycp Thu Dec 3 17:09:38 2009 @@ -759,6 +759,134 @@ } /** + * Derive a reasonable model info from an arbitrary description string. + * @param string from which a model is derived. + * @return string (possibly the empty string) + */ +global string DeriveModelName( string description ) +{ string model_info = ""; + list <string> description_words = splitstring( description, " " ); + // Remove empty words because a sequence of spaces results empty words in description_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; + } + } + ); + 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, " " ); + } + y2milestone("DeriveModelName: derived '%1' from '%2'", model_info, description ); + return model_info; +} + +/** + * Derive a reasonable model info from an arbitrary description string. + * @param string from which a model 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"]. + // Avoid having meaningless words like "series" or "Serie" + // and "Mita" (from "Kyocera Mita") in the driver_filter_string + // (the driver_filter_string "kyocera.*FS-1000" finds the "Kyocera Mita FS-1000+") + words = filter( string word, + words, + { return( "" != word + && ! issubstring( tolower( word ), "serie" ) + && "mita" != 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, + // 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 '.*' + // 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 + ".*+" ); + // 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, "+" ), "\\+" ); + } + y2milestone("DeriveDriverFilterString: derived '%1' from '%2'", driver_filter_string, driver_filter_input_text ); + return driver_filter_string; +} + +/** * Create a valid new queue name. * @param proposal string from which a valid new queue name is derived. * @return string Modified: trunk/printer/src/basicadd.ycp URL: http://svn.opensuse.org/viewcvs/yast/trunk/printer/src/basicadd.ycp?rev=59942&r1=59941&r2=59942&view=diff ============================================================================== --- trunk/printer/src/basicadd.ycp (original) +++ trunk/printer/src/basicadd.ycp Thu Dec 3 17:09:38 2009 @@ -408,33 +408,10 @@ ) { queue_name_proposal = Printer::NewQueueName( tolower( model ) ); driver_filter_input_text = model; - // 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, - // for example searching with "ACME 1000" should work to also - // find "ACME FunPrinter 1000" and "ACME Fancy Printer 1000 XL" - list <string> words = splitstring( driver_filter_input_text, " " ); - // A sequence of spaces results empty strings in words which are removed here: - words = filter( string word, - words, - { return( "" != word ); - } - ); - // Besides the regular expression characters '.*' - // 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, ".*" ) ), 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( 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 because of the above the words in driver_filter_string are joined with '.*' + // 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: @@ -515,30 +492,7 @@ 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 '^'). - // 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, - // for example searching with "ACME 1000" should work to also - // find "ACME FunPrinter 1000" and "ACME Fancy Printer 1000 XL" - list <string> words = splitstring( driver_filter_input_text, " " ); - // A sequence of spaces results empty strings in words which are removed here: - words = filter( string word, - words, - { return( "" != word ); - } - ); - // Besides the regular expression characters '.*' - // 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, ".*" ) ), 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( driver_filter_input_text ); if( "" == driver_filter_string ) { driver_filter_input_text = _("any model"); } Modified: trunk/printer/src/basicmodify.ycp URL: http://svn.opensuse.org/viewcvs/yast/trunk/printer/src/basicmodify.ycp?rev=59942&r1=59941&r2=59942&view=diff ============================================================================== --- trunk/printer/src/basicmodify.ycp (original) +++ trunk/printer/src/basicmodify.ycp Thu Dec 3 17:09:38 2009 @@ -76,41 +76,7 @@ false ); Wizard::HideAbortButton(); - string model = ""; - list <string> description_words = splitstring( description, " " ); - // 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 string: - description_words = filter( string word, - description_words, - { return( "with" != word && "driver" != word ); - } - ); - // Use the queue description only if its first word is actually a known manufacturer: - boolean description_starts_with_known_manufacturer = false; - foreach( string known_manufacturer, - Printer::known_manufacturers, - { if( tolower( description_words[0]:"" ) == tolower( known_manufacturer ) ) - { description_starts_with_known_manufacturer = true; - break; - } - } - ); - if( description_starts_with_known_manufacturer ) - { if( size( description_words ) > 2 ) - { model = description_words[0]:"" + " " - + description_words[1]:"" + " " - + description_words[2]:""; - } - if( size( description_words ) == 2 ) - { model = description_words[0]:"" + " " - + description_words[1]:""; - } - if( size( description_words ) == 1 ) - { model = description_words[0]:""; - } - } + 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 ); @@ -298,6 +264,13 @@ true ); } + 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"; + } term contents = `VBox ( `VBox ( `HBox @@ -540,6 +513,13 @@ string description_input = (string)UI::QueryWidget( `id(`description_input), `Value ); // Delete ' characters because they are used for quoting in the bash commandline: description_input = deletechars( description_input, "'" ); + // Leading and/or trailing and/or sequences of spaces look ugly and are condensed here: + description_input = mergestring( filter( string word, + splitstring( description_input, " " ), + { return( "" != word ); } + ), + " " + ); if( description_input != description ) { commandline = commandline + " -D '" + description_input + "'"; something_has_changed = true; @@ -547,6 +527,13 @@ string location_input = (string)UI::QueryWidget( `id(`location_input), `Value ); // Delete ' characters because they are used for quoting in the bash commandline: location_input = deletechars( location_input, "'" ); + // Leading and/or trailing and/or sequences of spaces look ugly and are condensed here: + location_input = mergestring( filter( string word, + splitstring( location_input, " " ), + { return( "" != word ); } + ), + " " + ); if( location_input != location ) { commandline = commandline + " -L '" + location_input + "'"; something_has_changed = true; @@ -773,33 +760,10 @@ && "unknown" != tolower( model ) ) { driver_filter_input_text = model; - // 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, - // for example searching with "ACME 1000" should work to also - // find "ACME FunPrinter 1000" and "ACME Fancy Printer 1000 XL" - list <string> words = splitstring( driver_filter_input_text, " " ); - // A sequence of spaces results empty strings in words which are removed here: - words = filter( string word, - words, - { return( "" != word ); - } - ); - // Besides the regular expression characters '.*' - // 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, ".*" ) ), 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( 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 because of the above the words in driver_filter_string are joined with '.*' + // 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: @@ -834,72 +798,12 @@ driver_filter_string = "^" + filterchars( tolower( nick_name ), Printer::lower_alnum_chars ); } else - { description_words = splitstring( description, " " ); - // 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 string: - description_words = filter( string word, - description_words, - { return( "with" != word && "driver" != word ); - } - ); - // Use the queue description only if its first word is actually a known manufacturer: - boolean description_starts_with_known_manufacturer = false; - foreach( string known_manufacturer, - Printer::known_manufacturers, - { if( tolower( description_words[0]:"" ) == tolower( known_manufacturer ) ) - { description_starts_with_known_manufacturer = true; - break; - } - } - ); - if( description_starts_with_known_manufacturer ) - { if( size( description_words ) > 2 ) - if( size( description_words ) > 2 ) - { model = description_words[0]:"" + " " - + description_words[1]:"" + " " - + description_words[2]:""; - } - if( size( description_words ) == 2 ) - { model = description_words[0]:"" + " " - + description_words[1]:""; - } - if( size( description_words ) == 1 ) - { model = description_words[0]:""; - } - } - else - { model = ""; - } + { model = Printer::DeriveModelName( description ); driver_filter_input_text = model; - // 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, - // for example searching with "ACME 1000" should work to also - // find "ACME FunPrinter 1000" and "ACME Fancy Printer 1000 XL" - list <string> words = splitstring( driver_filter_input_text, " " ); - // A sequence of spaces results empty strings in words which are removed here: - words = filter( string word, - words, - { return( "" != word ); - } - ); - // Besides the regular expression characters '.*' - // 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, ".*" ) ), 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( 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 because of the above the words in driver_filter_string are joined with '.*' + // 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: @@ -1063,30 +967,7 @@ 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 '^'). - // 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, - // for example searching with "ACME 1000" should work to also - // find "ACME FunPrinter 1000" and "ACME Fancy Printer 1000 XL" - list <string> words = splitstring( driver_filter_input_text, " " ); - // A sequence of spaces results empty strings in words which are removed here: - words = filter( string word, - words, - { return( "" != word ); - } - ); - // Besides the regular expression characters '.*' - // 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, ".*" ) ), 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( driver_filter_input_text ); if( "" == driver_filter_string ) { driver_filter_input_text = _("any model"); } Modified: trunk/printer/src/connectionwizard.ycp URL: http://svn.opensuse.org/viewcvs/yast/trunk/printer/src/connectionwizard.ycp?rev=59942&r1=59941&r2=59942&view=diff ============================================================================== --- trunk/printer/src/connectionwizard.ycp (original) +++ trunk/printer/src/connectionwizard.ycp Thu Dec 3 17:09:38 2009 @@ -158,49 +158,7 @@ if( "" != current_model_info && "unknown" != tolower( current_model_info ) ) - { list <string> description_words = splitstring( current_model_info, " " ); - // 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 current_model_info: - description_words = filter( string word, - description_words, - { return( "with" != word && "driver" != word ); - } - ); - // Use the queue description only if its first word is actually a known manufacturer: - boolean description_starts_with_known_manufacturer = false; - foreach( string known_manufacturer, - Printer::known_manufacturers, - { if( tolower( description_words[0]:"" ) == tolower( known_manufacturer ) ) - { description_starts_with_known_manufacturer = true; - break; - } - } - ); - if( description_starts_with_known_manufacturer ) - { if( size( description_words ) > 2 - && "with" != description_words[1]:"" - && "with" != description_words[2]:"" - && "driver" != description_words[2]:"" - ) - { current_model_info = description_words[0]:"" + " " - + description_words[1]:"" + " " - + description_words[2]:""; - } - if( size( description_words ) == 2 - && "with" != description_words[1]:"" - ) - { current_model_info = description_words[0]:"" + " " - + description_words[1]:""; - } - if( size( description_words ) == 1 ) - { current_model_info = description_words[0]:""; - } - } - else - { current_model_info = ""; - } + { current_model_info = Printer::DeriveModelName( current_model_info ); } } if( "" != current_model_info -- To unsubscribe, e-mail: yast-commit+unsubscribe@opensuse.org For additional commands, e-mail: yast-commit+help@opensuse.org