You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
koffice/lib/kotext/KoVariable.cpp

2878 lines
94 KiB

/* This file is part of the KDE project
Copyright (C) 1998, 1999 Reginald Stadlbauer <reggie@kde.org>
Copyright (C) 2005 David Faure <faure@kde.org>
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Library General Public
License as published by the Free Software Foundation; either
version 2 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Library General Public License for more details.
You should have received a copy of the GNU Library General Public License
along with this library; see the file COPYING.LIB. If not, write to
the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
* Boston, MA 02110-1301, USA.
*/
#include "KoVariable.h"
#include "KoVariable.moc"
#include "KoTextZoomHandler.h"
#include "TimeFormatWidget.h"
#include "DateFormatWidget.h"
#include "KoTextCommand.h"
#include "KoTextObject.h"
#include "KoTextParag.h"
#include "KoOasisContext.h"
#include <KoOasisSettings.h>
#include <KoDocumentInfo.h>
#include <KoOasisStyles.h>
#include <KoXmlWriter.h>
#include <KoDocument.h>
#include <KoXmlNS.h>
#include <KoDom.h>
#include <klocale.h>
#include <kdebug.h>
#include <kglobal.h>
#include <kdialogbase.h>
#include <kconfig.h>
#include <tdeversion.h>
#include <kinstance.h>
#include <kcalendarsystem.h>
#include <kaboutdata.h>
#include <tqstringlist.h>
#include <tqcombobox.h>
#include <tqvaluelist.h>
#include <tqdom.h>
#include <tqradiobutton.h>
#include "IsoDuration.h"
class KoVariableSettings::KoVariableSettingPrivate
{
public:
KoVariableSettingPrivate()
{
m_lastPrintingDate.setTime_t(0); // Default is 1970-01-01 midnight locale time
}
TQDateTime m_lastPrintingDate;
TQDateTime m_creationDate;
TQDateTime m_modificationDate;
};
KoVariableSettings::KoVariableSettings()
{
d = new KoVariableSettingPrivate;
m_startingPageNumber = 1;
m_displayLink = true;
m_displayComment = true;
m_underlineLink = true;
m_displayFieldCode = false;
}
KoVariableSettings::~KoVariableSettings()
{
delete d;
d = 0;
}
TQDateTime KoVariableSettings::lastPrintingDate() const
{
return d->m_lastPrintingDate;
}
void KoVariableSettings::setLastPrintingDate( const TQDateTime & _date)
{
d->m_lastPrintingDate = _date;
}
TQDateTime KoVariableSettings::creationDate() const
{
return d->m_creationDate;
}
void KoVariableSettings::setCreationDate( const TQDateTime & _date )
{
d->m_creationDate = _date;
}
TQDateTime KoVariableSettings::modificationDate() const
{
return d->m_modificationDate;
}
void KoVariableSettings::setModificationDate( const TQDateTime & _date)
{
d->m_modificationDate = _date;
}
void KoVariableSettings::saveOasis( KoXmlWriter &settingsWriter ) const
{
settingsWriter.startElement("config:config-item-set");
settingsWriter.addAttribute("config:name", "configuration-variable-settings");
settingsWriter.addConfigItem("displaylink", m_displayLink );
settingsWriter.addConfigItem( "underlinelink", m_underlineLink);
settingsWriter.addConfigItem( "displaycomment", m_displayComment);
settingsWriter.addConfigItem( "displayfieldcode", m_displayFieldCode);
// m_startingPageNumber isn't saved to OASIS. Applications must use either
// style:page-number in the first parag of a page (see KoTextParag), or
// style:first-page-number in style:page-tqlayout, for spreadsheets etc.
if ( d->m_lastPrintingDate.isValid())
settingsWriter.addConfigItem("lastPrintingDate", d->m_lastPrintingDate.toString(Qt::ISODate));
if ( d->m_creationDate.isValid())
settingsWriter.addConfigItem("creationDate", d->m_creationDate.toString(Qt::ISODate));
if ( d->m_modificationDate.isValid())
settingsWriter.addConfigItem("modificationDate", d->m_modificationDate.toString(Qt::ISODate));
settingsWriter.endElement(); // config:config-item-set
}
void KoVariableSettings::loadOasis(const KoOasisSettings&settingsDoc)
{
KoOasisSettings::Items configurationSettings = settingsDoc.itemSet( "configuration-variable-settings" );
if ( !configurationSettings.isNull() )
{
m_displayLink = configurationSettings.parseConfigItemBool( "displaylink", true );
m_underlineLink = configurationSettings.parseConfigItemBool( "underlinelink", true );
m_displayComment = configurationSettings.parseConfigItemBool( "displaycomment", true );
m_displayFieldCode = configurationSettings.parseConfigItemBool( "displayfieldcode", false );
TQString str = configurationSettings.parseConfigItemString( "lastPrintingDate" );
if ( !str.isEmpty() )
d->m_lastPrintingDate = TQDateTime::fromString( str, Qt::ISODate );
else
d->m_lastPrintingDate.setTime_t(0); // 1970-01-01 00:00:00.000 locale time
str = configurationSettings.parseConfigItemString( "creationDate" );
if ( !str.isEmpty() ) {
d->m_creationDate = TQDateTime::fromString( str, Qt::ISODate );
}
str = configurationSettings.parseConfigItemString( "modificationDate" );
if ( !str.isEmpty() )
d->m_modificationDate = TQDateTime::fromString( str, Qt::ISODate );
// m_startingPageNumber isn't loaded from OASIS here. KWTextParag::loadOasis does it.
}
}
void KoVariableSettings::save( TQDomElement &parentElem )
{
TQDomElement elem = parentElem.ownerDocument().createElement( "VARIABLESETTINGS" );
parentElem.appendChild( elem );
if(m_startingPageNumber!=1)
{
elem.setAttribute( "startingPageNumber", m_startingPageNumber );
}
elem.setAttribute("displaylink",(int)m_displayLink);
elem.setAttribute("underlinelink",(int)m_underlineLink);
elem.setAttribute("displaycomment",(int)m_displayComment);
elem.setAttribute("displayfieldcode", (int)m_displayFieldCode);
if ( d->m_lastPrintingDate.isValid())
elem.setAttribute("lastPrintingDate", d->m_lastPrintingDate.toString(Qt::ISODate));
if ( d->m_creationDate.isValid())
elem.setAttribute("creationDate", d->m_creationDate.toString(Qt::ISODate));
if ( d->m_modificationDate.isValid())
elem.setAttribute("modificationDate", d->m_modificationDate.toString(Qt::ISODate));
}
void KoVariableSettings::load( TQDomElement &elem )
{
TQDomElement e = elem.namedItem( "VARIABLESETTINGS" ).toElement();
if (!e.isNull())
{
if(e.hasAttribute("startingPageNumber"))
m_startingPageNumber = e.attribute("startingPageNumber").toInt();
if(e.hasAttribute("displaylink"))
m_displayLink=(bool)e.attribute("displaylink").toInt();
if(e.hasAttribute("underlinelink"))
m_underlineLink=(bool)e.attribute("underlinelink").toInt();
if(e.hasAttribute("displaycomment"))
m_displayComment=(bool)e.attribute("displaycomment").toInt();
if (e.hasAttribute("displayfieldcode"))
m_displayFieldCode=(bool)e.attribute("displayfieldcode").toInt();
if (e.hasAttribute("lastPrintingDate"))
d->m_lastPrintingDate = TQDateTime::fromString( e.attribute( "lastPrintingDate" ), Qt::ISODate );
else
d->m_lastPrintingDate.setTime_t(0); // 1970-01-01 00:00:00.000 locale time
if (e.hasAttribute("creationDate")) {
d->m_creationDate = TQDateTime::fromString( e.attribute( "creationDate" ), Qt::ISODate );
}
if (e.hasAttribute("modificationDate"))
d->m_modificationDate = TQDateTime::fromString( e.attribute( "modificationDate" ), Qt::ISODate );
}
}
KoVariableDateFormat::KoVariableDateFormat() : KoVariableFormat()
{
}
TQString KoVariableDateFormat::convert( const TQVariant& data ) const
{
if ( data.type() != TQVariant::Date && data.type() != TQVariant::DateTime )
{
kdWarning(32500)<<" Error in KoVariableDateFormat::convert. Value is a "
<< data.typeName() << "(" << data.type() << ")" << endl;
// dateTime will be invalid, then set to 1970-01-01
}
TQDateTime dateTime ( data.toDateTime() );
if ( !dateTime.isValid() )
return i18n("No date set"); // e.g. old KWord documents
if (m_strFormat.lower() == "locale" || m_strFormat.isEmpty())
return KGlobal::locale()->formatDate( dateTime.date(), false );
else if ( m_strFormat.lower() == "localeshort" )
return KGlobal::locale()->formatDate( dateTime.date(), true );
else if ( m_strFormat.lower() == "localedatetime" )
return KGlobal::locale()->formatDateTime( dateTime, false );
else if ( m_strFormat.lower() == "localedatetimeshort" )
return KGlobal::locale()->formatDateTime( dateTime, true );
TQString tmp ( dateTime.toString(m_strFormat) );
const int month = dateTime.date().month();
tmp.replace("PPPP", KGlobal::locale()->calendar()->monthNamePossessive(month, false)); //long possessive month name
tmp.replace("PPP", KGlobal::locale()->calendar()->monthNamePossessive(month, true)); //short possessive month name
return tmp;
}
TQCString KoVariableDateFormat::key() const
{
return getKey( m_strFormat );
}
TQCString KoVariableDateFormat::getKey( const TQString& props ) const
{
return TQCString("DATE") + props.utf8();
}
void KoVariableDateFormat::load( const TQCString &key )
{
TQCString params( key.mid( 4 ) ); // skip "DATE"
if ( !params.isEmpty() )
{
if (params[0] == '1' || params[0] == '0') // old m_bShort crap
params = params.mid(1); // skip it
m_strFormat = TQString::fromUtf8( params );
}
}
// Used by KoVariableFormatCollection::popupActionList(), to apply all formats
// to the current data, in the popup menu.
TQStringList KoVariableDateFormat::staticFormatPropsList()
{
TQStringList listDateFormat;
listDateFormat<<"locale";
listDateFormat<<"localeshort";
listDateFormat<<"localedatetime";
listDateFormat<<"localedatetimeshort";
listDateFormat<<"dd/MM/yy";
listDateFormat<<"dd/MM/yyyy";
listDateFormat<<"MMM dd,yy";
listDateFormat<<"MMM dd,yyyy";
listDateFormat<<"dd.MMM.yyyy";
listDateFormat<<"MMMM dd, yyyy";
listDateFormat<<"ddd, MMM dd,yy";
listDateFormat<<"dddd, MMM dd,yy";
listDateFormat<<"MM-dd";
listDateFormat<<"yyyy-MM-dd";
listDateFormat<<"dd/yy";
listDateFormat<<"MMMM";
listDateFormat<<"yyyy-MM-dd hh:mm";
listDateFormat<<"dd.MMM.yyyy hh:mm";
listDateFormat<<"MMM dd,yyyy h:mm AP";
listDateFormat<<"yyyy-MM-ddThh:mm:ss"; // ISO 8601
return listDateFormat;
}
// Used by dateformatwidget_impl
// TODO: shouldn't it apply the formats to the value, like the popupmenu does?
TQStringList KoVariableDateFormat::staticTranslatedFormatPropsList()
{
TQStringList listDateFormat;
listDateFormat<<i18n("Locale date format");
listDateFormat<<i18n("Short locale date format");
listDateFormat<<i18n("Locale date & time format");
listDateFormat<<i18n("Short locale date & time format");
listDateFormat<<"dd/MM/yy";
listDateFormat<<"dd/MM/yyyy";
listDateFormat<<"MMM dd,yy";
listDateFormat<<"MMM dd,yyyy";
listDateFormat<<"dd.MMM.yyyy";
listDateFormat<<"MMMM dd, yyyy";
listDateFormat<<"ddd, MMM dd,yy";
listDateFormat<<"dddd, MMM dd,yy";
listDateFormat<<"MM-dd";
listDateFormat<<"yyyy-MM-dd";
listDateFormat<<"dd/yy";
listDateFormat<<"MMMM";
listDateFormat<<"yyyy-MM-dd hh:mm";
listDateFormat<<"dd.MMM.yyyy hh:mm";
listDateFormat<<"MMM dd,yyyy h:mm AP";
listDateFormat<<"yyyy-MM-ddThh:mm:ss"; // ISO 8601
return listDateFormat;
}
////
KoVariableTimeFormat::KoVariableTimeFormat() : KoVariableFormat()
{
}
void KoVariableTimeFormat::load( const TQCString &key )
{
TQCString params( key.mid( 4 ) );
if ( !params.isEmpty() )
m_strFormat = TQString::fromUtf8(params);
}
TQString KoVariableTimeFormat::convert( const TQVariant & time ) const
{
if ( time.type() != TQVariant::Time )
{
kdDebug(32500)<<" Error in KoVariableTimeFormat::convert. Value is a "
<< time.typeName() << "(" << time.type() << ")" << endl;
return TQString();
}
if( m_strFormat.lower() == "locale" || m_strFormat.isEmpty() )
return KGlobal::locale()->formatTime( time.toTime() );
return time.toTime().toString(m_strFormat);
}
TQCString KoVariableTimeFormat::key() const
{
return getKey( m_strFormat );
}
TQCString KoVariableTimeFormat::getKey( const TQString& props ) const
{
return TQCString("TIME") + props.utf8();
}
// Used by KoVariableFormatCollection::popupActionList(), to apply all formats
// to the current data, in the popup menu.
TQStringList KoVariableTimeFormat::staticFormatPropsList()
{
TQStringList listTimeFormat;
listTimeFormat<<"locale";
listTimeFormat<<"hh:mm";
listTimeFormat<<"hh:mm:ss";
listTimeFormat<<"hh:mm AP";
listTimeFormat<<"hh:mm:ss AP";
listTimeFormat<<"mm:ss.zzz";
return listTimeFormat;
}
// Used by timeformatwidget_impl
TQStringList KoVariableTimeFormat::staticTranslatedFormatPropsList()
{
TQStringList listTimeFormat;
listTimeFormat<<i18n("Locale format");
listTimeFormat<<"hh:mm";
listTimeFormat<<"hh:mm:ss";
listTimeFormat<<"hh:mm AP";
listTimeFormat<<"hh:mm:ss AP";
listTimeFormat<<"mm:ss.zzz";
return listTimeFormat;
}
////
TQString KoVariableStringFormat::convert( const TQVariant & string ) const
{
if ( string.type() != TQVariant::String )
{
kdDebug(32500)<<" Error in KoVariableStringFormat::convert. Value is a " << string.typeName() << endl;
return TQString();
}
return string.toString();
}
TQCString KoVariableStringFormat::key() const
{
return getKey( TQString() );
// TODO prefix & suffix
}
TQCString KoVariableStringFormat::getKey( const TQString& props ) const
{
return TQCString("STRING") + props.utf8();
}
////
TQString KoVariableNumberFormat::convert( const TQVariant &value ) const
{
if ( value.type() != TQVariant::Int )
{
kdDebug(32500)<<" Error in KoVariableNumberFormat::convert. Value is a " << value.typeName() << endl;
return TQString();
}
return TQString::number( value.toInt() );
}
TQCString KoVariableNumberFormat::key() const
{
return getKey(TQString());
}
TQCString KoVariableNumberFormat::getKey( const TQString& props ) const
{
return TQCString("NUMB") + props.utf8();
}
////
KoVariableFormatCollection::KoVariableFormatCollection()
{
m_dict.setAutoDelete( true );
}
KoVariableFormat * KoVariableFormatCollection::format( const TQCString &key )
{
KoVariableFormat *f = m_dict[ key.data() ];
if (f)
return f;
else
return createFormat( key );
}
KoVariableFormat * KoVariableFormatCollection::createFormat( const TQCString &key )
{
kdDebug(32500) << "KoVariableFormatCollection: creating format for key=" << key << endl;
KoVariableFormat * format = 0L;
// The first 4 chars identify the class
TQCString type = key.left(4);
if ( type == "DATE" )
format = new KoVariableDateFormat();
else if ( type == "TIME" )
format = new KoVariableTimeFormat();
else if ( type == "NUMB" ) // this type of programming makes me numb ;)
format = new KoVariableNumberFormat();
else if ( type == "STRI" )
format = new KoVariableStringFormat();
if ( format )
{
format->load( key );
m_dict.insert( format->key() /* not 'key', it could be incomplete */, format );
}
return format;
}
/******************************************************************/
/* Class: KoVariableCollection */
/******************************************************************/
KoVariableCollection::KoVariableCollection(KoVariableSettings *_settings, KoVariableFormatCollection *formatCollection)
{
m_variableSettings = _settings;
m_varSelected = 0L;
m_formatCollection = formatCollection;
}
KoVariableCollection::~KoVariableCollection()
{
delete m_variableSettings;
}
void KoVariableCollection::clear()
{
variables.clear();
varValues.clear();
m_varSelected = 0;
}
void KoVariableCollection::registerVariable( KoVariable *var )
{
if ( !var )
return;
variables.append( var );
}
void KoVariableCollection::unregisterVariable( KoVariable *var )
{
variables.take( variables.findRef( var ) );
}
TQValueList<KoVariable *> KoVariableCollection::recalcVariables(int type)
{
TQValueList<KoVariable *> modifiedVariables;
TQPtrListIterator<KoVariable> it( variables );
for ( ; it.current() ; ++it )
{
KoVariable* variable = it.current();
if ( variable->isDeleted() )
continue;
if ( variable->type() == type || type == VT_ALL )
{
TQVariant oldValue = variable->varValue();
variable->recalc();
if(variable->height == 0)
variable->resize();
if ( variable->varValue() != oldValue )
modifiedVariables.append( variable );
KoTextParag * parag = variable->paragraph();
if ( parag )
{
//kdDebug(32500) << "KoDoc::recalcVariables -> invalidating parag " << parag->paragId() << endl;
parag->tqinvalidate( 0 );
parag->setChanged( true );
}
}
}
#if 0
// TODO pass list of textdocuments as argument
// Or even better, call emitRepaintChanged on all modified textobjects
if( !modifiedVariables.isEmpty() )
emit repaintVariable();
#endif
return modifiedVariables;
}
void KoVariableCollection::setVariableValue( const TQString &name, const TQString &value )
{
varValues[ name ] = value;
}
TQString KoVariableCollection::getVariableValue( const TQString &name ) const
{
if ( !varValues.contains( name ) )
return i18n( "No value" );
return varValues[ name ];
}
bool KoVariableCollection::customVariableExist(const TQString &varname) const
{
return varValues.contains( varname );
}
void KoVariableCollection::setVariableSelected(KoVariable * var)
{
m_varSelected=var;
}
// TODO change to TQValueList<KAction *>, but only once plugActionList takes that
TQPtrList<KAction> KoVariableCollection::popupActionList() const
{
TQPtrList<KAction> listAction;
// Insert list of actions that change the subtype
const TQStringList subTypeList = m_varSelected->subTypeList();
kdDebug() << k_funcinfo << "current subtype=" << m_varSelected->subType() << endl;
TQStringList::ConstIterator it = subTypeList.begin();
for ( int i = 0; it != subTypeList.end() ; ++it, ++i )
{
if ( !(*it).isEmpty() ) // in case of removed subtypes or placeholders
{
// We store the subtype number as the action name
TQCString name; name.setNum(i);
KToggleAction * act = new KToggleAction( *it, KShortcut(), 0, name );
connect( act, TQT_SIGNAL(activated()), this, TQT_SLOT(slotChangeSubType()) );
if ( i == m_varSelected->subType() )
act->setChecked( true );
//m_subTextMap.insert( act, i );
listAction.append( act );
}
}
// Insert list of actions that change the format properties
KoVariableFormat* format = m_varSelected->variableFormat();
TQString currentFormat = format->formatProperties();
const TQStringList list = format->formatPropsList();
it = list.begin();
for ( int i = 0; it != list.end() ; ++it, ++i )
{
if( i == 0 ) // first item, and list not empty
listAction.append( new KActionSeparator() );
if ( !(*it).isEmpty() ) // in case of removed subtypes or placeholders
{
format->setFormatProperties( *it ); // temporary change
TQString text = format->convert( m_varSelected->varValue() );
// We store the raw format as the action name
KToggleAction * act = new KToggleAction(text, KShortcut(), 0, (*it).utf8());
connect( act, TQT_SIGNAL(activated()), this, TQT_SLOT(slotChangeFormat()) );
if ( (*it) == currentFormat )
act->setChecked( true );
listAction.append( act );
}
}
// Restore current format
format->setFormatProperties( currentFormat );
return listAction;
}
void KoVariableCollection::slotChangeSubType()
{
KAction * act = (KAction *)(sender());
int menuNumber = TQCString(act->name()).toInt();
int newSubType = m_varSelected->variableSubType(menuNumber);
kdDebug(32500) << "slotChangeSubType: menuNumber=" << menuNumber << " newSubType=" << newSubType << endl;
if ( m_varSelected->subType() != newSubType )
{
KoChangeVariableSubType *cmd=new KoChangeVariableSubType(
m_varSelected->subType(), newSubType, m_varSelected );
cmd->execute();
m_varSelected->textDocument()->emitNewCommand(cmd);
}
}
void KoVariableCollection::slotChangeFormat()
{
KAction * act = (KAction *)(sender());
TQString newFormat = TQString::fromUtf8(act->name());
TQString oldFormat = m_varSelected->variableFormat()->formatProperties();
if (oldFormat != newFormat )
{
KCommand *cmd=new KoChangeVariableFormatProperties(
oldFormat, newFormat, m_varSelected );
cmd->execute();
m_varSelected->textDocument()->emitNewCommand(cmd);
}
}
KoVariable * KoVariableCollection::createVariable( int type, short int subtype, KoVariableFormatCollection * coll, KoVariableFormat *varFormat,KoTextDocument *textdoc, KoDocument * doc, int _correct, bool _forceDefaultFormat, bool /*loadFootNote*/ )
{
Q_ASSERT( coll == m_formatCollection ); // why do we need a parameter ?!?
TQCString string;
TQStringList stringList;
if ( varFormat == 0L )
{
// Get the default format for this variable (this method is only called in the interactive case, not when loading)
switch ( type ) {
case VT_DATE:
case VT_DATE_VAR_KWORD10: // compatibility with kword 1.0
{
if ( _forceDefaultFormat )
varFormat = coll->format( KoDateVariable::defaultFormat() );
else
{
TQCString result = KoDateVariable::formatStr(_correct);
if ( result.isNull() )//we cancel insert variable
return 0L;
varFormat = coll->format( result );
}
break;
}
case VT_TIME:
case VT_TIME_VAR_KWORD10: // compatibility with kword 1.0
{
if ( _forceDefaultFormat )
varFormat = coll->format( KoTimeVariable::defaultFormat() );
else
{
TQCString result = KoTimeVariable::formatStr(_correct);
if ( result.isNull() )//we cancel insert variable
return 0L;
varFormat = coll->format( result );
}
break;
}
case VT_PGNUM:
varFormat = coll->format( "NUMBER" );
break;
case VT_FIELD:
case VT_CUSTOM:
case VT_MAILMERGE:
case VT_LINK:
case VT_NOTE:
varFormat = coll->format( "STRING" );
break;
case VT_FOOTNOTE: // this is a KWord-specific variable
kdError() << "Footnote type not handled in KoVariableCollection: VT_FOOTNOTE" << endl;
return 0L;
case VT_STATISTIC:
kdError() << " Statistic type not handled in KoVariableCollection: VT_STATISTIC" << endl;
return 0L;
}
}
Q_ASSERT( varFormat );
if ( varFormat == 0L ) // still 0 ? Impossible!
return 0L ;
kdDebug(32500) << "Creating variable. Format=" << varFormat->key() << " type=" << type << endl;
KoVariable * var = 0L;
switch ( type ) {
case VT_DATE:
case VT_DATE_VAR_KWORD10: // compatibility with kword 1.0
var = new KoDateVariable( textdoc, subtype, varFormat, this, _correct );
break;
case VT_TIME:
case VT_TIME_VAR_KWORD10: // compatibility with kword 1.0
var = new KoTimeVariable( textdoc, subtype, varFormat, this, _correct );
break;
case VT_PGNUM:
kdError() << "VT_PGNUM must be handled by the application's reimplementation of KoVariableCollection::createVariable" << endl;
//var = new KoPageVariable( textdoc, subtype, varFormat, this );
break;
case VT_FIELD:
var = new KoFieldVariable( textdoc, subtype, varFormat,this,doc );
break;
case VT_CUSTOM:
var = new KoCustomVariable( textdoc, TQString(), varFormat, this);
break;
case VT_MAILMERGE:
var = new KoMailMergeVariable( textdoc, TQString(), varFormat ,this);
break;
case VT_LINK:
var = new KoLinkVariable( textdoc,TQString(), TQString(), varFormat ,this);
break;
case VT_NOTE:
var = new KoNoteVariable( textdoc, TQString(), varFormat ,this);
break;
}
Q_ASSERT( var );
return var;
}
KoVariable* KoVariableCollection::loadOasisField( KoTextDocument* textdoc, const TQDomElement& tag, KoOasisContext& context )
{
const TQString localName( tag.localName() );
const bool isTextNS = tag.namespaceURI() == KoXmlNS::text;
TQString key;
int type = -1;
if ( isTextNS )
{
if ( localName.endsWith( "date" ) || localName.endsWith( "time" ) )
{
TQString dataStyleName = tag.attributeNS( KoXmlNS::style, "data-style-name", TQString() );
TQString dateFormat = "locale";
const KoOasisStyles::DataFormatsMap& map = context.oasisStyles().dataFormats();
KoOasisStyles::DataFormatsMap::const_iterator it = map.find( dataStyleName );
if ( it != map.end() )
dateFormat = (*it).formatStr;
// Only text:time is a pure time (the data behind is only h/m/s)
// ### FIXME: not true, a time can have a date too (reason: for MS Word (already from long ago) time and date are the same thing. But for OO the correction is not in the same unit for time and date.)
// Whereas print-time/creation-time etc. are actually related to a date/time value.
if ( localName == "time" )
{
type = VT_TIME;
key = "TIME" + dateFormat;
}
else
{
type = VT_DATE;
key = "DATE" + dateFormat;
}
}
else if (localName == "page-number" || localName == "page-count" )
{
type = VT_PGNUM;
key = "NUMBER";
}
else if (localName == "chapter")
{
type = VT_PGNUM;
key = "STRING";
}
else if (localName == "file-name")
{
type = VT_FIELD;
key = "STRING";
}
else if (localName == "author-name"
|| localName == "author-initials"
|| localName == "subject"
|| localName == "title"
|| localName == "description"
|| localName == "keywords")
{
type = VT_FIELD;
key = "STRING";
}
else if ( localName.startsWith( "sender-" )
&& localName != "sender-firstname" // not supported
&& localName != "sender-lastname" // not supported
&& localName != "sender-initials" // not supported
)
{
type = VT_FIELD;
key = "STRING";
}
else if ( localName == "variable-set"
|| localName == "user-defined"
|| localName == "user-field-get" )
{
key = "STRING";
type = VT_CUSTOM;
}
else
return 0L;
}
else if ( tag.namespaceURI() == KoXmlNS::office && localName == "annotation" )
{
type = VT_NOTE;
key = "NUMBER";
}
else
{
// Not an error. It's simply not a variable tag (the caller doesn't check for that)
return 0;
}
// TODO localName == "page-variable-get", "initial-creator" and many more
// TODO VT_MAILMERGE
return loadOasisFieldCreateVariable( textdoc, tag, context, key, type );
}
KoVariable* KoVariableCollection::loadOasisFieldCreateVariable( KoTextDocument* textdoc, const TQDomElement& tag, KoOasisContext& context, const TQString &key, int type )
{
KoVariableFormat * varFormat = key.isEmpty() ? 0 : m_formatCollection->format( key.latin1() );
// If varFormat is 0 (no key specified), the default format will be used.
KoVariable* var = createVariable( type, -1, m_formatCollection, varFormat, textdoc, context.koDocument(), 0 /*correct*/, true );
var->loadOasis( tag, context );
return var;
}
/******************************************************************/
/* Class: KoVariable */
/******************************************************************/
KoVariable::KoVariable( KoTextDocument *textdoc, KoVariableFormat *varFormat, KoVariableCollection *_varColl)
: KoTextCustomItem( textdoc )
{
//d = new Private;
m_varColl=_varColl;
m_varFormat = varFormat;
m_varColl->registerVariable( this );
m_ascent = 0;
}
KoVariable::~KoVariable()
{
//kdDebug(32500) << "KoVariable::~KoVariable " << this << endl;
m_varColl->unregisterVariable( this );
//delete d;
}
TQStringList KoVariable::subTypeList()
{
return TQStringList();
}
void KoVariable::resize()
{
if ( m_deleted )
return;
KoTextFormat *fmt = format();
TQFontMetrics fm = fmt->refFontMetrics();
TQString txt = text();
width = 0;
// size at 100%
for ( int i = 0 ; i < (int)txt.length() ; ++i )
width += fm.width( txt[i] ); // was fm.charWidth(txt,i), but see drawCustomItemHelper...
// zoom to LU
width = tqRound( KoTextZoomHandler::ptToLayoutUnitPt( width ) );
height = fmt->height();
m_ascent = fmt->ascent();
//kdDebug(32500) << "KoVariable::resize text=" << txt << " width=" << width << " height=" << height << " ascent=" << m_ascent << endl;
}
void KoVariable::recalcAndRepaint()
{
recalc();
KoTextParag * parag = paragraph();
if ( parag )
{
//kdDebug(32500) << "KoVariable::recalcAndRepaint -> invalidating parag " << parag->paragId() << endl;
parag->tqinvalidate( 0 );
parag->setChanged( true );
}
textDocument()->emitRepaintChanged();
}
TQString KoVariable::fieldCode()
{
return i18n("Variable");
}
TQString KoVariable::text(bool realValue)
{
KoTextFormat *fmt = format();
TQString str;
if (m_varColl->variableSetting()->displayFieldCode()&&!realValue)
str = fieldCode();
else
str = m_varFormat->convert( m_varValue );
return fmt->displayedString( str);
}
void KoVariable::drawCustomItem( TQPainter* p, int x, int y, int wpix, int hpix, int ascentpix, int /*cx*/, int /*cy*/, int /*cw*/, int /*ch*/, const TQColorGroup& cg, bool selected, int offset, bool drawingShadow )
{
KoTextFormat * fmt = format();
KoTextZoomHandler * zh = textDocument()->paintingZoomHandler();
TQFont font( fmt->screenFont( zh ) );
drawCustomItemHelper( p, x, y, wpix, hpix, ascentpix, cg, selected, offset, fmt, font, fmt->color(), drawingShadow );
}
void KoVariable::drawCustomItemHelper( TQPainter* p, int x, int y, int wpix, int hpix, int ascentpix, const TQColorGroup& cg, bool selected, int offset, KoTextFormat* fmt, const TQFont& font, TQColor textColor, bool drawingShadow )
{
// Important: the y value already includes the difference between the parag baseline
// and the char's own baseline (ascent) (see paintDefault in korichtext.cpp)
// So we just draw the text there. But we need the baseline for drawFontEffects...
KoTextZoomHandler * zh = textDocument()->paintingZoomHandler();
p->save();
if ( fmt->textBackgroundColor().isValid() )
p->fillRect( x, y, wpix, hpix, fmt->textBackgroundColor() );
if ( drawingShadow ) // Use shadow color if drawing a shadow
{
textColor = fmt->shadowColor();
p->setPen( textColor );
}
else if ( selected )
{
textColor = cg.color( TQColorGroup::HighlightedText );
p->setPen( TQPen( textColor ) );
p->fillRect( x, y, wpix, hpix, cg.color( TQColorGroup::Highlight ) );
}
else if ( textDocument() && textDocument()->drawFormattingChars()
&& p->device()->devType() != TQInternal::Printer )
{
textColor = cg.color( TQColorGroup::Highlight );
p->setPen( TQPen ( textColor, 0, TQt::DotLine ) );
p->drawRect( x, y, wpix, hpix );
}
else {
if ( !textColor.isValid() ) // Resolve the color at this point
textColor = KoTextFormat::defaultTextColor( p );
p->setPen( TQPen( textColor ) );
}
p->setFont( font ); // already done by KoTextCustomItem::draw but someone might
// change the font passed to drawCustomItemHelper (e.g. KoLinkVariable)
TQString str = text();
KoTextParag::drawFontEffects( p, fmt, zh, font, textColor, x, ascentpix, wpix, y, hpix, str[0] );
int posY = y + ascentpix + offset;
if ( fmt->vAlign() == KoTextFormat::AlignSubScript )
posY +=p->fontMetrics().height() / 6;
if ( fmt->vAlign() != KoTextFormat::AlignSuperScript )
posY -= fmt->offsetFromBaseLine();
else if ( fmt->offsetFromBaseLine() < 0 )
posY -= 2*fmt->offsetFromBaseLine();
//p->drawText( x, posY, str );
// We can't just drawText, it wouldn't use the same kerning as the one
// that resize() planned for [which is zoom-independent].
// We need to do the tqlayout using tqlayout units instead, so for simplicity
// I just draw every char individually (whereas KoTextFormatter/KoTextParag
// detect runs of text that can be drawn together)
const int len = str.length();
int xLU = zh->pixelToLayoutUnitX( x );
TQFontMetrics fm = fmt->refFontMetrics();
for ( int i = 0; i < len; ++i )
{
const TQChar ch = str[i];
p->drawText( x, posY, TQString(ch) );
// Do like KoTextFormatter: do the tqlayout in tqlayout units.
xLU += KoTextZoomHandler::ptToLayoutUnitPt( fm.width( ch ) );
// And then compute the X position in pixels from the tqlayout unit X.
x = zh->layoutUnitToPixelX( xLU );
}
p->restore();
}
void KoVariable::save( TQDomElement &parentElem )
{
//kdDebug(32500) << "KoVariable::save" << endl;
TQDomElement variableElem = parentElem.ownerDocument().createElement( "VARIABLE" );
parentElem.appendChild( variableElem );
TQDomElement typeElem = parentElem.ownerDocument().createElement( "TYPE" );
variableElem.appendChild( typeElem );
typeElem.setAttribute( "type", static_cast<int>( type() ) );
//// Of course, saving the key is ugly. We'll drop this when
//// switching to the OO format.
typeElem.setAttribute( "key", m_varFormat->key().data() );
typeElem.setAttribute( "text", text(true) );
if ( correctValue() != 0)
typeElem.setAttribute( "correct", correctValue() );
saveVariable( variableElem );
}
void KoVariable::load( TQDomElement & )
{
}
void KoVariable::loadOasis( const TQDomElement &/*elem*/, KoOasisContext& /*context*/ )
{
// nothing to do here, reimplemented in subclasses (make it pure virtual?)
}
void KoVariable::saveOasis( KoXmlWriter& /*writer*/, KoSavingContext& /*context*/ ) const
{
}
void KoVariable::setVariableFormat( KoVariableFormat *_varFormat )
{
// TODO if ( _varFormat ) _varFormat->deref();
m_varFormat = _varFormat;
// TODO m_varFormat->ref();
}
#define addText( text, newFormat ) { \
if ( !text.isEmpty() ) \
{ \
newFormat +=text; \
text=""; \
} \
}
TQString KoVariable::convertKlocaleToTQDateTimeFormat( const TQString & _format )
{
TQString newFormat;
TQString format( _format );
TQString text;
do
{
if ( format.startsWith( "%Y" ) )
{
addText( text, newFormat );
newFormat+="yyyy";
format = format.remove( 0, 2 );
}
else if ( format.startsWith( "%y" ) )
{
addText( text, newFormat );
newFormat+="yyyy";
format = format.remove( 0, 2 );
}
else if ( format.startsWith( "%n" ) )
{
addText( text, newFormat );
newFormat+="M";
format = format.remove( 0, 2 );
}
else if ( format.startsWith( "%m" ) )
{
addText( text, newFormat );
newFormat+="MM";
format = format.remove( 0, 2 );
}
else if ( format.startsWith( "%e" ) )
{
addText( text, newFormat );
newFormat+="d";
format = format.remove( 0, 2 );
}
else if ( format.startsWith( "%d" ) )
{
addText( text, newFormat );
newFormat+="dd";
format = format.remove( 0, 2 );
}
else if ( format.startsWith( "%b" ) )
{
addText( text, newFormat );
newFormat+="MMM";
format = format.remove( 0, 2 );
}
else if ( format.startsWith( "%B" ) )
{
addText( text, newFormat );
newFormat+="MMMM";
format = format.remove( 0, 2 );
}
else if ( format.startsWith( "%a" ) )
{
addText( text, newFormat );
newFormat+="ddd";
format = format.remove( 0, 2 );
}
else if ( format.startsWith( "%A" ) )
{
addText( text, newFormat );
newFormat+="dddd";
format = format.remove( 0, 2 );
}
if ( format.startsWith( "%H" ) ) //hh
{
//hour in 24h
addText( text, newFormat );
newFormat+="hh";
format = format.remove( 0, 2 );
}
else if ( format.startsWith( "%k" ) )//h
{
addText( text, newFormat );
newFormat+="h";
format = format.remove( 0, 2 );
}
else if ( format.startsWith( "%I" ) )// ?????
{
addText( text, newFormat );
//TODO hour in 12h
}
else if ( format.startsWith( "%l" ) )
{
addText( text, newFormat );
//TODO hour in 12h with 1 digit
}
else if ( format.startsWith( "%M" ) )// mm
{
addText( text, newFormat );
newFormat+="mm";
format = format.remove( 0, 2 );
}
else if ( format.startsWith( "%S" ) ) //ss
{
addText( text, newFormat );
newFormat+="ss";
format = format.remove( 0, 2 );
}
else if ( format.startsWith( "%p" ) )
{
//TODO am or pm
addText( text, newFormat );
newFormat+="ap";
format = format.remove( 0, 2 );
}
else
{
text += format[0];
format = format.remove( 0, 1 );
}
}
while ( format.length() > 0 );
addText( text, format );
return format;
}
/******************************************************************/
/* Class: KoDateVariable */
/******************************************************************/
KoDateVariable::KoDateVariable( KoTextDocument *textdoc, short int subtype, KoVariableFormat *_varFormat, KoVariableCollection *_varColl, int _correctDate)
: KoVariable( textdoc, _varFormat,_varColl ), m_subtype( subtype ), m_correctDate( _correctDate)
{
}
TQString KoDateVariable::fieldCode()
{
if ( m_subtype == VST_DATE_FIX )
return i18n("Date (Fixed)");
else if ( m_subtype == VST_DATE_CURRENT)
return i18n("Date");
else if ( m_subtype == VST_DATE_LAST_PRINTING)
return i18n("Last Printing");
else if ( m_subtype == VST_DATE_CREATE_FILE )
return i18n( "File Creation");
else if ( m_subtype == VST_DATE_MODIFY_FILE )
return i18n( "File Modification");
else
return i18n("Date");
}
void KoDateVariable::resize()
{
KoTextFormat * fmt = format();
TQString oldLanguage;
if ( !fmt->language().isEmpty())
{
oldLanguage=KGlobal::locale()->language();
bool changeLanguage = KGlobal::locale()->setLanguage( fmt->language() );
KoVariable::resize();
if ( changeLanguage )
KGlobal::locale()->setLanguage( oldLanguage );
}
else
KoVariable::resize();
}
void KoDateVariable::recalc()
{
if ( m_subtype == VST_DATE_CURRENT )
m_varValue = TQDateTime(TQDateTime::tqcurrentDateTime().addDays(m_correctDate));
else if ( m_subtype == VST_DATE_LAST_PRINTING )
m_varValue = m_varColl->variableSetting()->lastPrintingDate();
else if ( m_subtype == VST_DATE_CREATE_FILE )
m_varValue = m_varColl->variableSetting()->creationDate();
else if ( m_subtype == VST_DATE_MODIFY_FILE )
m_varValue = m_varColl->variableSetting()->modificationDate();
else
{
// Only if never set before (i.e. upon insertion)
if ( m_varValue.isNull() )
m_varValue = TQDateTime(TQDateTime::tqcurrentDateTime().addDays(m_correctDate));
}
resize();
}
void KoDateVariable::saveVariable( TQDomElement& varElem )
{
TQDomElement elem = varElem.ownerDocument().createElement( "DATE" );
varElem.appendChild( elem );
TQDate date = m_varValue.toDate(); // works with Date and DateTime
date = date.addDays( -m_correctDate );//remove correctDate value otherwise value stored is bad
elem.setAttribute( "year", date.year() );
elem.setAttribute( "month", date.month() );
elem.setAttribute( "day", date.day() );
elem.setAttribute( "fix", m_subtype == VST_DATE_FIX ); // for compat
elem.setAttribute( "correct", m_correctDate);
elem.setAttribute( "subtype", m_subtype);
if ( m_varValue.type() == TQVariant::DateTime )
{
TQTime time = m_varValue.toTime();
elem.setAttribute( "hour", time.hour() );
elem.setAttribute( "minute", time.minute() );
elem.setAttribute( "second", time.second() );
}
}
void KoDateVariable::load( TQDomElement& elem )
{
KoVariable::load( elem );
TQDomElement e = elem.namedItem( "DATE" ).toElement();
if (!e.isNull())
{
const bool fix = e.attribute("fix").toInt() == 1;
if ( e.hasAttribute("correct"))
m_correctDate = e.attribute("correct").toInt();
if ( fix )
{
const int y = e.attribute("year").toInt();
const int month = e.attribute("month").toInt();
const int d = e.attribute("day").toInt();
const int h = e.attribute("hour").toInt();
const int min = e.attribute("minute").toInt();
const int s = e.attribute("second").toInt();
const int ms = e.attribute("msecond").toInt();
TQDate date( y, month, d );
date = date.addDays( m_correctDate );
const TQTime time( h, min, s, ms );
if (time.isValid())
m_varValue = TQVariant ( TQDateTime( date, time ) );
else
m_varValue = TQVariant( date );
}
//old date variable format
m_subtype = fix ? VST_DATE_FIX : VST_DATE_CURRENT;
if ( e.hasAttribute( "subtype" ))
m_subtype = e.attribute( "subtype").toInt();
}
}
void KoDateVariable::saveOasis( KoXmlWriter& writer, KoSavingContext& context ) const
{
switch( m_subtype )
{
case VST_DATE_FIX:
case VST_DATE_CURRENT:
writer.startElement( "text:date" );
if ( m_subtype == VST_DATE_FIX )
{
writer.addAttribute( "text:date-value", m_varValue.toDate().toString( Qt::ISODate) );
writer.addAttribute( "text:fixed", "true" );
}
break;
case VST_DATE_LAST_PRINTING:
writer.startElement( "text:print-date" );
break;
case VST_DATE_CREATE_FILE:
writer.startElement( "text:creation-date" );
break;
case VST_DATE_MODIFY_FILE:
writer.startElement( "text:modification-date" );
break;
}
TQString value( m_varFormat->formatProperties() );
bool klocaleFormat = false;
if ( value.lower() == "locale" ||
value.isEmpty() ||
value.lower() == "localeshort" ||
value.lower() == "localedatetime" ||
value.lower() == "localedatetimeshort" )
{
if ( value.lower() == "locale" || value.isEmpty())
value = KGlobal::locale()->dateFormat();
else if ( value.lower() == "localeshort" )
value = KGlobal::locale()->dateFormatShort();
else if ( value.lower() == "localedatetime" )
value = TQString( "%1 %2" ).tqarg( KGlobal::locale()->dateFormat() ).tqarg( KGlobal::locale()->timeFormat() );
else if ( value.lower() == "localedatetimeshort" )
value = TQString( "%1 %2" ).tqarg( KGlobal::locale()->dateFormatShort() ).tqarg( KGlobal::locale()->timeFormat() );
klocaleFormat = true;
}
writer.addAttribute( "style:data-style-name", KoOasisStyles::saveOasisDateStyle(context.mainStyles(), value, klocaleFormat ) );
if ( m_correctDate != 0 )
writer.addAttribute( "text:date-adjust", daysToISODuration( m_correctDate ) );
writer.endElement();
}
void KoDateVariable::loadOasis( const TQDomElement &elem, KoOasisContext& /*context*/ )
{
const TQString localName( elem.localName() );
if ( localName == "date" ) // current (or fixed) date
{
// Standard form of the date is in text:date-value. Example: 2004-01-21T10:57:05
const TQString dateValue = elem.attributeNS( KoXmlNS::text, "date-value", TQString());
TQDateTime dt;
if ( !dateValue.isEmpty() ) // avoid TQDate warning
dt = TQDate::fromString(dateValue, Qt::ISODate);
bool fixed = (elem.hasAttributeNS( KoXmlNS::text, "fixed") && elem.attributeNS( KoXmlNS::text, "fixed", TQString())=="true");
if (!dt.isValid())
fixed = false; // OOo docs say so: not valid = current datetime
if ( fixed )
m_varValue = TQVariant( dt );
m_subtype = fixed ? VST_DATE_FIX : VST_DATE_CURRENT;
}
// For all those the value of the date will be retrieved from meta.xml
else if ( localName.startsWith( "print" ) )
m_subtype = VST_DATE_LAST_PRINTING;
else if ( localName.startsWith( "creation" ) )
m_subtype = VST_DATE_CREATE_FILE;
else if ( localName.startsWith( "modification" ) )
m_subtype = VST_DATE_MODIFY_FILE;
const TQString adjustStr = elem.attributeNS( KoXmlNS::text, "date-adjust", TQString() );
if ( !adjustStr.isEmpty() )
m_correctDate = ISODurationToDays( adjustStr );
}
TQStringList KoDateVariable::actionTexts()
{
TQStringList lst;
lst << i18n( "Current Date (fixed)" );
lst << i18n( "Current Date (variable)" );
lst << i18n( "Date of Last Printing" );
lst << i18n( "Date of File Creation" );
lst << i18n( "Date of File Modification" );
return lst;
}
TQStringList KoDateVariable::subTypeList()
{
return KoDateVariable::actionTexts();
}
TQCString KoDateVariable::defaultFormat()
{
return TQCString("DATE") + "locale";
}
TQCString KoDateVariable::formatStr(int & correct)
{
TQCString string;
TQStringList stringList;
KDialogBase* dialog=new KDialogBase(0, 0, true, i18n("Date Format"), KDialogBase::Ok|KDialogBase::Cancel);
DateFormatWidget* widget=new DateFormatWidget(dialog);
int count=0;
dialog->setMainWidget(widget);
KConfig* config = KoGlobal::kofficeConfig();
if( config->hasGroup("Date format history") )
{
KConfigGroupSaver cgs( config, "Date format history");
const int noe=config->readNumEntry("Number Of Entries", 5);
for(int i=0;i<noe;i++)
{
TQString num;
num.setNum(i);
const TQString tmpString(config->readEntry("Last Used"+num));
if(tmpString.startsWith("locale"))
continue;
else if(stringList.contains(tmpString))
continue;
else if(!tmpString.isEmpty())
{
stringList.append(tmpString);
count++;
}
}
}
if(!stringList.isEmpty())
{
widget->combo1->insertItem("---");
widget->combo1->insertStringList(stringList);
}
if(false) { // ### TODO: select the last used item
TQComboBox *combo= widget->combo1;
combo->setCurrentItem(combo->count() -1);
widget->updateLabel();
}
if(dialog->exec()==TQDialog::Accepted)
{
string = widget->resultString().utf8();
correct = widget->correctValue();
}
else
{
delete dialog;
return 0;
}
config->setGroup("Date format history");
stringList.remove(string);
stringList.prepend(string);
for(int i=0;i<=count;i++)
{
TQString num;
num.setNum(i);
config->writeEntry("Last Used"+num, stringList[i]);
}
config->sync();
delete dialog;
return TQCString("DATE") + string;
}
/******************************************************************/
/* Class: KoTimeVariable */
/******************************************************************/
KoTimeVariable::KoTimeVariable( KoTextDocument *textdoc, short int subtype, KoVariableFormat *varFormat, KoVariableCollection *_varColl, int _correct)
: KoVariable( textdoc, varFormat,_varColl ), m_subtype( subtype ), m_correctTime( _correct)
{
}
TQString KoTimeVariable::fieldCode()
{
return (m_subtype == VST_TIME_FIX)?i18n("Time (Fixed)"):i18n("Time");
}
void KoTimeVariable::resize()
{
KoTextFormat * fmt = format();
if ( !fmt->language().isEmpty() )
{
TQString oldLanguage = KGlobal::locale()->language();
bool changeLanguage = KGlobal::locale()->setLanguage( fmt->language() );
KoVariable::resize();
if ( changeLanguage )
KGlobal::locale()->setLanguage( oldLanguage );
}
else
KoVariable::resize();
}
void KoTimeVariable::recalc()
{
if ( m_subtype == VST_TIME_CURRENT )
m_varValue = TQVariant( TQTime(TQTime::currentTime().addSecs(60*m_correctTime)));
else
{
// Only if never set before (i.e. upon insertion)
if ( m_varValue.toTime().isNull() )
m_varValue = TQVariant( TQTime(TQTime::currentTime().addSecs(60*m_correctTime)));
}
resize();
}
void KoTimeVariable::saveVariable( TQDomElement& parentElem )
{
TQDomElement elem = parentElem.ownerDocument().createElement( "TIME" );
parentElem.appendChild( elem );
TQTime time = m_varValue.toTime();
time = time.addSecs(-60*m_correctTime);
elem.setAttribute( "hour", time.hour() );
elem.setAttribute( "minute", time.minute() );
elem.setAttribute( "second", time.second() );
elem.setAttribute( "msecond", time.msec() );
elem.setAttribute( "fix", m_subtype == VST_TIME_FIX );
elem.setAttribute( "correct", m_correctTime );
}
void KoTimeVariable::load( TQDomElement& elem )
{
KoVariable::load( elem );
TQDomElement e = elem.namedItem( "TIME" ).toElement();
if (!e.isNull())
{
int h = e.attribute("hour").toInt();
int m = e.attribute("minute").toInt();
int s = e.attribute("second").toInt();
int ms = e.attribute("msecond").toInt();
int correct = 0;
if ( e.hasAttribute("correct"))
correct=e.attribute("correct").toInt();
bool fix = static_cast<bool>( e.attribute("fix").toInt() );
if ( fix )
{
TQTime time;
time.setHMS( h, m, s, ms );
time = time.addSecs( 60*m_correctTime );
m_varValue = TQVariant( time);
}
m_subtype = fix ? VST_TIME_FIX : VST_TIME_CURRENT;
m_correctTime = correct;
}
}
void KoTimeVariable::loadOasis( const TQDomElement &elem, KoOasisContext& /*context*/ )
{
const TQString localName( elem.localName() );
Q_ASSERT( localName == "time" ); // caller checked for it
if ( localName == "time" ) // current (or fixed) time
{
// Use TQDateTime to work around a possible problem of TQTime::fromString in TQt 3.2.2
TQDateTime dt(TQDateTime::fromString(elem.attributeNS( KoXmlNS::text, "time-value", TQString()), Qt::ISODate));
bool fixed = (elem.hasAttributeNS( KoXmlNS::text, "fixed") && elem.attributeNS( KoXmlNS::text, "fixed", TQString())=="true");
if (!dt.isValid())
fixed = false; // OOo docs say so: not valid = current datetime
if ( fixed )
m_varValue = TQVariant( dt.time() );
m_subtype = fixed ? VST_TIME_FIX : VST_TIME_CURRENT;
TQString adjustStr = elem.attributeNS( KoXmlNS::text, "time-adjust", TQString() );
if ( !adjustStr.isEmpty() )
m_correctTime = ISODurationToMinutes( adjustStr );
}
}
void KoTimeVariable::saveOasis( KoXmlWriter& writer, KoSavingContext& context ) const
{
writer.startElement( "text:time" );
if ( m_correctTime != 0 ) {
writer.addAttribute( "text:time-adjust", minutesToISODuration( m_correctTime ) );
}
if (m_subtype == VST_TIME_FIX )
{
writer.addAttribute( "text:fixed", "true" );
writer.addAttribute( "text:time-value", m_varValue.toTime().toString( Qt::ISODate ) );
}
TQString value( m_varFormat->formatProperties() );
bool klocaleFormat = false;
if ( value.lower() == "locale" )
{
value = KGlobal::locale()->timeFormat();
klocaleFormat = true;
}
writer.addAttribute( "style:data-style-name", KoOasisStyles::saveOasisTimeStyle(context.mainStyles(), m_varFormat->formatProperties(), klocaleFormat ) );
//writer.addTextNode( /*value*/ value displayed as texte );
//TODO save text value
//<text:time style:data-style-name="N43" text:time-value="2004-11-11T14:42:19" text:fixed="true">02:42:19 PM</text:time>
writer.endElement();
}
TQStringList KoTimeVariable::actionTexts()
{
TQStringList lst;
lst << i18n( "Current Time (fixed)" );
lst << i18n( "Current Time (variable)" );
return lst;
}
TQStringList KoTimeVariable::subTypeList()
{
return KoTimeVariable::actionTexts();
}
TQCString KoTimeVariable::formatStr(int & _correct)
{
TQCString string;
TQStringList stringList;
KDialogBase* dialog=new KDialogBase(0, 0, true, i18n("Time Format"), KDialogBase::Ok|KDialogBase::Cancel);
TimeFormatWidget* widget=new TimeFormatWidget(dialog);
dialog->setMainWidget(widget);
KConfig* config = KoGlobal::kofficeConfig();
int count=0;
if( config->hasGroup("Time format history") )
{
KConfigGroupSaver cgs( config, "Time format history" );
const int noe=config->readNumEntry("Number Of Entries", 5);
for(int i=0;i<noe;i++)
{
TQString num;
num.setNum(i);
TQString tmpString(config->readEntry("Last Used"+num));
if(tmpString.startsWith("locale"))
continue;
else if(stringList.contains(tmpString))
continue;
else if(!tmpString.isEmpty())
{
stringList.append(tmpString);
count++;
}
}
}
if(!stringList.isEmpty())
{
widget->combo1->insertItem("---");
widget->combo1->insertStringList(stringList);
}
if(false) // ### TODO: select the last used item
{
TQComboBox *combo= widget->combo1;
combo->setCurrentItem(combo->count() -1);
}
if(dialog->exec()==TQDialog::Accepted)
{
string = widget->resultString().utf8();
_correct = widget->correctValue();
}
else
{
delete dialog;
return 0;
}
config->setGroup("Time format history");
stringList.remove(string);
stringList.prepend(string);
for(int i=0;i<=count;i++)
{
TQString num;
num.setNum(i);
config->writeEntry("Last Used"+num, stringList[i]);
}
config->sync();
delete dialog;
return TQCString("TIME"+string );
}
TQCString KoTimeVariable::defaultFormat()
{
return TQCString(TQCString("TIME")+TQCString("locale") );
}
/******************************************************************/
/* Class: KoCustomVariable */
/******************************************************************/
KoCustomVariable::KoCustomVariable( KoTextDocument *textdoc, const TQString &name, KoVariableFormat *varFormat, KoVariableCollection *_varColl )
: KoVariable( textdoc, varFormat,_varColl )
{
m_varValue = TQVariant( name );
}
TQString KoCustomVariable::fieldCode()
{
return i18n("Custom Variable");
}
TQString KoCustomVariable::text(bool realValue)
{
if (m_varColl->variableSetting()->displayFieldCode()&&!realValue)
return fieldCode();
else
return value();
} // use a format when they are customizable
void KoCustomVariable::saveVariable( TQDomElement& parentElem )
{
TQDomElement elem = parentElem.ownerDocument().createElement( "CUSTOM" );
parentElem.appendChild( elem );
elem.setAttribute( "name", m_varValue.toString() );
elem.setAttribute( "value", value() );
}
void KoCustomVariable::load( TQDomElement& elem )
{
KoVariable::load( elem );
TQDomElement e = elem.namedItem( "CUSTOM" ).toElement();
if (!e.isNull())
{
m_varValue = TQVariant (e.attribute( "name" ));
setValue( e.attribute( "value" ) );
}
}
void KoCustomVariable::loadOasis( const TQDomElement &elem, KoOasisContext& /*context*/ )
{
const TQString localName( elem.localName() );
// We treat all those the same. For OO/OpenDocument the difference is that
// - user-field-get is related to text:user-field-decls in <body>
// - variable-set is related to variable-decls (defined in <body>);
// its value can change in the middle of the document.
// - user-defined is related to meta:user-defined in meta.xml
if ( localName == "variable-set"
|| localName == "user-defined"
|| localName == "user-field-get" ) {
m_varValue = elem.attributeNS( KoXmlNS::text, "name", TQString() );
setValue( elem.text() );
}
}
void KoCustomVariable::saveOasis( KoXmlWriter& writer, KoSavingContext& /*context*/ ) const
{
//TODO save value into meta:user-defined
writer.startElement( "text:user-field-get" ); //see 6.3.6
writer.addAttribute( "text:name", m_varValue.toString() );
writer.addTextNode( value() );
writer.endElement();
}
TQString KoCustomVariable::value() const
{
return m_varColl->getVariableValue( m_varValue.toString() );
}
void KoCustomVariable::setValue( const TQString &v )
{
m_varColl->setVariableValue( m_varValue.toString(), v );
}
TQStringList KoCustomVariable::actionTexts()
{
return TQStringList( i18n( "Custom..." ) );
}
void KoCustomVariable::recalc()
{
resize();
}
/******************************************************************/
/* Class: KoMailMergeVariable */
/******************************************************************/
KoMailMergeVariable::KoMailMergeVariable( KoTextDocument *textdoc, const TQString &name, KoVariableFormat *varFormat,KoVariableCollection *_varColl )
: KoVariable( textdoc, varFormat, _varColl )
{
m_varValue = TQVariant ( name );
}
TQString KoMailMergeVariable::fieldCode()
{
return i18n("Mail Merge");
}
void KoMailMergeVariable::loadOasis( const TQDomElement &/*elem*/, KoOasisContext& /*context*/ )
{
// TODO
}
void KoMailMergeVariable::saveOasis( KoXmlWriter& /*writer*/, KoSavingContext& /*context*/ ) const
{
kdWarning(32500) << "Not implemented: OASIS saving of mail merge variables" << endl;
}
void KoMailMergeVariable::saveVariable( TQDomElement& parentElem )
{
TQDomElement elem = parentElem.ownerDocument().createElement( "MAILMERGE" );
parentElem.appendChild( elem );
elem.setAttribute( "name", m_varValue.toString() );
}
void KoMailMergeVariable::load( TQDomElement& elem )
{
KoVariable::load( elem );
TQDomElement e = elem.namedItem( "MAILMERGE" ).toElement();
if (!e.isNull())
m_varValue = TQVariant( e.attribute( "name" ) );
}
TQString KoMailMergeVariable::value() const
{
return TQString();//m_doc->getMailMergeDataBase()->getValue( m_name );
}
TQString KoMailMergeVariable::text(bool /*realValue*/)
{
// ## should use a format maybe
TQString v = value();
if ( v == name() )
return "<" + v + ">";
return v;
}
TQStringList KoMailMergeVariable::actionTexts()
{
return TQStringList( i18n( "&Mail Merge..." ) );
}
/******************************************************************/
/* Class: KoPageVariable */
/******************************************************************/
KoPageVariable::KoPageVariable( KoTextDocument *textdoc, short int subtype, KoVariableFormat *varFormat,KoVariableCollection *_varColl )
: KoVariable( textdoc, varFormat, _varColl ), m_subtype( subtype )
{
}
TQString KoPageVariable::fieldCode()
{
if ( m_subtype == VST_PGNUM_CURRENT )
return i18n("Page Current Num");
else if ( m_subtype == VST_PGNUM_TOTAL )
return i18n("Total Page Num");
else if ( m_subtype == VST_CURRENT_SECTION )
return i18n("Current Section");
else if ( m_subtype == VST_PGNUM_PREVIOUS )
return i18n("Previous Page Number");
else if ( m_subtype == VST_PGNUM_NEXT )
return i18n("Next Page Number");
else
return i18n("Current Section");
}
void KoPageVariable::saveVariable( TQDomElement& parentElem )
{
TQDomElement pgNumElem = parentElem.ownerDocument().createElement( "PGNUM" );
parentElem.appendChild( pgNumElem );
pgNumElem.setAttribute( "subtype", m_subtype );
if ( m_subtype != VST_CURRENT_SECTION )
pgNumElem.setAttribute( "value", m_varValue.toInt() );
else
pgNumElem.setAttribute( "value", m_varValue.toString() );
}
void KoPageVariable::load( TQDomElement& elem )
{
KoVariable::load( elem );
TQDomElement pgNumElem = elem.namedItem( "PGNUM" ).toElement();
if (!pgNumElem.isNull())
{
m_subtype = pgNumElem.attribute("subtype").toInt();
// ### This could use the format...
if ( m_subtype != VST_CURRENT_SECTION )
m_varValue = TQVariant(pgNumElem.attribute("value").toInt());
else
m_varValue = TQVariant(pgNumElem.attribute("value"));
}
}
void KoPageVariable::saveOasis( KoXmlWriter& writer, KoSavingContext& /*context*/ ) const
{
switch( m_subtype )
{
case VST_PGNUM_PREVIOUS:
case VST_PGNUM_NEXT:
case VST_PGNUM_CURRENT:
{
writer.startElement( "text:page-number" );
if ( m_subtype == VST_PGNUM_PREVIOUS )
{
writer.addAttribute( "text:select-page", "previous" );
}
else if ( m_subtype == VST_PGNUM_NEXT )
{
writer.addAttribute( "text:select-page", "next" );
}
else if ( m_subtype == VST_PGNUM_CURRENT )
{
writer.addAttribute( "text:select-page", "current" );
}
writer.addTextNode( m_varValue.toString() );
writer.endElement();
}
break;
case VST_CURRENT_SECTION:
{
writer.startElement( "text:chapter" );
writer.addTextNode( m_varValue.toString() );
writer.endElement();
}
break;
case VST_PGNUM_TOTAL:
{
writer.startElement( "text:page-count" );
writer.addTextNode( m_varValue.toString() );
writer.endElement();
}
break;
}
}
void KoPageVariable::loadOasis( const TQDomElement &elem, KoOasisContext& /*context*/ )
{
const TQString localName( elem.localName() );
if ( localName == "page-number" )
{
m_subtype = VST_PGNUM_CURRENT;
if ( elem.hasAttributeNS( KoXmlNS::text, "select-page") )
{
const TQString select = elem.attributeNS( KoXmlNS::text, "select-page", TQString());
if (select == "previous")
m_subtype = VST_PGNUM_PREVIOUS;
else if (select == "next")
m_subtype = VST_PGNUM_NEXT;
}
// Missing: fixed, page adjustment, formatting style
m_varValue = TQVariant( elem.text().toInt() );
}
else if ( localName == "chapter" )
{
m_subtype = VST_CURRENT_SECTION;
m_varValue = TQVariant( elem.text() );
// text:display attribute can be name, number (i.e. with prefix/suffix),
// number-and-name, plain-number-and-name, plain-number
// TODO: a special format class for this, so that it can be easily switched using the RMB
}
else if ( localName == "page-count" )
{
m_subtype = VST_PGNUM_TOTAL;
m_varValue = TQVariant( elem.text() );
}
}
TQStringList KoPageVariable::actionTexts()
{
TQStringList lst;
lst << i18n( "Page Number" );
lst << i18n( "Number of Pages" );
lst << i18n( "Section Title" );
lst << i18n( "Previous Page" );
lst << i18n( "Next Page" );
return lst;
}
TQStringList KoPageVariable::subTypeList()
{
return KoPageVariable::actionTexts();
}
void KoPageVariable::setVariableSubType( short int type )
{
m_subtype = type;
Q_ASSERT( m_varColl );
KoVariableFormatCollection* fc = m_varColl->formatCollection();
setVariableFormat((m_subtype == VST_CURRENT_SECTION) ? fc->format("STRING") : fc->format("NUMBER"));
}
/******************************************************************/
/* Class: KoFieldVariable */
/******************************************************************/
KoFieldVariable::KoFieldVariable( KoTextDocument *textdoc, short int subtype, KoVariableFormat *varFormat, KoVariableCollection *_varColl ,KoDocument *_doc )
: KoVariable( textdoc, varFormat,_varColl ), m_subtype( subtype ), m_doc(_doc)
{
}
TQString KoFieldVariable::fieldCode()
{
switch( m_subtype ) {
case VST_FILENAME:
return i18n("Filename");
break;
case VST_DIRECTORYNAME:
return i18n("Directory Name");
break;
case VST_PATHFILENAME:
return i18n("Path Filename");
break;
case VST_FILENAMEWITHOUTEXTENSION:
return i18n("Filename Without Extension");
break;
case VST_AUTHORNAME:
return i18n("Author Name");
break;
case VST_EMAIL:
return i18n("Email");
break;
case VST_COMPANYNAME:
return i18n("Company Name");
break;
case VST_TELEPHONE_WORK:
return i18n("Telephone (work)");
break;
case VST_TELEPHONE_HOME:
return i18n("Telephone (home)");
break;
case VST_FAX:
return i18n("Fax");
break;
case VST_COUNTRY:
return i18n("Country");
break;
case VST_POSTAL_CODE:
return i18n("Postal Code");
break;
case VST_CITY:
return i18n("City");
break;
case VST_STREET:
return i18n("Street");
break;
case VST_AUTHORTITLE:
return i18n("Author Title");
break;
case VST_TITLE:
return i18n("Title");
break;
case VST_SUBJECT:
return i18n("Subject");
break;
case VST_ABSTRACT:
return i18n("Abstract");
break;
case VST_KEYWORDS:
return i18n("Keywords");
break;
case VST_INITIAL:
return i18n("Initials");
break;
}
return i18n("Field");
}
TQString KoFieldVariable::text(bool realValue)
{
if (m_varColl->variableSetting()->displayFieldCode()&&!realValue)
return fieldCode();
else
return value();
} // use a format when they are customizable
void KoFieldVariable::saveVariable( TQDomElement& parentElem )
{
//kdDebug(32500) << "KoFieldVariable::saveVariable" << endl;
TQDomElement elem = parentElem.ownerDocument().createElement( "FIELD" );
parentElem.appendChild( elem );
elem.setAttribute( "subtype", m_subtype );
elem.setAttribute( "value", m_varValue.toString() );
}
void KoFieldVariable::load( TQDomElement& elem )
{
KoVariable::load( elem );
TQDomElement e = elem.namedItem( "FIELD" ).toElement();
if (!e.isNull())
{
m_subtype = e.attribute( "subtype" ).toInt();
if ( m_subtype == VST_NONE )
kdWarning() << "Field subtype of -1 found in the file !" << endl;
m_varValue = TQVariant( e.attribute( "value" ) );
} else
kdWarning() << "FIELD element not found !" << endl;
}
void KoFieldVariable::loadOasis( const TQDomElement &elem, KoOasisContext& /*context*/ )
{
const TQString localName( elem.localName() );
if ( localName == "file-name" ) {
const TQString display = elem.attributeNS( KoXmlNS::text, "display", TQString() );
if (display == "path")
m_subtype = VST_DIRECTORYNAME;
else if (display == "name")
m_subtype = VST_FILENAMEWITHOUTEXTENSION;
else if (display == "name-and-extension")
m_subtype = VST_FILENAME;
else
m_subtype = VST_PATHFILENAME;
}
else if ( localName == "author-name" )
m_subtype = VST_AUTHORNAME;
else if ( localName == "author-initials" )
m_subtype = VST_INITIAL;
else if ( localName == "subject" )
m_subtype = VST_SUBJECT;
else if ( localName == "title" )
m_subtype = VST_TITLE;
else if ( localName == "description" )
m_subtype = VST_ABSTRACT;
else if ( localName == "keywords" )
m_subtype = VST_KEYWORDS;
else if ( localName == "sender-company" )
m_subtype = VST_COMPANYNAME;
else if ( localName == "sender-firstname" )
; // ## This is different from author-name, but the notion of 'sender' is unclear...
else if ( localName == "sender-lastname" )
; // ## This is different from author-name, but the notion of 'sender' is unclear...
else if ( localName == "sender-initials" )
; // ## This is different from author-initials, but the notion of 'sender' is unclear...
else if ( localName == "sender-street" )
m_subtype = VST_STREET;
else if ( localName == "sender-country" )
m_subtype = VST_COUNTRY;
else if ( localName == "sender-postal-code" )
m_subtype = VST_POSTAL_CODE;
else if ( localName == "sender-city" )
m_subtype = VST_CITY;
else if ( localName == "sender-title" )
m_subtype = VST_AUTHORTITLE; // Small hack (it's supposed to be about the sender, not about the author)
else if ( localName == "sender-position" )
m_subtype = VST_AUTHORPOSITION;
else if ( localName == "sender-phone-private" )
m_subtype = VST_TELEPHONE_HOME;
else if ( localName == "sender-phone-work" )
m_subtype = VST_TELEPHONE_WORK;
else if ( localName == "sender-fax" )
m_subtype = VST_FAX;
else if ( localName == "sender-email" )
m_subtype = VST_EMAIL;
m_varValue = TQVariant( elem.text() );
}
void KoFieldVariable::saveOasis( KoXmlWriter& writer, KoSavingContext& /*context*/ ) const
{
switch( m_subtype )
{
case VST_NONE:
break;
case VST_FILENAME:
writer.startElement( "text:file-name" );
writer.addAttribute( "text:display", "name-and-extension" );
break;
case VST_DIRECTORYNAME:
writer.startElement( "text:file-name" );
writer.addAttribute( "text:display", "path" );
break;
case VST_AUTHORNAME:
writer.startElement( "text:author-name" );
break;
case VST_EMAIL:
writer.startElement("text:sender-email" );
break;
case VST_COMPANYNAME:
writer.startElement("text:sender-company" );
break;
case VST_PATHFILENAME:
writer.startElement("text:display" );
writer.addAttribute( "text:display", "pathfilename" ); // ???????? not define !
break;
case VST_FILENAMEWITHOUTEXTENSION:
writer.startElement("text:display" );
writer.addAttribute( "text:display", "name-and-extension" ); // ???????? not define !
break;
case VST_TELEPHONE_WORK:
writer.startElement("text:sender-phone-work" );
break;
case VST_TELEPHONE_HOME:
writer.startElement("text:sender-phone-private" );
break;
case VST_FAX:
writer.startElement("text:sender-fax" );
break;
case VST_COUNTRY:
writer.startElement("text:sender-country" );
break;
case VST_TITLE:
writer.startElement("text:title" );
break;
case VST_KEYWORDS:
writer.startElement("text:keywords" );
break;
case VST_SUBJECT:
writer.startElement("text:subject" );
break;
case VST_ABSTRACT:
writer.startElement("text:description" );
break;
case VST_POSTAL_CODE:
writer.startElement("text:sender-postal-code" );
break;
case VST_CITY:
writer.startElement("text:sender-city" );
break;
case VST_STREET:
writer.startElement("text:sender-street" );
break;
case VST_AUTHORTITLE:
writer.startElement("text:sender-title" );
break;
case VST_AUTHORPOSITION:
writer.startElement("text:sender-position" );
break;
case VST_INITIAL:
writer.startElement("text:author-initials" );
break;
}
writer.addTextNode( m_varValue.toString() );
writer.endElement();
}
void KoFieldVariable::recalc()
{
TQString value;
switch( m_subtype ) {
case VST_NONE:
kdWarning() << "KoFieldVariable::recalc() called with m_subtype = VST_NONE !" << endl;
break;
case VST_FILENAME:
value = m_doc->url().fileName();
break;
case VST_DIRECTORYNAME:
value = m_doc->url().directory();
break;
case VST_PATHFILENAME:
value=m_doc->url().path();
break;
case VST_FILENAMEWITHOUTEXTENSION:
{
TQString file=m_doc->url().fileName();
int pos=file.findRev(".");
if(pos !=-1)
value=file.mid(0,pos);
else
value=file;
}
break;
case VST_AUTHORNAME:
case VST_EMAIL:
case VST_COMPANYNAME:
case VST_TELEPHONE_WORK:
case VST_TELEPHONE_HOME:
case VST_FAX:
case VST_COUNTRY:
case VST_POSTAL_CODE:
case VST_CITY:
case VST_STREET:
case VST_AUTHORTITLE:
case VST_AUTHORPOSITION:
case VST_INITIAL:
{
KoDocumentInfo * info = m_doc->documentInfo();
KoDocumentInfoAuthor * authorPage = static_cast<KoDocumentInfoAuthor *>(info->page( "author" ));
if ( !authorPage )
kdWarning() << "Author information not found in documentInfo !" << endl;
else
{
if ( m_subtype == VST_AUTHORNAME )
value = authorPage->fullName();
else if ( m_subtype == VST_EMAIL )
value = authorPage->email();
else if ( m_subtype == VST_COMPANYNAME )
value = authorPage->company();
else if ( m_subtype == VST_TELEPHONE_WORK )
value = authorPage->telephoneWork();
else if ( m_subtype == VST_TELEPHONE_HOME )
value = authorPage->telephoneHome();
else if ( m_subtype == VST_FAX )
value = authorPage->fax();
else if ( m_subtype == VST_COUNTRY )
value = authorPage->country();
else if ( m_subtype == VST_POSTAL_CODE )
value = authorPage->postalCode();
else if ( m_subtype == VST_CITY )
value = authorPage->city();
else if ( m_subtype == VST_STREET )
value = authorPage->street();
else if ( m_subtype == VST_AUTHORTITLE )
value = authorPage->title();
else if ( m_subtype == VST_INITIAL )
value = authorPage->initial();
else if ( m_subtype == VST_AUTHORPOSITION )
value = authorPage->position();
}
}
break;
case VST_TITLE:
case VST_ABSTRACT:
case VST_SUBJECT:
case VST_KEYWORDS:
{
KoDocumentInfo * info = m_doc->documentInfo();
KoDocumentInfoAbout * aboutPage = static_cast<KoDocumentInfoAbout *>(info->page( "about" ));
if ( !aboutPage )
kdWarning() << "'About' page not found in documentInfo !" << endl;
else
{
if ( m_subtype == VST_TITLE )
value = aboutPage->title();
else if ( m_subtype == VST_SUBJECT )
value = aboutPage->subject();
else if ( m_subtype == VST_KEYWORDS )
value = aboutPage->keywords();
else
value = aboutPage->abstract();
}
}
break;
}
if (value.isEmpty()) // try the initial value
value = m_varValue.toString();
if (value.isEmpty()) // still empty? give up
value = i18n("<None>");
m_varValue = TQVariant( value );
resize();
}
TQStringList KoFieldVariable::actionTexts()
{
// NOTE: if you change here, also change fieldSubType()
TQStringList lst;
lst << i18n( "Author Name" );
lst << i18n( "Title" );
lst << i18n( "Initials" );
lst << i18n( "Position" );
lst << i18n( "Company" );
lst << i18n( "Email" );
lst << i18n( "Telephone (work)");
lst << i18n( "Telephone (private)");
lst << i18n( "Fax");
lst << i18n( "Street" );
lst << i18n( "Postal Code" );
lst << i18n( "City" );
lst << i18n( "Country");
lst << i18n( "Document Title" );
lst << i18n( "Document Abstract" );
lst << i18n( "Document Subject" );
lst << i18n( "Document Keywords" );
lst << i18n( "File Name" );
lst << i18n( "File Name without Extension" );
lst << i18n( "Directory Name" ); // is "Name" necessary ?
lst << i18n( "Directory && File Name" );
return lst;
}
short int KoFieldVariable::variableSubType( short int menuNumber )
{
return fieldSubType(menuNumber);
}
KoFieldVariable::FieldSubType KoFieldVariable::fieldSubType(short int menuNumber)
{
// NOTE: if you change here, also change actionTexts()
FieldSubType v;
switch (menuNumber)
{
case 0: v = VST_AUTHORNAME;
break;
case 1: v = VST_AUTHORTITLE;
break;
case 2: v = VST_INITIAL;
break;
case 3: v = VST_AUTHORPOSITION;
break;
case 4: v = VST_COMPANYNAME;
break;
case 5: v = VST_EMAIL;
break;
case 6: v = VST_TELEPHONE_WORK;
break;
case 7: v = VST_TELEPHONE_HOME;
break;
case 8: v = VST_FAX;
break;
case 9: v = VST_STREET;
break;
case 10: v = VST_POSTAL_CODE;
break;
case 11: v = VST_CITY;
break;
case 12: v = VST_COUNTRY;
break;
case 13: v = VST_TITLE;
break;
case 14: v = VST_ABSTRACT;
break;
case 15: v = VST_SUBJECT;
break;
case 16: v = VST_KEYWORDS;
break;
case 17: v = VST_FILENAME;
break;
case 18: v = VST_FILENAMEWITHOUTEXTENSION;
break;
case 19: v = VST_DIRECTORYNAME;
break;
case 20: v = VST_PATHFILENAME;
break;
default:
v = VST_NONE;
break;
}
return v;
}
TQStringList KoFieldVariable::subTypeList()
{
return KoFieldVariable::actionTexts();
}
/******************************************************************/
/* Class: KoLinkVariable */
/******************************************************************/
KoLinkVariable::KoLinkVariable( KoTextDocument *textdoc, const TQString & _linkName, const TQString & _ulr,KoVariableFormat *varFormat,KoVariableCollection *_varColl )
: KoVariable( textdoc, varFormat,_varColl )
,m_url(_ulr)
{
m_varValue = TQVariant( _linkName );
}
TQString KoLinkVariable::fieldCode()
{
return i18n("Link");
}
void KoLinkVariable::loadOasis( const TQDomElement &elem, KoOasisContext& /*context*/ )
{
if ( elem.localName() == "a" && elem.namespaceURI() == KoXmlNS::text ) {
m_url = elem.attributeNS( KoXmlNS::xlink, "href", TQString());
m_varValue = TQVariant(elem.text());
}
}
void KoLinkVariable::saveOasis( KoXmlWriter& writer, KoSavingContext& /*context*/ ) const
{
//<text:a xlink:type="simple" xlink:href="http://www.kde.org/" office:name="sdgfsdfgs">kde org wxc &lt;wxc </text:a>
writer.startElement( "text:a" );
writer.addAttribute( "xlink:type", "simple" );
writer.addAttribute( "xlink:href", m_url );
writer.addAttribute( "office:name", m_varValue.toString() );
writer.addTextNode( m_varValue.toString() );
writer.endElement();
}
TQString KoLinkVariable::text(bool realValue)
{
if (m_varColl->variableSetting()->displayFieldCode()&&!realValue)
return fieldCode();
else
return value();
}
void KoLinkVariable::saveVariable( TQDomElement& parentElem )
{
TQDomElement linkElem = parentElem.ownerDocument().createElement( "LINK" );
parentElem.appendChild( linkElem );
linkElem.setAttribute( "linkName", m_varValue.toString() );
linkElem.setAttribute( "hrefName", m_url );
}
void KoLinkVariable::load( TQDomElement& elem )
{
KoVariable::load( elem );
TQDomElement linkElem = elem.namedItem( "LINK" ).toElement();
if (!linkElem.isNull())
{
m_varValue = TQVariant(linkElem.attribute("linkName"));
m_url = linkElem.attribute("hrefName");
}
}
void KoLinkVariable::recalc()
{
resize();
}
TQStringList KoLinkVariable::actionTexts()
{
return TQStringList( i18n( "Link..." ) );
}
void KoLinkVariable::drawCustomItem( TQPainter* p, int x, int y, int wpix, int hpix, int ascentpix, int /*cx*/, int /*cy*/, int /*cw*/, int /*ch*/, const TQColorGroup& cg, bool selected, int offset, bool drawingShadow )
{
KoTextFormat * fmt = format();
KoTextZoomHandler * zh = textDocument()->paintingZoomHandler();
bool displayLink = m_varColl->variableSetting()->displayLink();
TQFont font( fmt->screenFont( zh ) );
if ( m_varColl->variableSetting()->underlineLink() )
font.setUnderline( true );
TQColor textColor = displayLink ? cg.color( TQColorGroup::Link ) : fmt->color();
drawCustomItemHelper( p, x, y, wpix, hpix, ascentpix, cg, selected, offset, fmt, font, textColor, drawingShadow );
}
/******************************************************************/
/* Class: KoNoteVariable */
/******************************************************************/
KoNoteVariable::KoNoteVariable( KoTextDocument *textdoc, const TQString & _note,KoVariableFormat *varFormat,KoVariableCollection *_varColl )
: KoVariable( textdoc, varFormat,_varColl )
, m_createdNoteDate( TQDate::tqcurrentDate() )
{
m_varValue = TQVariant( _note );
}
TQString KoNoteVariable::fieldCode()
{
return i18n("Note");
}
TQString KoNoteVariable::createdNote() const
{
return KGlobal::locale()->formatDate( m_createdNoteDate, false );
}
void KoNoteVariable::loadOasis( const TQDomElement &elem, KoOasisContext& /*context*/ )
{
const TQString localName = elem.localName();
TQString note;
if ( localName == "annotation" && elem.namespaceURI() == KoXmlNS::office )
{
TQDomElement date = KoDom::namedItemNS( elem, KoXmlNS::dc, "date" );
m_createdNoteDate = TQDate::fromString( date.text(), Qt::ISODate );
TQDomNode text = KoDom::namedItemNS( elem, KoXmlNS::text, "p" );
for ( ; !text.isNull(); text = text.nextSibling() )
{
if ( text.isElement() )
{
TQDomElement t = text.toElement();
note += t.text() + "\n";
}
}
}
m_varValue = TQVariant( note );
}
void KoNoteVariable::saveOasis( KoXmlWriter& writer, KoSavingContext& /*context*/ ) const
{
// <office:annotation><dc:date>2004-11-10</dc:date><text:p/><text:p>---- 10/11/2004, 16:18 ----</text:p><text:p>dfgsdfsdfg</text:p><text:p>---- 10/11/2004, 16:18 ----</text:p><text:p/><text:p>---- 10/11/2004, 16:18 ----</text:p><text:p>gs</text:p><text:p>---- 10/11/2004, 16:18 ----</text:p><text:p>fg</text:p></office:annotation>
writer.startElement( "office:annotation" );
writer.startElement( "dc:date" );
writer.addTextNode( m_createdNoteDate.toString(Qt::ISODate) );
writer.endElement();
TQStringList text = TQStringList::split( "\n", m_varValue.toString() );
for ( TQStringList::Iterator it = text.begin(); it != text.end(); ++it ) {
writer.startElement( "text:p" );
writer.addTextNode( *it );
writer.endElement();
}
writer.endElement();
}
void KoNoteVariable::saveVariable( TQDomElement& parentElem )
{
TQDomElement linkElem = parentElem.ownerDocument().createElement( "NOTE" );
parentElem.appendChild( linkElem );
linkElem.setAttribute( "note", m_varValue.toString() );
}
void KoNoteVariable::load( TQDomElement& elem )
{
KoVariable::load( elem );
TQDomElement linkElem = elem.namedItem( "NOTE" ).toElement();
if (!linkElem.isNull())
{
m_varValue = TQVariant(linkElem.attribute("note"));
}
}
void KoNoteVariable::recalc()
{
resize();
}
TQStringList KoNoteVariable::actionTexts()
{
return TQStringList( i18n( "Note..." ) );
}
TQString KoNoteVariable::text(bool realValue)
{
if (m_varColl->variableSetting()->displayComment() &&
m_varColl->variableSetting()->displayFieldCode()&&!realValue)
return fieldCode();
else
//for a note return just a "space" we can look at
//note when we "right button"
return TQString(" ");
}
void KoNoteVariable::drawCustomItem( TQPainter* p, int x, int y, int wpix, int hpix, int ascentpix, int cx, int cy, int cw, int ch, const TQColorGroup& cg, bool selected, int offset, bool drawingShadow )
{
if ( !m_varColl->variableSetting()->displayComment())
return;
KoTextFormat * fmt = format();
//kdDebug(32500) << "KoNoteVariable::drawCustomItem index=" << index() << " x=" << x << " y=" << y << endl;
p->save();
p->setPen( TQPen( fmt->color() ) );
if ( fmt->textBackgroundColor().isValid() )
p->fillRect( x, y, wpix, hpix, fmt->textBackgroundColor() );
if ( selected )
{
p->setPen( TQPen( cg.color( TQColorGroup::HighlightedText ) ) );
p->fillRect( x, y, wpix, hpix, cg.color( TQColorGroup::Highlight ) );
}
else if ( textDocument() && p->device()->devType() != TQInternal::Printer
&& !textDocument()->dontDrawingNoteVariable())
{
p->fillRect( x, y, wpix, hpix, TQt::yellow);
p->setPen( TQPen( cg.color( TQColorGroup::Highlight ), 0, TQt::DotLine ) );
p->drawRect( x, y, wpix, hpix );
}
//call it for use drawCustomItemHelper just for draw font effect
KoVariable::drawCustomItem( p, x, y, wpix, hpix, ascentpix, cx, cy, cw, ch, cg, selected, offset, drawingShadow );
p->restore();
}
void KoPageVariable::setSectionTitle( const TQString& _title )
{
TQString title( _title );
if ( title.isEmpty() )
{
title = i18n("<No title>");
}
m_varValue = TQVariant( title );
}
// ----------------------------------------------------------------
// class KoStatisticVariable
bool KoStatisticVariable::m_extendedType = false;
KoStatisticVariable::KoStatisticVariable( KoTextDocument *textdoc,
short int subtype,
KoVariableFormat *varFormat,
KoVariableCollection *_varColl )
: KoVariable( textdoc, varFormat, _varColl ),
m_subtype( subtype )
{
}
TQStringList KoStatisticVariable::actionTexts()
{
TQStringList lst;
lst << i18n( "Number of Words" );
lst << i18n( "Number of Sentences" );
lst << i18n( "Number of Lines" );
lst << i18n( "Number of Characters" );
lst << i18n( "Number of Non-Whitespace Characters" );
lst << i18n( "Number of Syllables" );
lst << i18n( "Number of Frames" );
lst << i18n( "Number of Embedded Objects" );
lst << i18n( "Number of Pictures" );
if ( m_extendedType )
lst << i18n( "Number of Tables" );
return lst;
}
void KoStatisticVariable::setVariableSubType( short int subtype )
{
m_subtype = subtype;
Q_ASSERT( m_varColl );
KoVariableFormatCollection* fc = m_varColl->formatCollection();
setVariableFormat(fc->format("NUMBER") );
}
TQStringList KoStatisticVariable::subTypeList()
{
return KoStatisticVariable::actionTexts();
}
void KoStatisticVariable::saveVariable( TQDomElement& varElem )
{
TQDomElement elem = varElem.ownerDocument().createElement( "STATISTIC" );
varElem.appendChild( elem );
elem.setAttribute( "type", TQString::number(m_subtype) );
elem.setAttribute( "value", TQString::number(m_varValue.toInt()) );
}
void KoStatisticVariable::load( TQDomElement &elem )
{
KoVariable::load( elem );
TQDomElement e = elem.namedItem( "STATISTIC" ).toElement();
if ( !e.isNull() ) {
// FIXME: Error handling.
m_subtype = e.attribute( "type" ).toInt();
m_varValue = e.attribute( "value" ).toInt();
}
}
void KoStatisticVariable::loadOasis( const TQDomElement &elem, KoOasisContext& /*context*/ )
{
const TQString localName( elem.localName() );
if ( localName == "object-count" )
{
m_subtype = VST_STATISTIC_NB_EMBEDDED;
m_varValue = TQVariant( elem.text().toInt() );
}
else if ( localName == "table-count" )
{
m_subtype = VST_STATISTIC_NB_TABLE;
m_varValue = TQVariant( elem.text().toInt() );
}
else if ( localName == "picture-count" )
{
m_subtype = VST_STATISTIC_NB_PICTURE;
m_varValue = TQVariant( elem.text().toInt() );
}
else if ( localName == "word-count" )
{
m_subtype = VST_STATISTIC_NB_WORD;
m_varValue = TQVariant( elem.text().toInt() );
}
else if ( localName == "character-count" )
{
m_subtype = VST_STATISTIC_NB_CHARACTERE;
m_varValue = TQVariant( elem.text().toInt() );
}
else if ( localName == "frame-count" )
{
m_subtype = VST_STATISTIC_NB_FRAME;
m_varValue = TQVariant( elem.text().toInt() );
}
else if ( localName == "line-count" )
{
m_subtype = VST_STATISTIC_NB_LINES;
m_varValue = TQVariant( elem.text().toInt() );
}
else if ( localName == "sentence-count" )
{
m_subtype = VST_STATISTIC_NB_SENTENCE;
m_varValue = TQVariant( elem.text().toInt() );
}
else if ( localName == "non-whitespace-character-count" )
{
m_subtype = VST_STATISTIC_NB_NON_WHITESPACE_CHARACTERE;
m_varValue = TQVariant( elem.text().toInt() );
}
else if ( localName == "syllable-count" )
{
m_subtype = VST_STATISTIC_NB_SYLLABLE;
m_varValue = TQVariant( elem.text().toInt() );
}
//TODO other copy
}
void KoStatisticVariable::saveOasis( KoXmlWriter& writer, KoSavingContext& /*context*/ ) const
{
switch( m_subtype )
{
case VST_STATISTIC_NB_EMBEDDED:
writer.startElement( "text:object-count" );
writer.addTextNode( TQString::number( m_varValue.toInt() ) );
writer.endElement();
break;
case VST_STATISTIC_NB_TABLE:
writer.startElement( "text:table-count" );
writer.addTextNode( TQString::number( m_varValue.toInt() ) );
writer.endElement();
break;
case VST_STATISTIC_NB_PICTURE:
writer.startElement( "text:picture-count" );
writer.addTextNode( TQString::number( m_varValue.toInt() ) );
writer.endElement();
break;
case VST_STATISTIC_NB_FRAME:
//TODO verify that it's implemented into oasis file format
writer.startElement( "text:frame-count" );
writer.addTextNode( TQString::number( m_varValue.toInt() ) );
writer.endElement();
break;
case VST_STATISTIC_NB_WORD:
writer.startElement( "text:word-count" );
writer.addTextNode( TQString::number( m_varValue.toInt() ) );
writer.endElement();
break;
case VST_STATISTIC_NB_SENTENCE:
//TODO verify that it's implemented into oasis file format
writer.startElement( "text:sentence-count" );
writer.addTextNode( TQString::number( m_varValue.toInt() ) );
writer.endElement();
break;
case VST_STATISTIC_NB_CHARACTERE:
writer.startElement( "text:character-count" );
writer.addTextNode( TQString::number( m_varValue.toInt() ) );
writer.endElement();
break;
case VST_STATISTIC_NB_LINES:
//TODO verify that it's implemented into oasis file format
writer.startElement( "text:line-count" );
writer.addTextNode( TQString::number( m_varValue.toInt() ) );
writer.endElement();
break;
case VST_STATISTIC_NB_NON_WHITESPACE_CHARACTERE:
//TODO verify that it's implemented into oasis file format
writer.startElement( "text:non-whitespace-character-count" );
writer.addTextNode( TQString::number( m_varValue.toInt() ) );
writer.endElement();
break;
case VST_STATISTIC_NB_SYLLABLE:
//TODO verify that it's implemented into oasis file format
writer.startElement( "text:syllable-count" );
writer.addTextNode( TQString::number( m_varValue.toInt() ) );
writer.endElement();
break;
}
}
TQString KoStatisticVariable::fieldCode()
{
if ( m_subtype == VST_STATISTIC_NB_FRAME )
{
return i18n( "Number of Frames" );
}
else if( m_subtype == VST_STATISTIC_NB_PICTURE )
{
return i18n( "Number of Pictures" );
}
else if( m_subtype == VST_STATISTIC_NB_TABLE )
{
return i18n( "Number of Tables" );
}
else if( m_subtype == VST_STATISTIC_NB_EMBEDDED )
{
return i18n( "Number of Embedded Objects" );
}
else if( m_subtype == VST_STATISTIC_NB_WORD )
{
return i18n( "Number of Words" );
}
else if( m_subtype == VST_STATISTIC_NB_SENTENCE )
{
return i18n( "Number of Sentences" );
}
else if( m_subtype == VST_STATISTIC_NB_LINES )
{
return i18n( "Number of Lines" );
}
else if ( m_subtype == VST_STATISTIC_NB_CHARACTERE )
{
return i18n( "Number of Characters" );
}
else if ( m_subtype == VST_STATISTIC_NB_NON_WHITESPACE_CHARACTERE )
{
return i18n( "Number of Non-Whitespace Characters" );
}
else if ( m_subtype == VST_STATISTIC_NB_SYLLABLE )
{
return i18n( "Number of Syllables" );
}
else
return i18n( "Number of Frames" );
}