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