1069
1029
QDomElement picturesElem = domElement.namedItem( "PICTURES" ).toElement();
1070
1030
if ( !picturesElem.isNull() )
1072
m_pictureCollection.readXML( picturesElem, m_pictureMap );
1032
m_pictureCollection->readXML( picturesElem, m_pictureMap );
1076
1036
QDomElement pixmapsElem = domElement.namedItem( "PIXMAPS" ).toElement();
1077
1037
if ( !pixmapsElem.isNull() )
1079
m_pictureCollection.readXML( pixmapsElem, m_pictureMap );
1039
m_pictureCollection->readXML( pixmapsElem, m_pictureMap );
1083
1043
QDomElement clipartsElem = domElement.namedItem( "CLIPARTS" ).toElement();
1084
1044
if ( !clipartsElem.isNull() )
1086
m_pictureCollection.readXML( pixmapsElem, m_pictureMap );
1046
m_pictureCollection->readXML( pixmapsElem, m_pictureMap );
1051
bool KWDocument::loadOasis( const QDomDocument& doc, KoOasisStyles& oasisStyles, const QDomDocument& settings, KoStore* store )
1055
emit sigProgress( 0 );
1057
kdDebug(32001) << "KWDocument::loadOasis" << endl;
1059
KoColumns __columns;
1060
__columns.columns = 1;
1061
__columns.ptColumnSpacing = m_defaultColumnSpacing;
1062
KoKWHeaderFooter __hf;
1063
__hf.header = HF_SAME;
1064
__hf.footer = HF_SAME;
1065
__hf.ptHeaderBodySpacing = 10.0;
1066
__hf.ptFooterBodySpacing = 10.0;
1067
__hf.ptFootNoteBodySpacing = 10.0;
1069
QDomElement content = doc.documentElement();
1070
QDomElement body ( KoDom::namedItemNS( content, KoXmlNS::office, "body" ) );
1071
if ( body.isNull() )
1073
kdError(32001) << "No office:body found!" << endl;
1074
setErrorMessage( i18n( "Invalid OASIS document. No office:body tag found." ) );
1077
body = KoDom::namedItemNS( body, KoXmlNS::office, "text" );
1078
if ( body.isNull() )
1080
kdError(32001) << "No office:text found!" << endl;
1081
// ## TODO: print the actual tag that was found, it might help finding the right app to use :)
1082
setErrorMessage( i18n( "Invalid OASIS document. No office:text tag found." ) );
1086
// TODO check versions and mimetypes etc.
1088
QString masterPageName = "Standard"; // use default layout as fallback
1089
// In theory the page format is the style:master-page-name of the first paragraph...
1090
// But, hmm, in a doc with only a table there was no reference to the master page at all...
1091
QDomElement* masterPage = oasisStyles.masterPages()[ masterPageName ];
1092
Q_ASSERT( masterPage );
1093
QDomElement *masterPageStyle = masterPage ? oasisStyles.styles()[masterPage->attributeNS( KoXmlNS::style, "page-layout-name", QString::null )] : 0;
1094
Q_ASSERT( masterPageStyle );
1095
if ( masterPageStyle )
1097
m_pageLayout.loadOasis( *masterPageStyle );
1098
if ( m_pageLayout.ptWidth <= 1e-13 || m_pageLayout.ptHeight <= 1e-13 )
1100
// Loading page layout failed, try to see why.
1101
QDomElement properties( KoDom::namedItemNS( *masterPageStyle, KoXmlNS::style, "page-layout-properties" ) );
1102
//if ( properties.isNull() )
1103
// setErrorMessage( i18n( "Invalid document. No page layout properties were found. The application which produced this document isn't OASIS-compliant." ) );
1104
//else if ( properties.hasAttributeNS( KoXmlNS::fo, "page-width" ) )
1105
// setErrorMessage( i18n( "Invalid document. Page layout has no page width. The application which produced this document isn't OASIS-compliant." ) );
1107
if ( properties.hasAttributeNS( "http://www.w3.org/1999/XSL/Format", "page-width" ) )
1108
setErrorMessage( i18n( "Invalid document. 'fo' has the wrong namespace. The application which produced this document is not OASIS-compliant." ) );
1110
setErrorMessage( i18n( "Invalid document. Paper size: %1x%2" ).arg( m_pageLayout.ptWidth ).arg( m_pageLayout.ptHeight ) );
1114
//__hf.ptHeaderBodySpacing = getAttribute( paper, "spHeadBody", 0.0 );
1115
//__hf.ptFooterBodySpacing = getAttribute( paper, "spFootBody", 0.0 );
1116
//__hf.ptFootNoteBodySpacing = getAttribute( paper, "spFootNoteBody", 10.0 );
1118
const QDomElement properties( KoDom::namedItemNS( *masterPageStyle, KoXmlNS::style, "page-layout-properties" ) );
1119
const QDomElement footnoteSep = KoDom::namedItemNS( properties, KoXmlNS::style, "footnote-sep" );
1120
if ( !footnoteSep.isNull() ) {
1121
// style:width="0.018cm" style:distance-before-sep="0.101cm"
1122
// style:distance-after-sep="0.101cm" style:adjustment="left"
1123
// style:rel-width="25%" style:color="#000000"
1124
const QString width = footnoteSep.attributeNS( KoXmlNS::style, "width", QString::null );
1125
if ( !width.isEmpty() ) {
1126
m_footNoteSeparatorLineWidth = KoUnit::parseValue( width );
1129
QString pageWidth = footnoteSep.attributeNS( KoXmlNS::style, "rel-width", QString::null );
1130
if ( pageWidth.endsWith( "%" ) ) {
1131
pageWidth.truncate( pageWidth.length() - 1 ); // remove '%'
1132
m_iFootNoteSeparatorLineLength = qRound( pageWidth.toDouble() );
1134
// Not in KWord: color, distance before and after separator
1136
const QString style = footnoteSep.attributeNS( KoXmlNS::style, "line-style", QString::null );
1137
if ( style == "solid" || style.isEmpty() )
1138
m_footNoteSeparatorLineType = SLT_SOLID;
1139
else if ( style == "dash" )
1140
m_footNoteSeparatorLineType = SLT_DASH;
1141
else if ( style == "dotted" )
1142
m_footNoteSeparatorLineType = SLT_DOT;
1143
else if ( style == "dot-dash" )
1144
m_footNoteSeparatorLineType = SLT_DASH_DOT;
1145
else if ( style == "dot-dot-dash" )
1146
m_footNoteSeparatorLineType = SLT_DASH_DOT_DOT;
1148
kdDebug() << "Unknown value for m_footNoteSeparatorLineType: " << style << endl;
1150
const QString pos = footnoteSep.attributeNS( KoXmlNS::style, "adjustment", QString::null );
1151
if ( pos == "centered" )
1152
m_footNoteSeparatorLinePos = SLP_CENTERED;
1153
else if ( pos == "right")
1154
m_footNoteSeparatorLinePos = SLP_RIGHT;
1155
else // if ( pos == "left" )
1156
m_footNoteSeparatorLinePos = SLP_LEFT;
1159
__columns.columns = 1;
1160
__columns.ptColumnSpacing = m_defaultColumnSpacing;
1162
const QDomElement columnsElem = KoDom::namedItemNS( properties, KoXmlNS::style, "columns" );
1163
if ( !columnsElem.isNull() )
1165
__columns.columns = columnsElem.attributeNS( KoXmlNS::fo, "column-count", QString::null ).toInt();
1166
if ( __columns.columns == 0 )
1167
__columns.columns = 1;
1168
// TODO OASIS OpenDocument supports columns of different sizes, using <style:column style:rel-width="...">
1169
// (with fo:start-indent/fo:end-indent for per-column spacing)
1170
// But well, it also allows us to specify a single gap.
1171
if ( columnsElem.hasAttributeNS( KoXmlNS::fo, "column-gap" ) )
1172
__columns.ptColumnSpacing = KoUnit::parseValue( columnsElem.attributeNS( KoXmlNS::fo, "column-gap", QString::null ) );
1173
// It also supports drawing a vertical line as a separator...
1176
m_headerVisible = false;
1177
m_footerVisible = false;
1179
// TODO spHeadBody (where is this in OOo?)
1180
// TODO spFootBody (where is this in OOo?)
1181
// Answer: margins of the <style:header-footer> element
1183
else // this doesn't happen with normal documents, but it can happen if copying something,
1184
// pasting into konq as foo.odt, then opening that...
1186
__columns.columns = 1;
1187
__columns.ptColumnSpacing = 2;
1188
m_headerVisible = false;
1189
m_footerVisible = false;
1190
m_pageLayout = KoPageLayout::standardLayout();
1193
createLoadingInfo();
1194
KWOasisLoader oasisLoader( this );
1196
// <text:page-sequence> oasis extension for DTP (2003-10-27 post by Daniel)
1197
m_processingType = ( !KoDom::namedItemNS( body, KoXmlNS::text, "page-sequence" ).isNull() )
1200
// TODO settings (m_unit, spellcheck settings)
1203
m_tabStop = MM_TO_POINT(15);
1204
QDomElement* defaultParagStyle = oasisStyles.defaultStyle( "paragraph" );
1205
if ( defaultParagStyle ) {
1207
stack.push( *defaultParagStyle );
1208
stack.setTypeProperties( "paragraph" );
1209
QString tabStopVal = stack.attributeNS( KoXmlNS::style, "tab-stop-distance" );
1210
if ( !tabStopVal.isEmpty() )
1211
m_tabStop = KoUnit::parseValue( tabStopVal );
1213
m_initialEditing = 0;
1215
// TODO variable settings
1216
// By default display real variable value
1217
if ( !isReadWrite())
1218
m_varColl->variableSetting()->setDisplayFieldCode(false);
1222
KoOasisContext context( this, *m_varColl, oasisStyles, store );
1223
Q_ASSERT( !oasisStyles.officeStyle().isNull() );
1225
// Load all styles before the corresponding paragraphs try to use them!
1226
m_styleColl->loadOasisStyleTemplates( context );
1227
static_cast<KWVariableSettings *>( m_varColl->variableSetting() )
1228
->loadNoteConfiguration( oasisStyles.officeStyle() );
1230
// TODO framestyles and tablestyles
1232
loadDefaultTableTemplates();
1234
if ( m_processingType == WP ) {
1235
// Create main frameset
1236
KWTextFrameSet *fs = new KWTextFrameSet( this, i18n( "Main Text Frameset" ) );
1237
m_lstFrameSet.append( fs ); // don't use addFrameSet here. We'll call finalize() once and for all in completeLoading
1238
fs->loadOasisContent( body, context );
1239
KWFrame* frame = new KWFrame( fs, 29, 42, 798-29, 566-42 );
1240
frame->setFrameBehavior( KWFrame::AutoCreateNewFrame );
1241
frame->setNewFrameBehavior( KWFrame::Reconnect );
1242
fs->addFrame( frame );
1244
fs->renumberFootNotes( false /*no repaint*/ );
1247
// DTP mode: the items in the body are page-sequence and then frames
1249
forEachElement( tag, body )
1251
context.styleStack().save();
1252
const QString localName = tag.localName();
1253
if ( localName == "page-sequence" && tag.namespaceURI() == KoXmlNS::text )
1255
// We don't have support for changing the page layout yet, so just take the
1259
forEachElement( page, tag )
1261
kdDebug() << "DTP mode: found " << m_pages << "pages" << endl;
1263
else if ( localName == "frame" && tag.namespaceURI() == KoXmlNS::draw )
1264
oasisLoader.loadFrame( tag, context );
1266
kdWarning(32001) << "Unsupported tag in DTP loading:" << tag.tagName() << endl;
1271
// TODO support for first-page
1272
bool hasEvenOddHeader = false;
1273
bool hasEvenOddFooter = false;
1274
if ( masterPageStyle )
1276
QDomElement headerStyle = KoDom::namedItemNS( *masterPageStyle, KoXmlNS::style, "header-style" );
1277
QDomElement footerStyle = KoDom::namedItemNS( *masterPageStyle, KoXmlNS::style, "footer-style" );
1278
QDomElement headerLeftElem = KoDom::namedItemNS( *masterPage, KoXmlNS::style, "header-left" );
1279
if ( !headerLeftElem.isNull() ) {
1280
kdDebug() << "Found header-left" << endl;
1281
hasEvenOddHeader = true;
1282
__hf.header = HF_EO_DIFF; // ###
1283
oasisLoader.loadOasisHeaderFooter( headerLeftElem, hasEvenOddHeader, headerStyle, context );
1285
QDomElement headerElem = KoDom::namedItemNS( *masterPage, KoXmlNS::style, "header" );
1286
if ( !headerElem.isNull() ) {
1287
kdDebug() << "Found header" << endl;
1288
oasisLoader.loadOasisHeaderFooter( headerElem, hasEvenOddHeader, headerStyle, context );
1290
QDomElement footerLeftElem = KoDom::namedItemNS( *masterPage, KoXmlNS::style, "footer-left" );
1291
if ( !footerLeftElem.isNull() ) {
1292
kdDebug() << "Found footer-left" << endl;
1293
hasEvenOddFooter = true;
1294
__hf.footer = HF_EO_DIFF; // ###
1295
oasisLoader.loadOasisHeaderFooter( footerLeftElem, hasEvenOddFooter, footerStyle, context );
1297
QDomElement footerElem = KoDom::namedItemNS( *masterPage, KoXmlNS::style, "footer" );
1298
if ( !footerElem.isNull() ) {
1299
kdDebug() << "Found footer" << endl;
1300
oasisLoader.loadOasisHeaderFooter( footerElem, hasEvenOddFooter, footerStyle, context );
1304
// TODO embedded objects
1306
if ( context.cursorTextParagraph() ) {
1307
// Maybe, once 1.3-support is dropped, we can get rid of InitialEditing and fetch the
1308
// values from KoOasisContext? But well, it lives a bit longer.
1309
// At least we could store a KWFrameSet* and a KoTextParag* instead of a name and an id.
1310
m_initialEditing = new InitialEditing();
1311
KWTextFrameSet* fs = static_cast<KWTextDocument *>( context.cursorTextParagraph()->textDocument() )->textFrameSet();
1312
m_initialEditing->m_initialFrameSet = fs->name();
1313
m_initialEditing->m_initialCursorParag = context.cursorTextParagraph()->paragId();
1314
m_initialEditing->m_initialCursorIndex = context.cursorTextIndex();
1317
kdDebug(32001) << "Loading took " << (float)(dt.elapsed()) / 1000 << " seconds" << endl;
1320
// This sets the columns and header/footer flags, and calls recalcFrames,
1321
// so it must be done last.
1322
setPageLayout( m_pageLayout, __columns, __hf, false );
1324
if ( !settings.isNull() )
1326
oasisLoader.loadOasisSettings( settings );
1333
// called before loading
1334
void KWDocument::clear()
1336
m_pictureMap.clear();
1337
m_textImageRequests.clear();
1338
m_pictureRequests.clear();
1339
m_anchorRequests.clear();
1340
m_footnoteVarRequests.clear();
1341
m_spellCheckIgnoreList.clear();
1342
m_pageColumns.columns = 1;
1343
m_pageColumns.ptColumnSpacing = m_defaultColumnSpacing;
1345
m_pageHeaderFooter.header = HF_SAME;
1346
m_pageHeaderFooter.footer = HF_SAME;
1347
m_pageHeaderFooter.ptHeaderBodySpacing = 10;
1348
m_pageHeaderFooter.ptFooterBodySpacing = 10;
1349
m_pageHeaderFooter.ptFootNoteBodySpacing = 10;
1350
m_pageColumns.columns = 1;
1351
m_pageColumns.ptColumnSpacing = m_defaultColumnSpacing;
1353
m_bHasEndNotes = false;
1356
m_pictureCollection->clear();
1357
m_varFormatCollection->clear();
1359
m_styleColl->clear();
1360
m_frameStyleColl->clear();
1361
m_tableStyleColl->clear();
1362
m_tableTemplateColl->clear();
1364
// Some simple import filters don't define any style,
1365
// so let's have a Standard style at least
1366
KoParagStyle * standardStyle = new KoParagStyle( "Standard" ); // This gets translated later on
1367
//kdDebug() << "KWDocument::KWDocument creating standardStyle " << standardStyle << endl;
1368
standardStyle->format().setFont( m_defaultFont );
1369
m_styleColl->addStyleTemplate( standardStyle );
1371
// And let's do the same for framestyles
1372
KWFrameStyle * standardFrameStyle = new KWFrameStyle( "Plain" );
1373
standardFrameStyle->setBackgroundColor(Qt::white);
1374
standardFrameStyle->setTopBorder(KoBorder(Qt::black,KoBorder::SOLID,0));
1375
standardFrameStyle->setRightBorder(KoBorder(Qt::black,KoBorder::SOLID,0));
1376
standardFrameStyle->setLeftBorder(KoBorder(Qt::black,KoBorder::SOLID,0));
1377
standardFrameStyle->setBottomBorder(KoBorder(Qt::black,KoBorder::SOLID,0));
1378
m_frameStyleColl->addFrameStyleTemplate( standardFrameStyle );
1380
// And let's do the same for tablestyles
1381
KWTableStyle *standardTableStyle = new KWTableStyle( "Plain", standardStyle, standardFrameStyle );
1382
m_tableStyleColl->addTableStyleTemplate( standardTableStyle );
1091
1385
bool KWDocument::loadXML( QIODevice *, const QDomDocument & doc )
1095
1389
emit sigProgress( 0 );
1096
//kdDebug(32001) << "KWDocument::loadXML" << endl;
1097
m_pictureMap.clear();
1098
m_textImageRequests.clear();
1099
m_pictureRequests.clear();
1100
m_anchorRequests.clear();
1101
m_footnoteVarRequests.clear();
1102
m_spellListIgnoreAll.clear();
1104
m_pageColumns.columns = 1;
1105
m_pageColumns.ptColumnSpacing = m_defaultColumnSpacing;
1107
m_pageHeaderFooter.header = HF_SAME;
1108
m_pageHeaderFooter.footer = HF_SAME;
1109
m_pageHeaderFooter.ptHeaderBodySpacing = 10;
1110
m_pageHeaderFooter.ptFooterBodySpacing = 10;
1111
m_pageHeaderFooter.ptFootNoteBodySpacing = 10;
1112
m_varFormatCollection->clear();
1115
m_bHasEndNotes = false;
1390
kdDebug(32001) << "KWDocument::loadXML" << endl;
1117
1393
KoPageLayout __pgLayout;
1118
1394
KoColumns __columns;
2301
2648
refreshDocStructure( (int)Embedded );
2651
bool KWDocument::saveOasis( KoStore* store, KoXmlWriter* manifestWriter )
2653
return saveOasis( store, manifestWriter, SaveAll );
2656
// can't be const due to recalcVariables()
2657
// TODO: rename to saveOasisHelper
2658
bool KWDocument::saveOasis( KoStore* store, KoXmlWriter* manifestWriter, SaveFlag saveFlag,
2659
QString* plainText, KoPicture* picture, KWTextFrameSet* fs )
2661
m_pictureCollection->assignUniqueIds();
2663
manifestWriter->addManifestEntry( "content.xml", "text/xml" );
2664
KoOasisStore oasisStore( store );
2666
KoXmlWriter* contentWriter = oasisStore.contentWriter();
2667
if ( !contentWriter )
2670
QValueList<KoPictureKey> pictureList;
2671
if ( saveFlag == SaveAll )
2672
pictureList = savePictureList();
2674
m_varColl->variableSetting()->setModificationDate(QDateTime::currentDateTime());
2675
recalcVariables( VT_DATE );
2676
recalcVariables( VT_TIME ); // for "current time"
2677
m_syntaxVersion = CURRENT_SYNTAX_VERSION; // ### clean this up once we remove the old format
2679
KoGenStyles mainStyles;
2680
KoSavingContext savingContext( mainStyles, m_varColl->variableSetting(), m_pageColumns.columns > 1, KoSavingContext::Store );
2682
// Save user styles as KoGenStyle objects
2683
KoSavingContext::StyleNameMap map = m_styleColl->saveOasis( mainStyles, KoGenStyle::STYLE_USER, savingContext );
2684
savingContext.setStyleNameMap( map );
2686
if ( saveFlag == SaveAll )
2688
// Save visual info for the first view, such as the active frameset and cursor position
2689
// It looks like a hack, but reopening a document creates only one view anyway (David)
2690
KWView * view = static_cast<KWView*>(views().getFirst());
2691
if ( view ) // no view if embedded document
2693
KWFrameSetEdit* edit = view->getGUI()->canvasWidget()->currentFrameSetEdit();
2696
KWTextFrameSetEdit* textedit = dynamic_cast<KWTextFrameSetEdit *>(edit);
2697
if ( textedit && textedit->cursor() ) {
2698
KoTextCursor* cursor = textedit->cursor();
2699
savingContext.setCursorPosition( cursor->parag(),
2706
KoXmlWriter* bodyWriter = oasisStore.bodyWriter();
2707
bodyWriter->startElement( "office:body" );
2708
bodyWriter->startElement( "office:text" );
2710
if ( saveFlag == SaveAll )
2712
// save the body into bodyWriter
2713
saveOasisBody( *bodyWriter, savingContext );
2715
else // SaveSelected
2717
// In theory we should pass a view to this method, in order to
2718
// copy what is currently selected in that view only. But selection
2719
// is currently part of the KoTextParag data, so it's shared between views.
2721
*plainText = fs->textDocument()->copySelection( *bodyWriter, savingContext, KoTextDocument::Standard );
2722
// Collect inline framesets for e.g. pictures
2723
KWCollectFramesetsVisitor visitor;
2724
fs->textDocument()->visitSelection( KoTextDocument::Standard, &visitor );
2725
const QValueList<KWFrameSet *>& frameset = visitor.frameSets();
2726
kdDebug(32001) << frameset.count() << " inline framesets" << endl;
2727
for ( QValueList<KWFrameSet *>::ConstIterator it = frameset.begin(); it != frameset.end(); ++it )
2729
switch ( (*it)->type() ) {
2732
const KoPictureKey key = static_cast<KWPictureFrameSet *>( *it )->key();
2733
if ( !pictureList.contains( key ) )
2734
pictureList.append( key );
2745
// write selected (non-inline) frames
2747
saveSelectedFrames( *bodyWriter, store, manifestWriter, savingContext, pictureList,
2748
&newText ); // output vars
2749
*plainText += newText;
2750
// Single image -> return it
2751
if ( picture && pictureList.count() == 1 )
2753
*picture = m_pictureCollection->findPicture( pictureList.first() );
2757
bodyWriter->endElement(); // office:text
2758
bodyWriter->endElement(); // office:body
2760
KWOasisSaver::writeAutomaticStyles( *contentWriter, mainStyles, savingContext );
2762
oasisStore.closeContentWriter();
2764
// Done with content.xml
2766
if ( !store->open( "styles.xml" ) )
2768
manifestWriter->addManifestEntry( "styles.xml", "text/xml" );
2769
saveOasisDocumentStyles( store, mainStyles, savingContext, saveFlag );
2770
if ( !store->close() ) // done with styles.xml
2773
//kdDebug(32001) << "saveOasis: " << pictureList.count() << " pictures" << endl;
2774
m_pictureCollection->saveOasisToStore( store, pictureList, manifestWriter );
2776
if ( saveFlag == SaveAll )
2779
if(!store->open("settings.xml"))
2782
KoStoreDevice contentDev( store );
2783
KoXmlWriter& settingsWriter = *createOasisXmlWriter(&contentDev, "office:document-settings");
2785
saveOasisSettings( settingsWriter );
2787
delete &settingsWriter;
2792
manifestWriter->addManifestEntry("settings.xml", "text/xml");
2797
// can't be const due to recalcVariables()
2798
QDragObject* KWDocument::dragSelected( QWidget* parent, KWTextFrameSet* fs )
2800
// We'll create a store (ZIP format) in memory
2802
QCString mimeType = KWOasisSaver::selectionMimeType();
2803
KoStore* store = KoStore::createStore( &buffer, KoStore::Write, mimeType );
2805
Q_ASSERT( !store->bad() );
2806
KoOasisStore oasisStore( store );
2808
KoXmlWriter* manifestWriter = oasisStore.manifestWriter( mimeType );
2812
if ( !saveOasis( store, manifestWriter, KWDocument::SaveSelected, &plainText, &picture, fs )
2813
|| !oasisStore.closeManifestWriter() )
2821
KMultipleDrag* multiDrag = new KMultipleDrag( parent );
2822
if ( !plainText.isEmpty() )
2823
multiDrag->addDragObject( new QTextDrag( plainText, 0 ) );
2824
if ( !picture.isNull() )
2825
multiDrag->addDragObject( picture.dragObject( 0 ) );
2826
KoStoreDrag* storeDrag = new KoStoreDrag( KWOasisSaver::selectionMimeType(), 0 );
2827
kdDebug() << k_funcinfo << "setting zip data: " << buffer.buffer().size() << " bytes." << endl;
2828
storeDrag->setEncodedData( buffer.buffer() );
2829
multiDrag->addDragObject( storeDrag );
2833
void KWDocument::saveSelectedFrames( KoXmlWriter& bodyWriter, KoStore* store, KoXmlWriter* manifestWriter,
2834
KoSavingContext& savingContext, QValueList<KoPictureKey>& pictureList,
2835
QString* plainText ) const
2837
QPtrList<KoDocumentChild> embeddedObjects;
2839
QPtrListIterator<KWFrameSet> fit = framesetsIterator();
2840
for ( ; fit.current() ; ++fit ) {
2841
KWFrameSet * fs = fit.current();
2842
if ( fs->isVisible() && fs->type() == FT_PART
2843
&& fs->frameIterator().getFirst()->isSelected() ) {
2844
embeddedObjects.append( static_cast<KWPartFrameSet *>(fs)->getChild() );
2848
fit = framesetsIterator();
2849
for ( ; fit.current() ; ++fit )
2851
KWFrameSet * fs = fit.current();
2852
if ( fs->isVisible() )
2854
bool isTable = ( fs->type() == FT_TABLE );
2855
if ( fs->type() == FT_PART )
2857
QPtrListIterator<KWFrame> frameIt = fs->frameIterator();
2858
KWFrame * firstFrame = frameIt.current();
2859
for ( ; frameIt.current(); ++frameIt )
2861
KWFrame * frame = frameIt.current();
2862
if ( frame->isSelected() )
2864
kdDebug(32001) << "Selected frame " << frame << " from " << fs->getName() << endl;
2865
// Two cases to be distinguished here
2866
// If it's the first frame of a frameset, then copy the frameset contents and the frame itself
2867
// Otherwise copy only the frame information
2868
if ( frame == firstFrame || isTable )
2870
fs->saveOasis( bodyWriter, savingContext, /*TODO: check this: isTable ? true :*/ false );
2872
*plainText += fs->toPlainText();
2874
else if ( !isTable )
2877
// Save the frame information
2878
QDomElement frameElem = parentElem.ownerDocument().createElement( "FRAME" );
2879
parentElem.appendChild( frameElem );
2880
frame->save( frameElem );
2881
if ( frame != firstFrame )
2883
// Frame saved alone -> remember which frameset it's part of
2884
frameElem.setAttribute( "parentFrameset", fs->getName() );
2888
if ( fs->type() == FT_PICTURE ) {
2889
kdDebug(32001) << "found non-inline picture framesets" << endl;
2891
const KoPictureKey key = static_cast<KWPictureFrameSet *>( fs )->key();
2892
if ( !pictureList.contains( key ) )
2893
pictureList.append( key );
2895
if ( isTable ) // Copy tables only once, even if they have many cells selected
2902
// Save embedded objects - code inspired from KoDocument::saveChildrenOasis
2903
QPtrListIterator<KoDocumentChild> chl( embeddedObjects );
2904
for( ; chl.current(); ++chl ) {
2905
KoDocument* childDoc = chl.current()->document();
2908
if ( !childDoc->isStoredExtern() ) {
2909
if ( !chl.current()->saveOasisToStore( store, manifestWriter ) )
2912
//assert( childDoc->url().protocol() == INTERNAL_PROTOCOL );
2913
path = store->currentDirectory();
2914
if ( !path.isEmpty() )
2916
path += childDoc->url().path();
2918
path = childDoc->url().url();
2920
manifestWriter->addManifestEntry( path, childDoc->nativeOasisMimeType() );
2925
void KWDocument::saveOasisSettings( KoXmlWriter& settingsWriter ) const
2927
settingsWriter.startElement("office:settings");
2928
settingsWriter.startElement("config:config-item-set");
2930
settingsWriter.addAttribute("config:name", "view-settings");
2932
KoUnit::saveOasis(&settingsWriter, m_unit);
2934
settingsWriter.endElement(); // config:config-item-set
2936
settingsWriter.startElement("config:config-item-set");
2937
settingsWriter.addAttribute("config:name", "configuration-settings");
2938
settingsWriter.addConfigItem("SpellCheckerIgnoreList", m_spellCheckIgnoreList.join( "," ) );
2939
settingsWriter.endElement(); // config:config-item-set
2941
m_varColl->variableSetting()->saveOasis( settingsWriter );
2943
settingsWriter.endElement(); // office:settings
2944
settingsWriter.endElement(); // Root element
2945
settingsWriter.endDocument();
2948
void KWDocument::saveOasisDocumentStyles( KoStore* store, KoGenStyles& mainStyles, KoSavingContext& savingContext, SaveFlag saveFlag ) const
2950
KoStoreDevice stylesDev( store );
2951
KoXmlWriter* stylesWriter = createOasisXmlWriter( &stylesDev, "office:document-styles" );
2953
stylesWriter->startElement( "office:styles" );
2955
if ( saveFlag == SaveAll )
2957
stylesWriter->startElement( "style:default-style" );
2958
stylesWriter->addAttribute( "style:family", "paragraph" );
2959
stylesWriter->startElement( "style:paragraph-properties" );
2960
stylesWriter->addAttributePt( "style:tab-stop-distance", m_tabStop );
2961
stylesWriter->endElement(); // paragraph-properties
2962
stylesWriter->endElement(); // default-style
2965
QValueList<KoGenStyles::NamedStyle> styles = mainStyles.styles( KoGenStyle::STYLE_USER );
2966
QValueList<KoGenStyles::NamedStyle>::const_iterator it = styles.begin();
2967
for ( ; it != styles.end() ; ++it ) {
2968
(*it).style->writeStyle( stylesWriter, mainStyles, "style:style", (*it).name, "style:paragraph-properties" );
2970
styles = mainStyles.styles( KoGenStyle::STYLE_LIST );
2971
it = styles.begin();
2972
for ( ; it != styles.end() ; ++it ) {
2973
(*it).style->writeStyle( stylesWriter, mainStyles, "text:list-style", (*it).name, 0 );
2975
m_styleColl->saveOasisOutlineStyles( *stylesWriter );
2976
if ( saveFlag == SaveAll )
2977
static_cast<KWVariableSettings *>( m_varColl->variableSetting() )->saveNoteConfiguration( *stylesWriter );
2978
stylesWriter->endElement(); // office:styles
2980
QString pageLayoutName;
2981
QByteArray headerFooters;
2982
if ( saveFlag == SaveAll )
2984
stylesWriter->startElement( "office:automatic-styles" );
2986
KoGenStyle pageLayout = m_pageLayout.saveOasis();
2987
pageLayout.addAttribute( "style:page-usage", "all" ); // needed?
2988
// This is for e.g. spreadsheets, not for word-processors.
2989
//pageLayout.addProperty( "style:first-page-number", m_varColl->variableSetting()->startingPage() );
2992
buffer.open( IO_WriteOnly );
2993
KoXmlWriter footnoteSepTmpWriter( &buffer ); // TODO pass indentation level
2994
footnoteSepTmpWriter.startElement( "style:footnote-sep" );
2996
switch( m_footNoteSeparatorLinePos )
3009
footnoteSepTmpWriter.addAttribute( "style:adjustment", tmp );
3010
footnoteSepTmpWriter.addAttributePt( "style:width", m_footNoteSeparatorLineWidth );
3011
footnoteSepTmpWriter.addAttribute( "style:rel-width", QString::number( footNoteSeparatorLineLength() ) + "%" );
3012
switch( m_footNoteSeparatorLineType )
3026
case SLT_DASH_DOT_DOT:
3027
tmp = "dot-dot-dash";
3031
footnoteSepTmpWriter.addAttribute( "style:line-style", tmp );
3033
footnoteSepTmpWriter.endElement();
3034
const QString elementContents = QString::fromUtf8( buffer.buffer(), buffer.buffer().size() );
3035
pageLayout.addChildElement( "separator", elementContents );
3038
if ( m_pageColumns.columns > 1 ) {
3039
buffer.setBuffer( QByteArray() ); // clear data
3040
buffer.open( IO_WriteOnly );
3041
KoXmlWriter columnsTmpWriter( &buffer ); // TODO pass indentation level
3042
columnsTmpWriter.startElement( "style:columns" );
3043
columnsTmpWriter.addAttribute( "fo:column-count", m_pageColumns.columns );
3044
columnsTmpWriter.addAttributePt( "fo:column-gap", m_pageColumns.ptColumnSpacing );
3045
columnsTmpWriter.endElement(); // style:columns
3047
const QString elementContents = QString::fromUtf8( buffer.buffer(), buffer.buffer().size() );
3048
pageLayout.addChildElement( "columns", elementContents );
3051
// This is a bit of a hack, which only works as long as we have only one page master
3052
// if there's more than one pagemaster we need to rethink all this
3054
pageLayoutName = mainStyles.lookup( pageLayout, "pm" );
3055
pageLayout.writeStyle( stylesWriter, mainStyles, "style:page-layout", pageLayoutName,
3056
"style:page-layout-properties", false /*don't close*/ );
3058
// Header and footers save their content into master-styles/master-page, but their
3059
// styles into the page-layout automatic-style. To avoid splitting that code
3060
// in two places (and inconsistent iteration), we save both here, the content
3062
buffer.setBuffer( headerFooters );
3063
buffer.open( IO_WriteOnly );
3064
// Ouch another problem: there is only one header style in oasis
3065
// ##### can't have different borders for even/odd headers...
3066
bool headerStyleSaved = false;
3067
bool footerStyleSaved = false;
3068
KoXmlWriter headerFooterTmpWriter( &buffer ); // TODO pass indentation level
3069
QPtrListIterator<KWFrameSet> fit = framesetsIterator();
3070
for ( ; fit.current() ; ++fit ) {
3071
const KWFrameSet* fs = fit.current();
3072
if ( fs->isVisible() && // HACK to avoid saving [hidden] headers/footers framesets for now
3073
!fs->isFloating() &&
3075
fs->type() == FT_TEXT &&
3076
fs->isHeaderOrFooter() )
3079
headerFooterTmpWriter.startElement( fs->headerFooterTag() ); // e.g. style:header
3080
static_cast<const KWTextFrameSet *>(fs)->saveOasisContent( headerFooterTmpWriter, savingContext );
3081
headerFooterTmpWriter.endElement();
3083
KWFrame* frame = fs->frame(0);
3084
if ( fs->isAHeader() ) {
3085
if ( headerStyleSaved )
3087
stylesWriter->startElement( "style:header-style" );
3089
if ( footerStyleSaved )
3091
stylesWriter->startElement( "style:footer-style" );
3093
#if 0 // more code reuse, but harder to integrate
3095
hfStyle.addPropertyPt( "fo:min-height", frame->minFrameHeight() );
3096
frame->saveBorderProperties( hfStyle );
3097
frame->saveMarginProperties( hfStyle );
3100
stylesWriter->startElement( "style:header-footer-properties" );
3101
stylesWriter->addAttributePt( "fo:min-height", frame->minFrameHeight() );
3102
// TODO frame->saveBorderAttributes( *stylesWriter );
3103
frame->saveMarginAttributes( *stylesWriter );
3104
stylesWriter->endElement(); // header-footer-properties
3105
stylesWriter->endElement(); // header-style
3108
stylesWriter->endElement(); // style:page-layout
3109
stylesWriter->endElement(); // office:automatic-styles
3113
stylesWriter->startElement( "office:master-styles" );
3114
stylesWriter->startElement( "style:master-page" );
3115
stylesWriter->addAttribute( "style:name", "Standard" );
3116
stylesWriter->addAttribute( "style:page-layout-name", pageLayoutName );
3118
if ( isHeaderVisible() || isFooterVisible() ) { // ### TODO save them even when hidden (and not empty)?
3119
headerFooters.resize( headerFooters.size() + 1 );
3120
headerFooters[headerFooters.size()-1] = '\0';
3121
stylesWriter->addCompleteElement( headerFooters.data() );
3124
stylesWriter->endElement();
3125
stylesWriter->endElement(); // office:master-styles
3127
stylesWriter->endElement(); // root element (office:document-styles)
3128
stylesWriter->endDocument();
3129
delete stylesWriter;
3132
void KWDocument::saveOasisCustomFied( KoXmlWriter &writer )const
3134
bool customVariableFound = false;
3135
QPtrListIterator<KoVariable> it( m_varColl->getVariables() );
3136
for ( ; it.current() ; ++it )
3138
if ( it.current()->type() == VT_CUSTOM )
3140
if ( !customVariableFound )
3142
writer.startElement( "text:user-field-decls" );
3143
customVariableFound = true;
3145
//<text:user-field-decl office:value-type="string" office:string-value="dfddd" text:name="cvbcbcbx"/>
3146
writer.startElement( "text:user-field-decl" );
3147
writer.addAttribute( "office:value-type", "string" );
3148
writer.addAttribute( "office:string-value", static_cast<KoCustomVariable *>( it.current() )->value() );
3149
writer.addAttribute( "text:name", static_cast<KoCustomVariable*>( it.current() )->name() );
3150
writer.endElement();
3153
if ( customVariableFound )
3154
writer.endElement();
3157
void KWDocument::saveOasisBody( KoXmlWriter& writer, KoSavingContext& context ) const
3159
saveOasisCustomFied( writer );
3160
if ( m_processingType == WP ) {
3161
// Write out the main text frameset's contents
3162
KWTextFrameSet *frameset = dynamic_cast<KWTextFrameSet *>( m_lstFrameSet.getFirst() );
3164
frameset->saveOasisContent( writer, context );
3166
// Write out the other (non-inline) framesets
3167
QPtrListIterator<KWFrameSet> fit = framesetsIterator();
3168
++fit; // skip main text frameset
3169
for ( ; fit.current() ; ++fit ) {
3170
KWFrameSet* fs = fit.current();
3171
if ( !fs->isFloating() &&
3173
// footnotes already saved inline, header/footers elsewhere
3174
fs->frameSetInfo() == KWFrameSet::FI_BODY )
3176
fs->saveOasis( writer, context, true );
3180
} else { // DTP mode: all framesets are equal
3181
// write text:page-sequence, one item per page.
3182
writer.startElement( "text:page-sequence" );
3183
for ( int page = 0; page < m_pages; ++page )
3185
writer.startElement( "text:page" );
3186
// "pm" is a hack, see mainStyles.lookup( pageLayout, "pm" ) in saveOasis
3187
// [which currently happens afterwards...]
3188
writer.addAttribute( "text:master-page-name", "pm" );
3189
writer.endElement(); // text:page
3191
writer.endElement() ; // "text:page-sequence";
3192
// Now write the framesets
3193
QPtrListIterator<KWFrameSet> fit = framesetsIterator();
3194
for ( ; fit.current() ; ++fit ) {
3195
KWFrameSet* fs = fit.current();
3196
if ( !fs->isFloating() &&
3198
fs->frameSetInfo() == KWFrameSet::FI_BODY )
3200
fs->saveOasis( writer, context, true );
2304
3206
QDomDocument KWDocument::saveXML()
2306
3208
m_varColl->variableSetting()->setModificationDate(QDateTime::currentDateTime());