
/***************************************************************************
 *                                                                         *
 *   This program is free software; you can redistribute it and/or modify  *
 *   it under the terms of the GNU General Public License as published by  *
 *   the Free Software Foundation; either version 2 of the License, or     *
 *   (at your option) any later version.                                   *
 *                                                                         *
 ***************************************************************************/

/*  This code generated by: 
 *      Author : thomas
 *      Date   : Wed Jun 18 2003
 */

#include <qregexp.h>

#include "textblock.h"
#include "codedocument.h"
#include "codegenerationpolicy.h"

// Constructors/Destructors
//  

TextBlock::TextBlock ( CodeDocument * parent, const QString & text ) 
    : QObject ( (QObject *)parent, "textBlock")
{
	initFields(parent);
	setText(text);
} 

TextBlock::~TextBlock ( ) { }

//  
// Methods
//  


// Accessor methods
//  


/**
 * Set the value of the  parent code document
 * @param new_var the new value of m_parentDocument
 */
void TextBlock::setParentDocument ( CodeDocument * new_var ) {
        m_parentDocument = new_var;
}

bool TextBlock::canDelete ( ) {
	return m_canDelete;
}

/**
 * Get the value of m_parentDocument
 * @return the value of m_parentDocument
 */
CodeDocument * TextBlock::getParentDocument ( ) {
        return m_parentDocument;
}

/**
 * Set the value of m_text
 * The actual text of this code block.
 * @param new_var the new value of m_text
 */
void TextBlock::setText ( const QString &new_var ) {
	m_text = new_var;
}

/**
 * Add text to this object.
 *
 */
void TextBlock::appendText ( const QString &new_text ) {
	m_text = m_text + new_text;
}

/**
 * Get the value of m_text
 * The actual text of this code block.
 * @return the value of m_text
 */
QString TextBlock::getText ( ) const {
	return m_text;
}

/**
 * Get the tag of this text block. This tag
 * may be used to find this text block in the code document
 * to which it belongs.
 */
QString TextBlock::getTag( ) const {
	return m_tag;
}

/**
 * Set the tag of this text block. This tag
 * may be used to find this text block in the code document
 * to which it belongs.
 */
void TextBlock::setTag ( const QString &value ) {
	m_tag = value;
}

/**
 * Set the value of m_writeOutText
 * Whether or not to include the text of this TextBlock into a file.
 * @param new_var the new value of m_writeOutText
 */
void TextBlock::setWriteOutText ( bool new_var ) {
	m_writeOutText = new_var;
}

/**
 * Get the value of m_writeOutText
 * Whether or not to include the text of this TextBlock into a file.
 * @return the value of m_writeOutText
 */
bool TextBlock::getWriteOutText ( ) {
	return m_writeOutText;
}

/** Set how many times to indent this text block. 
 */
void TextBlock::setIndentationLevel ( int level ) {
	m_indentationLevel = level;
}

/** Get how many times to indent this text block. 
 * The amount of each indenatation is determined from the parent
 * codedocument codegeneration policy.
 */
int TextBlock::getIndentationLevel ( ) {
	return m_indentationLevel;
}

QString TextBlock::getNewLineEndingChars ( ) {
	CodeGenerationPolicy * policy = m_parentDocument->getPolicy ( );
	return policy->getNewLineEndingChars();
}

QString TextBlock::getIndentation() {
	CodeGenerationPolicy * policy = m_parentDocument->getPolicy ( );
	return policy->getIndentation();
}

QString TextBlock::getIndentationString ( int level ) {
	if (!level)
		level = m_indentationLevel;
	QString indentAmount = getIndentation();
	QString indentation = "";
	for(int i=0; i<level; i++)
		indentation.append(indentAmount);
	return indentation;
}

// Other methods
//  

/** Ush. These are terrifically bad and must one day go away.
 * Both methods indicate the range of lines in this textblock
 * which may be edited by the codeeditor (assuming that any are
 * actually editable). The default case is no lines are editable.
 * The line numbering starts with '0' and a '-1' means no line
 * qualifies.
 */
int TextBlock::firstEditableLine() { return 0; }
int TextBlock::lastEditableLine() { return 0; }

QString TextBlock::getNewEditorLine ( int amount ) {
	return getIndentationString(amount);
}

// will remove indenation from this text block.
QString TextBlock::unformatText ( const QString & text, const QString & indent )
{
	QString output = text;
	QString myIndent = indent;
	if(myIndent.isEmpty())
		myIndent = getIndentationString();

	if(!output.isEmpty())
		output.remove(QRegExp("^"+myIndent)); 

	return output;
}

void TextBlock::release () {
	this->disconnect();
	//this->deleteLater();
}

QString TextBlock::formatMultiLineText ( const QString &work, const QString &linePrefix, 
                                         QString breakStr, bool addBreak, bool lastLineHasBreak ) {
        QString output = "";
        QString text = work;
        QString endLine = getNewLineEndingChars();
	int matches = text.contains(QRegExp(breakStr));
	if(matches)
	{
		// check that last part of string matches, if not, then
		// we have to tack on extra match
		if(!text.contains(QRegExp(breakStr+"\\$")))
			matches++;

		for(int i=0; i < matches; i++)
		{
			QString line = text.section(QRegExp(breakStr),i,i);
                	output += linePrefix + line;
			if((i != matches-1) || lastLineHasBreak)
				output += endLine; // add break to line
		}
	} else { 
        	output = linePrefix + text; 
		if(addBreak)
        		output += breakStr;
	}

        return output;
}

void TextBlock::setAttributesOnNode ( QDomDocument & doc, QDomElement & blockElement) 
{

	QString endLine = m_parentDocument->getNewLineEndingChars();

	if (&doc != 0 ) {

		blockElement.setAttribute("tag",getTag());

		// only write these if different from defaults
		if(getIndentationLevel())
			blockElement.setAttribute("indentLevel",QString::number(getIndentationLevel()));
		if(!m_text.isEmpty())
			blockElement.setAttribute("text",encodeText(m_text,endLine));
		if(!getWriteOutText())
        		blockElement.setAttribute("writeOutText",getWriteOutText()?"true":"false");
		if(!canDelete())
        		blockElement.setAttribute("canDelete",canDelete()?"true":"false");

	}

}

void TextBlock::setAttributesFromObject(TextBlock * obj) 
{

	// DONT set tag here.
        setIndentationLevel(obj->getIndentationLevel());
        setText(obj->getText());
        setWriteOutText(obj->getWriteOutText());
        m_canDelete = obj->canDelete();

}

void TextBlock::setAttributesFromNode (QDomElement & root ) {

	QString endLine = m_parentDocument->getNewLineEndingChars();

        setIndentationLevel(root.attribute("indentLevel","0").toInt());
        setTag(root.attribute("tag",""));
        setText(decodeText(root.attribute("text",""),endLine));
        setWriteOutText(root.attribute("writeOutText","true") == "true" ? true : false);
        m_canDelete = root.attribute("canDelete","true") == "true" ? true : false;

}

// encode text for XML storage
// we simply convert all types of newLines to the "\n" or &#010;
// entity.
QString TextBlock::encodeText( QString text, const QString &endLine) {
	QString encoded = text.replace(QRegExp(endLine),"&#010;");
	return encoded;
}

// encode text for XML storage
// we simply convert all types of newLines to the "\n" or &#010;
// entity.
QString TextBlock::decodeText( QString text, const QString &endLine) {
	QString decoded = text.replace(QRegExp("&#010;"),endLine);
	return decoded;
}

/**
 * @return	QString
 */
QString TextBlock::toString ( ) 
{

	// simple output method
	if(m_writeOutText && !m_text.isEmpty())
	{
		QString endLine = m_parentDocument->getNewLineEndingChars();
		return formatMultiLineText(m_text, getIndentationString(), endLine);
	} else 
		return "";
}

void TextBlock::initFields ( CodeDocument * parent ) {
	m_canDelete = true;
	m_writeOutText = true;
	m_parentDocument = parent;
	m_text = "";
	m_tag = "";
	m_indentationLevel = 0;
}

#include "textblock.moc"
