/** From 'Programming in Qt', page 180  */

import org.kde.qt.*;

/**
  * A class that validates ISBN numbers. See the text for the
  * specification.
  */
public class ISBNValidator extends QValidator
{
	public ISBNValidator()
	{
		super();
	}
	
	/**
	  * This method is called after every input. Since we can check every
	  * character as soon as it is entered, we only need to check one
	  * character at a time for validity. To determine whether
	  * the whole string is acceptable, we must look at the whole
	  * string
	  * Note that input can also be deleted. This makes it useless
	  * to save state (like the number of entered digits) between
	  * invocations of validate(), because we would have to keep an extra
	  * copy of the last string.
	  */
	public int validate(StringBuffer text, int[] position)
	{
		int pos = position[0] - 1;
		
		if( text.length() == 0 )
			return Valid;
			
		/* Protect against spurious calls to validate() */
		if (pos > text.length() )
			return Valid;
			
		/* Anything but decimal digits and dashes is invalid. We only need
		 * to check the character at the cursor positions. This speeds
		 * things up massively.
		 */
		if( !Character.isDigit(text.charAt(pos)) && ( text.charAt(pos) != '-' ) )
		{
			System.out.println( "Typed character is neither digit nor dash" );
			return Invalid;
		}
		
		/* Dashes are only valid at position 1 (the second position),
		 * position 8 (if there was no dash at position 1), or position 9 (if
		 * there was a dash at position 1).
		 */
		if( text.charAt(pos) == '-' )
		{
			if( pos != 1 && pos != 8 && pos != 9 )
			{
				System.out.println( "Dash at wrong position" );
				return Invalid;
			}
			
			if( ( pos == 8 && text.charAt(1) == '-' ) ||
			    ( pos == 9 && text.charAt(1) != '-' ) )
			{
				System.out.println( "Dash at wrong position" );
				return Invalid;
			}
		}
		
		/* If the characters entered so far are valid, but the string
		 * contains less than ten digits, it could be made acceptable, but
		 * is not yet.
		 */
		int numdigits = text.length();
		if( text.length() > 1 && text.charAt(1) == '-' ) numdigits--;
		if( text.length() > 8 && text.charAt(8) == '-' ) numdigits--;
		if( text.length() > 9 && text.charAt(9) == '-' ) numdigits--;
		
		if( numdigits < 10 )
		{
			System.out.println( "Less than ten digits; input valid but not yet acceptable" );
			return Valid;
		}
		
		if( numdigits > 10 )
		{
			System.out.println( "More than ten digits; input invalid" );
			return Invalid;
		}
		
		if( text.charAt(1) != '-' || text.charAt(9) != '-' )
		{
			System.out.println( "Ten digits, but dashes not in the right places. Could be fixed up" );
			return Valid;
		}
		
		System.out.println( "Input acceptable" );
		return Acceptable;
	}	
	
	/**
	  * This method is called when the user has pressed return, but
	  * validate() has judged the string valid but not acceptable. Note
	  * that fixup() is not required to return an acceptable string. It is
	  * guaranteed that the caller will validate() the string once again
	  * after the call to fixup().
	  */
	public void fixup(StringBuffer text)
	{
		/* We can fix the input only if the dashes are missing,
		 * since we cannot implement the missing digits. (We could at least
		 * compute the last one with the checksum algorithm, but won't do so
		 * here.)
		 */
		
		/* If at least one digit has been entered but there is no dash at
		 * position 1, insert one.
		 */
		if( text.length() > 1 && text.charAt(1) != '-' )
			text.insert( 1, "-" );
			
		/* If at least nine digits have been entered but there is no dash
		 * at position 10 (because of the last two lines, we can safely
		 * assume that the first dash is already in place), insert one.
		 */
		if( text.length() > 10 /* nine digits plus dash */ && text.charAt(10) != '-' )
			text.insert( 10, "-" );
			
	}
	
	
	public static void main(String[] args)
	{
		class ReturnReceiver extends QObject {
			public void slotReturnPressed()
			{
				System.out.println( "return pressed - input accepted" );
			}
		}
		
		QApplication myapp = new QApplication( args );
		
		// create a line edit
		QLineEdit myedit = new QLineEdit((QWidget) null);
		myedit.resize( 100, 30 );
		
		// create and assign a validator for the line edit
		ISBNValidator myvalidator = new ISBNValidator();
		myedit.setValidator(myvalidator);
		
		// set up a receiver for the returnPressed() signal
		ReturnReceiver receiver = new ReturnReceiver();
		QObject.connect( myedit, SIGNAL( "returnPressed()" ),
						 receiver, SLOT( "slotReturnPressed()" ) );
						
		myapp.setMainWidget( myedit );
		myedit.show();
		myapp.exec();
		return;
	}
	
	static {
                qtjava.initialize();
	}
}
