lib

KoVariable.cpp

00001 /* This file is part of the KDE project
00002    Copyright (C) 1998, 1999 Reginald Stadlbauer <reggie@kde.org>
00003    Copyright (C) 2005 David Faure <faure@kde.org>
00004 
00005    This library is free software; you can redistribute it and/or
00006    modify it under the terms of the GNU Library General Public
00007    License as published by the Free Software Foundation; either
00008    version 2 of the License, or (at your option) any later version.
00009 
00010    This library is distributed in the hope that it will be useful,
00011    but WITHOUT ANY WARRANTY; without even the implied warranty of
00012    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00013    Library General Public License for more details.
00014 
00015    You should have received a copy of the GNU Library General Public License
00016    along with this library; see the file COPYING.LIB.  If not, write to
00017    the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
00018  * Boston, MA 02110-1301, USA.
00019 */
00020 
00021 #include "KoVariable.h"
00022 #include "KoVariable.moc"
00023 #include "KoTextZoomHandler.h"
00024 #include "TimeFormatWidget.h"
00025 #include "DateFormatWidget.h"
00026 #include "KoTextCommand.h"
00027 #include "KoTextObject.h"
00028 #include "KoTextParag.h"
00029 #include "KoOasisContext.h"
00030 #include <KoOasisSettings.h>
00031 
00032 #include <KoDocumentInfo.h>
00033 #include <KoOasisStyles.h>
00034 #include <KoXmlWriter.h>
00035 #include <KoDocument.h>
00036 #include <KoXmlNS.h>
00037 #include <KoDom.h>
00038 
00039 #include <klocale.h>
00040 #include <kdebug.h>
00041 #include <kglobal.h>
00042 #include <kdialogbase.h>
00043 #include <kconfig.h>
00044 #include <kdeversion.h>
00045 #include <kinstance.h>
00046 #include <kcalendarsystem.h>
00047 #include <kaboutdata.h>
00048 
00049 #include <qstringlist.h>
00050 #include <qcombobox.h>
00051 #include <qvaluelist.h>
00052 #include <qdom.h>
00053 #include <qradiobutton.h>
00054 
00055 #include "IsoDuration.h"
00056 
00057 class KoVariableSettings::KoVariableSettingPrivate
00058 {
00059 public:
00060     KoVariableSettingPrivate()
00061     {
00062         m_lastPrintingDate.setTime_t(0); // Default is 1970-01-01 midnight locale time
00063     }
00064     QDateTime m_lastPrintingDate;
00065     QDateTime m_creationDate;
00066     QDateTime m_modificationDate;
00067 };
00068 
00069 
00070 KoVariableSettings::KoVariableSettings()
00071 {
00072     d = new KoVariableSettingPrivate;
00073     m_startingPageNumber = 1;
00074     m_displayLink = true;
00075     m_displayComment = true;
00076     m_underlineLink = true;
00077     m_displayFieldCode = false;
00078 }
00079 
00080 KoVariableSettings::~KoVariableSettings()
00081 {
00082     delete d;
00083     d = 0;
00084 }
00085 
00086 QDateTime KoVariableSettings::lastPrintingDate() const
00087 {
00088     return d->m_lastPrintingDate;
00089 }
00090 
00091 void KoVariableSettings::setLastPrintingDate( const QDateTime & _date)
00092 {
00093     d->m_lastPrintingDate = _date;
00094 }
00095 
00096 QDateTime KoVariableSettings::creationDate() const
00097 {
00098     return d->m_creationDate;
00099 }
00100 
00101 void KoVariableSettings::setCreationDate( const QDateTime & _date )
00102 {
00103     d->m_creationDate = _date;
00104 }
00105 
00106 QDateTime KoVariableSettings::modificationDate() const
00107 {
00108     return d->m_modificationDate;
00109 }
00110 
00111 void KoVariableSettings::setModificationDate( const QDateTime & _date)
00112 {
00113     d->m_modificationDate = _date;
00114 }
00115 
00116 void KoVariableSettings::saveOasis( KoXmlWriter &settingsWriter ) const
00117 {
00118     settingsWriter.startElement("config:config-item-set");
00119     settingsWriter.addAttribute("config:name", "configuration-variable-settings");
00120     settingsWriter.addConfigItem("displaylink", m_displayLink );
00121     settingsWriter.addConfigItem( "underlinelink", m_underlineLink);
00122     settingsWriter.addConfigItem( "displaycomment", m_displayComment);
00123     settingsWriter.addConfigItem( "displayfieldcode", m_displayFieldCode);
00124     // m_startingPageNumber isn't saved to OASIS. Applications must use either
00125     // style:page-number in the first parag of a page (see KoTextParag), or
00126     // style:first-page-number in style:page-layout, for spreadsheets etc.
00127     if ( d->m_lastPrintingDate.isValid())
00128         settingsWriter.addConfigItem("lastPrintingDate", d->m_lastPrintingDate.toString(Qt::ISODate));
00129 
00130     if ( d->m_creationDate.isValid())
00131         settingsWriter.addConfigItem("creationDate", d->m_creationDate.toString(Qt::ISODate));
00132 
00133     if ( d->m_modificationDate.isValid())
00134         settingsWriter.addConfigItem("modificationDate", d->m_modificationDate.toString(Qt::ISODate));
00135 
00136     settingsWriter.endElement(); // config:config-item-set
00137 }
00138 
00139 void KoVariableSettings::loadOasis(const KoOasisSettings&settingsDoc)
00140 {
00141     KoOasisSettings::Items configurationSettings = settingsDoc.itemSet( "configuration-variable-settings" );
00142     if ( !configurationSettings.isNull() )
00143     {
00144         m_displayLink = configurationSettings.parseConfigItemBool( "displaylink", true );
00145         m_underlineLink = configurationSettings.parseConfigItemBool( "underlinelink", true );
00146         m_displayComment = configurationSettings.parseConfigItemBool( "displaycomment", true );
00147         m_displayFieldCode = configurationSettings.parseConfigItemBool( "displayfieldcode", false );
00148 
00149         QString str = configurationSettings.parseConfigItemString( "lastPrintingDate" );
00150         if ( !str.isEmpty() )
00151             d->m_lastPrintingDate = QDateTime::fromString( str, Qt::ISODate );
00152         else
00153             d->m_lastPrintingDate.setTime_t(0); // 1970-01-01 00:00:00.000 locale time
00154 
00155         str = configurationSettings.parseConfigItemString( "creationDate" );
00156         if ( !str.isEmpty() ) {
00157             d->m_creationDate = QDateTime::fromString( str, Qt::ISODate );
00158         }
00159 
00160         str = configurationSettings.parseConfigItemString( "modificationDate" );
00161         if ( !str.isEmpty() )
00162             d->m_modificationDate = QDateTime::fromString( str, Qt::ISODate );
00163 
00164         // m_startingPageNumber isn't loaded from OASIS here. KWTextParag::loadOasis does it.
00165     }
00166 }
00167 
00168 void KoVariableSettings::save( QDomElement &parentElem )
00169 {
00170      QDomElement elem = parentElem.ownerDocument().createElement( "VARIABLESETTINGS" );
00171      parentElem.appendChild( elem );
00172     if(m_startingPageNumber!=1)
00173     {
00174         elem.setAttribute( "startingPageNumber", m_startingPageNumber );
00175     }
00176     elem.setAttribute("displaylink",(int)m_displayLink);
00177     elem.setAttribute("underlinelink",(int)m_underlineLink);
00178     elem.setAttribute("displaycomment",(int)m_displayComment);
00179     elem.setAttribute("displayfieldcode", (int)m_displayFieldCode);
00180 
00181     if ( d->m_lastPrintingDate.isValid())
00182         elem.setAttribute("lastPrintingDate", d->m_lastPrintingDate.toString(Qt::ISODate));
00183 
00184     if ( d->m_creationDate.isValid())
00185         elem.setAttribute("creationDate", d->m_creationDate.toString(Qt::ISODate));
00186 
00187     if ( d->m_modificationDate.isValid())
00188         elem.setAttribute("modificationDate", d->m_modificationDate.toString(Qt::ISODate));
00189 }
00190 
00191 void KoVariableSettings::load( QDomElement &elem )
00192 {
00193     QDomElement e = elem.namedItem( "VARIABLESETTINGS" ).toElement();
00194     if (!e.isNull())
00195     {
00196         if(e.hasAttribute("startingPageNumber"))
00197             m_startingPageNumber = e.attribute("startingPageNumber").toInt();
00198         if(e.hasAttribute("displaylink"))
00199             m_displayLink=(bool)e.attribute("displaylink").toInt();
00200         if(e.hasAttribute("underlinelink"))
00201             m_underlineLink=(bool)e.attribute("underlinelink").toInt();
00202         if(e.hasAttribute("displaycomment"))
00203             m_displayComment=(bool)e.attribute("displaycomment").toInt();
00204         if (e.hasAttribute("displayfieldcode"))
00205             m_displayFieldCode=(bool)e.attribute("displayfieldcode").toInt();
00206 
00207         if (e.hasAttribute("lastPrintingDate"))
00208             d->m_lastPrintingDate = QDateTime::fromString( e.attribute( "lastPrintingDate" ), Qt::ISODate );
00209         else
00210             d->m_lastPrintingDate.setTime_t(0); // 1970-01-01 00:00:00.000 locale time
00211 
00212         if (e.hasAttribute("creationDate")) {
00213             d->m_creationDate = QDateTime::fromString( e.attribute( "creationDate" ), Qt::ISODate );
00214         }
00215 
00216         if (e.hasAttribute("modificationDate"))
00217             d->m_modificationDate = QDateTime::fromString( e.attribute( "modificationDate" ), Qt::ISODate );
00218     }
00219 }
00220 
00221 KoVariableDateFormat::KoVariableDateFormat() : KoVariableFormat()
00222 {
00223 }
00224 
00225 QString KoVariableDateFormat::convert( const QVariant& data ) const
00226 {
00227     if ( data.type() != QVariant::Date && data.type() != QVariant::DateTime )
00228     {
00229         kdWarning(32500)<<" Error in KoVariableDateFormat::convert. Value is a "
00230                       << data.typeName() << "(" << data.type() << ")" << endl;
00231         // dateTime will be invalid, then set to 1970-01-01
00232     }
00233     QDateTime dateTime ( data.toDateTime() );
00234     if ( !dateTime.isValid() )
00235         return i18n("No date set"); // e.g. old KWord documents
00236 
00237     if (m_strFormat.lower() == "locale" || m_strFormat.isEmpty())
00238         return KGlobal::locale()->formatDate( dateTime.date(), false );
00239     else if ( m_strFormat.lower() == "localeshort" )
00240         return KGlobal::locale()->formatDate( dateTime.date(), true );
00241     else if ( m_strFormat.lower() == "localedatetime" )
00242         return KGlobal::locale()->formatDateTime( dateTime, false );
00243     else if ( m_strFormat.lower() == "localedatetimeshort" )
00244         return KGlobal::locale()->formatDateTime( dateTime, true );
00245 
00246     QString tmp ( dateTime.toString(m_strFormat) );
00247     const int month = dateTime.date().month();
00248     tmp.replace("PPPP", KGlobal::locale()->calendar()->monthNamePossessive(month, false)); //long possessive month name
00249     tmp.replace("PPP",  KGlobal::locale()->calendar()->monthNamePossessive(month, true));  //short possessive month name
00250     return tmp;
00251 }
00252 
00253 QCString KoVariableDateFormat::key() const
00254 {
00255     return getKey( m_strFormat );
00256 }
00257 
00258 QCString KoVariableDateFormat::getKey( const QString& props ) const
00259 {
00260     return QCString("DATE") + props.utf8();
00261 }
00262 
00263 void KoVariableDateFormat::load( const QCString &key )
00264 {
00265     QCString params( key.mid( 4 ) ); // skip "DATE"
00266     if ( !params.isEmpty() )
00267     {
00268         if (params[0] == '1' || params[0] == '0') // old m_bShort crap
00269             params = params.mid(1); // skip it
00270         m_strFormat = QString::fromUtf8( params );
00271     }
00272 }
00273 
00274 // Used by KoVariableFormatCollection::popupActionList(), to apply all formats
00275 // to the current data, in the popup menu.
00276 QStringList KoVariableDateFormat::staticFormatPropsList()
00277 {
00278     QStringList listDateFormat;
00279     listDateFormat<<"locale";
00280     listDateFormat<<"localeshort";
00281     listDateFormat<<"localedatetime";
00282     listDateFormat<<"localedatetimeshort";
00283     listDateFormat<<"dd/MM/yy";
00284     listDateFormat<<"dd/MM/yyyy";
00285     listDateFormat<<"MMM dd,yy";
00286     listDateFormat<<"MMM dd,yyyy";
00287     listDateFormat<<"dd.MMM.yyyy";
00288     listDateFormat<<"MMMM dd, yyyy";
00289     listDateFormat<<"ddd, MMM dd,yy";
00290     listDateFormat<<"dddd, MMM dd,yy";
00291     listDateFormat<<"MM-dd";
00292     listDateFormat<<"yyyy-MM-dd";
00293     listDateFormat<<"dd/yy";
00294     listDateFormat<<"MMMM";
00295     listDateFormat<<"yyyy-MM-dd hh:mm";
00296     listDateFormat<<"dd.MMM.yyyy hh:mm";
00297     listDateFormat<<"MMM dd,yyyy h:mm AP";
00298     listDateFormat<<"yyyy-MM-ddThh:mm:ss"; // ISO 8601
00299     return listDateFormat;
00300 }
00301 
00302 // Used by dateformatwidget_impl
00303 // TODO: shouldn't it apply the formats to the value, like the popupmenu does?
00304 QStringList KoVariableDateFormat::staticTranslatedFormatPropsList()
00305 {
00306     QStringList listDateFormat;
00307     listDateFormat<<i18n("Locale date format");
00308     listDateFormat<<i18n("Short locale date format");
00309     listDateFormat<<i18n("Locale date & time format");
00310     listDateFormat<<i18n("Short locale date & time format");
00311     listDateFormat<<"dd/MM/yy";
00312     listDateFormat<<"dd/MM/yyyy";
00313     listDateFormat<<"MMM dd,yy";
00314     listDateFormat<<"MMM dd,yyyy";
00315     listDateFormat<<"dd.MMM.yyyy";
00316     listDateFormat<<"MMMM dd, yyyy";
00317     listDateFormat<<"ddd, MMM dd,yy";
00318     listDateFormat<<"dddd, MMM dd,yy";
00319     listDateFormat<<"MM-dd";
00320     listDateFormat<<"yyyy-MM-dd";
00321     listDateFormat<<"dd/yy";
00322     listDateFormat<<"MMMM";
00323     listDateFormat<<"yyyy-MM-dd hh:mm";
00324     listDateFormat<<"dd.MMM.yyyy hh:mm";
00325     listDateFormat<<"MMM dd,yyyy h:mm AP";
00326     listDateFormat<<"yyyy-MM-ddThh:mm:ss"; // ISO 8601
00327     return listDateFormat;
00328 }
00329 
00331 
00332 KoVariableTimeFormat::KoVariableTimeFormat() : KoVariableFormat()
00333 {
00334 }
00335 
00336 void KoVariableTimeFormat::load( const QCString &key )
00337 {
00338     QCString params( key.mid( 4 ) );
00339     if ( !params.isEmpty() )
00340     m_strFormat = QString::fromUtf8(params);
00341 }
00342 
00343 QString KoVariableTimeFormat::convert( const QVariant & time ) const
00344 {
00345     if ( time.type() != QVariant::Time )
00346     {
00347         kdDebug(32500)<<" Error in KoVariableTimeFormat::convert. Value is a "
00348                       << time.typeName() << "(" << time.type() << ")" << endl;
00349         return QString::null;
00350     }
00351 
00352     if( m_strFormat.lower() == "locale" || m_strFormat.isEmpty() )
00353     return KGlobal::locale()->formatTime( time.toTime() );
00354     return time.toTime().toString(m_strFormat);
00355 }
00356 
00357 QCString KoVariableTimeFormat::key() const
00358 {
00359     return getKey( m_strFormat );
00360 }
00361 
00362 QCString KoVariableTimeFormat::getKey( const QString& props ) const
00363 {
00364     return QCString("TIME") + props.utf8();
00365 }
00366 
00367 // Used by KoVariableFormatCollection::popupActionList(), to apply all formats
00368 // to the current data, in the popup menu.
00369 QStringList KoVariableTimeFormat::staticFormatPropsList()
00370 {
00371     QStringList listTimeFormat;
00372     listTimeFormat<<"locale";
00373     listTimeFormat<<"hh:mm";
00374     listTimeFormat<<"hh:mm:ss";
00375     listTimeFormat<<"hh:mm AP";
00376     listTimeFormat<<"hh:mm:ss AP";
00377     listTimeFormat<<"mm:ss.zzz";
00378     return listTimeFormat;
00379 }
00380 
00381 // Used by timeformatwidget_impl
00382 QStringList KoVariableTimeFormat::staticTranslatedFormatPropsList()
00383 {
00384     QStringList listTimeFormat;
00385     listTimeFormat<<i18n("Locale format");
00386     listTimeFormat<<"hh:mm";
00387     listTimeFormat<<"hh:mm:ss";
00388     listTimeFormat<<"hh:mm AP";
00389     listTimeFormat<<"hh:mm:ss AP";
00390     listTimeFormat<<"mm:ss.zzz";
00391     return listTimeFormat;
00392 }
00393 
00395 
00396 QString KoVariableStringFormat::convert( const QVariant & string ) const
00397 {
00398     if ( string.type() != QVariant::String )
00399     {
00400         kdDebug(32500)<<" Error in KoVariableStringFormat::convert. Value is a " << string.typeName() << endl;
00401         return QString::null;
00402     }
00403 
00404     return string.toString();
00405 }
00406 
00407 QCString KoVariableStringFormat::key() const
00408 {
00409     return getKey( QString::null );
00410     // TODO prefix & suffix
00411 }
00412 
00413 QCString KoVariableStringFormat::getKey( const QString& props ) const
00414 {
00415     return QCString("STRING") + props.utf8();
00416 }
00417 
00419 
00420 QString KoVariableNumberFormat::convert( const QVariant &value ) const
00421 {
00422     if ( value.type() != QVariant::Int )
00423     {
00424         kdDebug(32500)<<" Error in KoVariableNumberFormat::convert. Value is a " << value.typeName() << endl;
00425         return QString::null;
00426     }
00427 
00428     return QString::number( value.toInt() );
00429 }
00430 
00431 QCString KoVariableNumberFormat::key() const
00432 {
00433     return getKey(QString::null);
00434 }
00435 
00436 QCString KoVariableNumberFormat::getKey( const QString& props ) const
00437 {
00438     return QCString("NUMB") + props.utf8();
00439 }
00440 
00442 
00443 KoVariableFormatCollection::KoVariableFormatCollection()
00444 {
00445     m_dict.setAutoDelete( true );
00446 }
00447 
00448 KoVariableFormat * KoVariableFormatCollection::format( const QCString &key )
00449 {
00450     KoVariableFormat *f = m_dict[ key.data() ];
00451     if (f)
00452         return f;
00453     else
00454         return createFormat( key );
00455 }
00456 
00457 KoVariableFormat * KoVariableFormatCollection::createFormat( const QCString &key )
00458 {
00459     kdDebug(32500) << "KoVariableFormatCollection: creating format for key=" << key << endl;
00460     KoVariableFormat * format = 0L;
00461     // The first 4 chars identify the class
00462     QCString type = key.left(4);
00463     if ( type == "DATE" )
00464         format = new KoVariableDateFormat();
00465     else if ( type == "TIME" )
00466         format = new KoVariableTimeFormat();
00467     else if ( type == "NUMB" ) // this type of programming makes me numb ;)
00468         format = new KoVariableNumberFormat();
00469     else if ( type == "STRI" )
00470         format = new KoVariableStringFormat();
00471 
00472     if ( format )
00473     {
00474         format->load( key );
00475         m_dict.insert( format->key() /* not 'key', it could be incomplete */, format );
00476     }
00477     return format;
00478 }
00479 
00480 /******************************************************************/
00481 /* Class:       KoVariableCollection                              */
00482 /******************************************************************/
00483 KoVariableCollection::KoVariableCollection(KoVariableSettings *_settings, KoVariableFormatCollection *formatCollection)
00484 {
00485     m_variableSettings = _settings;
00486     m_varSelected = 0L;
00487     m_formatCollection = formatCollection;
00488 }
00489 
00490 KoVariableCollection::~KoVariableCollection()
00491 {
00492     delete m_variableSettings;
00493 }
00494 
00495 void KoVariableCollection::clear()
00496 {
00497     variables.clear();
00498     varValues.clear();
00499     m_varSelected = 0;
00500 }
00501 
00502 void KoVariableCollection::registerVariable( KoVariable *var )
00503 {
00504     if ( !var )
00505         return;
00506     variables.append( var );
00507 }
00508 
00509 void KoVariableCollection::unregisterVariable( KoVariable *var )
00510 {
00511     variables.take( variables.findRef( var ) );
00512 }
00513 
00514 QValueList<KoVariable *> KoVariableCollection::recalcVariables(int type)
00515 {
00516     QValueList<KoVariable *> modifiedVariables;
00517     QPtrListIterator<KoVariable> it( variables );
00518     for ( ; it.current() ; ++it )
00519     {
00520         KoVariable* variable = it.current();
00521         if ( variable->isDeleted() )
00522             continue;
00523         if ( variable->type() == type || type == VT_ALL )
00524         {
00525             QVariant oldValue = variable->varValue();
00526             variable->recalc();
00527             if(variable->height == 0)
00528                 variable->resize();
00529             if ( variable->varValue() != oldValue )
00530                 modifiedVariables.append( variable );
00531             KoTextParag * parag = variable->paragraph();
00532             if ( parag )
00533             {
00534                 //kdDebug(32500) << "KoDoc::recalcVariables -> invalidating parag " << parag->paragId() << endl;
00535                 parag->invalidate( 0 );
00536                 parag->setChanged( true );
00537             }
00538         }
00539     }
00540 #if 0
00541     // TODO pass list of textdocuments as argument
00542     // Or even better, call emitRepaintChanged on all modified textobjects
00543     if( !modifiedVariables.isEmpty() )
00544         emit repaintVariable();
00545 #endif
00546     return modifiedVariables;
00547 }
00548 
00549 
00550 void KoVariableCollection::setVariableValue( const QString &name, const QString &value )
00551 {
00552     varValues[ name ] = value;
00553 }
00554 
00555 QString KoVariableCollection::getVariableValue( const QString &name ) const
00556 {
00557     if ( !varValues.contains( name ) )
00558         return i18n( "No value" );
00559     return varValues[ name ];
00560 }
00561 
00562 bool KoVariableCollection::customVariableExist(const QString &varname) const
00563 {
00564     return varValues.contains( varname );
00565 }
00566 
00567 void KoVariableCollection::setVariableSelected(KoVariable * var)
00568 {
00569     m_varSelected=var;
00570 }
00571 
00572 // TODO change to QValueList<KAction *>, but only once plugActionList takes that
00573 QPtrList<KAction> KoVariableCollection::popupActionList() const
00574 {
00575     QPtrList<KAction> listAction;
00576     // Insert list of actions that change the subtype
00577     const QStringList subTypeList = m_varSelected->subTypeList();
00578     kdDebug() << k_funcinfo << "current subtype=" << m_varSelected->subType() << endl;
00579     QStringList::ConstIterator it = subTypeList.begin();
00580     for ( int i = 0; it != subTypeList.end() ; ++it, ++i )
00581     {
00582         if ( !(*it).isEmpty() ) // in case of removed subtypes or placeholders
00583         {
00584             // We store the subtype number as the action name
00585             QCString name; name.setNum(i);
00586             KToggleAction * act = new KToggleAction( *it, KShortcut(), 0, name );
00587             connect( act, SIGNAL(activated()), this, SLOT(slotChangeSubType()) );
00588             if ( i == m_varSelected->subType() )
00589                 act->setChecked( true );
00590             //m_subTextMap.insert( act, i );
00591             listAction.append( act );
00592         }
00593     }
00594     // Insert list of actions that change the format properties
00595     KoVariableFormat* format = m_varSelected->variableFormat();
00596     QString currentFormat = format->formatProperties();
00597 
00598     const QStringList list = format->formatPropsList();
00599     it = list.begin();
00600     for ( int i = 0; it != list.end() ; ++it, ++i )
00601     {
00602         if( i == 0 ) // first item, and list not empty
00603             listAction.append( new KActionSeparator() );
00604 
00605         if ( !(*it).isEmpty() ) // in case of removed subtypes or placeholders
00606         {
00607             format->setFormatProperties( *it ); // temporary change
00608             QString text = format->convert( m_varSelected->varValue() );
00609             // We store the raw format as the action name
00610             KToggleAction * act = new KToggleAction(text, KShortcut(), 0, (*it).utf8());
00611             connect( act, SIGNAL(activated()), this, SLOT(slotChangeFormat()) );
00612             if ( (*it) == currentFormat )
00613                 act->setChecked( true );
00614             listAction.append( act );
00615         }
00616     }
00617 
00618     // Restore current format
00619     format->setFormatProperties( currentFormat );
00620     return listAction;
00621 }
00622 
00623 void KoVariableCollection::slotChangeSubType()
00624 {
00625     KAction * act = (KAction *)(sender());
00626     int menuNumber = QCString(act->name()).toInt();
00627     int newSubType = m_varSelected->variableSubType(menuNumber);
00628     kdDebug(32500) << "slotChangeSubType: menuNumber=" << menuNumber << " newSubType=" << newSubType << endl;
00629     if ( m_varSelected->subType() != newSubType )
00630     {
00631         KoChangeVariableSubType *cmd=new KoChangeVariableSubType(
00632             m_varSelected->subType(), newSubType, m_varSelected );
00633         cmd->execute();
00634         m_varSelected->textDocument()->emitNewCommand(cmd);
00635     }
00636 }
00637 
00638 void KoVariableCollection::slotChangeFormat()
00639 {
00640     KAction * act = (KAction *)(sender());
00641     QString newFormat = QString::fromUtf8(act->name());
00642     QString oldFormat = m_varSelected->variableFormat()->formatProperties();
00643     if (oldFormat != newFormat )
00644     {
00645         KCommand *cmd=new KoChangeVariableFormatProperties(
00646             oldFormat, newFormat, m_varSelected );
00647         cmd->execute();
00648         m_varSelected->textDocument()->emitNewCommand(cmd);
00649     }
00650 }
00651 
00652 KoVariable * KoVariableCollection::createVariable( int type, short int subtype, KoVariableFormatCollection * coll, KoVariableFormat *varFormat,KoTextDocument *textdoc, KoDocument * doc, int _correct, bool _forceDefaultFormat, bool /*loadFootNote*/ )
00653 {
00654     Q_ASSERT( coll == m_formatCollection ); // why do we need a parameter ?!?
00655     QCString string;
00656     QStringList stringList;
00657     if ( varFormat == 0L )
00658     {
00659         // Get the default format for this variable (this method is only called in the interactive case, not when loading)
00660         switch ( type ) {
00661         case VT_DATE:
00662         case VT_DATE_VAR_KWORD10:  // compatibility with kword 1.0
00663         {
00664             if ( _forceDefaultFormat )
00665                 varFormat = coll->format( KoDateVariable::defaultFormat() );
00666             else
00667             {
00668                 QCString result = KoDateVariable::formatStr(_correct);
00669                 if ( result.isNull() )//we cancel insert variable
00670                     return 0L;
00671                 varFormat = coll->format( result );
00672             }
00673             break;
00674         }
00675         case VT_TIME:
00676         case VT_TIME_VAR_KWORD10:  // compatibility with kword 1.0
00677         {
00678             if ( _forceDefaultFormat )
00679                 varFormat = coll->format( KoTimeVariable::defaultFormat() );
00680             else
00681             {
00682                 QCString result = KoTimeVariable::formatStr(_correct);
00683                 if ( result.isNull() )//we cancel insert variable
00684                     return 0L;
00685                 varFormat = coll->format( result );
00686             }
00687             break;
00688         }
00689         case VT_PGNUM:
00690             varFormat = coll->format( "NUMBER" );
00691             break;
00692         case VT_FIELD:
00693         case VT_CUSTOM:
00694         case VT_MAILMERGE:
00695         case VT_LINK:
00696         case VT_NOTE:
00697             varFormat = coll->format( "STRING" );
00698             break;
00699         case VT_FOOTNOTE: // this is a KWord-specific variable
00700             kdError() << "Footnote type not handled in KoVariableCollection: VT_FOOTNOTE" << endl;
00701             return 0L;
00702         case VT_STATISTIC:
00703             kdError() << " Statistic type not handled in KoVariableCollection: VT_STATISTIC" << endl;
00704             return 0L;
00705         }
00706     }
00707     Q_ASSERT( varFormat );
00708     if ( varFormat == 0L ) // still 0 ? Impossible!
00709         return 0L ;
00710 
00711     kdDebug(32500) << "Creating variable. Format=" << varFormat->key() << " type=" << type << endl;
00712     KoVariable * var = 0L;
00713     switch ( type ) {
00714         case VT_DATE:
00715         case VT_DATE_VAR_KWORD10:  // compatibility with kword 1.0
00716             var = new KoDateVariable( textdoc, subtype, varFormat, this, _correct );
00717             break;
00718         case VT_TIME:
00719         case VT_TIME_VAR_KWORD10:  // compatibility with kword 1.0
00720             var = new KoTimeVariable( textdoc, subtype, varFormat, this, _correct );
00721             break;
00722         case VT_PGNUM:
00723             kdError() << "VT_PGNUM must be handled by the application's reimplementation of KoVariableCollection::createVariable" << endl;
00724             //var = new KoPageVariable( textdoc, subtype, varFormat, this );
00725             break;
00726         case VT_FIELD:
00727             var = new KoFieldVariable( textdoc, subtype, varFormat,this,doc );
00728             break;
00729         case VT_CUSTOM:
00730             var = new KoCustomVariable( textdoc, QString::null, varFormat, this);
00731             break;
00732         case VT_MAILMERGE:
00733             var = new KoMailMergeVariable( textdoc, QString::null, varFormat ,this);
00734             break;
00735         case VT_LINK:
00736             var = new KoLinkVariable( textdoc,QString::null, QString::null, varFormat ,this);
00737             break;
00738         case VT_NOTE:
00739             var = new KoNoteVariable( textdoc, QString::null, varFormat ,this);
00740             break;
00741     }
00742     Q_ASSERT( var );
00743     return var;
00744 }
00745 
00746 
00747 KoVariable* KoVariableCollection::loadOasisField( KoTextDocument* textdoc, const QDomElement& tag, KoOasisContext& context )
00748 {
00749     const QString localName( tag.localName() );
00750     const bool isTextNS = tag.namespaceURI() == KoXmlNS::text;
00751     QString key;
00752     int type = -1;
00753     if ( isTextNS )
00754     {
00755         if ( localName.endsWith( "date" ) || localName.endsWith( "time" ) )
00756         {
00757             QString dataStyleName = tag.attributeNS( KoXmlNS::style, "data-style-name", QString::null );
00758             QString dateFormat = "locale";
00759             const KoOasisStyles::DataFormatsMap& map = context.oasisStyles().dataFormats();
00760             KoOasisStyles::DataFormatsMap::const_iterator it = map.find( dataStyleName );
00761             if ( it != map.end() )
00762                 dateFormat = (*it).formatStr;
00763 
00764             // Only text:time is a pure time (the data behind is only h/m/s)
00765             // ### 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.)
00766             // Whereas print-time/creation-time etc. are actually related to a date/time value.
00767             if ( localName == "time" )
00768             {
00769                 type = VT_TIME;
00770                 key = "TIME" + dateFormat;
00771             }
00772             else
00773             {
00774                 type = VT_DATE;
00775                 key = "DATE" + dateFormat;
00776             }
00777         }
00778         else if (localName == "page-number" || localName == "page-count" )
00779         {
00780             type = VT_PGNUM;
00781             key = "NUMBER";
00782         }
00783         else if (localName == "chapter")
00784         {
00785             type = VT_PGNUM;
00786             key = "STRING";
00787         }
00788         else if (localName == "file-name")
00789         {
00790             type = VT_FIELD;
00791             key = "STRING";
00792         }
00793         else if (localName == "author-name"
00794                  || localName == "author-initials"
00795                  || localName == "subject"
00796                  || localName == "title"
00797                  || localName == "description"
00798                  || localName == "keywords")
00799         {
00800             type = VT_FIELD;
00801             key = "STRING";
00802         }
00803         else if ( localName.startsWith( "sender-" )
00804                   && localName != "sender-firstname" // not supported
00805                   && localName != "sender-lastname" // not supported
00806                   && localName != "sender-initials" // not supported
00807             )
00808         {
00809             type = VT_FIELD;
00810             key = "STRING";
00811         }
00812         else if ( localName == "variable-set"
00813                   || localName == "user-defined"
00814                   || localName == "user-field-get" )
00815         {
00816             key = "STRING";
00817             type = VT_CUSTOM;
00818         }
00819         else
00820             return 0L;
00821     }
00822     else if ( tag.namespaceURI() == KoXmlNS::office && localName == "annotation" )
00823     {
00824         type = VT_NOTE;
00825         key = "NUMBER";
00826     }
00827     else
00828     {
00829         // Not an error. It's simply not a variable tag (the caller doesn't check for that)
00830         return 0;
00831     }
00832 // TODO localName == "page-variable-get", "initial-creator" and many more
00833 // TODO VT_MAILMERGE
00834 
00835     return loadOasisFieldCreateVariable( textdoc, tag, context, key, type );
00836 }
00837 
00838 KoVariable* KoVariableCollection::loadOasisFieldCreateVariable( KoTextDocument* textdoc, const QDomElement& tag, KoOasisContext& context, const QString &key, int type )
00839 {
00840     KoVariableFormat * varFormat = key.isEmpty() ? 0 : m_formatCollection->format( key.latin1() );
00841     // If varFormat is 0 (no key specified), the default format will be used.
00842 
00843     KoVariable* var = createVariable( type, -1, m_formatCollection, varFormat, textdoc, context.koDocument(), 0 /*correct*/, true );
00844     var->loadOasis( tag, context );
00845     return var;
00846 }
00847 
00848 /******************************************************************/
00849 /* Class: KoVariable                                              */
00850 /******************************************************************/
00851 KoVariable::KoVariable( KoTextDocument *textdoc, KoVariableFormat *varFormat, KoVariableCollection *_varColl)
00852     : KoTextCustomItem( textdoc )
00853 {
00854     //d = new Private;
00855     m_varColl=_varColl;
00856     m_varFormat = varFormat;
00857     m_varColl->registerVariable( this );
00858     m_ascent = 0;
00859 }
00860 
00861 KoVariable::~KoVariable()
00862 {
00863     //kdDebug(32500) << "KoVariable::~KoVariable " << this << endl;
00864     m_varColl->unregisterVariable( this );
00865     //delete d;
00866 }
00867 
00868 QStringList KoVariable::subTypeList()
00869 {
00870     return QStringList();
00871 }
00872 
00873 void KoVariable::resize()
00874 {
00875     if ( m_deleted )
00876         return;
00877     KoTextFormat *fmt = format();
00878     QFontMetrics fm = fmt->refFontMetrics();
00879     QString txt = text();
00880 
00881     width = 0;
00882      // size at 100%
00883     for ( int i = 0 ; i < (int)txt.length() ; ++i )
00884         width += fm.width( txt[i] ); // was fm.charWidth(txt,i), but see drawCustomItemHelper...
00885     // zoom to LU
00886     width = qRound( KoTextZoomHandler::ptToLayoutUnitPt( width ) );
00887     height = fmt->height();
00888     m_ascent = fmt->ascent();
00889     //kdDebug(32500) << "KoVariable::resize text=" << txt << " width=" << width << " height=" << height << " ascent=" << m_ascent << endl;
00890 }
00891 
00892 void KoVariable::recalcAndRepaint()
00893 {
00894     recalc();
00895     KoTextParag * parag = paragraph();
00896     if ( parag )
00897     {
00898         //kdDebug(32500) << "KoVariable::recalcAndRepaint -> invalidating parag " << parag->paragId() << endl;
00899         parag->invalidate( 0 );
00900         parag->setChanged( true );
00901     }
00902     textDocument()->emitRepaintChanged();
00903 }
00904 
00905 QString KoVariable::fieldCode()
00906 {
00907     return i18n("Variable");
00908 }
00909 
00910 QString KoVariable::text(bool realValue)
00911 {
00912     KoTextFormat *fmt = format();
00913     QString str;
00914     if (m_varColl->variableSetting()->displayFieldCode()&&!realValue)
00915         str = fieldCode();
00916     else
00917         str = m_varFormat->convert( m_varValue );
00918 
00919     return fmt->displayedString( str);
00920 }
00921 
00922 void KoVariable::drawCustomItem( QPainter* p, int x, int y, int wpix, int hpix, int ascentpix, int /*cx*/, int /*cy*/, int /*cw*/, int /*ch*/, const QColorGroup& cg, bool selected, int offset, bool drawingShadow )
00923 {
00924     KoTextFormat * fmt = format();
00925     KoTextZoomHandler * zh = textDocument()->paintingZoomHandler();
00926     QFont font( fmt->screenFont( zh ) );
00927     drawCustomItemHelper( p, x, y, wpix, hpix, ascentpix, cg, selected, offset, fmt, font, fmt->color(), drawingShadow );
00928 }
00929 
00930 void KoVariable::drawCustomItemHelper( QPainter* p, int x, int y, int wpix, int hpix, int ascentpix, const QColorGroup& cg, bool selected, int offset, KoTextFormat* fmt, const QFont& font, QColor textColor, bool drawingShadow )
00931 {
00932     // Important: the y value already includes the difference between the parag baseline
00933     // and the char's own baseline (ascent) (see paintDefault in korichtext.cpp)
00934     // So we just draw the text there. But we need the baseline for drawFontEffects...
00935     KoTextZoomHandler * zh = textDocument()->paintingZoomHandler();
00936 
00937     p->save();
00938 
00939     if ( fmt->textBackgroundColor().isValid() )
00940         p->fillRect( x, y, wpix, hpix, fmt->textBackgroundColor() );
00941 
00942     if ( drawingShadow ) // Use shadow color if drawing a shadow
00943     {
00944         textColor = fmt->shadowColor();
00945         p->setPen( textColor );
00946     }
00947     else if ( selected )
00948     {
00949         textColor = cg.color( QColorGroup::HighlightedText );
00950         p->setPen( QPen( textColor ) );
00951         p->fillRect( x, y, wpix, hpix, cg.color( QColorGroup::Highlight ) );
00952     }
00953     else if ( textDocument() && textDocument()->drawFormattingChars()
00954               && p->device()->devType() != QInternal::Printer )
00955     {
00956         textColor = cg.color( QColorGroup::Highlight );
00957         p->setPen( QPen ( textColor, 0, Qt::DotLine ) );
00958         p->drawRect( x, y, wpix, hpix );
00959     }
00960     else {
00961         if ( !textColor.isValid() ) // Resolve the color at this point
00962             textColor = KoTextFormat::defaultTextColor( p );
00963         p->setPen( QPen( textColor ) );
00964     }
00965 
00966     p->setFont( font ); // already done by KoTextCustomItem::draw but someone might
00967                         // change the font passed to drawCustomItemHelper (e.g. KoLinkVariable)
00968     QString str = text();
00969     KoTextParag::drawFontEffects( p, fmt, zh, font, textColor, x, ascentpix, wpix, y, hpix, str[0] );
00970     int posY = y + ascentpix + offset;
00971     if ( fmt->vAlign() == KoTextFormat::AlignSubScript )
00972         posY +=p->fontMetrics().height() / 6;
00973     if ( fmt->vAlign() != KoTextFormat::AlignSuperScript )
00974         posY -= fmt->offsetFromBaseLine();
00975     else if ( fmt->offsetFromBaseLine() < 0 )
00976         posY -= 2*fmt->offsetFromBaseLine();
00977 
00978     //p->drawText( x, posY, str );
00979     // We can't just drawText, it wouldn't use the same kerning as the one
00980     // that resize() planned for [which is zoom-independent].
00981     // We need to do the layout using layout units instead, so for simplicity
00982     // I just draw every char individually (whereas KoTextFormatter/KoTextParag
00983     // detect runs of text that can be drawn together)
00984     const int len = str.length();
00985     int xLU = zh->pixelToLayoutUnitX( x );
00986     QFontMetrics fm = fmt->refFontMetrics();
00987     for ( int i = 0; i < len; ++i )
00988     {
00989         const QChar ch = str[i];
00990         p->drawText( x, posY, ch );
00991         // Do like KoTextFormatter: do the layout in layout units.
00992         xLU += KoTextZoomHandler::ptToLayoutUnitPt( fm.width( ch ) );
00993         // And then compute the X position in pixels from the layout unit X.
00994         x = zh->layoutUnitToPixelX( xLU );
00995     }
00996 
00997     p->restore();
00998 }
00999 
01000 void KoVariable::save( QDomElement &parentElem )
01001 {
01002     //kdDebug(32500) << "KoVariable::save" << endl;
01003     QDomElement variableElem = parentElem.ownerDocument().createElement( "VARIABLE" );
01004     parentElem.appendChild( variableElem );
01005     QDomElement typeElem = parentElem.ownerDocument().createElement( "TYPE" );
01006     variableElem.appendChild( typeElem );
01007     typeElem.setAttribute( "type", static_cast<int>( type() ) );
01008 
01011     typeElem.setAttribute( "key", m_varFormat->key() );
01012     typeElem.setAttribute( "text", text(true) );
01013     if ( correctValue() != 0)
01014         typeElem.setAttribute( "correct", correctValue() );
01015     saveVariable( variableElem );
01016 }
01017 
01018 void KoVariable::load( QDomElement & )
01019 {
01020 }
01021 
01022 
01023 void KoVariable::loadOasis( const QDomElement &/*elem*/, KoOasisContext& /*context*/ )
01024 {
01025     // nothing to do here, reimplemented in subclasses (make it pure virtual?)
01026 }
01027 
01028 void KoVariable::saveOasis( KoXmlWriter& /*writer*/, KoSavingContext& /*context*/ ) const
01029 {
01030 }
01031 
01032 void KoVariable::setVariableFormat( KoVariableFormat *_varFormat )
01033 {
01034     // TODO if ( _varFormat ) _varFormat->deref();
01035     m_varFormat = _varFormat;
01036     // TODO m_varFormat->ref();
01037 }
01038 
01039 #define addText( text, newFormat ) { \
01040         if ( !text.isEmpty() ) \
01041         { \
01042             newFormat +=text; \
01043             text=""; \
01044         } \
01045 }
01046 
01047 QString KoVariable::convertKlocaleToQDateTimeFormat( const QString & _format )
01048 {
01049     QString newFormat;
01050     QString format( _format );
01051     QString text;
01052     do
01053     {
01054         if ( format.startsWith( "%Y" ) )
01055         {
01056             addText( text, newFormat );
01057             newFormat+="yyyy";
01058             format = format.remove( 0, 2 );
01059         }
01060         else if ( format.startsWith( "%y" ) )
01061         {
01062             addText( text, newFormat );
01063             newFormat+="yyyy";
01064 
01065             format = format.remove( 0, 2 );
01066         }
01067         else if ( format.startsWith( "%n" ) )
01068         {
01069             addText( text, newFormat );
01070             newFormat+="M";
01071             format = format.remove( 0, 2 );
01072         }
01073         else if ( format.startsWith( "%m" ) )
01074         {
01075             addText( text, newFormat );
01076             newFormat+="MM";
01077             format = format.remove( 0, 2 );
01078         }
01079         else if ( format.startsWith( "%e" ) )
01080         {
01081             addText( text, newFormat );
01082             newFormat+="d";
01083             format = format.remove( 0, 2 );
01084         }
01085         else if ( format.startsWith( "%d" ) )
01086         {
01087             addText( text, newFormat );
01088             newFormat+="dd";
01089             format = format.remove( 0, 2 );
01090         }
01091         else if ( format.startsWith( "%b" ) )
01092         {
01093             addText( text, newFormat );
01094             newFormat+="MMM";
01095             format = format.remove( 0, 2 );
01096         }
01097         else if ( format.startsWith( "%B" ) )
01098         {
01099             addText( text, newFormat );
01100             newFormat+="MMMM";
01101             format = format.remove( 0, 2 );
01102         }
01103         else if ( format.startsWith( "%a" ) )
01104         {
01105             addText( text, newFormat );
01106             newFormat+="ddd";
01107 
01108             format = format.remove( 0, 2 );
01109         }
01110         else if ( format.startsWith( "%A" ) )
01111         {
01112             addText( text, newFormat );
01113             newFormat+="dddd";
01114             format = format.remove( 0, 2 );
01115         }
01116         if ( format.startsWith( "%H" ) ) //hh
01117         {
01118             //hour in 24h
01119             addText( text, newFormat );
01120             newFormat+="hh";
01121             format = format.remove( 0, 2 );
01122         }
01123         else if ( format.startsWith( "%k" ) )//h
01124         {
01125             addText( text, newFormat );
01126             newFormat+="h";
01127             format = format.remove( 0, 2 );
01128         }
01129         else if ( format.startsWith( "%I" ) )// ?????
01130         {
01131             addText( text, newFormat );
01132             //TODO hour in 12h
01133         }
01134         else if ( format.startsWith( "%l" ) )
01135         {
01136             addText( text, newFormat );
01137             //TODO hour in 12h with 1 digit
01138         }
01139         else if ( format.startsWith( "%M" ) )// mm
01140         {
01141             addText( text, newFormat );
01142             newFormat+="mm";
01143             format = format.remove( 0, 2 );
01144         }
01145         else if ( format.startsWith( "%S" ) ) //ss
01146         {
01147             addText( text, newFormat );
01148             newFormat+="ss";
01149             format = format.remove( 0, 2 );
01150         }
01151         else if ( format.startsWith( "%p" ) )
01152         {
01153             //TODO am or pm
01154             addText( text, newFormat );
01155             newFormat+="ap";
01156             format = format.remove( 0, 2 );
01157         }
01158 
01159         else
01160         {
01161             text += format[0];
01162             format = format.remove( 0, 1 );
01163         }
01164     }
01165     while ( format.length() > 0 );
01166     addText( text, format );
01167     return format;
01168 }
01169 
01170 
01171 /******************************************************************/
01172 /* Class: KoDateVariable                                          */
01173 /******************************************************************/
01174 KoDateVariable::KoDateVariable( KoTextDocument *textdoc, short int subtype, KoVariableFormat *_varFormat, KoVariableCollection *_varColl, int _correctDate)
01175     : KoVariable( textdoc, _varFormat,_varColl ), m_subtype( subtype ), m_correctDate( _correctDate)
01176 {
01177 }
01178 
01179 QString KoDateVariable::fieldCode()
01180 {
01181     if ( m_subtype == VST_DATE_FIX )
01182         return i18n("Date (Fixed)");
01183     else if ( m_subtype == VST_DATE_CURRENT)
01184         return i18n("Date");
01185     else if ( m_subtype == VST_DATE_LAST_PRINTING)
01186         return i18n("Last Printing");
01187     else if ( m_subtype == VST_DATE_CREATE_FILE )
01188         return i18n( "File Creation");
01189     else if ( m_subtype == VST_DATE_MODIFY_FILE )
01190         return i18n( "File Modification");
01191     else
01192         return i18n("Date");
01193 }
01194 
01195 void KoDateVariable::resize()
01196 {
01197     KoTextFormat * fmt = format();
01198     QString oldLanguage;
01199     if ( !fmt->language().isEmpty())
01200     {
01201          oldLanguage=KGlobal::locale()->language();
01202          bool changeLanguage = KGlobal::locale()->setLanguage( fmt->language() );
01203          KoVariable::resize();
01204          if ( changeLanguage )
01205              KGlobal::locale()->setLanguage( oldLanguage );
01206     }
01207     else
01208         KoVariable::resize();
01209 }
01210 
01211 void KoDateVariable::recalc()
01212 {
01213     if ( m_subtype == VST_DATE_CURRENT )
01214         m_varValue = QDateTime::currentDateTime().addDays(m_correctDate);
01215     else if ( m_subtype == VST_DATE_LAST_PRINTING )
01216         m_varValue = m_varColl->variableSetting()->lastPrintingDate();
01217     else if ( m_subtype == VST_DATE_CREATE_FILE )
01218         m_varValue = m_varColl->variableSetting()->creationDate();
01219     else if ( m_subtype == VST_DATE_MODIFY_FILE )
01220         m_varValue = m_varColl->variableSetting()->modificationDate();
01221     else
01222     {
01223         // Only if never set before (i.e. upon insertion)
01224         if ( m_varValue.isNull() )
01225             m_varValue = QDateTime::currentDateTime().addDays(m_correctDate);
01226     }
01227     resize();
01228 }
01229 
01230 void KoDateVariable::saveVariable( QDomElement& varElem )
01231 {
01232     QDomElement elem = varElem.ownerDocument().createElement( "DATE" );
01233     varElem.appendChild( elem );
01234 
01235     QDate date = m_varValue.toDate(); // works with Date and DateTime
01236     date = date.addDays( -m_correctDate );//remove correctDate value otherwise value stored is bad
01237     elem.setAttribute( "year", date.year() );
01238     elem.setAttribute( "month", date.month() );
01239     elem.setAttribute( "day", date.day() );
01240     elem.setAttribute( "fix", m_subtype == VST_DATE_FIX ); // for compat
01241     elem.setAttribute( "correct", m_correctDate);
01242     elem.setAttribute( "subtype", m_subtype);
01243     if ( m_varValue.type() == QVariant::DateTime )
01244     {
01245         QTime time = m_varValue.toTime();
01246         elem.setAttribute( "hour", time.hour() );
01247         elem.setAttribute( "minute", time.minute() );
01248         elem.setAttribute( "second", time.second() );
01249     }
01250 }
01251 
01252 void KoDateVariable::load( QDomElement& elem )
01253 {
01254     KoVariable::load( elem );
01255 
01256     QDomElement e = elem.namedItem( "DATE" ).toElement();
01257     if (!e.isNull())
01258     {
01259         const bool fix = e.attribute("fix").toInt() == 1;
01260         if ( e.hasAttribute("correct"))
01261             m_correctDate = e.attribute("correct").toInt();
01262         if ( fix )
01263         {
01264             const int y = e.attribute("year").toInt();
01265             const int month = e.attribute("month").toInt();
01266             const int d = e.attribute("day").toInt();
01267             const int h = e.attribute("hour").toInt();
01268             const int min = e.attribute("minute").toInt();
01269             const int s = e.attribute("second").toInt();
01270             const int ms = e.attribute("msecond").toInt();
01271             QDate date( y, month, d );
01272             date = date.addDays( m_correctDate );
01273             const QTime time( h, min, s, ms );
01274             if (time.isValid())
01275                 m_varValue = QVariant ( QDateTime( date, time ) );
01276             else
01277                 m_varValue = QVariant( date );
01278         }
01279         //old date variable format
01280         m_subtype = fix ? VST_DATE_FIX : VST_DATE_CURRENT;
01281         if ( e.hasAttribute( "subtype" ))
01282             m_subtype = e.attribute( "subtype").toInt();
01283     }
01284 }
01285 
01286 void KoDateVariable::saveOasis( KoXmlWriter& writer, KoSavingContext& context ) const
01287 {
01288     switch( m_subtype )
01289     {
01290     case VST_DATE_FIX:
01291     case VST_DATE_CURRENT:
01292         writer.startElement( "text:date" );
01293         if ( m_subtype == VST_DATE_FIX )
01294         {
01295             writer.addAttribute( "text:date-value", m_varValue.toDate().toString( Qt::ISODate) );
01296             writer.addAttribute( "text:fixed", "true" );
01297         }
01298         break;
01299     case VST_DATE_LAST_PRINTING:
01300         writer.startElement( "text:print-date" );
01301         break;
01302     case VST_DATE_CREATE_FILE:
01303         writer.startElement( "text:creation-date" );
01304         break;
01305     case VST_DATE_MODIFY_FILE:
01306         writer.startElement( "text:modification-date" );
01307         break;
01308     }
01309     QString value(  m_varFormat->formatProperties() );
01310     bool klocaleFormat = false;
01311     if ( value.lower() == "locale" ||
01312          value.isEmpty() ||
01313          value.lower() == "localeshort" ||
01314          value.lower() == "localedatetime" ||
01315          value.lower() == "localedatetimeshort" )
01316     {
01317         if ( value.lower() == "locale" || value.isEmpty())
01318             value =  KGlobal::locale()->dateFormat();
01319         else if ( value.lower() == "localeshort" )
01320             value = KGlobal::locale()->dateFormatShort();
01321         else if ( value.lower() == "localedatetime" )
01322             value =  QString( "%1 %2" ).arg( KGlobal::locale()->dateFormat() ).arg( KGlobal::locale()->timeFormat() );
01323         else if ( value.lower() == "localedatetimeshort" )
01324             value =  QString( "%1 %2" ).arg( KGlobal::locale()->dateFormatShort() ).arg( KGlobal::locale()->timeFormat() );
01325         klocaleFormat = true;
01326     }
01327     writer.addAttribute( "style:data-style-name", KoOasisStyles::saveOasisDateStyle(context.mainStyles(), value, klocaleFormat ) );
01328 
01329     if ( m_correctDate != 0 )
01330         writer.addAttribute( "text:date-adjust", daysToISODuration( m_correctDate ) );
01331     writer.endElement();
01332 }
01333 
01334 void KoDateVariable::loadOasis( const QDomElement &elem, KoOasisContext& /*context*/ )
01335 {
01336     const QString localName( elem.localName() );
01337     if ( localName == "date" ) // current (or fixed) date
01338     {
01339         // Standard form of the date is in text:date-value. Example: 2004-01-21T10:57:05
01340         const QString dateValue = elem.attributeNS( KoXmlNS::text, "date-value", QString::null);
01341         QDateTime dt;
01342         if ( !dateValue.isEmpty() ) // avoid QDate warning
01343             dt = QDate::fromString(dateValue, Qt::ISODate);
01344 
01345         bool fixed = (elem.hasAttributeNS( KoXmlNS::text, "fixed") && elem.attributeNS( KoXmlNS::text, "fixed", QString::null)=="true");
01346         if (!dt.isValid())
01347             fixed = false; // OOo docs say so: not valid = current datetime
01348         if ( fixed )
01349             m_varValue = QVariant( dt );
01350         m_subtype = fixed ? VST_DATE_FIX : VST_DATE_CURRENT;
01351     }
01352     // For all those the value of the date will be retrieved from meta.xml
01353     else if ( localName.startsWith( "print" ) )
01354         m_subtype = VST_DATE_LAST_PRINTING;
01355     else if ( localName.startsWith( "creation" ) )
01356         m_subtype = VST_DATE_CREATE_FILE;
01357     else if ( localName.startsWith( "modification" ) )
01358         m_subtype = VST_DATE_MODIFY_FILE;
01359     const QString adjustStr = elem.attributeNS( KoXmlNS::text, "date-adjust", QString::null );
01360     if ( !adjustStr.isEmpty() )
01361         m_correctDate = ISODurationToDays( adjustStr );
01362 }
01363 
01364 QStringList KoDateVariable::actionTexts()
01365 {
01366     QStringList lst;
01367     lst << i18n( "Current Date (fixed)" );
01368     lst << i18n( "Current Date (variable)" );
01369     lst << i18n( "Date of Last Printing" );
01370     lst << i18n( "Date of File Creation" );
01371     lst << i18n( "Date of File Modification" );
01372     return lst;
01373 }
01374 
01375 QStringList KoDateVariable::subTypeList()
01376 {
01377     return KoDateVariable::actionTexts();
01378 }
01379 
01380 QCString KoDateVariable::defaultFormat()
01381 {
01382     return QCString("DATE") + "locale";
01383 }
01384 
01385 QCString KoDateVariable::formatStr(int & correct)
01386 {
01387     QCString string;
01388     QStringList stringList;
01389     KDialogBase* dialog=new KDialogBase(0, 0, true, i18n("Date Format"), KDialogBase::Ok|KDialogBase::Cancel);
01390     DateFormatWidget* widget=new DateFormatWidget(dialog);
01391     int count=0;
01392     dialog->setMainWidget(widget);
01393     KConfig* config = KoGlobal::kofficeConfig();
01394     if( config->hasGroup("Date format history") )
01395     {
01396         KConfigGroupSaver cgs( config, "Date format history");
01397         const int noe=config->readNumEntry("Number Of Entries", 5);
01398         for(int i=0;i<noe;i++)
01399         {
01400             QString num;
01401             num.setNum(i);
01402             const QString tmpString(config->readEntry("Last Used"+num));
01403             if(tmpString.startsWith("locale"))
01404                 continue;
01405             else if(stringList.contains(tmpString))
01406                 continue;
01407             else if(!tmpString.isEmpty())
01408             {
01409                 stringList.append(tmpString);
01410                 count++;
01411             }
01412         }
01413 
01414     }
01415     if(!stringList.isEmpty())
01416     {
01417         widget->combo1->insertItem("---");
01418         widget->combo1->insertStringList(stringList);
01419     }
01420     if(false) { // ### TODO: select the last used item
01421         QComboBox *combo= widget->combo1;
01422         combo->setCurrentItem(combo->count() -1);
01423         widget->updateLabel();
01424     }
01425 
01426     if(dialog->exec()==QDialog::Accepted)
01427     {
01428         string = widget->resultString().utf8();
01429         correct = widget->correctValue();
01430     }
01431     else
01432     {
01433         delete dialog;
01434         return 0;
01435     }
01436     config->setGroup("Date format history");
01437     stringList.remove(string);
01438     stringList.prepend(string);
01439     for(int i=0;i<=count;i++)
01440     {
01441         QString num;
01442         num.setNum(i);
01443         config->writeEntry("Last Used"+num, stringList[i]);
01444     }
01445     config->sync();
01446     delete dialog;
01447     return QCString("DATE") + string;
01448 }
01449 
01450 /******************************************************************/
01451 /* Class: KoTimeVariable                                          */
01452 /******************************************************************/
01453 KoTimeVariable::KoTimeVariable( KoTextDocument *textdoc, short int subtype, KoVariableFormat *varFormat, KoVariableCollection *_varColl, int _correct)
01454     : KoVariable( textdoc, varFormat,_varColl ), m_subtype( subtype ), m_correctTime( _correct)
01455 {
01456 }
01457 
01458 QString KoTimeVariable::fieldCode()
01459 {
01460     return (m_subtype == VST_TIME_FIX)?i18n("Time (Fixed)"):i18n("Time");
01461 }
01462 
01463 
01464 void KoTimeVariable::resize()
01465 {
01466     KoTextFormat * fmt = format();
01467     if ( !fmt->language().isEmpty() )
01468     {
01469         QString oldLanguage = KGlobal::locale()->language();
01470         bool changeLanguage = KGlobal::locale()->setLanguage( fmt->language() );
01471         KoVariable::resize();
01472         if ( changeLanguage )
01473             KGlobal::locale()->setLanguage( oldLanguage );
01474     }
01475     else
01476         KoVariable::resize();
01477 }
01478 
01479 void KoTimeVariable::recalc()
01480 {
01481     if ( m_subtype == VST_TIME_CURRENT )
01482         m_varValue = QVariant( QTime::currentTime().addSecs(60*m_correctTime));
01483     else
01484     {
01485         // Only if never set before (i.e. upon insertion)
01486         if ( m_varValue.toTime().isNull() )
01487             m_varValue = QVariant( QTime::currentTime().addSecs(60*m_correctTime));
01488     }
01489     resize();
01490 }
01491 
01492 
01493 void KoTimeVariable::saveVariable( QDomElement& parentElem )
01494 {
01495     QDomElement elem = parentElem.ownerDocument().createElement( "TIME" );
01496     parentElem.appendChild( elem );
01497 
01498     QTime time = m_varValue.toTime();
01499     time = time.addSecs(-60*m_correctTime);
01500     elem.setAttribute( "hour", time.hour() );
01501     elem.setAttribute( "minute", time.minute() );
01502     elem.setAttribute( "second", time.second() );
01503     elem.setAttribute( "msecond", time.msec() );
01504     elem.setAttribute( "fix", m_subtype == VST_TIME_FIX );
01505     elem.setAttribute( "correct", m_correctTime );
01506 }
01507 
01508 void KoTimeVariable::load( QDomElement& elem )
01509 {
01510     KoVariable::load( elem );
01511 
01512     QDomElement e = elem.namedItem( "TIME" ).toElement();
01513     if (!e.isNull())
01514     {
01515         int h = e.attribute("hour").toInt();
01516         int m = e.attribute("minute").toInt();
01517         int s = e.attribute("second").toInt();
01518         int ms = e.attribute("msecond").toInt();
01519         int correct = 0;
01520         if ( e.hasAttribute("correct"))
01521             correct=e.attribute("correct").toInt();
01522         bool fix = static_cast<bool>( e.attribute("fix").toInt() );
01523         if ( fix )
01524         {
01525             QTime time;
01526             time.setHMS( h, m, s, ms );
01527             time = time.addSecs( 60*m_correctTime );
01528             m_varValue = QVariant( time);
01529 
01530         }
01531         m_subtype = fix ? VST_TIME_FIX : VST_TIME_CURRENT;
01532         m_correctTime = correct;
01533     }
01534 }
01535 
01536 void KoTimeVariable::loadOasis( const QDomElement &elem, KoOasisContext& /*context*/ )
01537 {
01538     const QString localName( elem.localName() );
01539     Q_ASSERT( localName == "time" ); // caller checked for it
01540     if ( localName == "time" ) // current (or fixed) time
01541     {
01542         // Use QDateTime to work around a possible problem of QTime::fromString in Qt 3.2.2
01543         QDateTime dt(QDateTime::fromString(elem.attributeNS( KoXmlNS::text, "time-value", QString::null), Qt::ISODate));
01544 
01545         bool fixed = (elem.hasAttributeNS( KoXmlNS::text, "fixed") && elem.attributeNS( KoXmlNS::text, "fixed", QString::null)=="true");
01546         if (!dt.isValid())
01547             fixed = false; // OOo docs say so: not valid = current datetime
01548         if ( fixed )
01549             m_varValue = QVariant( dt.time() );
01550         m_subtype = fixed ? VST_TIME_FIX : VST_TIME_CURRENT;
01551         QString adjustStr = elem.attributeNS( KoXmlNS::text, "time-adjust", QString::null );
01552         if ( !adjustStr.isEmpty() )
01553             m_correctTime = ISODurationToMinutes( adjustStr );
01554     }
01555 }
01556 
01557 void KoTimeVariable::saveOasis( KoXmlWriter& writer, KoSavingContext& context ) const
01558 {
01559     writer.startElement( "text:time" );
01560     if ( m_correctTime != 0 ) {
01561         writer.addAttribute( "text:time-adjust", minutesToISODuration( m_correctTime ) );
01562     }
01563     if (m_subtype == VST_TIME_FIX )
01564     {
01565         writer.addAttribute( "text:fixed", "true" );
01566         writer.addAttribute( "text:time-value", m_varValue.toTime().toString( Qt::ISODate ) );
01567     }
01568 
01569     QString value(  m_varFormat->formatProperties() );
01570     bool klocaleFormat = false;
01571     if ( value.lower() == "locale" )
01572     {
01573         value = KGlobal::locale()->timeFormat();
01574         klocaleFormat = true;
01575     }
01576     writer.addAttribute( "style:data-style-name", KoOasisStyles::saveOasisTimeStyle(context.mainStyles(), m_varFormat->formatProperties(), klocaleFormat ) );
01577     //writer.addTextNode( /*value*/ value displayed as texte );
01578     //TODO save text value
01579     //<text:time style:data-style-name="N43" text:time-value="2004-11-11T14:42:19" text:fixed="true">02:42:19 PM</text:time>
01580     writer.endElement();
01581 }
01582 
01583 
01584 QStringList KoTimeVariable::actionTexts()
01585 {
01586     QStringList lst;
01587     lst << i18n( "Current Time (fixed)" );
01588     lst << i18n( "Current Time (variable)" );
01589     return lst;
01590 }
01591 
01592 QStringList KoTimeVariable::subTypeList()
01593 {
01594     return KoTimeVariable::actionTexts();
01595 }
01596 
01597 QCString KoTimeVariable::formatStr(int & _correct)
01598 {
01599     QCString string;
01600     QStringList stringList;
01601     KDialogBase* dialog=new KDialogBase(0, 0, true, i18n("Time Format"), KDialogBase::Ok|KDialogBase::Cancel);
01602     TimeFormatWidget* widget=new TimeFormatWidget(dialog);
01603     dialog->setMainWidget(widget);
01604     KConfig* config = KoGlobal::kofficeConfig();
01605     int count=0;
01606     if( config->hasGroup("Time format history") )
01607     {
01608         KConfigGroupSaver cgs( config, "Time format history" );
01609         const int noe=config->readNumEntry("Number Of Entries", 5);
01610         for(int i=0;i<noe;i++)
01611         {
01612             QString num;
01613             num.setNum(i);
01614             QString tmpString(config->readEntry("Last Used"+num));
01615             if(tmpString.startsWith("locale"))
01616                 continue;
01617             else if(stringList.contains(tmpString))
01618                 continue;
01619             else if(!tmpString.isEmpty())
01620             {
01621                 stringList.append(tmpString);
01622                 count++;
01623             }
01624         }
01625     }
01626     if(!stringList.isEmpty())
01627     {
01628         widget->combo1->insertItem("---");
01629         widget->combo1->insertStringList(stringList);
01630     }
01631     if(false) // ### TODO: select the last used item
01632     {
01633         QComboBox *combo= widget->combo1;
01634         combo->setCurrentItem(combo->count() -1);
01635     }
01636     if(dialog->exec()==QDialog::Accepted)
01637     {
01638         string = widget->resultString().utf8();
01639         _correct = widget->correctValue();
01640     }
01641     else
01642     {
01643         delete dialog;
01644         return 0;
01645     }
01646     config->setGroup("Time format history");
01647     stringList.remove(string);
01648     stringList.prepend(string);
01649     for(int i=0;i<=count;i++)
01650     {
01651         QString num;
01652         num.setNum(i);
01653         config->writeEntry("Last Used"+num, stringList[i]);
01654     }
01655     config->sync();
01656     delete dialog;
01657     return QCString("TIME"+string );
01658 }
01659 
01660 QCString KoTimeVariable::defaultFormat()
01661 {
01662     return QCString(QCString("TIME")+QCString("locale") );
01663 }
01664 
01665 
01666 /******************************************************************/
01667 /* Class: KoCustomVariable                                        */
01668 /******************************************************************/
01669 KoCustomVariable::KoCustomVariable( KoTextDocument *textdoc, const QString &name, KoVariableFormat *varFormat, KoVariableCollection *_varColl )
01670     : KoVariable( textdoc, varFormat,_varColl )
01671 {
01672     m_varValue = QVariant( name );
01673 }
01674 
01675 QString KoCustomVariable::fieldCode()
01676 {
01677     return i18n("Custom Variable");
01678 }
01679 
01680 QString KoCustomVariable::text(bool realValue)
01681 {
01682     if (m_varColl->variableSetting()->displayFieldCode()&&!realValue)
01683         return fieldCode();
01684     else
01685         return value();
01686 } // use a format when they are customizable
01687 
01688 
01689 
01690 void KoCustomVariable::saveVariable( QDomElement& parentElem )
01691 {
01692     QDomElement elem = parentElem.ownerDocument().createElement( "CUSTOM" );
01693     parentElem.appendChild( elem );
01694     elem.setAttribute( "name", m_varValue.toString() );
01695     elem.setAttribute( "value", value() );
01696 }
01697 
01698 void KoCustomVariable::load( QDomElement& elem )
01699 {
01700     KoVariable::load( elem );
01701     QDomElement e = elem.namedItem( "CUSTOM" ).toElement();
01702     if (!e.isNull())
01703     {
01704         m_varValue = QVariant (e.attribute( "name" ));
01705         setValue( e.attribute( "value" ) );
01706     }
01707 }
01708 
01709 void KoCustomVariable::loadOasis( const QDomElement &elem, KoOasisContext& /*context*/ )
01710 {
01711     const QString localName( elem.localName() );
01712     // We treat all those the same. For OO/OpenDocument the difference is that
01713     // - user-field-get is related to text:user-field-decls in <body>
01714     // - variable-set is related to variable-decls (defined in <body>);
01715     //                 its value can change in the middle of the document.
01716     // - user-defined is related to meta:user-defined in meta.xml
01717     if ( localName == "variable-set"
01718          || localName == "user-defined"
01719         || localName == "user-field-get" ) {
01720         m_varValue = elem.attributeNS( KoXmlNS::text, "name", QString::null );
01721         setValue( elem.text() );
01722     }
01723 }
01724 
01725 void KoCustomVariable::saveOasis( KoXmlWriter& writer, KoSavingContext& /*context*/ ) const
01726 {
01727     //TODO save value into meta:user-defined
01728     writer.startElement( "text:user-field-get" ); //see 6.3.6
01729     writer.addAttribute( "text:name", m_varValue.toString() );
01730     writer.addTextNode( value() );
01731     writer.endElement();
01732 }
01733 
01734 QString KoCustomVariable::value() const
01735 {
01736     return m_varColl->getVariableValue( m_varValue.toString() );
01737 }
01738 
01739 void KoCustomVariable::setValue( const QString &v )
01740 {
01741     m_varColl->setVariableValue( m_varValue.toString(), v );
01742 }
01743 
01744 QStringList KoCustomVariable::actionTexts()
01745 {
01746     return QStringList( i18n( "Custom..." ) );
01747 }
01748 
01749 void KoCustomVariable::recalc()
01750 {
01751     resize();
01752 }
01753 
01754 /******************************************************************/
01755 /* Class: KoMailMergeVariable                                  */
01756 /******************************************************************/
01757 KoMailMergeVariable::KoMailMergeVariable( KoTextDocument *textdoc, const QString &name, KoVariableFormat *varFormat,KoVariableCollection *_varColl )
01758     : KoVariable( textdoc, varFormat, _varColl )
01759 {
01760     m_varValue = QVariant ( name );
01761 }
01762 
01763 QString KoMailMergeVariable::fieldCode()
01764 {
01765     return i18n("Mail Merge");
01766 }
01767 
01768 void KoMailMergeVariable::loadOasis( const QDomElement &/*elem*/, KoOasisContext& /*context*/ )
01769 {
01770     // TODO
01771 }
01772 
01773 void KoMailMergeVariable::saveOasis( KoXmlWriter& /*writer*/, KoSavingContext& /*context*/ ) const
01774 {
01775         kdWarning(32500) << "Not implemented: OASIS saving of mail merge variables" << endl;
01776 }
01777 
01778 
01779 
01780 void KoMailMergeVariable::saveVariable( QDomElement& parentElem )
01781 {
01782     QDomElement elem = parentElem.ownerDocument().createElement( "MAILMERGE" );
01783     parentElem.appendChild( elem );
01784     elem.setAttribute( "name", m_varValue.toString() );
01785 }
01786 
01787 void KoMailMergeVariable::load( QDomElement& elem )
01788 {
01789     KoVariable::load( elem );
01790     QDomElement e = elem.namedItem( "MAILMERGE" ).toElement();
01791     if (!e.isNull())
01792         m_varValue = QVariant( e.attribute( "name" ) );
01793 }
01794 
01795 QString KoMailMergeVariable::value() const
01796 {
01797     return QString();//m_doc->getMailMergeDataBase()->getValue( m_name );
01798 }
01799 
01800 QString KoMailMergeVariable::text(bool /*realValue*/)
01801 {
01802     // ## should use a format maybe
01803     QString v = value();
01804     if ( v == name() )
01805         return "<" + v + ">";
01806     return v;
01807 }
01808 
01809 QStringList KoMailMergeVariable::actionTexts()
01810 {
01811     return QStringList( i18n( "&Mail Merge..." ) );
01812 }
01813 
01814 /******************************************************************/
01815 /* Class: KoPageVariable                                         */
01816 /******************************************************************/
01817 KoPageVariable::KoPageVariable( KoTextDocument *textdoc, short int subtype, KoVariableFormat *varFormat,KoVariableCollection *_varColl )
01818         : KoVariable( textdoc, varFormat, _varColl ), m_subtype( subtype )
01819 {
01820 }
01821 
01822 QString KoPageVariable::fieldCode()
01823 {
01824     if ( m_subtype == VST_PGNUM_CURRENT )
01825         return i18n("Page Current Num");
01826     else if ( m_subtype == VST_PGNUM_TOTAL )
01827         return i18n("Total Page Num");
01828     else if ( m_subtype == VST_CURRENT_SECTION )
01829         return i18n("Current Section");
01830     else if ( m_subtype == VST_PGNUM_PREVIOUS )
01831         return i18n("Previous Page Number");
01832     else if ( m_subtype == VST_PGNUM_NEXT )
01833         return i18n("Next Page Number");
01834 
01835     else
01836         return i18n("Current Section");
01837 }
01838 
01839 
01840 void KoPageVariable::saveVariable( QDomElement& parentElem )
01841 {
01842     QDomElement pgNumElem = parentElem.ownerDocument().createElement( "PGNUM" );
01843     parentElem.appendChild( pgNumElem );
01844     pgNumElem.setAttribute( "subtype", m_subtype );
01845     if ( m_subtype != VST_CURRENT_SECTION )
01846         pgNumElem.setAttribute( "value", m_varValue.toInt() );
01847     else
01848         pgNumElem.setAttribute( "value", m_varValue.toString() );
01849 }
01850 
01851 void KoPageVariable::load( QDomElement& elem )
01852 {
01853     KoVariable::load( elem );
01854     QDomElement pgNumElem = elem.namedItem( "PGNUM" ).toElement();
01855     if (!pgNumElem.isNull())
01856     {
01857         m_subtype = pgNumElem.attribute("subtype").toInt();
01858         // ### This could use the format...
01859         if ( m_subtype != VST_CURRENT_SECTION )
01860             m_varValue = QVariant(pgNumElem.attribute("value").toInt());
01861         else
01862             m_varValue = QVariant(pgNumElem.attribute("value"));
01863     }
01864 }
01865 
01866 void KoPageVariable::saveOasis( KoXmlWriter& writer, KoSavingContext& /*context*/ ) const
01867 {
01868     switch( m_subtype )
01869     {
01870     case VST_PGNUM_PREVIOUS:
01871     case VST_PGNUM_NEXT:
01872     case VST_PGNUM_CURRENT:
01873     {
01874         writer.startElement( "text:page-number" );
01875         if ( m_subtype == VST_PGNUM_PREVIOUS )
01876         {
01877             writer.addAttribute( "text:select-page", "previous" );
01878         }
01879         else if ( m_subtype == VST_PGNUM_NEXT )
01880         {
01881             writer.addAttribute( "text:select-page", "next" );
01882         }
01883         else if ( m_subtype == VST_PGNUM_CURRENT )
01884         {
01885             writer.addAttribute( "text:select-page", "current" );
01886         }
01887         writer.addTextNode( m_varValue.toString() );
01888         writer.endElement();
01889     }
01890     break;
01891     case VST_CURRENT_SECTION:
01892     {
01893         writer.startElement( "text:chapter" );
01894         writer.addTextNode( m_varValue.toString() );
01895         writer.endElement();
01896     }
01897     break;
01898     case VST_PGNUM_TOTAL:
01899     {
01900         writer.startElement( "text:page-count" );
01901         writer.addTextNode( m_varValue.toString() );
01902         writer.endElement();
01903     }
01904     break;
01905     }
01906 }
01907 
01908 void KoPageVariable::loadOasis( const QDomElement &elem, KoOasisContext& /*context*/ )
01909 {
01910     const QString localName( elem.localName() );
01911     if ( localName == "page-number" )
01912     {
01913         m_subtype = VST_PGNUM_CURRENT;
01914 
01915         if ( elem.hasAttributeNS( KoXmlNS::text, "select-page") )
01916         {
01917             const QString select = elem.attributeNS( KoXmlNS::text, "select-page", QString::null);
01918             if (select == "previous")
01919                 m_subtype = VST_PGNUM_PREVIOUS;
01920             else if (select == "next")
01921                 m_subtype = VST_PGNUM_NEXT;
01922         }
01923         // Missing: fixed, page adjustment, formatting style
01924         m_varValue = QVariant( elem.text().toInt() );
01925     }
01926     else if ( localName == "chapter" )
01927     {
01928         m_subtype = VST_CURRENT_SECTION;
01929         m_varValue = QVariant( elem.text() );
01930         // text:display attribute can be name, number (i.e. with prefix/suffix),
01931         // number-and-name, plain-number-and-name, plain-number
01932         // TODO: a special format class for this, so that it can be easily switched using the RMB
01933     }
01934     else if ( localName == "page-count" )
01935     {
01936         m_subtype = VST_PGNUM_TOTAL;
01937         m_varValue = QVariant( elem.text() );
01938     }
01939 }
01940 
01941 QStringList KoPageVariable::actionTexts()
01942 {
01943     QStringList lst;
01944     lst << i18n( "Page Number" );
01945     lst << i18n( "Number of Pages" );
01946     lst << i18n( "Section Title" );
01947     lst << i18n( "Previous Page" );
01948     lst << i18n( "Next Page" );
01949     return lst;
01950 }
01951 
01952 QStringList KoPageVariable::subTypeList()
01953 {
01954     return KoPageVariable::actionTexts();
01955 }
01956 
01957 void KoPageVariable::setVariableSubType( short int type )
01958 {
01959     m_subtype = type;
01960     Q_ASSERT( m_varColl );
01961     KoVariableFormatCollection* fc = m_varColl->formatCollection();
01962     setVariableFormat((m_subtype == VST_CURRENT_SECTION) ? fc->format("STRING") : fc->format("NUMBER"));
01963 }
01964 
01965 /******************************************************************/
01966 /* Class: KoFieldVariable                                         */
01967 /******************************************************************/
01968 KoFieldVariable::KoFieldVariable( KoTextDocument *textdoc, short int subtype, KoVariableFormat *varFormat, KoVariableCollection *_varColl ,KoDocument *_doc )
01969     : KoVariable( textdoc, varFormat,_varColl ), m_subtype( subtype ), m_doc(_doc)
01970 {
01971 }
01972 
01973 QString KoFieldVariable::fieldCode()
01974 {
01975     switch( m_subtype ) {
01976     case VST_FILENAME:
01977         return i18n("Filename");
01978         break;
01979     case VST_DIRECTORYNAME:
01980         return i18n("Directory Name");
01981         break;
01982     case VST_PATHFILENAME:
01983         return i18n("Path Filename");
01984         break;
01985     case VST_FILENAMEWITHOUTEXTENSION:
01986         return i18n("Filename Without Extension");
01987         break;
01988     case VST_AUTHORNAME:
01989         return i18n("Author Name");
01990         break;
01991     case VST_EMAIL:
01992         return i18n("Email");
01993         break;
01994     case VST_COMPANYNAME:
01995         return i18n("Company Name");
01996         break;
01997     case VST_TELEPHONE_WORK:
01998         return i18n("Telephone (work)");
01999         break;
02000     case VST_TELEPHONE_HOME:
02001         return i18n("Telephone (home)");
02002         break;
02003     case VST_FAX:
02004         return i18n("Fax");
02005         break;
02006     case VST_COUNTRY:
02007         return i18n("Country");
02008         break;
02009     case VST_POSTAL_CODE:
02010         return i18n("Postal Code");
02011         break;
02012     case VST_CITY:
02013         return i18n("City");
02014         break;
02015     case VST_STREET:
02016         return i18n("Street");
02017         break;
02018     case VST_AUTHORTITLE:
02019         return i18n("Author Title");
02020         break;
02021     case VST_TITLE:
02022         return i18n("Title");
02023         break;
02024     case VST_SUBJECT:
02025         return i18n("Subject");
02026         break;
02027     case VST_ABSTRACT:
02028         return i18n("Abstract");
02029         break;
02030     case VST_KEYWORDS:
02031         return i18n("Keywords");
02032         break;
02033     case VST_INITIAL:
02034         return i18n("Initials");
02035         break;
02036     }
02037     return i18n("Field");
02038 }
02039 
02040 QString KoFieldVariable::text(bool realValue)
02041 {
02042     if (m_varColl->variableSetting()->displayFieldCode()&&!realValue)
02043         return fieldCode();
02044     else
02045         return value();
02046 } // use a format when they are customizable
02047 
02048 
02049 void KoFieldVariable::saveVariable( QDomElement& parentElem )
02050 {
02051     //kdDebug(32500) << "KoFieldVariable::saveVariable" << endl;
02052     QDomElement elem = parentElem.ownerDocument().createElement( "FIELD" );
02053     parentElem.appendChild( elem );
02054     elem.setAttribute( "subtype", m_subtype );
02055     elem.setAttribute( "value", m_varValue.toString() );
02056 }
02057 
02058 void KoFieldVariable::load( QDomElement& elem )
02059 {
02060     KoVariable::load( elem );
02061     QDomElement e = elem.namedItem( "FIELD" ).toElement();
02062     if (!e.isNull())
02063     {
02064         m_subtype = e.attribute( "subtype" ).toInt();
02065         if ( m_subtype == VST_NONE )
02066             kdWarning() << "Field subtype of -1 found in the file !" << endl;
02067         m_varValue = QVariant( e.attribute( "value" ) );
02068     } else
02069         kdWarning() << "FIELD element not found !" << endl;
02070 }
02071 
02072 void KoFieldVariable::loadOasis( const QDomElement &elem, KoOasisContext& /*context*/ )
02073 {
02074     const QString localName( elem.localName() );
02075     if ( localName == "file-name" ) {
02076         const QString display = elem.attributeNS( KoXmlNS::text, "display", QString::null );
02077         if (display == "path")
02078             m_subtype = VST_DIRECTORYNAME;
02079         else if (display == "name")
02080             m_subtype = VST_FILENAMEWITHOUTEXTENSION;
02081         else if (display == "name-and-extension")
02082             m_subtype = VST_FILENAME;
02083         else
02084             m_subtype = VST_PATHFILENAME;
02085     }
02086     else if ( localName == "author-name" )
02087         m_subtype = VST_AUTHORNAME;
02088     else if ( localName == "author-initials" )
02089         m_subtype = VST_INITIAL;
02090     else if ( localName == "subject" )
02091         m_subtype = VST_SUBJECT;
02092     else if ( localName == "title" )
02093         m_subtype = VST_TITLE;
02094     else if ( localName == "description" )
02095         m_subtype = VST_ABSTRACT;
02096     else if ( localName == "keywords" )
02097         m_subtype = VST_KEYWORDS;
02098 
02099     else if ( localName == "sender-company" )
02100         m_subtype = VST_COMPANYNAME;
02101     else if ( localName == "sender-firstname" )
02102         ; // ## This is different from author-name, but the notion of 'sender' is unclear...
02103     else if ( localName == "sender-lastname" )
02104         ; // ## This is different from author-name, but the notion of 'sender' is unclear...
02105     else if ( localName == "sender-initials" )
02106         ; // ## This is different from author-initials, but the notion of 'sender' is unclear...
02107     else if ( localName == "sender-street" )
02108         m_subtype = VST_STREET;
02109     else if ( localName == "sender-country" )
02110         m_subtype = VST_COUNTRY;
02111     else if ( localName == "sender-postal-code" )
02112         m_subtype = VST_POSTAL_CODE;
02113     else if ( localName == "sender-city" )
02114         m_subtype = VST_CITY;
02115     else if ( localName == "sender-title" )
02116         m_subtype = VST_AUTHORTITLE; // Small hack (it's supposed to be about the sender, not about the author)
02117     else if ( localName == "sender-position" )
02118         m_subtype = VST_AUTHORPOSITION;
02119     else if ( localName == "sender-phone-private" )
02120         m_subtype = VST_TELEPHONE_HOME;
02121     else if ( localName == "sender-phone-work" )
02122         m_subtype = VST_TELEPHONE_WORK;
02123     else if ( localName == "sender-fax" )
02124         m_subtype = VST_FAX;
02125     else if ( localName == "sender-email" )
02126         m_subtype = VST_EMAIL;
02127 
02128     m_varValue = QVariant( elem.text() );
02129 }
02130 
02131 void KoFieldVariable::saveOasis( KoXmlWriter& writer, KoSavingContext& /*context*/ ) const
02132 {
02133     switch( m_subtype )
02134     {
02135     case VST_NONE:
02136         break;
02137     case VST_FILENAME:
02138         writer.startElement( "text:file-name" );
02139         writer.addAttribute( "text:display", "name-and-extension" );
02140         break;
02141     case VST_DIRECTORYNAME:
02142         writer.startElement( "text:file-name" );
02143         writer.addAttribute( "text:display", "path" );
02144         break;
02145     case VST_AUTHORNAME:
02146         writer.startElement( "text:author-name" );
02147         break;
02148     case VST_EMAIL:
02149         writer.startElement("text:sender-email" );
02150         break;
02151     case VST_COMPANYNAME:
02152         writer.startElement("text:sender-company" );
02153         break;
02154     case VST_PATHFILENAME:
02155         writer.startElement("text:display" );
02156         writer.addAttribute( "text:display", "pathfilename" ); // ???????? not define !
02157         break;
02158     case VST_FILENAMEWITHOUTEXTENSION:
02159         writer.startElement("text:display" );
02160         writer.addAttribute( "text:display", "name-and-extension" ); // ???????? not define !
02161         break;
02162     case VST_TELEPHONE_WORK:
02163         writer.startElement("text:sender-phone-work" );
02164         break;
02165     case VST_TELEPHONE_HOME:
02166         writer.startElement("text:sender-phone-private" );
02167         break;
02168     case VST_FAX:
02169         writer.startElement("text:sender-fax" );
02170         break;
02171     case VST_COUNTRY:
02172         writer.startElement("text:sender-country" );
02173         break;
02174     case VST_TITLE:
02175         writer.startElement("text:title" );
02176         break;
02177     case VST_KEYWORDS:
02178         writer.startElement("text:keywords" );
02179         break;
02180     case VST_SUBJECT:
02181         writer.startElement("text:subject" );
02182         break;
02183     case VST_ABSTRACT:
02184         writer.startElement("text:description" );
02185         break;
02186     case VST_POSTAL_CODE:
02187         writer.startElement("text:sender-postal-code" );
02188         break;
02189     case VST_CITY:
02190         writer.startElement("text:sender-city" );
02191         break;
02192     case VST_STREET:
02193         writer.startElement("text:sender-street" );
02194         break;
02195     case VST_AUTHORTITLE:
02196         writer.startElement("text:sender-title" );
02197         break;
02198     case VST_AUTHORPOSITION:
02199         writer.startElement("text:sender-position" );
02200         break;
02201     case VST_INITIAL:
02202         writer.startElement("text:author-initials" );
02203         break;
02204     }
02205     writer.addTextNode( m_varValue.toString() );
02206     writer.endElement();
02207 }
02208 
02209 void KoFieldVariable::recalc()
02210 {
02211     QString value;
02212     switch( m_subtype ) {
02213         case VST_NONE:
02214             kdWarning() << "KoFieldVariable::recalc() called with m_subtype = VST_NONE !" << endl;
02215             break;
02216         case VST_FILENAME:
02217             value = m_doc->url().fileName();
02218             break;
02219         case VST_DIRECTORYNAME:
02220             value = m_doc->url().directory();
02221             break;
02222         case VST_PATHFILENAME:
02223             value=m_doc->url().path();
02224             break;
02225         case VST_FILENAMEWITHOUTEXTENSION:
02226         {
02227             QString file=m_doc->url().fileName();
02228             int pos=file.findRev(".");
02229             if(pos !=-1)
02230                 value=file.mid(0,pos);
02231             else
02232                 value=file;
02233         }
02234         break;
02235         case VST_AUTHORNAME:
02236         case VST_EMAIL:
02237         case VST_COMPANYNAME:
02238         case VST_TELEPHONE_WORK:
02239         case VST_TELEPHONE_HOME:
02240         case VST_FAX:
02241         case VST_COUNTRY:
02242         case VST_POSTAL_CODE:
02243         case VST_CITY:
02244         case VST_STREET:
02245         case VST_AUTHORTITLE:
02246     case VST_AUTHORPOSITION:
02247         case VST_INITIAL:
02248         {
02249             KoDocumentInfo * info = m_doc->documentInfo();
02250             KoDocumentInfoAuthor * authorPage = static_cast<KoDocumentInfoAuthor *>(info->page( "author" ));
02251             if ( !authorPage )
02252                 kdWarning() << "Author information not found in documentInfo !" << endl;
02253             else
02254             {
02255                 if ( m_subtype == VST_AUTHORNAME )
02256                     value = authorPage->fullName();
02257                 else if ( m_subtype == VST_EMAIL )
02258                     value = authorPage->email();
02259                 else if ( m_subtype == VST_COMPANYNAME )
02260                     value = authorPage->company();
02261                 else if ( m_subtype == VST_TELEPHONE_WORK )
02262                     value = authorPage->telephoneWork();
02263                 else if ( m_subtype == VST_TELEPHONE_HOME )
02264                     value = authorPage->telephoneHome();
02265                 else if ( m_subtype == VST_FAX )
02266                     value = authorPage->fax();
02267                 else if ( m_subtype == VST_COUNTRY )
02268                     value = authorPage->country();
02269                 else if ( m_subtype == VST_POSTAL_CODE )
02270                     value = authorPage->postalCode();
02271                 else if ( m_subtype == VST_CITY )
02272                     value = authorPage->city();
02273                 else if ( m_subtype == VST_STREET )
02274                     value = authorPage->street();
02275                 else if ( m_subtype == VST_AUTHORTITLE )
02276                     value = authorPage->title();
02277                 else if ( m_subtype == VST_INITIAL )
02278                     value = authorPage->initial();
02279                 else if ( m_subtype == VST_AUTHORPOSITION )
02280                     value = authorPage->position();
02281             }
02282         }
02283         break;
02284         case VST_TITLE:
02285         case VST_ABSTRACT:
02286     case VST_SUBJECT:
02287     case VST_KEYWORDS:
02288         {
02289             KoDocumentInfo * info = m_doc->documentInfo();
02290             KoDocumentInfoAbout * aboutPage = static_cast<KoDocumentInfoAbout *>(info->page( "about" ));
02291             if ( !aboutPage )
02292                 kdWarning() << "'About' page not found in documentInfo !" << endl;
02293             else
02294             {
02295                 if ( m_subtype == VST_TITLE )
02296                     value = aboutPage->title();
02297                 else if ( m_subtype == VST_SUBJECT )
02298                     value = aboutPage->subject();
02299                 else if ( m_subtype == VST_KEYWORDS )
02300                     value = aboutPage->keywords();
02301                 else
02302                     value = aboutPage->abstract();
02303             }
02304         }
02305         break;
02306     }
02307 
02308     if (value.isEmpty())        // try the initial value
02309         value = m_varValue.toString();
02310 
02311     if (value.isEmpty())        // still empty? give up
02312         value = i18n("<None>");
02313 
02314     m_varValue = QVariant( value );
02315 
02316     resize();
02317 }
02318 
02319 QStringList KoFieldVariable::actionTexts()
02320 {
02321     // NOTE: if you change here, also change fieldSubType()
02322     QStringList lst;
02323     lst << i18n( "Author Name" );
02324     lst << i18n( "Title" );
02325     lst << i18n( "Initials" );
02326     lst << i18n( "Position" );
02327     lst << i18n( "Company" );
02328     lst << i18n( "Email" );
02329     lst << i18n( "Telephone (work)");
02330     lst << i18n( "Telephone (private)");
02331 
02332     lst << i18n( "Fax");
02333     lst << i18n( "Street" );
02334     lst << i18n( "Postal Code" );
02335     lst << i18n( "City" );
02336     lst << i18n( "Country");
02337 
02338     lst << i18n( "Document Title" );
02339     lst << i18n( "Document Abstract" );
02340     lst << i18n( "Document Subject" );
02341     lst << i18n( "Document Keywords" );
02342 
02343     lst << i18n( "File Name" );
02344     lst << i18n( "File Name without Extension" );
02345     lst << i18n( "Directory Name" ); // is "Name" necessary ?
02346     lst << i18n( "Directory && File Name" );
02347     return lst;
02348 }
02349 
02350 short int KoFieldVariable::variableSubType( short int menuNumber )
02351 {
02352     return fieldSubType(menuNumber);
02353 }
02354 
02355 KoFieldVariable::FieldSubType KoFieldVariable::fieldSubType(short int menuNumber)
02356 {
02357     // NOTE: if you change here, also change actionTexts()
02358     FieldSubType v;
02359     switch (menuNumber)
02360     {
02361         case 0: v = VST_AUTHORNAME;
02362                 break;
02363         case 1: v = VST_AUTHORTITLE;
02364                 break;
02365         case 2: v = VST_INITIAL;
02366                 break;
02367         case 3: v = VST_AUTHORPOSITION;
02368                 break;
02369         case 4: v = VST_COMPANYNAME;
02370                 break;
02371         case 5: v = VST_EMAIL;
02372                 break;
02373         case 6: v = VST_TELEPHONE_WORK;
02374                 break;
02375         case 7: v = VST_TELEPHONE_HOME;
02376                 break;
02377         case 8: v = VST_FAX;
02378                 break;
02379         case 9: v = VST_STREET;
02380                 break;
02381         case 10: v = VST_POSTAL_CODE;
02382                 break;
02383         case 11: v = VST_CITY;
02384                 break;
02385         case 12: v = VST_COUNTRY;
02386                 break;
02387         case 13: v = VST_TITLE;
02388                 break;
02389         case 14: v = VST_ABSTRACT;
02390                 break;
02391         case 15: v = VST_SUBJECT;
02392                 break;
02393         case 16: v = VST_KEYWORDS;
02394                 break;
02395         case 17: v = VST_FILENAME;
02396                 break;
02397         case 18: v = VST_FILENAMEWITHOUTEXTENSION;
02398                 break;
02399         case 19: v = VST_DIRECTORYNAME;
02400                 break;
02401         case 20: v = VST_PATHFILENAME;
02402                 break;
02403         default:
02404             v = VST_NONE;
02405             break;
02406     }
02407     return v;
02408 }
02409 
02410 QStringList KoFieldVariable::subTypeList()
02411 {
02412     return KoFieldVariable::actionTexts();
02413 }
02414 
02415 /******************************************************************/
02416 /* Class: KoLinkVariable                                          */
02417 /******************************************************************/
02418 KoLinkVariable::KoLinkVariable( KoTextDocument *textdoc, const QString & _linkName, const QString & _ulr,KoVariableFormat *varFormat,KoVariableCollection *_varColl )
02419     : KoVariable( textdoc, varFormat,_varColl )
02420     ,m_url(_ulr)
02421 {
02422     m_varValue = QVariant( _linkName );
02423 }
02424 
02425 QString KoLinkVariable::fieldCode()
02426 {
02427     return i18n("Link");
02428 }
02429 
02430 void KoLinkVariable::loadOasis( const QDomElement &elem, KoOasisContext& /*context*/ )
02431 {
02432     if ( elem.localName() == "a" && elem.namespaceURI() == KoXmlNS::text ) {
02433         m_url = elem.attributeNS( KoXmlNS::xlink, "href", QString::null);
02434         m_varValue = QVariant(elem.text());
02435     }
02436 }
02437 
02438 void KoLinkVariable::saveOasis( KoXmlWriter& writer, KoSavingContext& /*context*/ ) const
02439 {
02440     //<text:a xlink:type="simple" xlink:href="http://www.kde.org/" office:name="sdgfsdfgs">kde org wxc &lt;wxc </text:a>
02441     writer.startElement( "text:a" );
02442     writer.addAttribute( "xlink:type", "simple" );
02443     writer.addAttribute( "xlink:href", m_url );
02444     writer.addAttribute( "office:name", m_varValue.toString() );
02445     writer.addTextNode( m_varValue.toString() );
02446     writer.endElement();
02447 
02448 }
02449 
02450 QString KoLinkVariable::text(bool realValue)
02451 {
02452     if (m_varColl->variableSetting()->displayFieldCode()&&!realValue)
02453         return fieldCode();
02454     else
02455         return value();
02456 }
02457 
02458 void KoLinkVariable::saveVariable( QDomElement& parentElem )
02459 {
02460     QDomElement linkElem = parentElem.ownerDocument().createElement( "LINK" );
02461     parentElem.appendChild( linkElem );
02462     linkElem.setAttribute( "linkName", m_varValue.toString() );
02463     linkElem.setAttribute( "hrefName", m_url );
02464 }
02465 
02466 void KoLinkVariable::load( QDomElement& elem )
02467 {
02468     KoVariable::load( elem );
02469     QDomElement linkElem = elem.namedItem( "LINK" ).toElement();
02470     if (!linkElem.isNull())
02471     {
02472         m_varValue = QVariant(linkElem.attribute("linkName"));
02473         m_url = linkElem.attribute("hrefName");
02474     }
02475 }
02476 
02477 void KoLinkVariable::recalc()
02478 {
02479     resize();
02480 }
02481 
02482 QStringList KoLinkVariable::actionTexts()
02483 {
02484     return QStringList( i18n( "Link..." ) );
02485 }
02486 
02487 
02488 void KoLinkVariable::drawCustomItem( QPainter* p, int x, int y, int wpix, int hpix, int ascentpix, int /*cx*/, int /*cy*/, int /*cw*/, int /*ch*/, const QColorGroup& cg, bool selected, int offset, bool drawingShadow )
02489 {
02490     KoTextFormat * fmt = format();
02491     KoTextZoomHandler * zh = textDocument()->paintingZoomHandler();
02492 
02493     bool displayLink = m_varColl->variableSetting()->displayLink();
02494     QFont font( fmt->screenFont( zh ) );
02495     if ( m_varColl->variableSetting()->underlineLink() )
02496         font.setUnderline( true );
02497     QColor textColor = displayLink ? cg.color( QColorGroup::Link ) : fmt->color();
02498 
02499     drawCustomItemHelper( p, x, y, wpix, hpix, ascentpix, cg, selected, offset, fmt, font, textColor, drawingShadow );
02500 }
02501 
02502 
02503 /******************************************************************/
02504 /* Class: KoNoteVariable                                          */
02505 /******************************************************************/
02506 KoNoteVariable::KoNoteVariable( KoTextDocument *textdoc, const QString & _note,KoVariableFormat *varFormat,KoVariableCollection *_varColl )
02507     : KoVariable( textdoc, varFormat,_varColl )
02508     , m_createdNoteDate( QDate::currentDate() )
02509 {
02510     m_varValue = QVariant( _note );
02511 }
02512 
02513 QString KoNoteVariable::fieldCode()
02514 {
02515     return i18n("Note");
02516 }
02517 
02518 QString KoNoteVariable::createdNote() const
02519 {
02520     return KGlobal::locale()->formatDate( m_createdNoteDate, false );
02521 }
02522 
02523 void KoNoteVariable::loadOasis( const QDomElement &elem, KoOasisContext& /*context*/ )
02524 {
02525     const QString localName = elem.localName();
02526     QString note;
02527     if ( localName == "annotation" && elem.namespaceURI() == KoXmlNS::office )
02528     {
02529         QDomElement date = KoDom::namedItemNS( elem, KoXmlNS::dc, "date" );
02530         m_createdNoteDate = QDate::fromString( date.text(), Qt::ISODate );
02531         QDomNode text = KoDom::namedItemNS( elem, KoXmlNS::text, "p" );
02532         for ( ; !text.isNull(); text = text.nextSibling() )
02533         {
02534             if ( text.isElement() )
02535             {
02536                 QDomElement t = text.toElement();
02537                 note += t.text() + "\n";
02538             }
02539         }
02540     }
02541     m_varValue = QVariant( note  );
02542 }
02543 
02544 void KoNoteVariable::saveOasis( KoXmlWriter& writer, KoSavingContext& /*context*/ ) const
02545 {
02546 //    <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>
02547     writer.startElement( "office:annotation" );
02548     writer.startElement( "dc:date" );
02549     writer.addTextNode( m_createdNoteDate.toString(Qt::ISODate) );
02550     writer.endElement();
02551     QStringList text = QStringList::split( "\n", m_varValue.toString() );
02552     for ( QStringList::Iterator it = text.begin(); it != text.end(); ++it ) {
02553         writer.startElement( "text:p" );
02554         writer.addTextNode( *it );
02555         writer.endElement();
02556     }
02557     writer.endElement();
02558 }
02559 
02560 void KoNoteVariable::saveVariable( QDomElement& parentElem )
02561 {
02562     QDomElement linkElem = parentElem.ownerDocument().createElement( "NOTE" );
02563     parentElem.appendChild( linkElem );
02564     linkElem.setAttribute( "note", m_varValue.toString() );
02565 }
02566 
02567 void KoNoteVariable::load( QDomElement& elem )
02568 {
02569     KoVariable::load( elem );
02570     QDomElement linkElem = elem.namedItem( "NOTE" ).toElement();
02571     if (!linkElem.isNull())
02572     {
02573         m_varValue = QVariant(linkElem.attribute("note"));
02574     }
02575 }
02576 
02577 void KoNoteVariable::recalc()
02578 {
02579     resize();
02580 }
02581 
02582 QStringList KoNoteVariable::actionTexts()
02583 {
02584     return QStringList( i18n( "Note..." ) );
02585 }
02586 
02587 QString KoNoteVariable::text(bool realValue)
02588 {
02589     if (m_varColl->variableSetting()->displayComment() &&
02590         m_varColl->variableSetting()->displayFieldCode()&&!realValue)
02591         return fieldCode();
02592     else
02593         //for a note return just a "space" we can look at
02594         //note when we "right button"
02595         return QString(" ");
02596 
02597 }
02598 
02599 void KoNoteVariable::drawCustomItem( QPainter* p, int x, int y, int wpix, int hpix, int ascentpix, int cx, int cy, int cw, int ch, const QColorGroup& cg, bool selected, int offset, bool drawingShadow )
02600 {
02601     if ( !m_varColl->variableSetting()->displayComment())
02602         return;
02603 
02604     KoTextFormat * fmt = format();
02605     //kdDebug(32500) << "KoNoteVariable::drawCustomItem index=" << index() << " x=" << x << " y=" << y << endl;
02606 
02607     p->save();
02608     p->setPen( QPen( fmt->color() ) );
02609     if ( fmt->textBackgroundColor().isValid() )
02610         p->fillRect( x, y, wpix, hpix, fmt->textBackgroundColor() );
02611     if ( selected )
02612     {
02613         p->setPen( QPen( cg.color( QColorGroup::HighlightedText ) ) );
02614         p->fillRect( x, y, wpix, hpix, cg.color( QColorGroup::Highlight ) );
02615     }
02616     else if ( textDocument() && p->device()->devType() != QInternal::Printer
02617         && !textDocument()->dontDrawingNoteVariable())
02618     {
02619         p->fillRect( x, y, wpix, hpix, Qt::yellow);
02620         p->setPen( QPen( cg.color( QColorGroup::Highlight ), 0, Qt::DotLine ) );
02621         p->drawRect( x, y, wpix, hpix );
02622     }
02623     //call it for use drawCustomItemHelper just for draw font effect
02624     KoVariable::drawCustomItem( p, x, y, wpix, hpix, ascentpix, cx, cy, cw, ch, cg, selected, offset, drawingShadow );
02625 
02626     p->restore();
02627 }
02628 
02629 void KoPageVariable::setSectionTitle( const QString& _title )
02630 {
02631     QString title( _title );
02632     if ( title.isEmpty() )
02633     {
02634         title = i18n("<No title>");
02635     }
02636     m_varValue = QVariant( title );
02637 }
02638 
02639 
02640 // ----------------------------------------------------------------
02641 //                   class KoStatisticVariable
02642 
02643 
02644 bool KoStatisticVariable::m_extendedType = false;
02645 
02646 
02647 KoStatisticVariable::KoStatisticVariable( KoTextDocument *textdoc,
02648                       short int subtype,
02649                       KoVariableFormat *varFormat,
02650                       KoVariableCollection *_varColl )
02651     : KoVariable( textdoc, varFormat, _varColl ),
02652       m_subtype( subtype )
02653 {
02654 }
02655 
02656 
02657 QStringList KoStatisticVariable::actionTexts()
02658 {
02659     QStringList lst;
02660     lst << i18n( "Number of Words" );
02661     lst << i18n( "Number of Sentences" );
02662     lst << i18n( "Number of Lines" );
02663     lst << i18n( "Number of Characters" );
02664     lst << i18n( "Number of Non-Whitespace Characters" );
02665     lst << i18n( "Number of Syllables" );
02666     lst << i18n( "Number of Frames" );
02667     lst << i18n( "Number of Embedded Objects" );
02668     lst << i18n( "Number of Pictures" );
02669     if (  m_extendedType )
02670         lst << i18n( "Number of Tables" );
02671     return lst;
02672 }
02673 
02674 
02675 void KoStatisticVariable::setVariableSubType( short int subtype )
02676 {
02677     m_subtype = subtype;
02678     Q_ASSERT( m_varColl );
02679     KoVariableFormatCollection* fc = m_varColl->formatCollection();
02680     setVariableFormat(fc->format("NUMBER") );
02681 }
02682 
02683 
02684 QStringList KoStatisticVariable::subTypeList()
02685 {
02686     return KoStatisticVariable::actionTexts();
02687 }
02688 
02689 
02690 void KoStatisticVariable::saveVariable( QDomElement& varElem )
02691 {
02692     QDomElement  elem = varElem.ownerDocument().createElement( "STATISTIC" );
02693     varElem.appendChild( elem );
02694 
02695     elem.setAttribute( "type",  QString::number(m_subtype) );
02696     elem.setAttribute( "value", QString::number(m_varValue.toInt()) );
02697 }
02698 
02699 
02700 void KoStatisticVariable::load( QDomElement &elem )
02701 {
02702     KoVariable::load( elem );
02703 
02704     QDomElement e = elem.namedItem( "STATISTIC" ).toElement();
02705     if ( !e.isNull() ) {
02706     // FIXME: Error handling.
02707     m_subtype  = e.attribute( "type" ).toInt();
02708     m_varValue = e.attribute( "value" ).toInt();
02709     }
02710 }
02711 
02712 
02713 void KoStatisticVariable::loadOasis( const QDomElement &elem, KoOasisContext& /*context*/ )
02714 {
02715     const QString localName( elem.localName() );
02716     if ( localName == "object-count" )
02717     {
02718         m_subtype = VST_STATISTIC_NB_EMBEDDED;
02719         m_varValue = QVariant( elem.text().toInt() );
02720     }
02721     else if ( localName == "table-count" )
02722     {
02723         m_subtype = VST_STATISTIC_NB_TABLE;
02724         m_varValue = QVariant( elem.text().toInt() );
02725     }
02726     else if ( localName == "picture-count" )
02727     {
02728         m_subtype = VST_STATISTIC_NB_PICTURE;
02729         m_varValue = QVariant( elem.text().toInt() );
02730     }
02731     else if ( localName == "word-count" )
02732     {
02733         m_subtype = VST_STATISTIC_NB_WORD;
02734         m_varValue = QVariant( elem.text().toInt() );
02735     }
02736     else if ( localName == "character-count" )
02737     {
02738         m_subtype = VST_STATISTIC_NB_CHARACTERE;
02739         m_varValue = QVariant( elem.text().toInt() );
02740     }
02741     else if ( localName == "frame-count" )
02742     {
02743         m_subtype = VST_STATISTIC_NB_FRAME;
02744         m_varValue = QVariant( elem.text().toInt() );
02745     }
02746     else if ( localName == "line-count" )
02747     {
02748         m_subtype = VST_STATISTIC_NB_LINES;
02749         m_varValue = QVariant( elem.text().toInt() );
02750     }
02751     else if ( localName == "sentence-count" )
02752     {
02753         m_subtype = VST_STATISTIC_NB_SENTENCE;
02754         m_varValue = QVariant( elem.text().toInt() );
02755     }
02756     else if ( localName == "non-whitespace-character-count" )
02757     {
02758         m_subtype = VST_STATISTIC_NB_NON_WHITESPACE_CHARACTERE;
02759         m_varValue = QVariant( elem.text().toInt() );
02760     }
02761     else if ( localName == "syllable-count" )
02762     {
02763         m_subtype = VST_STATISTIC_NB_SYLLABLE;
02764         m_varValue = QVariant( elem.text().toInt() );
02765     }
02766     //TODO other copy
02767 }
02768 
02769 void KoStatisticVariable::saveOasis( KoXmlWriter& writer, KoSavingContext& /*context*/ ) const
02770 {
02771     switch( m_subtype )
02772     {
02773     case VST_STATISTIC_NB_EMBEDDED:
02774         writer.startElement( "text:object-count" );
02775         writer.addTextNode( QString::number( m_varValue.toInt() ) );
02776         writer.endElement();
02777         break;
02778     case VST_STATISTIC_NB_TABLE:
02779         writer.startElement( "text:table-count" );
02780         writer.addTextNode( QString::number( m_varValue.toInt() ) );
02781         writer.endElement();
02782         break;
02783     case VST_STATISTIC_NB_PICTURE:
02784         writer.startElement( "text:picture-count" );
02785         writer.addTextNode( QString::number( m_varValue.toInt() ) );
02786         writer.endElement();
02787         break;
02788     case VST_STATISTIC_NB_FRAME:
02789         //TODO verify that it's implemented into oasis file format
02790         writer.startElement( "text:frame-count" );
02791         writer.addTextNode( QString::number( m_varValue.toInt() ) );
02792         writer.endElement();
02793         break;
02794     case VST_STATISTIC_NB_WORD:
02795         writer.startElement( "text:word-count" );
02796         writer.addTextNode( QString::number( m_varValue.toInt() ) );
02797         writer.endElement();
02798         break;
02799     case VST_STATISTIC_NB_SENTENCE:
02800         //TODO verify that it's implemented into oasis file format
02801         writer.startElement( "text:sentence-count" );
02802         writer.addTextNode( QString::number( m_varValue.toInt() ) );
02803         writer.endElement();
02804         break;
02805     case VST_STATISTIC_NB_CHARACTERE:
02806         writer.startElement( "text:character-count" );
02807         writer.addTextNode( QString::number( m_varValue.toInt() ) );
02808         writer.endElement();
02809         break;
02810     case VST_STATISTIC_NB_LINES:
02811         //TODO verify that it's implemented into oasis file format
02812         writer.startElement( "text:line-count" );
02813         writer.addTextNode( QString::number( m_varValue.toInt() ) );
02814         writer.endElement();
02815         break;
02816     case VST_STATISTIC_NB_NON_WHITESPACE_CHARACTERE:
02817         //TODO verify that it's implemented into oasis file format
02818         writer.startElement( "text:non-whitespace-character-count" );
02819         writer.addTextNode( QString::number( m_varValue.toInt() ) );
02820         writer.endElement();
02821         break;
02822     case VST_STATISTIC_NB_SYLLABLE:
02823         //TODO verify that it's implemented into oasis file format
02824         writer.startElement( "text:syllable-count" );
02825         writer.addTextNode( QString::number( m_varValue.toInt() ) );
02826         writer.endElement();
02827         break;
02828     }
02829 }
02830 
02831 QString KoStatisticVariable::fieldCode()
02832 {
02833     if ( m_subtype == VST_STATISTIC_NB_FRAME )
02834     {
02835         return i18n( "Number of Frames" );
02836     }
02837     else if( m_subtype == VST_STATISTIC_NB_PICTURE )
02838     {
02839         return i18n( "Number of Pictures" );
02840     }
02841     else if( m_subtype == VST_STATISTIC_NB_TABLE )
02842     {
02843         return i18n( "Number of Tables" );
02844     }
02845     else if( m_subtype == VST_STATISTIC_NB_EMBEDDED )
02846     {
02847         return i18n( "Number of Embedded Objects" );
02848     }
02849     else if( m_subtype == VST_STATISTIC_NB_WORD )
02850     {
02851         return i18n( "Number of Words" );
02852     }
02853     else if( m_subtype == VST_STATISTIC_NB_SENTENCE )
02854     {
02855         return i18n( "Number of Sentences" );
02856     }
02857     else if( m_subtype == VST_STATISTIC_NB_LINES )
02858     {
02859         return i18n( "Number of Lines" );
02860     }
02861     else if ( m_subtype == VST_STATISTIC_NB_CHARACTERE )
02862     {
02863         return i18n( "Number of Characters" );
02864     }
02865     else if ( m_subtype == VST_STATISTIC_NB_NON_WHITESPACE_CHARACTERE )
02866     {
02867         return i18n( "Number of Non-Whitespace Characters" );
02868     }
02869     else if ( m_subtype == VST_STATISTIC_NB_SYLLABLE )
02870     {
02871         return i18n( "Number of Syllables" );
02872     }
02873     else
02874         return i18n( "Number of Frames" );
02875 }
02876 
02877 
KDE Home | KDE Accessibility Home | Description of Access Keys