summaryrefslogtreecommitdiffstats
path: root/kword
diff options
context:
space:
mode:
Diffstat (limited to 'kword')
-rw-r--r--kword/AUTHORS4
-rw-r--r--kword/CHANGES409
-rw-r--r--kword/DEBUG15
-rw-r--r--kword/DESIGN129
-rw-r--r--kword/HACKING218
-rw-r--r--kword/KWAboutData.h65
-rw-r--r--kword/KWAnchor.cpp306
-rw-r--r--kword/KWAnchor.h85
-rw-r--r--kword/KWAnchorPos.h40
-rw-r--r--kword/KWBgSpellCheck.cpp60
-rw-r--r--kword/KWBgSpellCheck.h44
-rw-r--r--kword/KWCanvas.cpp2493
-rw-r--r--kword/KWCanvas.h488
-rw-r--r--kword/KWCollectFramesetsVisitor.cpp41
-rw-r--r--kword/KWCollectFramesetsVisitor.h41
-rw-r--r--kword/KWCommand.cpp2094
-rw-r--r--kword/KWCommand.h901
-rw-r--r--kword/KWConfig.cpp1118
-rw-r--r--kword/KWConfig.h203
-rw-r--r--kword/KWConfigFootNoteDia.cpp216
-rw-r--r--kword/KWConfigFootNoteDia.h58
-rw-r--r--kword/KWCreateBookmarkDia.cpp155
-rw-r--r--kword/KWCreateBookmarkDia.h65
-rw-r--r--kword/KWCreateBookmarkDiaBase.ui57
-rw-r--r--kword/KWDeleteDia.cpp90
-rw-r--r--kword/KWDeleteDia.h65
-rw-r--r--kword/KWDocStruct.cpp1264
-rw-r--r--kword/KWDocStruct.h353
-rw-r--r--kword/KWDocument.cpp5466
-rw-r--r--kword/KWDocument.h1020
-rw-r--r--kword/KWEditPersonnalExpression.cpp370
-rw-r--r--kword/KWEditPersonnalExpression.h70
-rw-r--r--kword/KWFactory.cpp87
-rw-r--r--kword/KWFactory.h46
-rw-r--r--kword/KWFactoryInit.cpp23
-rw-r--r--kword/KWFindReplace.cpp62
-rw-r--r--kword/KWFindReplace.h56
-rw-r--r--kword/KWFootNoteDia.cpp138
-rw-r--r--kword/KWFootNoteDia.h65
-rw-r--r--kword/KWFormulaFrameSet.cpp540
-rw-r--r--kword/KWFormulaFrameSet.h177
-rw-r--r--kword/KWFrame.cpp753
-rw-r--r--kword/KWFrame.h335
-rw-r--r--kword/KWFrameDia.cpp2490
-rw-r--r--kword/KWFrameDia.h224
-rw-r--r--kword/KWFrameLayout.cpp649
-rw-r--r--kword/KWFrameLayout.h119
-rw-r--r--kword/KWFrameList.cpp197
-rw-r--r--kword/KWFrameList.h111
-rw-r--r--kword/KWFrameSet.cpp1277
-rw-r--r--kword/KWFrameSet.h504
-rw-r--r--kword/KWFrameSetEdit.cpp68
-rw-r--r--kword/KWFrameSetEdit.h120
-rw-r--r--kword/KWFrameStyle.cpp289
-rw-r--r--kword/KWFrameStyle.h139
-rw-r--r--kword/KWFrameStyleManager.cpp671
-rw-r--r--kword/KWFrameStyleManager.h209
-rw-r--r--kword/KWFrameView.cpp481
-rw-r--r--kword/KWFrameView.h190
-rw-r--r--kword/KWFrameViewManager.cpp434
-rw-r--r--kword/KWFrameViewManager.h238
-rw-r--r--kword/KWImportStyleDia.cpp343
-rw-r--r--kword/KWImportStyleDia.h76
-rw-r--r--kword/KWInsertDia.cpp85
-rw-r--r--kword/KWInsertDia.h55
-rw-r--r--kword/KWInsertPageDia.cpp53
-rw-r--r--kword/KWInsertPageDia.h38
-rw-r--r--kword/KWInsertPicDia.cpp180
-rw-r--r--kword/KWInsertPicDia.h62
-rw-r--r--kword/KWInsertTOCCommand.cpp261
-rw-r--r--kword/KWInsertTOCCommand.h52
-rw-r--r--kword/KWLoadingInfo.cpp14
-rw-r--r--kword/KWLoadingInfo.h94
-rw-r--r--kword/KWMailMergeDataBase.cpp559
-rw-r--r--kword/KWMailMergeDataBase.h164
-rw-r--r--kword/KWMailMergeDataSource.cpp8
-rw-r--r--kword/KWMailMergeDataSource.h76
-rw-r--r--kword/KWMailMergeLabelAction.cpp152
-rw-r--r--kword/KWMailMergeLabelAction.h44
-rw-r--r--kword/KWOasisLoader.cpp358
-rw-r--r--kword/KWOasisLoader.h64
-rw-r--r--kword/KWOasisSaver.cpp158
-rw-r--r--kword/KWOasisSaver.h78
-rw-r--r--kword/KWPage.cpp139
-rw-r--r--kword/KWPage.h128
-rw-r--r--kword/KWPageManager.cpp251
-rw-r--r--kword/KWPageManager.h142
-rw-r--r--kword/KWPartFrameSet.cpp378
-rw-r--r--kword/KWPartFrameSet.h169
-rw-r--r--kword/KWPictureFrameSet.cpp258
-rw-r--r--kword/KWPictureFrameSet.h96
-rw-r--r--kword/KWResizeTableDia.cpp102
-rw-r--r--kword/KWResizeTableDia.h65
-rw-r--r--kword/KWSelectBookmarkDiaBase.ui76
-rw-r--r--kword/KWSortDia.cpp53
-rw-r--r--kword/KWSortDia.h38
-rw-r--r--kword/KWSplitCellDia.cpp97
-rw-r--r--kword/KWSplitCellDia.h56
-rw-r--r--kword/KWStartupWidget.cpp93
-rw-r--r--kword/KWStartupWidget.h62
-rw-r--r--kword/KWStartupWidgetBase.ui103
-rw-r--r--kword/KWStatisticsDialog.cpp354
-rw-r--r--kword/KWStatisticsDialog.h61
-rw-r--r--kword/KWStyleManager.cpp68
-rw-r--r--kword/KWStyleManager.h49
-rw-r--r--kword/KWTableDia.cpp366
-rw-r--r--kword/KWTableDia.h113
-rw-r--r--kword/KWTableFrameSet.cpp2943
-rw-r--r--kword/KWTableFrameSet.h747
-rw-r--r--kword/KWTableStyle.cpp219
-rw-r--r--kword/KWTableStyle.h131
-rw-r--r--kword/KWTableStyleManager.cpp716
-rw-r--r--kword/KWTableStyleManager.h156
-rw-r--r--kword/KWTableTemplate.cpp299
-rw-r--r--kword/KWTableTemplate.h145
-rw-r--r--kword/KWTableTemplateSelector.cpp680
-rw-r--r--kword/KWTableTemplateSelector.h126
-rw-r--r--kword/KWTextDocument.cpp327
-rw-r--r--kword/KWTextDocument.h73
-rw-r--r--kword/KWTextFrameSet.cpp4154
-rw-r--r--kword/KWTextFrameSet.h547
-rw-r--r--kword/KWTextImage.cpp161
-rw-r--r--kword/KWTextImage.h74
-rw-r--r--kword/KWTextParag.cpp859
-rw-r--r--kword/KWTextParag.h98
-rw-r--r--kword/KWVariable.cpp739
-rw-r--r--kword/KWVariable.h183
-rw-r--r--kword/KWView.cpp7756
-rw-r--r--kword/KWView.h879
-rw-r--r--kword/KWViewMode.cpp603
-rw-r--r--kword/KWViewMode.h297
-rw-r--r--kword/KWordDocIface.cpp639
-rw-r--r--kword/KWordDocIface.h195
-rw-r--r--kword/KWordFootNoteFrameSetIface.cpp54
-rw-r--r--kword/KWordFootNoteFrameSetIface.h48
-rw-r--r--kword/KWordFormulaFrameSetEditIface.cpp276
-rw-r--r--kword/KWordFormulaFrameSetEditIface.h101
-rw-r--r--kword/KWordFormulaFrameSetIface.cpp48
-rw-r--r--kword/KWordFormulaFrameSetIface.h45
-rw-r--r--kword/KWordFrameSetIface.cpp520
-rw-r--r--kword/KWordFrameSetIface.h104
-rw-r--r--kword/KWordMailMergeDatabaseIface.h52
-rw-r--r--kword/KWordPartFrameSetIface.cpp49
-rw-r--r--kword/KWordPartFrameSetIface.h43
-rw-r--r--kword/KWordPictureFrameSetIface.cpp47
-rw-r--r--kword/KWordPictureFrameSetIface.h47
-rw-r--r--kword/KWordTableFrameSetIface.cpp87
-rw-r--r--kword/KWordTableFrameSetIface.h51
-rw-r--r--kword/KWordTextFrameSetEditIface.cpp161
-rw-r--r--kword/KWordTextFrameSetEditIface.h58
-rw-r--r--kword/KWordTextFrameSetIface.cpp310
-rw-r--r--kword/KWordTextFrameSetIface.h102
-rw-r--r--kword/KWordViewIface.cpp466
-rw-r--r--kword/KWordViewIface.h151
-rw-r--r--kword/Makefile.am94
-rw-r--r--kword/OASIS72
-rw-r--r--kword/TODO60
-rw-r--r--kword/data/Makefile.am2
-rw-r--r--kword/data/framestyles.xml108
-rw-r--r--kword/data/tablestyles.xml53
-rw-r--r--kword/data/tabletemplates.xml62
-rw-r--r--kword/defs.h84
-rw-r--r--kword/demos/DTPTest.kwt380
-rw-r--r--kword/demos/bidi.kwdbin0 -> 3155 bytes
-rw-r--r--kword/demos/chapters.kwd1541
-rw-r--r--kword/demos/eurosign.kwd260
-rw-r--r--kword/demos/flatland.kwdbin0 -> 105355 bytes
-rw-r--r--kword/demos/framestest.kwd710
-rw-r--r--kword/demos/mars.kwdbin0 -> 222700 bytes
-rw-r--r--kword/demos/statistics.kwdbin0 -> 2033 bytes
-rw-r--r--kword/dtd/DEBUG11
-rw-r--r--kword/dtd/Makefile.am16
-rw-r--r--kword/dtd/framestyles.dtd52
-rw-r--r--kword/dtd/kword.dtd1426
-rw-r--r--kword/dtd/tablestyles.dtd29
-rw-r--r--kword/dtd/tabletemplates.dtd57
-rw-r--r--kword/expression/Makefile.am4
-rw-r--r--kword/expression/expression.xml114
-rw-r--r--kword/horizontalline/Makefile.am4
-rw-r--r--kword/horizontalline/line.pngbin0 -> 275 bytes
-rw-r--r--kword/kwmailmerge.desktop71
-rw-r--r--kword/kword.desktop81
-rw-r--r--kword/kword.rc511
-rw-r--r--kword/kword_readonly.rc58
-rw-r--r--kword/kwordmailmergedatabaseiface.cpp31
-rw-r--r--kword/kwordpart.desktop102
-rw-r--r--kword/mailmerge/KWClassicSerialDataSource.cpp569
-rw-r--r--kword/mailmerge/KWClassicSerialDataSource.h172
-rw-r--r--kword/mailmerge/Makefile.am22
-rw-r--r--kword/mailmerge/configure.in.in41
-rw-r--r--kword/mailmerge/kabc/KWMailMergeKABC.cpp551
-rw-r--r--kword/mailmerge/kabc/KWMailMergeKABC.h185
-rw-r--r--kword/mailmerge/kabc/KWMailMergeKABCConfig.cpp546
-rw-r--r--kword/mailmerge/kabc/KWMailMergeKABCConfig.h149
-rw-r--r--kword/mailmerge/kabc/Makefile.am17
-rw-r--r--kword/mailmerge/kabc/addresspicker.ui297
-rw-r--r--kword/mailmerge/kabc/kwmailmerge_kabc.desktop105
-rw-r--r--kword/mailmerge/kspread/Makefile.am16
-rw-r--r--kword/mailmerge/kspread/kwmailmerge_kspread.cpp211
-rw-r--r--kword/mailmerge/kspread/kwmailmerge_kspread.desktop101
-rw-r--r--kword/mailmerge/kspread/kwmailmerge_kspread.h106
-rw-r--r--kword/mailmerge/kspread/kwmailmerge_kspread_config.cpp125
-rw-r--r--kword/mailmerge/kspread/kwmailmerge_kspread_config.h61
-rw-r--r--kword/mailmerge/kwserialletter_classic.desktop122
-rw-r--r--kword/mailmerge/sql/KWMySqlCursor.h69
-rw-r--r--kword/mailmerge/sql/KWQtSqlEasyFilter.cpp98
-rw-r--r--kword/mailmerge/sql/KWQtSqlEasyFilter.h29
-rw-r--r--kword/mailmerge/sql/KWQtSqlMailMergeOpen.cpp123
-rw-r--r--kword/mailmerge/sql/KWQtSqlMailMergeOpen.h57
-rw-r--r--kword/mailmerge/sql/KWQtSqlPowerSerialDataSource.cpp256
-rw-r--r--kword/mailmerge/sql/KWQtSqlPowerSerialDataSource.h96
-rw-r--r--kword/mailmerge/sql/KWQtSqlSerialDataSource.cpp218
-rw-r--r--kword/mailmerge/sql/KWQtSqlSerialDataSource.h85
-rw-r--r--kword/mailmerge/sql/KWQtSqlSerialDataSourceBase.cpp105
-rw-r--r--kword/mailmerge/sql/KWQtSqlSerialDataSourceBase.h63
-rw-r--r--kword/mailmerge/sql/Makefile.am28
-rw-r--r--kword/mailmerge/sql/kwqtsqlpower.ui233
-rw-r--r--kword/mailmerge/sql/kwserialletter_qtsqldb.desktop106
-rw-r--r--kword/mailmerge/sql/kwserialletter_qtsqldb_power.desktop107
-rw-r--r--kword/mailmerge/sql/qtsqldatasourceeditor.ui158
-rw-r--r--kword/mailmerge/sql/qtsqldatasourceeditor.ui.h13
-rw-r--r--kword/mailmerge/sql/qtsqlopenwidget.ui301
-rw-r--r--kword/main.cpp43
-rw-r--r--kword/pics/Makefile.am3
-rw-r--r--kword/pics/hi16-app-kword.pngbin0 -> 1062 bytes
-rw-r--r--kword/pics/hi22-app-kword.pngbin0 -> 1367 bytes
-rw-r--r--kword/pics/hi32-app-kword.pngbin0 -> 2322 bytes
-rw-r--r--kword/pics/hi48-app-kword.pngbin0 -> 3919 bytes
-rw-r--r--kword/stylenames.cpp74
-rw-r--r--kword/templates/CardsAndLabels/.directory47
-rw-r--r--kword/templates/CardsAndLabels/BusinessCards10.desktop55
-rw-r--r--kword/templates/CardsAndLabels/BusinessCards10.kwtbin0 -> 2842 bytes
-rw-r--r--kword/templates/CardsAndLabels/LabelsL16.desktop56
-rw-r--r--kword/templates/CardsAndLabels/LabelsL16.kwtbin0 -> 3044 bytes
-rw-r--r--kword/templates/CardsAndLabels/Makefile.am11
-rw-r--r--kword/templates/CardsAndLabels/cr48-action-template_businesscards10.pngbin0 -> 812 bytes
-rw-r--r--kword/templates/CardsAndLabels/cr48-action-template_labelsl16.pngbin0 -> 950 bytes
-rw-r--r--kword/templates/CardsAndLabels/crsc-action-template_businesscards10.svgzbin0 -> 1545 bytes
-rw-r--r--kword/templates/CardsAndLabels/crsc-action-template_labelsl16.svgzbin0 -> 1581 bytes
-rw-r--r--kword/templates/Envelopes/.directory48
-rw-r--r--kword/templates/Envelopes/EnvelopeC6.desktop57
-rw-r--r--kword/templates/Envelopes/EnvelopeC6.kwt250
-rw-r--r--kword/templates/Envelopes/EnvelopeDL.desktop57
-rw-r--r--kword/templates/Envelopes/EnvelopeDL.kwt267
-rw-r--r--kword/templates/Envelopes/Makefile.am11
-rw-r--r--kword/templates/Envelopes/cr48-action-template_envelopec6.pngbin0 -> 1114 bytes
-rw-r--r--kword/templates/Envelopes/cr48-action-template_envelopedl.pngbin0 -> 1062 bytes
-rw-r--r--kword/templates/Envelopes/crsc-action-template_envelopec6.svgzbin0 -> 1500 bytes
-rw-r--r--kword/templates/Envelopes/crsc-action-template_envelopedl.svgzbin0 -> 1487 bytes
-rw-r--r--kword/templates/Makefile.am1
-rw-r--r--kword/templates/Wordprocessing/.directory46
-rw-r--r--kword/templates/Wordprocessing/A4.desktop85
-rw-r--r--kword/templates/Wordprocessing/A4.kwt84
-rw-r--r--kword/templates/Wordprocessing/ColorfulA4.desktop84
-rw-r--r--kword/templates/Wordprocessing/ColorfulA4.odtbin0 -> 5778 bytes
-rw-r--r--kword/templates/Wordprocessing/ColorfulLetter.desktop84
-rw-r--r--kword/templates/Wordprocessing/ColorfulLetter.odtbin0 -> 5848 bytes
-rw-r--r--kword/templates/Wordprocessing/FaxA4.desktop98
-rw-r--r--kword/templates/Wordprocessing/FaxA4.odtbin0 -> 5765 bytes
-rw-r--r--kword/templates/Wordprocessing/FaxLetter.desktop98
-rw-r--r--kword/templates/Wordprocessing/FaxLetter.odtbin0 -> 5880 bytes
-rw-r--r--kword/templates/Wordprocessing/Letter.desktop86
-rw-r--r--kword/templates/Wordprocessing/Letter.kwt84
-rw-r--r--kword/templates/Wordprocessing/Makefile.am13
-rw-r--r--kword/templates/Wordprocessing/Memo.desktop69
-rw-r--r--kword/templates/Wordprocessing/Memo.kwt806
-rw-r--r--kword/templates/Wordprocessing/PlainText.kwt85
-rw-r--r--kword/templates/Wordprocessing/ProfessionalA4.desktop85
-rw-r--r--kword/templates/Wordprocessing/ProfessionalA4.odtbin0 -> 4204 bytes
-rw-r--r--kword/templates/Wordprocessing/ProfessionalLetter.desktop85
-rw-r--r--kword/templates/Wordprocessing/ProfessionalLetter.odtbin0 -> 4218 bytes
-rw-r--r--kword/templates/Wordprocessing/TwoColumns.desktop114
-rw-r--r--kword/templates/Wordprocessing/TwoColumns.kwt85
-rw-r--r--kword/templates/Wordprocessing/TwoColumnsLetter.desktop110
-rw-r--r--kword/templates/Wordprocessing/TwoColumnsLetter.kwt85
-rw-r--r--kword/templates/Wordprocessing/cr128-action-template_colorful.pngbin0 -> 14622 bytes
-rw-r--r--kword/templates/Wordprocessing/cr48-action-template_a4.pngbin0 -> 1078 bytes
-rw-r--r--kword/templates/Wordprocessing/cr48-action-template_colorful.pngbin0 -> 4997 bytes
-rw-r--r--kword/templates/Wordprocessing/cr48-action-template_fax.pngbin0 -> 1108 bytes
-rw-r--r--kword/templates/Wordprocessing/cr48-action-template_letter.pngbin0 -> 1095 bytes
-rw-r--r--kword/templates/Wordprocessing/cr48-action-template_memo.pngbin0 -> 1140 bytes
-rw-r--r--kword/templates/Wordprocessing/cr48-action-template_plaintext.pngbin0 -> 1022 bytes
-rw-r--r--kword/templates/Wordprocessing/cr48-action-template_twocolumns.pngbin0 -> 1606 bytes
-rw-r--r--kword/templates/Wordprocessing/crsc-action-template_a4.svgzbin0 -> 1620 bytes
-rw-r--r--kword/templates/Wordprocessing/crsc-action-template_fax.svgzbin0 -> 1869 bytes
-rw-r--r--kword/templates/Wordprocessing/crsc-action-template_letter.svgzbin0 -> 1630 bytes
-rw-r--r--kword/templates/Wordprocessing/crsc-action-template_memo.svgzbin0 -> 2139 bytes
-rw-r--r--kword/templates/Wordprocessing/crsc-action-template_plaintext.svgzbin0 -> 1604 bytes
-rw-r--r--kword/templates/Wordprocessing/crsc-action-template_twocolumns.svgzbin0 -> 1703 bytes
-rwxr-xr-xkword/templates/make_template.pl35
-rw-r--r--kword/tests/FrameTester.cpp152
-rw-r--r--kword/tests/FrameTester.h59
-rw-r--r--kword/tests/FrameViewTester.cpp295
-rw-r--r--kword/tests/FrameViewTester.h27
-rw-r--r--kword/tests/KWPageManagerTester.cpp320
-rw-r--r--kword/tests/KWPageManagerTester.h30
-rw-r--r--kword/tests/Makefile.am25
-rw-r--r--kword/tests/README26
-rwxr-xr-xkword/tests/checkFilter.pl52
-rw-r--r--kword/tests/oasis-kword.sh108
-rw-r--r--kword/toolbar/Makefile.am3
-rw-r--r--kword/toolbar/cr22-action-run_bounding.pngbin0 -> 740 bytes
-rw-r--r--kword/toolbar/cr22-action-run_not.pngbin0 -> 638 bytes
-rw-r--r--kword/toolbar/cr22-action-run_skip.pngbin0 -> 601 bytes
-rw-r--r--kword/toolbar/cr22-action-sl_addentry.pngbin0 -> 391 bytes
-rw-r--r--kword/toolbar/cr22-action-sl_addrecord.pngbin0 -> 412 bytes
-rw-r--r--kword/toolbar/cr22-action-sl_delentry.pngbin0 -> 371 bytes
-rw-r--r--kword/toolbar/cr22-action-sl_delrecord.pngbin0 -> 390 bytes
308 files changed, 77484 insertions, 0 deletions
diff --git a/kword/AUTHORS b/kword/AUTHORS
new file mode 100644
index 00000000..ecb41bc6
--- /dev/null
+++ b/kword/AUTHORS
@@ -0,0 +1,4 @@
+Reginald Stadlbauer <reggie@kde.org> Initial designer and overall main man
+Thomas Zander <zander@kde.org> Done much work on frames
+David Faure <faure@kde.org> Port to QRT, current maintainer
+
diff --git a/kword/CHANGES b/kword/CHANGES
new file mode 100644
index 00000000..70151163
--- /dev/null
+++ b/kword/CHANGES
@@ -0,0 +1,409 @@
+Changes after KWord-1.4
+=======================
+- OASIS OpenDocument support:
+ Fixed loading of headers and footers (#107424)
+ Implemented saving of headers and footers
+ Fix for text:h without outline-level
+ Simplified the XML by removing spurious <span> tags due to misspelled words
+ Save office:font-face-decls tag so that OOo loads the fonts
+ Fixed loading of font sizes specified as a percentage
+ Implemented loading of list indentation (space-before) (#109223)
+ Improved OOo compatibility when saving page breaks
+ Save first page number the right way so that OOo can load it
+- Text layouting: fix for formatting of multi-frame paragraphs (#65059)
+- Overwrite mode (activated with the "Insert" key)
+
+Changes after KWord-1.4-beta1
+=============================
+- Fixed crash when editing a cell on loading (#104982).
+- Many footnotes bugs have been solved (#85148,, #72506, #57298, #62360, #84678).
+- Show the content of the footnote/endnote in the status barwhen the mouse cursor is placed over a footnote/endnote reference (part of feature #48794).
+- Added an apply button to the frame property and the resize column dialog.
+- Added a reset button to the resize column dialog.
+- Resize column dialog: the maximum width for a cell is the width of the table's parent frame if the table is floating.
+- All KDoubleNumInputs have been replaced KoUnitDoubleSpinBoxes.
+- Disable the formula toolbar from start if no formula frame is activated.
+
+Changes between KWord-1.3.x and KWord-1.4-beta1
+===============================================
+See ../changes-1.4-beta1
+
+Changes between KWord 1.3.2 and 1.3.3
+=====================================
+- Fix the 3 style menus for any translation (#61007)
+- OASIS: proper loading/saving of inline tables
+- Disable creation of non-inline tables
+- OASIS: default tab width
+
+Changes after KWord-1.3
+=======================
+- Reorganized and simplified GUI of the configuration dialog
+- Support for "protect content" in all types of framesets
+- Support for different run-around-gaps on every side of the frame
+- Use kspell2
+- Copy/paste between kword/kpresenter
+- Add statistic variable
+
+Changes between KWord-1.3-rc and KWord-1.3
+==========================================
+- Fixed swapped resize mouse cursors with Qt-3.1.2
+- Fixed table column resizing (avoid overlapping columns)
+
+Changes after KWord 1.3 rc (1.2.94)
+===================================
+- Fixed crash in table operations (#66349)
+- Fixed crash in table iterator
+- Fixed "edit frameset" for tables in doc structure panel (#67084)
+- Save "no underline" explicitely if the paraglayout says "underline" but the
+ user removed the underline (#67735)
+- Fixed successive image DnD
+- Fixed the default document font (#69166)
+
+Changes after KWord 1.3 beta4
+=============================
+- fix for frames extending beyond the page getting the wrong size in 'preview mode'
+- Fixed wrong layouting of inline frames (e.g. pictures)
+- Don't select inline frame after pasting text containing it (only select non-inline frames)
+- Improved "create style from selection": use format at cursor if no selection,
+ allow to type the name of an existing style to update it, and select the style
+ for the current paragraph after creating it.
+
+Changes after KWord-1.3-beta3
+=============================
+- Fixed handling of part frames (clicking didn't select it anymore, #63041)
+- Fixed cursor shape when pressing Ctrl.
+- Unbreak text view mode (cursor disappeared, #57554)
+
+Changes after KWord-1.3-beta2
+=============================
+- Right-click on a selected frame shouldn't unselect it
+- Esc to deselect all frames
+- Fixed line-height bug due to hyphenation
+- Make the text view mode work again
+- Fix "frame borders always painted/printed even when off" (#45907)
+
+Changes after KWord-1.3-beta1
+=============================
+
+- Frames default to "auto-resize" mode instead of "auto-create-new-page"
+- Better handing of "auto-resize" mode (manually-set size acts as minimum size)
+- Make the find dialog avoid the area where the match is (requires kdelibs-CVS, will be in kde-3.2)
+- New: PDF import filter
+(see also koffice/lib/CHANGES, especially the kotext part)
+
+Changes after KWord-1.2
+=======================
+- Spellchecker can spell check only a selection
+- Shadow is a character property
+- Language added as a new character property
+- Paragraph numbering: simple lists are not restarted by simple text in between
+- Paragraph numbering: new properties "restart numbering at this paragraph",
+ "number of parent levels to display".
+- Add "copy link"
+- Add "Add to bookmark"
+- Now we can change "picture path" / "personal expression path"
+- Add "Remove link"
+- Add font properties : change relative font size when we sub/super script font
+- Add support to add offset from baseline
+- Now koinsertlink use "Recent document".
+- Add support to insert directly cursor
+- Add support for "word by word" format attribute.
+- Add new variable : Next page number, previous page number
+- Add time/date variable offset
+- Fix #24242 add variable : created/modified/printed document date
+- Now we can copy text of comment.
+- Add support for convert table to text
+- Add support for font attribute ( lowercase/uppercase )
+- Add double click on frame => open frame dialogbox
+- Add autocorrection : "Capitalize name of days"
+- New font attribute : small caps
+- The list of words to be ignored by the spellchecker can be edited
+- Add support for convert text to textbox
+- Now we can add/remove word in personal dictionary
+- The path where backup files are saved is now configurable
+- Improve statistics dialogbox : count number of lines.
+- The user can more easily add personal expressions to be inserted
+- New types of line spacing: "At least"/"Multiple"
+- Add horizontal line
+- Text can be sorted
+- Use new kospell API
+- Now right button gives spell check result
+- Load pictures only one time when inserting from file (Good for remote files)
+- Hyphenation support. Configurable as a character property (to disable hyphenation on specific words).
+- New checkbox in the style manager: "Include in table of contents".
+
+
+Changes between KWord-1.2-RC1 and KWord-1.2
+===========================================
+Bugfixes:
+- Fix update ruler tabs when we switch between text object
+- Fix move up/down table/frame style
+- Fix restore shortcut when we remove/add/rename style
+- Fix restore shortcut when we remove/move/add/rename frame/table style
+- Fix update resize handle when we change cell border
+- Fix update resize handle when we change frame/table style.
+
+KoText library fixes:
+- Fix move up/down style
+- Fix crash when we create a new style and delete this style.
+
+Layout:
+- Fixed layout of paragraph numbering in Right-To-Left mode.
+- First line indent is now from the right in Right-To-Left mode.
+
+Crashes:
+- Fixed crash when removing pages (and the page number is shown in header/footer)
+
+
+Changes between KWord-1.2-beta2 and KWord-1.2-RC1
+===================================================
+New:
+- Like all of KOffice: a readonly GUI for embedding into Konqueror
+- More DCOP calls
+
+Layout/painting fixes:
+- Fixed WYSIWYG algorithm, no more negative spaces at some zoom levels.
+- Transparency painting fixes: transparent frames, including text frames.
+Note that transparent images do not print properly with the current Qt, Qt 3.1 will fix it.
+- Footnote layout fix, when multiple footnotes are on the same page and the last one won't fit
+- Improved algorithm for the way the text flows between frames of the same frameset.
+- Zigzag lines for background checked words
+- Fixed paragraph height increasing when inserting a footnote.
+- Fixed the white lines during the painting of inline frames
+- Fixed footer layout in some first/even/odd footer settings
+- Fixed baseline alignment for variables
+- Delete overflowing frame (in auto-resize mode) when removing text from it
+- Compress repaint events coming from the background spell-checking
+
+Bugfixes:
+- Several fixes for the readonly case
+- Unified picture handling (images and cliparts)
+- Improvements to frame dialog when opened for multiple frames, many crashes fixed.
+- Fixed frame-creation rectangle remaining visible in margin after right click.
+- Many fixes for the background spellchecking
+- Many fixes for "Insert File" (pictures, embedded objects, inline frames...)
+- Ability to use the text view mode for any text frameset
+- Embedded document must be selected before clicking on them starts editing them.
+- More KOffice-1.1 compatibility on saving (when explicitely requested)
+- Save correct variable value even when variable codes are displayed.
+- When making an inline frame non-inline, ensure it appears on top (bigger z-order)
+- 'Copy' exports paragraph numbers with the text.
+- Keep key shortcuts when rebuilding dynamic menus (e.g. style lists)
+- Fixed 'raise frame' and 'lower frame' (handle equality case)
+- Several GUI fixes
+- No header/footer configuration in DTP mode
+- No page layout, frame resizing etc. in the text view mode.
+- More robustness in DCOP calls (to prevent crashes)
+- Faster pasting of text
+- Fix use keyboard when frameset is protect content.
+- Fix reload PgUp and PgDn config
+- Fixed disappearing frame after undoing deletion of inline frame
+- Inserting a non-inline table makes the text flow around it by default
+
+KoText library fixes:
+- Fixed preview in paragraph dialog (was truncated)
+- Fixed font size applied by "Find/Replace with formatting" and "Autocorrection with formatting".
+- Fixed background color not applied by "Find/Replace with formatting".
+- Fixed crash when we remove "autocorrect word formatted"
+- Fixed mem leak in autocorrect dialogbox (autocorrect list was not deleted )
+- Fixed non/working undo/redo when changing paragraph settings for a whole text frameset
+- Fixed calculation of centering (visible on very short paragraphs)
+- The height of the cursor now depends on the character on the left of the cursor
+(instead of being as high as the biggest char in the paragraph).
+
+Crashes:
+- Do not crash when pasting an embedded object (not implemented though)
+- Fixed crash when removing a footnote variable
+- Fixed crash when we close kword and "special char dialogbox" is not closed
+- Fixed several problems with footnote layout
+- Fixed crash when we delete style that is also used as a 'following style'.
+- Fixed crash with bookmarks
+- Fixed several memory leaks
+- Fixed crash when we canceled create time/date variable.
+
+
+Changes between KWord-1.2-beta1 and KWord-1.2-beta2
+===================================================
+- Footnotes
+- "Apply autoformat" feature
+- Extended Find/Replace to allow specifying text formatting
+- Support for frame margins
+- Support for frame "runaround gap"
+- Choice of which side of the frame the text should run around (left, right, biggest)
+- Creating a style directly from the selection
+- Paragraph selection, clicking on the left of the text frame
+- "Protect content" feature
+- Double line border type for frames and paragraphs
+- New dialogbox to resize a column in a table
+- Add new font format (improve underline, strikeout )
+- Add support to protect frameset size and position.
+- Fix the loading, displaying and saving of old images (KOffice 1.0 type)
+- The default width used by tab stops is now configurable
+- Headers and footers can be both "different on first page" and "different
+ on odd/even pages" at the same time.
+- Ability to save an image from a document to the disk
+- Cursor position is saved into the file, to restore it when reopening the document
+- The "text" view mode is finally operational.
+- Add option "Enable cursor in protected text object"
+- Now we can configure which type of formatting char we want to display
+- Now we can configure footnote line separator
+- Add support for framestyle (borders and backgroundcolor)
+- Creating a framestyle from a selected frame
+- Add support for tablestyles (combination of framestyle and style)
+- Add templates for tables (built up from tablestyles)
+- Add support to insert Native file
+- Import frame/table style from file
+- Import text style from file
+- Add display field code ( for variable)
+- We can change autoformat language
+- Painting of transparent images
+- Fixed handling of embedded documents
+
+
+Changes between KWord-1.1.1 and KWord-1.2-beta1
+===============================================
+
+Text layout and painting redesigned around WYSIWYG concept.
+KWord is also BiDi-enabled.
+
+Soft hyphens (inserted with Ctrl+'-')
+Non-breakable-spaces (inserted with Ctrl+' ' or menuitem)
+Support for hyperlinks, for text background color (marker).
+Improved handling of tabulators in ruler.
+Auto-hide mouse cursor while typing.
+
+"Change picture" feature.
+SVG support (for cliparts).
+Module for SVG previews in Konqueror.
+
+Rewrite of tables where positioning is much more fool-proof and table-borders actually work.
+More intelligent table-cell-scaling for cells with mixed text lengths
+
+Text shadow feature.
+Double-underline feature.
+Ability to choose where to inline a frame.
+Setting tabs via the rulers is more intuitive.
+Add link (internet link/ address mail / file link)
+Add dcop interface : now we can insert text, change text format, etc...
+Frame z-order ("Raise frame", "Lower frame")
+Preliminary support for background spell checking
+Support for manual completion (use CTRL+E)
+Support for note
+Ability to associate key shortcuts to styles
+"Section Title" variable
+
+Triple click selects a paragraph.
+New "PageUp/PageDown moves the caret" option, which defaults to false.
+ The new behaviour for PageUp/PageDown is to move the scrollbars, not the caret.
+
+
+Changes between KWord-1.1 and KWord-1.1.1
+=========================================
+Fixed crash when undoing "apply a style" (QTextFormatCommand, #34556)
+Fixed printing from preview mode
+Fixed default value for runaround when loading a frame.
+Save all frames of the main frameset even in WP mode (to keep borders etc.)
+Fixed list of allowed image formats in image selector dialog
+Fixed crash with Ctrl+K on empty paragraph
+Fixed consecutive tab problems
+Workaround for slow clipboard format checking in Qt2
+Hack around Tru64-compiler bug (KWTextFormat::~KWTextFormat())
+
+
+Changes between KWord-1.1-beta3 and KWord-1.1-rc1
+=================================================
+
+Improved auto-scrolling.
+[...]
+
+
+Changes between KWord-1.1-beta2 and KWord-1.1-beta3
+===================================================
+
+New view mode: preview (multiple pages per row)
+Inline items (variables, images, frames) are now correctly drawn when selected,
+can be made non-inline and back.
+Improved readonly mode, when embedding into konqueror (can now select and copy).
+Insert Frame/Page Break feature added (also as part of styles).
+Apply button added to the stylist.
+Zoom value can be set arbitrarily by the user (editable combobox).
+Auto-correction, typographical quotes.
+Formatting Characters feature.
+"1.5 lines" and "double" linespacing (also as part of styles).
+Insertion of predefined expressions (configurable).
+Auto-switching between editing of text and editing of frames.
+All types of frames can be set as "copy".
+Flesch reading ease score and enhanced layout added to the statistics dialog.
+Insert clipart (WMF).
+More spellchecking options (needs kdelibs-2.2-cvs).
+Added the ability for frames to grow and shrink when more or less text flows in them.
+Added undo-redo availability to many user-actions.
+New bullets-numbering dialog (visible in the stylist and the paragraph editor)
+Enhanced context-menus (Right mouse buttons popup)
+Added the possibility to change the case (capitals) of a selection of text.
+
+Useability improvements (better mouse selection, a few new keybindings).
+Custom variables appear in a submenu.
+Major speedups for long documents (paragraph formatting, loading),
+and painting fixes.
+Fixed recalculation of "page number" variable in header or footer.
+Painting and run-around-frame fixes (e.g. in multi-columns mode).
+Fixes for the creation and removal of pages.
+Fixed crash when embedding into Konqueror.
+Fixed Table Of Contents creation and updates.
+Fixed placement and drawing of tables.
+Many other fixes, this list is far from complete.
+
+
+Changes between KWord-1.1-beta1 and KWord-1.1-beta2
+===================================================
+
+Copying frames has been implemented, fixing headers and footers.
+Implemented tabulators (left/right/center/decimal aligned).
+Implemented floating framesets, mainly for inline formulas and tables.
+KWord can now be embedded into another KOffice application.
+More precise coordinate system (especially for frames).
+Many improvements for tables (including splitting and merging cells).
+Highlight mispelled word during spell-checking, and spell-check all framesets.
+UI improvements, undo/redo fixes, font-size fix, border-drawing improved, etc.
+Many new variables available.
+Redesigned style editor (stylist), now all in one dialog.
+When changing a style, only the changes are applied to existing paragraphs (not the whole style).
+Fixed drawing and printing of embedded objects.
+Respect user's color scheme.
+Improved visual appearance (page shape, with shadow).
+
+
+Main changes between KWord-0.8 (KOffice-1.0) and KWord-1.1-beta1
+========================================================================
+
+New overall design and new formatting engine.
+
+Better zooming; adapts to the DPI settings (of the screen and of the printer)
+This means, if your X server is correctly configured, the page on screen has
+the same size as the real paper page.
+
+Much better performance with huge documents (the text is formatted
+ as a background job, the repainting is done much better etc.).
+
+File should be smaller than before (smarter way of saving
+ the formatting information)
+
+Real document/view separation, working with different views on the same
+document is fully functional, cursors are in each view.
+
+Brand new formula widget (with doc/view design, zoom support etc.).
+Redesigned table support.
+Much improved find/replace functionality.
+
+Other new features:
+ - Real bullets instead of using characters as bullets.
+ - Line-level breaking of paragraphs at end of frame/page
+ - Right margin for a paragraph.
+ - Undo/redo fully working (all text operations, but also frame operations etc.)
+
+Fixes:
+ - Embedding a kpresenter part into kword now works
+ - Copy/Paste and Drag-and-drop work as expected (instead of for full paragraphs only)
+
+When Qt3 is out, KWord will support bi-directional editing of text (for hebrew, arabic etc.).
diff --git a/kword/DEBUG b/kword/DEBUG
new file mode 100644
index 00000000..8e792483
--- /dev/null
+++ b/kword/DEBUG
@@ -0,0 +1,15 @@
+Tips for developers
+===================
+
+KWord has a few hidden keys (aka easter-eggs :) that help debugging it,
+without the need for menuitems to be removed before releasing.
+
+The current debug keys are:
+
+Ctrl-Shift-F : Frames debug. Outputs information about all existing frames.
+Ctrl-Shift-P : Paragraphs debug. Outputs information about all paragraphs of the current frameset.
+Ctrl-Shift-V : Verbose parag debug. Includes formatting of each character.
+Ctrl-Shift-S : Styles debug. Prints all KoStyles.
+Ctrl-Shift-M : Mark the debug output. Just prints the current date/time.
+
+(The code is in koffice/kword/kwcanvas.cc.)
diff --git a/kword/DESIGN b/kword/DESIGN
new file mode 100644
index 00000000..6a01ae28
--- /dev/null
+++ b/kword/DESIGN
@@ -0,0 +1,129 @@
+Overall design
+==============
+
+* The document (KWDocument) has a list of framesets (KWFrameSet)
+
+* Framesets include: text frameset, picture/clipart frameset, table frameset etc.
+
+* A frameset has a list of frames, KWFrame. A KWFrame is basically a rectangle
+(KoRect) with a bunch of attributes.
+The frameset contains the contents, like the text or a picture.
+The frames visualize the contents of the frameset.
+Imagine a 10 pages document, with 1 text-frameset and 10 frames, because our
+example author wants to have one frame per page. This means that there is one
+text, and the frames define where on the pages this text is displayed.
+
+* About text framesets: they hold a text document (KWTextDocument, which is
+a QTextDocument from the KoText classes - more on KoText later).
+
+* About Tables; one table is a KWTableFrameset. This tableframeset contains
+all the cells as its frames. But because the cells have a different text per
+cell, we contain the cells in their own KWTextFrameset.
+
+ KWTableFrameSet
+ | |
+ | TextFrames
+ Cells +--------+
+ | |
+ + ---> KWTextFrameSet |
+ | +-> KWFrame <-+
+ | |
+ + ---> KWTextFrameSet |
+ | +-> KWFrame <-+
+ | |
+ + ---> KWTextFrameSet |
+ +-> KWFrame <-+
+
+* The z-order of the frames (i.e. which one is on top of which)
+is defined by m_zOrder in KWFrame. This number is relative to the other
+frames *on the same page*.
+
+Frame layout and pages
+======================
+Generally, the user is free to position frames where he/she wants to.
+
+KWTextFrameSet::slotAfterFormatting() takes care of triggering frame
+resizing (AutoExtend frames), creating a new page (AutoCreateNewFrame), etc.
+
+However, in Word Processing mode, some frames are special: main text frameset
+(which might include columns), headers, footers, and footnotes. All of those
+are laid out by the KWFrameLayout class, which is triggered by
+KWDocument::recalcFrames.
+
+When creating a new page, KWDocument::insertPage takes care of creating the
+followup frames for all frames with newFrameBehavior=Reconnect.
+
+The newFrameBehavior called "Copy" means "exact copy of the contents of
+the frame". This is used for headers/footers (but the user can also use
+it for logos and stuff). In such a case we don't copy anything, we simply
+paint the same contents in many pages.
+
+In WP mode, removing pages is automatically done by KWDocument::tryRemovingPages().
+
+In DTP mode pages are user-controlled (insert and delete page actions),
+but overflowing text can still create a new page as well.
+
+The difficulty with frame layout is that in most cases the frame size and
+number depends on the text inside, and the text layout depends on the frames
+(frame width, frames on top, etc.). This is why text layout (formatMore())
+and frame layout (e.g. KWFrameLayout) often call each other, resulting in
+infinite loops when some code goes wrong.
+
+Editing
+=======
+To edit the contents of a text frameset (including table cells), the user clicks on it.
+This creates an edit object for the frameset, which will be destroyed as soon as we go
+edit another frameset. This means, in a given view (canvas), there is only one edit
+object at a given moment (for text objects, it's the one with the cursor).
+There is one type of edit object per type of frameset. For instance: KWTextFrameSetEdit.
+
+The kotext library provides a base class for the 'text editing' object, it's KoTextView.
+
+Custom items
+============
+A custom item is anything (like an inline frame, a variable etc.) that
+is treated as a special character. QTextCustomItem is the base class for
+it, we have KoTextCustomItem in kotext.
+
+Inline frames are one kind of custom item. The frame (and its englobing
+frameset) exist as usual, but a KWAnchor instance is created, inserted
+into the text, and linked to the frame. The anchor always has the same size
+as the frame. When the text is flowed, the anchor is positioned, it tells
+the frame to move to the new position.
+
+Painting
+========
+Here's how the painting (drawing the stuff on screen, and on printer) works:
+Each frameset is responsible for drawing itself. The base class, KWFrameSet,
+handles the generic code for iterating through the frames, applying the
+"frame is a copy" stuff, drawing the borders, etc. So each specific frameset
+class only has to implement drawFrame (exception for KWTableFrameset though).
+
+Painting of text: KWTextFrameset paints the text for each frame, calling
+KoTextDocument::drawWYSIWYG (with flags for "only the changed paragraphs" etc).
+When printing this method delegates to drawWithoutDoubleBuffer.
+Both methods iterate through the paragraphs, and call drawParagWYSIWYG for each
+one to be redrawn. This method implements the double-buffering, paints the
+background color and the space on the right of the paragraph, and calls
+QTextParag::paint(). Its role is to draw series of characters with the same
+formatting at once (in one go). For each set of chars to be painted,
+KoTextParag::drawParagString is called.
+
+In short:
+KWFrame::drawContents -> KWTextFrameSet::drawFrame
+ -> KoTextDocument::drawWYSIWYG -> KoTextDocument::drawParagWYSIWYG
+ -> KoTextParag::paint -> KoTextParag::drawParagString -> KoTextParag::drawParagStringInternal
+
+The cursor is also drawn by KoTextParag::paint, which calls KoTextParag::drawCursor.
+The blinking cursor is implemented in KoTextView, which calls a virtual
+drawCursor() method, implemented in KWTextFrameSetEdit.
+
+More low-level things
+=====================
+.. such as coordinate systems, font sizes, justified spaces etc.
+See lib/kotext/DESIGN.
+
+
+Wow, you managed to read this until the end ? Good. "GOTO 10" now ;)
+
+David Faure <faure@kde.org>
diff --git a/kword/HACKING b/kword/HACKING
new file mode 100644
index 00000000..3e8a0f68
--- /dev/null
+++ b/kword/HACKING
@@ -0,0 +1,218 @@
+This is an outline of the files and directories in kword.
+(actual state of 2003-07-23)
+
+DIRECTORIES:
+ dtd:
+ the DTD definition for the kword file format
+ - kword.dtd
+ main document structure
+ - framstyles.dtd
+ borders, background
+ - tablestyles.dtd
+ borders, background and (text)style
+ - tabletemplates.dtd
+ pointers to a tablestyle for the first,
+ last row and column and body
+ pics:
+ application icons
+ horizontalline:
+ - line.png
+ horizontal line picture
+ data:
+ xml template files:
+ - framestyles.xml
+ - tablestyles.xml
+ - tabletemplates.xml
+ demos:
+ various example files for kword
+ (another interesting place for such files is the kofficetests
+ module in kde cvs):
+ - bidi.kwd
+ variuous multilingual text examples
+ - chapters.kwd
+ demonstrates chapter headers and text spaces
+ - DTPTest.kwt
+ DTP frames template
+ - eurosign.kwd
+ the euro sign in different fonts
+ - flatland.kwd
+ a lengthy (English) text file
+ (Flatland: A Romance of Many Dimensions by Edwin A. Abbott)
+ - frametest.kwd
+ frame/subframe formatting demo
+ - statistics.kwd
+ test cases for KWord's statistics
+ expression:
+ - expression.xml
+ builtin expressions template file
+ filters:
+ currently only contains the old non-compiled code for the "mif"
+ filter
+ has been deprecated in favour of ../filters
+ mailmerge:
+ source to allow merging of a (large) number of email addresses
+ into a single document
+ subdirectories:
+ kabc:
+ kwmailmerge_kabc.h/cc - KABC addressbook interface
+ sql:
+ various QTSQL interface implementation files
+ to handle table selection and mailmerge data
+ templates:
+ various page layout templates
+ make_template.pl - Perl script to create XML templates
+ - from KWord-saved XML files
+ subdirectories
+ (icons, template frames, and desktop definitions):
+ CardsAndLabels:
+ BusinessCards10.*
+ Labels16.*
+ DTP:
+ Empty.*
+ fax.*
+ SimpleLayout.*
+ Envelopes:
+ EnvelopeC6.*
+ EnvelopeDL.*
+ Wordprocessing:
+ A4.*
+ Letter.*
+ Memo.*
+ PlainText.*
+ TwoColumns.*
+
+FILES:
+ dcop interface:
+ *IFace.h/cc - the dcop interface
+
+ misc app stuff:
+ main.cc - the main
+ kwaboutdata.h - the appname, authors...
+ - shared between main.cc and kwfactory.cc
+ kword.rc - xml-gui layout
+ kword.desktop - application .desktop file
+
+ main document data structures:
+ defs.h - various global definitions
+ - FrameSetType, TypeStructDocItem
+ kwdoc.h/cc - classes: command history, child,
+ and document (config, defaults, load,
+ save, frames helpers, and almost
+ everything else that links doc
+ with ui)
+ configuration dialogs:
+ kwconfig.h/cc - config ui
+ configfootnotedia.h/cc - footnotes configuration
+ core:
+ kwfactory.h/cc - part factory + about data
+ commands:
+ kwcommand.h/cc - base classes for undo / redo
+ - (for core editing functionality)
+ misc ui:
+ resizehandles.h/cc - ui helper (resize handles)
+ core/ui:
+ app:
+ kwcanvas.h/cc - canvas (drawing area, mouse event
+ handlers)
+ kwview.h/cc - actions (menus, toolbars)
+ and their implementation
+ painting:
+ kwtextparag.h/cc - KWord's extension of KoTextParag
+ (e.g. for load and saving as xml)
+ kwtextdocument.h/cc - KoTextDocument reimplementation
+ kwanchor.h/cc - support for inline frames
+ kwanchorpos.h - (ditto)
+ view mode:
+ kwviewmode.h/cc - "page mode" / "preview mode" etc.
+ doc outline:
+ docstruct.h/cc - gui for overall document structure
+ styles:
+ stylenames.cc - contains builtin style names,
+ for translation purposes
+ kwstylemanager.h/cc - KWStyleManager, extension to KoStyleManager
+ (the style editor is in libkotext)
+ OASIS loading, saving:
+ kwoasisloader.h/cc - methods for OASIS loading
+ kwoasissaver.h/cc - OASIS saving of a document fragment (paragraphs)
+
+ advanced editing:
+ kwinserthorizontallinedia.h/cc - insert hor. line dialog
+ kwinsertpagedia.h/cc - insert page dialog
+ tables:
+ kwtableframeset.h/cc - all the table handling
+ kwtabletemplate.h/cc - holds table templates
+ kwtabletemplateselector.h/cc - manages table templates/ui
+ kwtablestyle.h/cc - table styles handlers
+ kwtablestylemanager.h/cc - table styles manager/ui
+ table dialogs:
+ tabledia.h/cc - table insertion dialog
+ deldia.h/cc - table row/column deletion dialog
+ insdia.h/cc - table row/column insertion dialog
+ splitcellsdia.h/cc - cell splitting dialog
+ resizetabledia.h/cc - table resize dialog
+ frames:
+ framedia.h/cc - frame dialog
+ kwframe.h/cc - frame, framesets (picture/formula/...),
+ - framesetedit objects for editing framesets
+ kwframelayout.h/cc - the frame layout engine for headers/main
+ frames/footers/footnotes.
+ (this is a helper for KWDoc::recalcFrames)
+ kwtextframeset.h/cc - text frameset
+ kwformulaframe.h/cc - formula frames
+ kwpartframeset.h/cc - frameset containing an embedded object
+ frame styles:
+ kwframestylemanager.h/cc - manage frame styles
+ - (list, preview, etc.)
+ kwframestyle.h/cc - frame style handling
+ kwimportstyledia.h/cc - import frame styles
+ pics:
+ kwtextimage.h/cc - old stuff
+ - (inline image without frame)
+ - (not available from the UI,
+ - only from old files)
+ kwinsertpicdia.h/cc - insert picture dialog
+
+ core features:
+ variables:
+ kwvariable.h/cc - basic document variables
+ - (Renamed variables.h/cc ???)
+ footnotes:
+ footnotedia.h/cc - footnote insertion dialog
+ configfootnotedia.h/cc - footnotes configuration
+ background spell checking:
+ kwbgspellcheck.h/cc
+ contents:
+ contents.h/cc - table of contents
+ search:
+ searchdia.h/cc - text find and replace
+
+ other features:
+ bookmarks:
+ KWCreateBookmarkDia.h/cc - bookmarks dialogs
+ KWCreateBookmarkDiaBase.h/cc - create a bookmark
+ KWSelectBookmarkDiaBase.h/cc - select/rename/delete
+ - bookmark
+ mailmerge:
+ mailmerge.h/cc
+ mailmerge_actions.h/cc
+ kwordmailmergedatabaseiface.cc
+ mailmerge_interface.h/cc - dcop
+ mailmerge_interface_skel.cc - (ditto)
+ kwmailmerge.desktop - mailmerge .desktop file
+ expressions:
+ kweditpersonnalexpressiondia.h/cc
+ text sorting:
+ sortdia.h/cc - sort text dialog
+
+ misc weird files: ;-)
+ kwstyle.h - Forwarder to kostyle.h,
+ - they're the same thing now.
+ dummy.cc - empty file to compile as a
+ - "kdeinit loadable module"
+
+MISC FILES:
+ Docs, hints, etc.:
+ DESIGN
+ DEBUG
+ TODO
+ HACKING
diff --git a/kword/KWAboutData.h b/kword/KWAboutData.h
new file mode 100644
index 00000000..42456598
--- /dev/null
+++ b/kword/KWAboutData.h
@@ -0,0 +1,65 @@
+/* This file is part of the KDE project
+ Copyright (C) 1998 - 2001 Reginald Stadlbauer <reggie@kde.org>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+*/
+
+#ifndef KWORD_ABOUTDATA
+#define KWORD_ABOUTDATA
+
+#include <kaboutdata.h>
+#include <klocale.h>
+#include <kofficeversion.h>
+
+static const char* KWORD_DESCRIPTION=I18N_NOOP("KOffice Word Processor");
+// First official public release Oct 2000 version 0.8
+// KOffice-1.1-beta1: version 0.9
+// KOffice-1.1-beta2: version 1.1 (to remove confusion)
+// KOffice-1.2: version 1.2
+// From then on: always the same as the KOffice version
+static const char* KWORD_VERSION=KOFFICE_VERSION_STRING;
+
+KAboutData * newKWordAboutData()
+{
+ KAboutData * aboutData=new KAboutData( "kword", I18N_NOOP("KWord"),
+ KWORD_VERSION, KWORD_DESCRIPTION, KAboutData::License_LGPL,
+ I18N_NOOP("(c) 1998-2006, The KWord Team"), 0,
+ "http://www.koffice.org/kword/" );
+ aboutData->addAuthor("David Faure", 0, "faure@kde.org");
+ aboutData->addAuthor("Reginald Stadlbauer", 0, "reggie@kde.org");
+ aboutData->addAuthor("Thomas Zander");
+ aboutData->addAuthor("Laurent Montel", 0, "montel@kde.org");
+ aboutData->addAuthor("Sven Lüppken", 0, "sven@kde.org");
+ aboutData->addAuthor("Frank Dekervel", 0, "Frank.dekervel@student.kuleuven.ac.Be");
+ aboutData->addAuthor("Krister Wicksell Eriksson", 0, "krister.wicksell@spray.se");
+ aboutData->addAuthor("Dag Andersen", 0, "danders@get2net.dk");
+ aboutData->addAuthor("Nash Hoogwater", 0, "nrhoogwater@wanadoo.nl");
+ aboutData->addAuthor("Ulrich Kuettler", I18N_NOOP("KFormula"), "ulrich.kuettler@mailbox.tu-dresden.de");
+ // filter developers
+ aboutData->addAuthor("Shaheed Haque", 0, "srhaque@iee.org");
+ aboutData->addAuthor("Werner Trobin", 0, "trobin@kde.org");
+ aboutData->addAuthor("Nicolas Goutte", 0, "goutte@kde.org");
+ aboutData->addAuthor("Ariya Hidayat", 0, "ariya@kde.org");
+ aboutData->addAuthor("Clarence Dang", 0, "dang@kde.org");
+ aboutData->addAuthor("Robert Jacolin", 0, "rjacolin@ifrance.com");
+ aboutData->addAuthor("Enno Bartels", 0, "ebartels@nwn.de");
+ aboutData->addAuthor("Ewald Snel", 0, "ewald@rambo.its.tudelft.nl");
+ aboutData->addAuthor("Tomasz Grobelny", 0, "grotk@poczta.onet.pl");
+ aboutData->addAuthor("Michael Johnson");
+ return aboutData;
+}
+
+#endif
diff --git a/kword/KWAnchor.cpp b/kword/KWAnchor.cpp
new file mode 100644
index 00000000..33242554
--- /dev/null
+++ b/kword/KWAnchor.cpp
@@ -0,0 +1,306 @@
+/* This file is part of the KDE project
+ Copyright (C) 2001 David Faure <faure@kde.org>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+*/
+
+#include "KWAnchor.h"
+#include "KWTextFrameSet.h"
+#include "KWDocument.h"
+#include "KWViewMode.h"
+#include "KWView.h"
+#include <KoXmlWriter.h>
+#include <kdebug.h>
+
+//#define DEBUG_DRAWING
+
+KWAnchor::KWAnchor( KoTextDocument *textDocument, KWFrameSet * frameset, int frameNum )
+ : KoTextCustomItem( textDocument),
+ m_frameset( frameset ),
+ m_frameNum( frameNum )
+{
+}
+
+KWAnchor::~KWAnchor()
+{
+ kdDebug(32001) << "KWAnchor::~KWAnchor" << endl;
+}
+
+void KWAnchor::setFormat( KoTextFormat* format )
+{
+ m_frameset->setAnchorFormat( format, m_frameNum );
+}
+
+void KWAnchor::finalize()
+{
+ if ( m_deleted )
+ return;
+
+ int paragx = paragraph()->rect().x();
+ int paragy = paragraph()->rect().y();
+ kdDebug(32001) << this << " KWAnchor::finalize " << x() << "," << y() << " paragx=" << paragx << " paragy=" << paragy << endl;
+
+ KWTextFrameSet * fs = static_cast<KWTextDocument *>(textDocument())->textFrameSet();
+ KoPoint dPoint;
+ if ( fs->internalToDocument( QPoint( x()+paragx, y()+paragy ), dPoint ) )
+ {
+ //kdDebug(32001) << "KWAnchor::finalize moving frame to " << dPoint.x() << "," << dPoint.y() << endl;
+ // Move the frame to position dPoint.
+ m_frameset->moveFloatingFrame( m_frameNum, dPoint );
+ } else
+ {
+ // This can happen if the page hasn't been created yet
+ kdDebug(32001) << "KWAnchor::move internalToDocument returned 0L for " << x()+paragx << ", " << y()+paragy << endl;
+ }
+}
+
+void KWAnchor::draw( QPainter* p, int x, int y, int cx, int cy, int cw, int ch, const QColorGroup& cg, bool selected )
+{
+ // (x,y) is the position of the inline item (in Layout Units)
+ // (cx,cy,cw,ch) is the rectangle to be painted, in layout units too
+
+ if ( m_deleted )
+ return;
+
+ Q_ASSERT( x == xpos );
+ Q_ASSERT( y == ypos );
+ if ( x != xpos || y != ypos )
+ kdDebug() << "Warning: x=" << x << " y=" << y << " xpos=" << xpos << " ypos=" << ypos << endl;
+
+ // The containing text-frameset.
+ KWTextFrameSet * fs = static_cast<KWTextDocument *>(textDocument())->textFrameSet();
+ KoTextZoomHandler* zh = fs->textDocument()->paintingZoomHandler();
+
+ int paragx = paragraph()->rect().x();
+ int paragy = paragraph()->rect().y();
+ QRect inlineFrameLU( paragx+xpos, paragy+ypos, width, height );
+#ifdef DEBUG_DRAWING
+ kdDebug(32001) << "KWAnchor::draw x:" << x << ", y:" << y << " paragx=" << paragx << " paragy=" << paragy << endl;
+ kdDebug(32001) << " inline frame in LU coordinates: " << inlineFrameLU << endl;
+#endif
+
+ QRect crectLU = QRect( (cx > 0 ? cx : 0)+paragx, cy+paragy, cw, ch );
+#ifdef DEBUG_DRAWING
+ kdDebug(32001) << " crect in LU coordinates: " << DEBUGRECT( crectLU ) << endl;
+#endif
+
+ crectLU = crectLU.intersect ( inlineFrameLU ); // KoTextParag::paintDefault could even do this
+
+
+#ifdef DEBUG_DRAWING
+ kdDebug(32001) << " crect&frame in LU coordinates: " << DEBUGRECT( crectLU ) << endl;
+#endif
+
+ // Convert crect to document coordinates, first topleft then bottomright
+ QPoint topLeftLU = crectLU.topLeft();
+ QPoint bottomRightLU = crectLU.bottomRight();
+ KWFrame* containingFrame = fs->currentDrawnFrame(); // always set, except in the textviewmode
+ if(containingFrame)
+ containingFrame = KWFrameSet::settingsFrame(containingFrame);
+ else { // if its not set (in textviewmode) try to get it from the FS
+ QPoint paragPos = inlineFrameLU.topLeft();
+ KoPoint dummy(0, 0);
+ containingFrame = fs->internalToDocument(paragPos, dummy);
+ }
+ KoPoint topLeftPt = fs->internalToDocumentKnowingFrame( topLeftLU, containingFrame );
+
+ // Now we can convert the bottomright
+ KoPoint bottomRightPt = fs->internalToDocumentKnowingFrame( bottomRightLU, containingFrame );
+ KoRect crectPt( topLeftPt, bottomRightPt );
+
+ // Convert crect to view coords
+ QRect crect = fs->currentViewMode()->normalToView( zh->zoomRect( crectPt ) );
+ // and add 1 to right and bottom, to avoid rounding errors (and due to qrect semantics)
+ crect.rBottom() += 2; // HACK: 1 doesn't do it, it leaves a white line along window borders
+ crect.rRight() += 1;
+#ifdef DEBUG_DRAWING
+ kdDebug() << " crect in view coordinates (pixel) : " << DEBUGRECT( crect ) << endl;
+#endif
+
+ // Ok, we finally have our crect in view coordinates!
+ // Now ensure the containing frame is the one actually containing our text
+ // (for copies, e.g. headers and footers, we need to go back until finding a real frame)
+
+ if ( containingFrame && containingFrame->isCopy() )
+ {
+ // Find last real frame, in case we are in a copied frame
+ QPtrListIterator<KWFrame> frameIt( fs->frameIterator() );
+ frameIt.toLast(); // from the end to avoid a 2*N in the worst case
+ while ( !frameIt.atFirst() && frameIt.current() != containingFrame ) // look for 'containingFrame'
+ --frameIt;
+ if ( frameIt.atFirst() && frameIt.current() != containingFrame )
+ kdWarning() << "KWAnchor::draw: containingFrame not found " << containingFrame << endl;
+ while ( !frameIt.atFirst() && frameIt.current()->isCopy() ) // go back to last non-copy
+ --frameIt;
+ containingFrame = frameIt.current();
+ //kdDebug() << "KWAnchor::draw frame=" << containingFrame << endl;
+ }
+
+ // Same calculation as in internalToDocument, but we know the frame already
+ KoPoint topLeftParagPt( 0, 0 );
+ if ( containingFrame ) // 0 in the textviewmode
+ topLeftParagPt = containingFrame->innerRect().topLeft();
+
+ topLeftParagPt.rx() += zh->layoutUnitPtToPt( zh->pixelYToPt( paragx ) );
+ topLeftParagPt.ry() += zh->layoutUnitPtToPt( zh->pixelYToPt( paragy ) );
+ if ( containingFrame ) // 0 in the textviewmode
+ topLeftParagPt.ry() -= containingFrame->internalY();
+
+ QPoint topLeftParag = fs->currentViewMode()->normalToView( zh->zoomPoint( topLeftParagPt ) );
+
+ // Finally, make the painter go back to view coord system
+ // (this is exactly the opposite of the code in KWFrameSet::drawContents)
+ // (It does translate(view - internal), so we do translate(internal - view) - e.g. with (0,0) for internal)
+ p->save();
+ p->translate( -topLeftParag.x(), -topLeftParag.y() );
+#ifdef DEBUG_DRAWING
+ kdDebug() << " translating by " << -topLeftParag.x() << "," << -topLeftParag.y() << endl;
+#endif
+
+ QColorGroup cg2( cg );
+
+ KWFrameViewManager *fvm = 0;
+ if(m_frameset->kWordDocument()) {
+ QValueList<KWView *> views = m_frameset->kWordDocument()->getAllViews();
+ // Note that "views" is empty when the KWDocument is an (inactive) embedded document
+ if ( !views.isEmpty() )
+ fvm = views.first()->frameViewManager();
+ }
+ m_frameset->drawContents( p, crect, cg2, false, true, 0L, fs->currentViewMode(), fvm);
+
+ if( selected && placement() == PlaceInline && p->device()->devType() != QInternal::Printer )
+ {
+ // The above rects are about the containing frame.
+ // To draw the inline frame as selected, we need to look at the inline frame's own size.
+ QRect frameRect = crect;
+#ifdef DEBUG_DRAWING
+ kdDebug() << "KWAnchor::draw selected frame. frameRect=" << frameRect << endl;
+#endif
+ p->fillRect( frameRect, QBrush( cg.highlight(), QBrush::Dense4Pattern) );
+ }
+ p->restore();
+
+#ifdef DEBUG_DRAWING
+ kdDebug() << "KWAnchor::draw done" << endl;
+#endif
+}
+
+QSize KWAnchor::size() const
+{
+ KoSize kosz = m_frameset->floatingFrameSize( m_frameNum );
+ //kdDebug() << "KWAnchor::size in pt: " << kosz.width() << "x" << kosz.height() << endl;
+ KoTextZoomHandler * zh = textDocument()->formattingZoomHandler();
+ QSize sz( zh->ptToLayoutUnitPixX( kosz.width() ), zh->ptToLayoutUnitPixY( kosz.height() ) );
+ //kdDebug() << "KWAnchor::size in LU: " << sz.width() << "x" << sz.height() << endl;
+ //kdDebug() << " size in pixels: " << zh->layoutUnitToPixelX( sz.width() ) << "x"
+ // << zh->layoutUnitToPixelY( sz.height() ) << endl;
+ if ( sz.isNull() ) // for some reason, we don't know the size yet
+ sz = QSize( width, height ); // LU
+ return sz;
+}
+
+int KWAnchor::ascent() const
+{
+ int baseline = m_frameset->floatingFrameBaseline( m_frameNum );
+ int ret = ( baseline == -1 ) ? height : baseline;
+ //kdDebug() << "KWAnchor::ascent " << ret << endl;
+ return ret;
+}
+
+void KWAnchor::resize()
+{
+ if ( m_deleted )
+ return;
+ QSize s = size();
+ if ( width != s.width() || height != s.height() )
+ {
+ width = s.width();
+ height = s.height();
+ kdDebug(32001) << "KWAnchor::resize " << width << "x" << height << endl;
+ KoTextParag * parag = paragraph();
+ if ( parag )
+ {
+ kdDebug(32001) << "KWAnchor::resize invalidating parag " << parag->paragId() << endl;
+ parag->invalidate( 0 );
+ }
+ }
+}
+
+KCommand * KWAnchor::createCommand()
+{
+ kdDebug(32001) << "KWAnchor::addCreateCommand" << endl;
+ return m_frameset->anchoredObjectCreateCommand( m_frameNum );
+}
+
+KCommand * KWAnchor::deleteCommand()
+{
+ kdDebug(32001) << "KWAnchor::addDeleteCommand" << endl;
+ return m_frameset->anchoredObjectDeleteCommand( m_frameNum );
+}
+
+void KWAnchor::setDeleted( bool b )
+{
+ // Do this first, because setAnchored->updateAllFrames->isDeleted, so it must have the right value already
+ KoTextCustomItem::setDeleted( b );
+
+ kdDebug() << "KWAnchor::setDeleted " << b << endl;
+ if ( b )
+ m_frameset->setAnchored( 0L );
+ else
+ m_frameset->setAnchored( static_cast<KWTextDocument *>(textDocument())->textFrameSet() );
+}
+
+void KWAnchor::save( QDomElement &parentElem )
+{
+ QDomElement anchorElem = parentElem.ownerDocument().createElement( "ANCHOR" );
+ parentElem.appendChild( anchorElem );
+ anchorElem.setAttribute( "type", "frameset" ); // the only possible value currently
+ //KWDocument * doc = textDocument()->textFrameSet()->kWordDocument();
+ // ## TODO save the frame number as well ? Only the first frame ? to be determined
+ // ## or maybe use len=<number of frames>. Difficult :}
+ anchorElem.setAttribute( "instance", m_frameset->name() );
+}
+
+void KWAnchor::saveOasis( KoXmlWriter& writer, KoSavingContext& context ) const
+{
+ if ( m_frameset->canBeSavedAsInlineCharacter() )
+ m_frameset->saveOasis( writer, context, true );
+ else // special case for inline tables [which are not alone in their paragraph, see KWTextParag]
+ {
+ writer.startElement( "draw:frame" );
+ writer.addAttribute( "draw:name", m_frameset->name() + "-Wrapper" );
+ // Mark as wrapper frame. KWTextDocument::loadSpanTag will try to get rid of it upon loading.
+ writer.addAttribute( "koffice:is-wrapper-frame", "true" );
+ //writer.addAttribute( "draw:style-name", saveOasisFrameStyle( mainStyles ) );
+ KoSize kosz = m_frameset->floatingFrameSize( m_frameNum );
+ writer.addAttributePt( "svg:width", kosz.width() );
+ writer.addAttributePt( "svg:height", kosz.height() );
+ writer.startElement( "draw:text-box" );
+ m_frameset->saveOasis( writer, context, true );
+ writer.endElement();
+ writer.endElement();
+ }
+}
+
+bool KWAnchor::ownLine() const
+{
+ if ( m_deleted )
+ return FALSE;
+
+ if ( m_frameset)
+ return m_frameset->ownLine();
+ return FALSE;
+}
diff --git a/kword/KWAnchor.h b/kword/KWAnchor.h
new file mode 100644
index 00000000..d03fd111
--- /dev/null
+++ b/kword/KWAnchor.h
@@ -0,0 +1,85 @@
+/* This file is part of the KDE project
+ Copyright (C) 2001 David Faure <faure@kde.org>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+*/
+
+#ifndef kwanchor_h
+#define kwanchor_h
+
+#include "KWTextDocument.h"
+class KCommand;
+class KWTextFrameSet;
+class KWFrame;
+class KWFrameSet;
+
+/**
+ * An anchor is a special character, or 'custom item'.
+ * It never appears as such. It is as big as the frame it is related to,
+ * so that the frame is effectively inline in the text.
+ */
+class KWAnchor : public KoTextCustomItem
+{
+public:
+ /**
+ * Constructor.
+ * @param textdoc the document this ancher will be one character of.
+ * @param frameset The frameset that is anchored. This frameset contains the content we are
+ displaying.
+ * @param frameNum Which frame of the frameset (previos argument) is used for displaying.
+ */
+ KWAnchor( KoTextDocument *textdoc, KWFrameSet * frameset, int frameNum );
+ ~KWAnchor();
+ bool ownLine() const;
+ virtual void setFormat( KoTextFormat* );
+
+ /** The frameset that will provide the content to display in this anchor object */
+ KWFrameSet * frameSet() const { return m_frameset; }
+ /** The index the frameset needs to access which content is displayed in the anchor object */
+ int frameNum() const { return m_frameNum; }
+
+ /** Return the size of the item, i.e. the size of the frame (zoomed) */
+ QSize size() const;
+
+ /* overloaded methods, see lib/kotext/kotextcustomitem.h for docu*/
+ virtual void resize();
+ virtual void finalize();
+
+ /* overloaded methods, see korichtext.h for docu*/
+ virtual Placement placement() const { return PlaceInline; }
+ virtual int widthHint() const { return size().width(); }
+ virtual int minimumWidth() const { return size().width(); }
+ virtual int ascent() const;
+
+ virtual void draw( QPainter* p, int x, int y, int cx, int cy, int cw, int ch, const QColorGroup& cg, bool selected );
+ /** Never called since we reimplement draw */
+ virtual void drawCustomItem(QPainter*, int, int, int, int, int, int, int, int, int, const QColorGroup&, bool, int, bool) { }
+
+ virtual KCommand * createCommand();
+ virtual KCommand * deleteCommand();
+ virtual void setDeleted( bool b );
+ virtual void save( QDomElement &formatElem );
+ virtual void saveOasis( KoXmlWriter& writer, KoSavingContext& context ) const;
+
+ virtual int typeId() const { return 6; }
+
+private:
+ KWFrameSet * m_frameset; // the frameset that implements the content for this special char.
+ int m_frameNum; // the reference the frameset needs to identify the content in its
+ // set of frames
+};
+
+#endif
diff --git a/kword/KWAnchorPos.h b/kword/KWAnchorPos.h
new file mode 100644
index 00000000..5a8864c1
--- /dev/null
+++ b/kword/KWAnchorPos.h
@@ -0,0 +1,40 @@
+/* This file is part of the KDE project
+ Copyright (C) 2001 David Faure <faure@kde.org>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+*/
+
+#ifndef kwanchorpos_h
+#define kwanchorpos_h
+
+class KWTextFrameSet;
+class KWTextParag;
+/**
+ * Definition of an anchor's position:
+ * - A text frameset
+ * - A paragraph in this frameset
+ * - An index in the paragraph
+ */
+struct KWAnchorPosition
+{
+ KWAnchorPosition() { textfs = 0L; paragId = -1; index = -1; }
+
+ KWTextFrameSet* textfs;
+ int paragId;
+ int index;
+};
+
+#endif
diff --git a/kword/KWBgSpellCheck.cpp b/kword/KWBgSpellCheck.cpp
new file mode 100644
index 00000000..1d0f173f
--- /dev/null
+++ b/kword/KWBgSpellCheck.cpp
@@ -0,0 +1,60 @@
+/* This file is part of the KDE project
+ Copyright (C) 2002 David Faure <faure@kde.org>
+ 2002 Laurent Montel <lmontel@mandrakesoft.com>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+*/
+
+
+#include "KWBgSpellCheck.h"
+
+#include "KWDocument.h"
+#include "KWTextFrameSet.h"
+
+#include "KoTextIterator.h"
+#include "KoTextObject.h"
+
+#include <kspell2/broker.h>
+using namespace KSpell2;
+
+#include <kdebug.h>
+#include <kconfig.h>
+#include <klocale.h>
+
+
+KWBgSpellCheck::KWBgSpellCheck(KWDocument *_doc)
+ : KoBgSpellCheck( Broker::openBroker( KSharedConfig::openConfig( "kwordrc" ) ),
+ _doc )
+{
+ m_doc=_doc;
+ m_currentFrame=0L;
+}
+
+KWBgSpellCheck::~KWBgSpellCheck()
+{
+}
+
+KoTextIterator *KWBgSpellCheck::createWholeDocIterator() const
+{
+ QValueList<KoTextObject *> objects = m_doc->visibleTextObjects( 0 );
+
+ kdDebug()<<"Number of visible text objects = "<< objects.count() << endl;
+
+ if ( objects.isEmpty() )
+ return 0;
+
+ return new KoTextIterator( objects, 0, 0 );
+}
diff --git a/kword/KWBgSpellCheck.h b/kword/KWBgSpellCheck.h
new file mode 100644
index 00000000..3c3c73af
--- /dev/null
+++ b/kword/KWBgSpellCheck.h
@@ -0,0 +1,44 @@
+/* This file is part of the KDE project
+ Copyright (C) 2002 David Faure <faure@kde.org>
+ 2002 Laurent Montel <lmontel@mandrakesoft.com>
+ 2004 Zack Rusin <zack@kde.org>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+*/
+
+#ifndef kwbgspellcheck_h
+#define kwbgspellcheck_h
+
+class KWDocument;
+class KWTextFrameSet;
+
+#include "KoBgSpellCheck.h"
+
+#include <qobject.h>
+class KWBgSpellCheck : public KoBgSpellCheck
+{
+public:
+ KWBgSpellCheck(KWDocument *_doc);
+ virtual ~KWBgSpellCheck();
+
+ virtual KoTextIterator *createWholeDocIterator() const;
+
+private:
+ KWDocument *m_doc;
+ KWTextFrameSet *m_currentFrame;
+};
+
+#endif
diff --git a/kword/KWCanvas.cpp b/kword/KWCanvas.cpp
new file mode 100644
index 00000000..37fd0ff5
--- /dev/null
+++ b/kword/KWCanvas.cpp
@@ -0,0 +1,2493 @@
+/* This file is part of the KDE project
+ Copyright (C) 1998, 1999 Reginald Stadlbauer <reggie@kde.org>
+ Copyright (C) 2002-2006 David Faure <faure@kde.org>
+ Copyright (C) 2005 Thomas Zander <zander@kde.org>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+
+
+#include "KWCanvas.h"
+#include "KWTableFrameSet.h"
+#include "KWPartFrameSet.h"
+#include "KWFormulaFrameSet.h"
+#include "KWDocument.h"
+#include "KWView.h"
+#include "KWViewMode.h"
+#include "KWFrameDia.h"
+#include "KWCommand.h"
+#include "KWTableTemplate.h"
+#include "KWTextDocument.h"
+#include "KWFrameList.h"
+#include "KWPageManager.h"
+#include "KWPage.h"
+#include "KWPictureFrameSet.h"
+#include "KWFrameView.h"
+#include "KWFrameViewManager.h"
+
+#include <qbuffer.h>
+#include <qtimer.h>
+#include <qclipboard.h>
+#include <qprogressdialog.h>
+#include <qobjectlist.h>
+#include <qapplication.h>
+#include <qwhatsthis.h>
+
+#include <KoStore.h>
+#include <KoStoreDrag.h>
+#include <KoPictureCollection.h>
+
+#include <ktempfile.h>
+#include <klocale.h>
+#include <kcursor.h>
+#include <kdebug.h>
+#include <kmessagebox.h>
+#include <kmultipledrag.h>
+#include <kurl.h>
+#include <kurldrag.h>
+#include <kio/netaccess.h>
+#include <kmimetype.h>
+
+#include <assert.h>
+
+KWCanvas::KWCanvas(const QString& viewMode, QWidget *parent, KWDocument *d, KWGUI *lGui)
+ : QScrollView( parent, "canvas", /*WNorthWestGravity*/ WStaticContents| WResizeNoErase | WRepaintNoErase ), m_doc( d )
+{
+ m_frameViewManager = new KWFrameViewManager(d);
+ m_gui = lGui;
+ m_currentFrameSetEdit = 0L;
+ m_mouseMeaning = MEANING_NONE;
+ m_mousePressed = false;
+ m_imageDrag = false;
+ m_frameInline = false;
+ m_overwriteMode = false;
+
+ //used by insert picture dialogbox
+ m_picture.pictureInline = false;
+ m_picture.keepRatio = true;
+
+
+
+ m_frameInlineType = FT_TABLE;
+ m_viewMode = KWViewMode::create( viewMode, m_doc, this );
+ m_interactionPolicy = 0;
+
+ // Default table parameters.
+ m_table.rows = 3;
+ m_table.cols = 2;
+ m_table.width = KWTableFrameSet::TblAuto;
+ m_table.height = KWTableFrameSet::TblAuto;
+ m_table.floating = true;
+ m_table.tableTemplateName=QString::null;
+ m_table.format=31;
+
+ m_footEndNote.noteType = FootNote;
+ m_footEndNote.numberingType = KWFootNoteVariable::Auto;
+
+
+ m_currentTable = 0L;
+ m_printing = false;
+ m_deleteMovingRect = false;
+ m_resizedFrameInitialMinHeight = 0;
+ m_temporaryStatusBarTextShown = false;
+
+ viewport()->setBackgroundMode( PaletteBase );
+ viewport()->setAcceptDrops( TRUE );
+
+ setKeyCompression( TRUE );
+ viewport()->setMouseTracking( TRUE );
+
+ m_scrollTimer = new QTimer( this );
+ connect( m_scrollTimer, SIGNAL( timeout() ),
+ this, SLOT( doAutoScroll() ) );
+
+ viewport()->setFocusProxy( this );
+ viewport()->setFocusPolicy( WheelFocus );
+ setInputMethodEnabled( true );
+ setFocus();
+ viewport()->installEventFilter( this );
+ installEventFilter( this );
+ KCursor::setAutoHideCursor( this, true, true );
+
+ connect( this, SIGNAL(contentsMoving( int, int )),
+ this, SLOT(slotContentsMoving( int, int )) );
+
+ connect( m_doc, SIGNAL( newContentsSize() ),
+ this, SLOT( slotNewContentsSize() ) );
+
+ connect( m_doc, SIGNAL( mainTextHeightChanged() ),
+ this, SLOT( slotMainTextHeightChanged() ) );
+
+ connect( m_doc, SIGNAL( sig_terminateEditing( KWFrameSet * ) ),
+ this, SLOT( terminateEditing( KWFrameSet * ) ) );
+
+ slotNewContentsSize();
+
+ m_mouseMode = MM_EDIT; // avoid UMR in setMouseMode
+ setMouseMode( MM_EDIT );
+
+ // Create the current frameset-edit last, to have everything ready for it
+ KWFrameSet * fs = 0L;
+ QString fsName = m_doc->initialFrameSet();
+ if ( !fsName.isEmpty() )
+ fs = m_doc->frameSetByName( fsName );
+ if ( !fs )
+ fs = m_doc->frameSet( 0 );
+ //Q_ASSERT( fs ); // empty page template -> no fs
+ if ( fs && fs->isVisible( m_viewMode ) ) {
+ checkCurrentEdit( fs );
+ KWTextFrameSetEdit* textedit = dynamic_cast<KWTextFrameSetEdit *>(m_currentFrameSetEdit);
+ if ( textedit ) {
+ int paragId = m_doc->initialCursorParag();
+ int index = m_doc->initialCursorIndex();
+ if ( paragId != 0 || index != 0 ) {
+ KoTextParag* parag = textedit->textDocument()->paragAt( paragId );
+ if ( parag )
+ textedit->setCursor( parag, index );
+ }
+ }
+ }
+ m_doc->deleteInitialEditingInfo();
+
+ connect(frameViewManager(), SIGNAL(sigFrameResized(const QValueList<KWFrame*>&)),
+ m_doc, SLOT(framesChanged(const QValueList<KWFrame*>&)));
+ connect(frameViewManager(), SIGNAL(sigFrameMoved(const QValueList<KWFrame*>&)),
+ m_doc, SLOT(framesChanged(const QValueList<KWFrame*>&)));
+}
+
+KWCanvas::~KWCanvas()
+{
+ delete m_interactionPolicy;
+ delete m_currentFrameSetEdit;
+ m_currentFrameSetEdit = 0;
+ delete m_viewMode;
+ m_viewMode = 0;
+ disconnect(frameViewManager(), SIGNAL(sigFrameResized(const QValueList<KWFrame*>&)),
+ m_doc, SLOT(framesChanged(const QValueList<KWFrame*>&)));
+ disconnect(frameViewManager(), SIGNAL(sigFrameMoved(const QValueList<KWFrame*>&)),
+ m_doc, SLOT(framesChanged(const QValueList<KWFrame*>&)));
+ delete m_frameViewManager;
+ m_frameViewManager = 0;
+}
+
+void KWCanvas::repaintChanged( KWFrameSet * fs, bool resetChanged )
+{
+ assert(fs); // the new code can't support fs being 0L here. Mail me if it happens (DF)
+ //kdDebug(32002) << "KWCanvas::repaintChanged this=" << this << " fs=" << fs << endl;
+ QPainter p( viewport() );
+ p.translate( -contentsX(), -contentsY() );
+ p.setBrushOrigin( -contentsX(), -contentsY() );
+ QRect crect( contentsX(), contentsY(), visibleWidth(), visibleHeight() );
+ drawFrameSet( fs, &p, crect, true, resetChanged, m_viewMode );
+ // ###### This repaints the whole grid every time. Ouch.
+ // We should return a QRegion from drawFrameSet.... Tricky.
+ if ( m_doc->showGrid() )
+ drawGrid( p, crect );
+}
+
+void KWCanvas::repaintAll( bool erase /* = false */ )
+{
+ //kdDebug(32002) << "KWCanvas::repaintAll erase=" << erase << endl;
+ viewport()->repaint( erase );
+}
+
+void KWCanvas::viewportResizeEvent( QResizeEvent * )
+{
+ viewport()->update();
+}
+
+void KWCanvas::print( QPainter *painter, KPrinter *printer )
+{
+ // Prevent cursor drawing and editing
+ if ( m_currentFrameSetEdit )
+ m_currentFrameSetEdit->focusOutEvent();
+ m_printing = true;
+ KWViewMode *viewMode = new KWViewModePrint( m_doc, this );
+ // Use page list specified in kdeprint dialogbox
+ QValueList<int> pageList = printer->pageList();
+ QProgressDialog progress( i18n( "Printing..." ), i18n( "Cancel" ),
+ pageList.count() + 1, this );
+ int j = 0;
+ progress.setProgress( 0 );
+ QValueList<int>::Iterator it = pageList.begin();
+ for ( ; it != pageList.end(); ++it )
+ {
+ progress.setProgress( ++j );
+ qApp->processEvents();
+
+ if ( progress.wasCancelled() )
+ break;
+
+ if ( it != pageList.begin() )
+ printer->newPage();
+
+ painter->save();
+ int pgNum = (*it);
+ int yOffset = m_doc->zoomItY( m_doc->pageManager()->topOfPage( pgNum ) );
+ kdDebug(32001) << "printing page " << pgNum << " yOffset=" << yOffset << endl;
+ QRect pageRect = m_doc->pageManager()->page(pgNum)->zoomedRect(m_doc);
+ painter->fillRect( pageRect, white );
+
+ painter->translate( 0, -yOffset );
+ painter->setBrushOrigin( 0, -yOffset );
+ drawDocument( painter, pageRect, viewMode );
+ qApp->processEvents();
+ painter->restore();
+ }
+ if ( m_currentFrameSetEdit )
+ m_currentFrameSetEdit->focusInEvent();
+ m_printing = false;
+ delete viewMode;
+}
+
+void KWCanvas::drawContents( QPainter *painter, int cx, int cy, int cw, int ch )
+{
+ if ( isUpdatesEnabled() )
+ {
+ // Note: in drawContents, the painter is already translated to the contents coordinates
+ painter->setBrushOrigin( -contentsX(), -contentsY() );
+ drawDocument( painter, QRect( cx, cy, cw, ch ), m_viewMode );
+ if ( m_doc->showGrid() )
+ drawGrid( *painter, QRect( cx, cy, cw, ch ) );
+ else if ( m_doc->snapToGrid() && ( m_interactionPolicy && m_interactionPolicy->gotDragEvents()
+ || m_mouseMode != MM_EDIT ) )
+ drawGrid( *painter, QRect(contentsX(), contentsY(), visibleWidth(), visibleHeight()) );
+ }
+}
+
+void KWCanvas::drawDocument( QPainter *painter, const QRect &crect, KWViewMode* viewMode )
+{
+ //kdDebug(32002) << "KWCanvas::drawDocument crect: " << crect << endl;
+
+ // Draw the outside of the pages (shadow, gray area)
+ // and the empty area first (in case of transparent frames)
+ if ( painter->device()->devType() != QInternal::Printer ) // except when printing
+ {
+ QRegion emptySpaceRegion( crect );
+ m_doc->createEmptyRegion( crect, emptySpaceRegion, viewMode );
+ viewMode->drawPageBorders( painter, crect, emptySpaceRegion );
+ }
+
+ // Draw all framesets contents
+ QPtrListIterator<KWFrameSet> fit = m_doc->framesetsIterator();
+ for ( ; fit.current() ; ++fit )
+ {
+ KWFrameSet * frameset = fit.current();
+ if(! frameset->isVisible()) continue;
+ drawFrameSet( frameset, painter, crect, false, true, viewMode );
+ }
+
+ m_doc->maybeDeleteDoubleBufferPixmap();
+}
+
+void KWCanvas::drawFrameSet( KWFrameSet * frameset, QPainter * painter,
+ const QRect & crect, bool onlyChanged, bool resetChanged, KWViewMode* viewMode )
+{
+ if ( !frameset->isVisible( viewMode ) )
+ return;
+ if ( !onlyChanged && frameset->isFloating() )
+ return;
+
+ bool focus = hasFocus() || viewport()->hasFocus();
+ if ( painter->device()->devType() == QInternal::Printer )
+ focus = false;
+
+ QColorGroup gb = QApplication::palette().active();
+ if ( focus && m_currentFrameSetEdit && frameset == m_currentFrameSetEdit->frameSet() )
+ // Currently edited frameset
+ m_currentFrameSetEdit->drawContents( painter, crect, gb, onlyChanged, resetChanged, viewMode, m_frameViewManager );
+ else
+ frameset->drawContents( painter, crect, gb, onlyChanged, resetChanged, 0L, viewMode, m_frameViewManager );
+}
+
+void KWCanvas::keyPressEvent( QKeyEvent *e )
+{
+ if( !m_doc->isReadWrite()) {
+ switch( e->key() ) {
+ case Qt::Key_Down:
+ setContentsPos( contentsX(), contentsY() + 10 );
+ break;
+ case Qt::Key_Up:
+ setContentsPos( contentsX(), contentsY() - 10 );
+ break;
+ case Qt::Key_Left:
+ setContentsPos( contentsX() - 10, contentsY() );
+ break;
+ case Qt::Key_Right:
+ setContentsPos( contentsX() + 10, contentsY() );
+ break;
+ case Qt::Key_PageUp:
+ setContentsPos( contentsX(), contentsY() - visibleHeight() );
+ break;
+ case Qt::Key_PageDown:
+ setContentsPos( contentsX(), contentsY() + visibleHeight() );
+ break;
+ case Qt::Key_Home:
+ setContentsPos( contentsX(), 0 );
+ break;
+ case Qt::Key_End:
+ setContentsPos( contentsX(), contentsHeight() - visibleHeight() );
+ break;
+ default:
+ break;
+ }
+ }
+ // The key events in read-write mode are handled by eventFilter(), otherwise
+ // we don't get <Tab> key presses.
+}
+
+void KWCanvas::switchViewMode( const QString& newViewMode )
+{
+ delete m_viewMode;
+ m_viewMode = KWViewMode::create( newViewMode, m_doc, this );
+}
+
+void KWCanvas::mpCreate( const QPoint& normalPoint, bool noGrid )
+{
+ KoPoint docPoint = m_doc->unzoomPoint( normalPoint );
+ if ( m_doc->snapToGrid() && !noGrid )
+ applyGrid( docPoint );
+ m_insRect.setCoords( docPoint.x(), docPoint.y(), 0, 0 );
+ m_deleteMovingRect = false;
+}
+
+void KWCanvas::mpCreatePixmap( const QPoint& normalPoint, bool noGrid )
+{
+ if ( !m_kopicture.isNull() )
+ {
+ // Apply grid for the first corner only
+ KoPoint docPoint = m_doc->unzoomPoint( normalPoint );
+ if ( m_doc->snapToGrid() && ! noGrid )
+ applyGrid( docPoint );
+ int pageNum = m_doc->pageManager()->pageNumber( docPoint );
+ m_insRect.setRect( docPoint.x(), docPoint.y(), 0, 0 );
+ m_deleteMovingRect = false;
+
+ if ( !m_pixmapSize.isEmpty() )
+ {
+ // This ensures 1-1 at 100% on screen, but allows zooming and printing with correct DPI values
+ uint width = qRound( (double)m_pixmapSize.width() * m_doc->zoomedResolutionX() / POINT_TO_INCH( KoGlobal::dpiX() ) );
+ uint height = qRound( (double)m_pixmapSize.height() * m_doc->zoomedResolutionY() / POINT_TO_INCH( KoGlobal::dpiY() ) );
+ m_insRect.setWidth( m_doc->unzoomItX( width ) );
+ m_insRect.setHeight( m_doc->unzoomItY( height ) );
+ // Apply reasonable limits
+ width = kMin( width, m_doc->paperWidth(pageNum) - normalPoint.x() - 5 );
+ height = kMin( height, m_doc->paperHeight(pageNum) - normalPoint.y() - 5 );
+ // And apply aspect-ratio if set
+ if ( m_keepRatio )
+ {
+ double ratio = ((double) m_pixmapSize.width()) / ((double) m_pixmapSize.height());
+ applyAspectRatio( ratio, m_insRect );
+ }
+
+ QPoint nPoint( normalPoint.x() + m_doc->zoomItX( m_insRect.width() ),
+ normalPoint.y() + m_doc->zoomItY( m_insRect.height() ) );
+ QPoint vPoint = m_viewMode->normalToView( nPoint );
+ vPoint = contentsToViewport( vPoint );
+ QRect viewportRect( contentsX(), contentsY(), visibleWidth(), visibleHeight() );
+ if ( viewportRect.contains( vPoint ) ) // Don't move the mouse out of the viewport
+ QCursor::setPos( viewport()->mapToGlobal( vPoint ) );
+ }
+ emit docStructChanged(Pictures);
+ if ( !m_doc->showGrid() && m_doc->snapToGrid() )
+ repaintContents( FALSE ); //draw the grid over the whole canvas
+ }
+}
+
+void KWCanvas::contentsMousePressEvent( QMouseEvent *e )
+{
+ QPoint normalPoint = m_viewMode->viewToNormal( e->pos() );
+ KoPoint docPoint = m_doc->unzoomPoint( normalPoint );
+
+
+ if ( e->button() == LeftButton )
+ {
+ m_mousePressed = true;
+ }
+
+ // Only edit-mode (and only LMB) allowed on read-only documents (to select text)
+ if ( !m_doc->isReadWrite() && ( m_mouseMode != MM_EDIT || e->button() != LeftButton ) )
+ return;
+ if ( m_printing )
+ return;
+
+ // This code here is common to all mouse buttons, so that RMB and MMB place the cursor (or select the frame) too
+ switch ( m_mouseMode ) {
+ case MM_EDIT:
+ {
+ if(! viewMode()->hasFrames() ) { // for the text mode we just forward the click to the text
+ // first, make clicks left of text be on the border;
+ docPoint = KoPoint(QMAX(0, docPoint.x()), QMAX(0, docPoint.y()));
+ if ( m_currentFrameSetEdit )
+ m_currentFrameSetEdit->mousePressEvent( e, normalPoint, docPoint );
+ break;
+ }
+ // See if we clicked on a frame's border
+ m_mouseMeaning = m_frameViewManager->mouseMeaning( docPoint, e->state());
+
+ //kdDebug(32001) << "contentsMousePressEvent meaning=" << m_mouseMeaning << endl;
+ switch ( m_mouseMeaning ) {
+ case MEANING_MOUSE_INSIDE:
+ case MEANING_MOUSE_OVER_LINK:
+ case MEANING_MOUSE_OVER_FOOTNOTE:
+ case MEANING_MOUSE_INSIDE_TEXT:
+ case MEANING_ACTIVATE_PART:
+ {
+ // LMB/MMB inside a frame always unselects all frames
+ // RMB inside a frame unselects too, except when
+ // right-clicking on a selected frame
+ KWFrameView *view = m_frameViewManager->view( docPoint, KWFrameViewManager::frameOnTop );
+ if ( ! ( e->button() == RightButton && view && view->selected() ) )
+ selectAllFrames( false );
+
+ KWFrame * frame = view ? view->frame() : 0L;
+ KWFrameSet * fs = frame ? frame->frameSet() : 0L;
+ if ( fs && fs->groupmanager() )
+ fs = fs->groupmanager();
+ bool emitChanged = false;
+ if ( fs )
+ {
+ // Clicked inside a frame - start editing it
+ emitChanged = checkCurrentEdit( fs );
+ }
+
+ if ( m_currentFrameSetEdit )
+ m_currentFrameSetEdit->mousePressEvent( e, normalPoint, docPoint );
+
+ if ( emitChanged ) { // emitted after mousePressEvent [for tables]
+ emit currentFrameSetEditChanged();
+ emit updateRuler();
+ }
+
+ if ( m_frameInline )
+ {
+ bool inlineCreated = true;
+ if(m_frameInlineType == FT_TABLE)
+ inlineCreated = insertInlineTable();
+ else if(m_frameInlineType == FT_PICTURE)
+ inlineCreated = insertInlinePicture();
+ if (!inlineCreated)
+ KMessageBox::information(0L, i18n("Read-only content cannot be changed. No modifications will be accepted."));
+ }
+ break;
+ }
+ case MEANING_RESIZE_COLUMN:
+ case MEANING_RESIZE_ROW:
+ {
+ terminateCurrentEdit();
+
+ // We know we're resizing a row or column, but we don't know which one yet...
+ // We're between two rows (or columns) so frameUnderMouse is a bit unprecise...
+ // We need it to find out which table we clicked on, though.
+ KWFrameView *view = m_frameViewManager->view(docPoint, KWFrameViewManager::frameOnTop);
+ if (view)
+ {
+ KWTableFrameSet::Cell* cell = dynamic_cast<KWTableFrameSet::Cell *>(view->frame()->frameSet());
+ if ( cell )
+ {
+ KWTableFrameSet* table = cell->groupmanager();
+ if ( m_mouseMeaning == MEANING_RESIZE_COLUMN )
+ {
+ m_rowColResized = table->columnEdgeAt( docPoint.x() );
+ m_previousTableSize = table->columnSize( m_rowColResized );
+ }
+ else
+ {
+ m_rowColResized = table->rowEdgeAt( docPoint.y() );
+ m_previousTableSize = table->rowSize( m_rowColResized );
+ }
+ m_currentTable = table;
+ kdDebug(32002) << "resizing row/col edge. m_rowColResized=" << m_rowColResized << endl;
+ }
+ }
+ break;
+ }
+ default:
+ m_mousePressed = true;
+ m_deleteMovingRect = false;
+
+ delete m_interactionPolicy;
+ m_interactionPolicy = InteractionPolicy::createPolicy(this, m_mouseMeaning, docPoint, e->button(), e->state());
+ if(m_interactionPolicy)
+ terminateCurrentEdit();
+ viewport()->setCursor( m_frameViewManager->mouseCursor( docPoint, e->state() ) );
+ }
+ }
+ break;
+ case MM_CREATE_TEXT: case MM_CREATE_PART: case MM_CREATE_TABLE:
+ case MM_CREATE_FORMULA:
+ if ( e->button() == LeftButton )
+ mpCreate( normalPoint, e->state() & Qt::ShiftButton);
+ break;
+ case MM_CREATE_PIX:
+ if ( e->button() == LeftButton )
+ mpCreatePixmap( normalPoint, e->state() & Qt::ShiftButton );
+ break;
+ default: break;
+ }
+ m_scrollTimer->start( 50 );
+
+ if ( e->button() == MidButton ) {
+ if ( m_doc->isReadWrite() && m_currentFrameSetEdit && m_mouseMode == MM_EDIT )
+ {
+ QApplication::clipboard()->setSelectionMode( true );
+ m_currentFrameSetEdit->paste();
+ QApplication::clipboard()->setSelectionMode( false );
+ }
+ }
+ else if ( e->button() == RightButton ) {
+ if(!m_doc->isReadWrite()) // The popups are not available in readonly mode, since the GUI isn't built...
+ return;
+ if ( m_deleteMovingRect )
+ deleteMovingRect();
+ // rmb menu
+ switch ( m_mouseMode )
+ {
+ case MM_EDIT:
+ if ( !viewMode()->hasFrames() ) { // text view mode
+ KWFrameView *view = m_frameViewManager->view(m_doc->frameSet( 0 )->frame(0));
+ view->showPopup(docPoint, m_gui->getView(), QCursor::pos());
+ }
+ else
+ m_frameViewManager->showPopup(docPoint, m_gui->getView(), e->state(), QCursor::pos());
+ break;
+ case MM_CREATE_TEXT:
+ case MM_CREATE_PART:
+ case MM_CREATE_TABLE:
+ case MM_CREATE_FORMULA:
+ case MM_CREATE_PIX:
+ setMouseMode( MM_EDIT );
+ default: break;
+ }
+ m_mousePressed = false;
+ }
+}
+
+// Called by KWTableDia
+void KWCanvas::createTable( unsigned int rows, unsigned int cols,
+ int wid, int hei,
+ bool isFloating,
+ KWTableTemplate *tt, int format )
+{
+ // Remember for next time in any case
+ m_table.rows = rows;
+ m_table.cols = cols;
+ m_table.width = wid;
+ m_table.height = hei;
+ m_table.floating = isFloating;
+ m_table.format = format;
+
+ m_table.tableTemplateName = tt ? tt->displayName():QString::null;
+ m_table.tt = tt;
+
+ if ( isFloating )
+ {
+ m_frameInline=true;
+ m_frameInlineType=FT_TABLE;
+ m_gui->getView()->displayFrameInlineInfo();
+ }
+ else
+ {
+ m_frameInline=false;
+ setMouseMode( MM_CREATE_TABLE );
+ }
+}
+
+bool KWCanvas::insertInlinePicture() // also called by DCOP
+{
+ bool inserted = m_gui->getView()->insertInlinePicture();
+ if ( inserted )
+ m_frameInline = false;
+ return inserted;
+}
+
+bool KWCanvas::insertInlineTable()
+{
+ KWTextFrameSetEdit * edit = dynamic_cast<KWTextFrameSetEdit *>(m_currentFrameSetEdit);
+ if(edit)
+ {
+ if ( edit->textFrameSet()->textObject()->protectContent() )
+ return false;
+ m_insRect = KoRect( 0, 0, edit->frameSet()->frame(0)->width(), 10 );
+
+ KWTableFrameSet * table = createTable();
+ m_doc->addFrameSet( table, false );
+ edit->insertFloatingFrameSet( table, i18n("Insert Inline Table") );
+ table->finalize();
+
+ if (m_table.tt) {
+ KWTableTemplateCommand *ttCmd=new KWTableTemplateCommand( "Apply template to inline table", table, m_table.tt );
+ m_doc->addCommand(ttCmd);
+ ttCmd->execute();
+ }
+
+ m_doc->updateAllFrames();
+ m_doc->refreshDocStructure(Tables);
+ }
+ m_gui->getView()->updateFrameStatusBarItem();
+ m_frameInline = false;
+ return true;
+}
+
+void KWCanvas::applyGrid( KoPoint &p )
+{
+ if ( m_viewMode->type() != "ModeNormal" )
+ return;
+ // The 1e-10 here is a workaround for some weird division problem.
+ // 360.00062366 / 2.83465058 gives 127 'exactly' when shown as a double,
+ // but when casting into an int, we get 126. In fact it's 127 - 5.64e-15 !
+
+ // This is a problem when calling applyGrid twice, we get 1 less than the time before.
+ p.setX( static_cast<int>( p.x() / m_doc->gridX() + 1e-10 ) * m_doc->gridX() );
+ p.setY( static_cast<int>( p.y() / m_doc->gridY() + 1e-10 ) * m_doc->gridY() );
+
+ //FIXME It doesn't work in preview mode - apply viewmode
+}
+
+void KWCanvas::drawGrid( QPainter &p, const QRect& rect )
+{
+ // Grid-positioning makes no sense in text view mode
+ if ( !m_viewMode->hasFrames() )
+ return;
+ QPen pen = QPen( Qt::black, 6, Qt::DotLine );
+ QPen oldPen = p.pen();
+ p.setPen( pen );
+
+ const double offsetX = m_doc->gridX();
+ const double offsetY = m_doc->gridY();
+
+ // per page, this is needed to paint correctly on preview mode as well as making sure
+ // we start the grid from the topleft of each page.
+ for ( int pgNum = m_doc->startPage() ; pgNum <= m_doc->lastPage() ; ++pgNum) {
+ const QRect pageRect = m_viewMode->viewPageRect( pgNum );
+ const QRect crect = pageRect & rect;
+ if ( crect.isEmpty() )
+ continue;
+
+ // To convert back to view coordinates later we can calculate the offset for each
+ // point again, or we can do it one time for the page and re-use the answer.
+ KoPoint pageTopLeft (0, m_doc->pageManager()->topOfPage(pgNum) + 2); // +2 to get around rounding problems..
+ QPoint pageTopLeftView = m_viewMode->normalToView( m_doc->zoomPoint(pageTopLeft) );
+
+ // docRect is the part of the document that needs to be painted.. Coordinates in pt
+ const KoRect docRect = m_doc->unzoomRect( m_viewMode->viewToNormal( crect ) );
+ // kdDebug() << "drawGrid page " << pgNum << " pageRect=" << pageRect << " crect=" << crect << " docRect=" << docRect << endl;
+
+ // the following is effectively a docRect.y() modulo offsetY
+ const double firstOffsetY = pageTopLeft.y() - offsetY * static_cast<int>( docRect.y() / offsetY );
+ const double bottom = docRect.bottom() - pageTopLeft.y();
+
+ for ( double x = 0; x <= docRect.right(); x += offsetX ) {
+ const int zoomedX = m_doc->zoomItX( x ) + pageTopLeftView.x();
+ for ( double y = firstOffsetY; y <= bottom; y += offsetY ) {
+ const int zoomedY = m_doc->zoomItY( y ) + pageTopLeftView.y();
+ p.drawPoint( zoomedX, zoomedY );
+ }
+ }
+ }
+
+ p.setPen( oldPen );
+}
+
+void KWCanvas::applyAspectRatio( double ratio, KoRect& insRect )
+{
+ double width = insRect.width();
+ double height = insRect.height();
+ if ( width < height ) // the biggest border is the one in control
+ width = height * ratio;
+ else
+ height = width / ratio;
+ insRect.setRight( insRect.left() + width );
+ insRect.setBottom( insRect.top() + height );
+ //kdDebug() << "KWCanvas::applyAspectRatio: width=" << width << " height=" << height << " insRect=" << DEBUGRECT(insRect) << endl;
+}
+
+void KWCanvas::mmCreate( const QPoint& normalPoint, bool noGrid ) // Mouse move when creating a frame
+{
+ QPainter p;
+ p.begin( viewport() );
+ p.translate( -contentsX(), -contentsY() );
+ p.setRasterOp( NotROP );
+ p.setPen( black );
+ p.setBrush( NoBrush );
+
+ if ( m_deleteMovingRect )
+ drawMovingRect( p );
+
+ int page = m_doc->pageManager()->pageNumber( m_insRect );
+ if( page == -1) {
+ return;
+ }
+ KoRect oldRect = m_insRect;
+
+ // Resize the rectangle
+ KoPoint docPoint = m_doc->unzoomPoint( normalPoint );
+ if ( m_doc->snapToGrid() && m_mouseMode != MM_CREATE_PIX && !noGrid )
+ applyGrid( docPoint );
+
+ m_insRect.setRight( docPoint.x() );
+ m_insRect.setBottom( docPoint.y() );
+
+ // But not out of the page
+ KoRect r = m_insRect.normalize();
+ if ( !m_doc->pageManager()->page(page)->rect().contains(r) )
+ {
+ // Even better would be to go to the limit of the page boundary, so that the result,
+ // when moving the mouse of the page, doesn't depend on how fast we're moving it...
+ m_insRect = oldRect;
+ // #### QCursor::setPos( viewport()->mapToGlobal( zoomPoint( m_insRect.bottomRight() ) ) );
+ }
+
+ // Apply keep-aspect-ratio feature
+ if ( m_mouseMode == MM_CREATE_PIX && m_keepRatio )
+ {
+ double ratio = (double)m_pixmapSize.width() / (double)m_pixmapSize.height();
+ applyAspectRatio( ratio, m_insRect );
+ }
+
+ drawMovingRect( p );
+ p.end();
+ m_deleteMovingRect = true;
+}
+
+void KWCanvas::drawMovingRect( QPainter & p )
+{
+ p.setPen( black );
+ p.drawRect( m_viewMode->normalToView( m_doc->zoomRect( m_insRect ) ) );
+}
+
+void KWCanvas::deleteMovingRect()
+{
+ Q_ASSERT( m_deleteMovingRect );
+ QPainter p;
+ p.begin( viewport() );
+ p.translate( -contentsX(), -contentsY() );
+ p.setRasterOp( NotROP );
+ p.setPen( black );
+ p.setBrush( NoBrush );
+ drawMovingRect( p );
+ m_deleteMovingRect = false;
+ p.end();
+}
+
+void KWCanvas::contentsMouseMoveEvent( QMouseEvent *e )
+{
+ if ( m_printing )
+ return;
+ QPoint normalPoint = m_viewMode->viewToNormal( e->pos() );
+ if(normalPoint.x() == -1) // e->pos() is an exceptional state...
+ return;
+ KoPoint docPoint = m_doc->unzoomPoint( normalPoint );
+
+ if ( m_mousePressed ) {
+ //doAutoScroll();
+
+ switch ( m_mouseMode ) {
+ case MM_EDIT:
+ {
+ if ( m_currentFrameSetEdit )
+ m_currentFrameSetEdit->mouseMoveEvent( e, normalPoint, docPoint );
+ if( ! m_doc->isReadWrite() )
+ break;
+ if ( m_mouseMeaning == MEANING_RESIZE_COLUMN || m_mouseMeaning == MEANING_RESIZE_ROW )
+ {
+ // TODO undo/redo support (esp. in mouse-release)
+ QRect oldRect( m_viewMode->normalToView( m_doc->zoomRect( m_currentTable->boundingRect() ) ) );
+ if ( m_mouseMeaning == MEANING_RESIZE_ROW )
+ m_currentTable->resizeRow( m_rowColResized, docPoint.y() );
+ else
+ m_currentTable->resizeColumn( m_rowColResized, docPoint.x() );
+ // Repaint only the changed rects (oldRect U newRect)
+ QRect newRect( m_viewMode->normalToView( m_doc->zoomRect( m_currentTable->boundingRect() ) ) );
+ repaintContents( QRegion(oldRect).unite(newRect).boundingRect(), FALSE );
+ }
+ else if (m_interactionPolicy) {
+ m_interactionPolicy->handleMouseMove(e->state(),
+ m_doc->unzoomPoint( normalPoint ));
+ m_interactionPolicy->hadDragEvents();
+ }
+ } break;
+ case MM_CREATE_TEXT: case MM_CREATE_PIX: case MM_CREATE_PART:
+ case MM_CREATE_TABLE: case MM_CREATE_FORMULA:
+ mmCreate( normalPoint, e->state() & ShiftButton );
+ default:
+ break;
+ }
+ }
+ else {
+ if ( m_mouseMode == MM_EDIT )
+ {
+ MouseMeaning meaning = m_frameViewManager->mouseMeaning( docPoint, e->state() );
+ switch ( meaning ) {
+ case MEANING_MOUSE_OVER_FOOTNOTE:
+ {
+ KWFrameView *view = m_frameViewManager->view(docPoint, KWFrameViewManager::frameOnTop);
+ KWFrame* frame = view ? view->frame() : 0;
+ KWFrameSet * fs = frame ? frame->frameSet() : 0;
+ if (fs && fs->type() == FT_TEXT)
+ {
+ KoVariable* var = static_cast<KWTextFrameSet *>(fs)->variableUnderMouse(docPoint);
+ if ( var )
+ {
+ KWFootNoteVariable * footNoteVar = dynamic_cast<KWFootNoteVariable *>( var );
+ if ( footNoteVar )
+ {
+ // show the content of the footnote in the status bar
+ gui()->getView()->setTemporaryStatusBarText( footNoteVar->frameSet()->textDocument()->firstParag()->string()->toString() );
+ m_temporaryStatusBarTextShown = true;
+ }
+ }
+
+ }
+ break;
+ }
+ case MEANING_MOUSE_OVER_LINK:
+ {
+ KWFrameView *view = m_frameViewManager->view(docPoint, KWFrameViewManager::frameOnTop);
+ KWFrame* frame = view ? view->frame() : 0;
+ KWFrameSet * fs = frame ? frame->frameSet() : 0L;
+ if (fs && fs->type() == FT_TEXT)
+ {
+ KWTextFrameSet *frameset = static_cast<KWTextFrameSet *>(fs);
+ //show the link target in the status bar
+ QString link = frameset->linkVariableUnderMouse(docPoint)->url();
+ if ( link.startsWith("bkm://") )
+ link.replace( 0, 6, i18n("Bookmark target: ") );
+ gui()->getView()->setTemporaryStatusBarText( link );
+ m_temporaryStatusBarTextShown = true;
+ }
+ break;
+ }
+ default:
+ resetStatusBarText();
+ break;
+ }
+ if(viewMode()->hasFrames())
+ viewport()->setCursor( m_frameViewManager->mouseCursor( docPoint, e->state() ) );
+ else
+ viewport()->setCursor( Qt::ibeamCursor );
+ }
+ }
+}
+
+void KWCanvas::mrEditFrame() {
+ //kdDebug() << "KWCanvas::mrEditFrame" << endl;
+ if(m_interactionPolicy) {
+ m_interactionPolicy->finishInteraction();
+ KCommand *cmd = m_interactionPolicy->createCommand();
+ if(cmd)
+ m_doc->addCommand(cmd);
+ delete(m_interactionPolicy);
+ m_interactionPolicy = 0;
+ if ( !m_doc->showGrid() && m_doc->snapToGrid() )
+ repaintContents();
+ }
+ m_mousePressed = false;
+}
+
+KCommand *KWCanvas::createTextBox( const KoRect & rect )
+{
+ if ( !m_doc->snapToGrid() || ( rect.width() > m_doc->gridX() && rect.height() > m_doc->gridY() ) ) {
+ KWFrame *frame = new KWFrame(0L, rect.x(), rect.y(), rect.width(), rect.height() );
+ frame->setNewFrameBehavior(KWFrame::Reconnect);
+ frame->setZOrder( m_doc->maxZOrder( frame->pageNumber(m_doc) ) + 1 ); // make sure it's on top
+
+ QString name = m_doc->generateFramesetName( i18n( "Text Frameset %1" ) );
+ KWTextFrameSet *_frameSet = new KWTextFrameSet(m_doc, name );
+ _frameSet->addFrame( frame );
+ m_doc->addFrameSet( _frameSet );
+ KWCreateFrameCommand *cmd=new KWCreateFrameCommand( i18n("Create Text Frame"), frame );
+ if ( checkCurrentEdit(frame->frameSet(), true) )
+ emit currentFrameSetEditChanged();
+ return cmd;
+ }
+ return 0L;
+}
+
+void KWCanvas::mrCreateText()
+{
+ m_insRect = m_insRect.normalize();
+ if ( !m_doc->snapToGrid() || ( m_insRect.width() > m_doc->gridX() && m_insRect.height() > m_doc->gridY() ) ) {
+ KWFrame *frame = new KWFrame(0L, m_insRect.x(), m_insRect.y(), m_insRect.width(), m_insRect.height() );
+ frame->setMinimumFrameHeight( frame->height() ); // so that AutoExtendFrame doesn't resize it down right away
+ frame->setNewFrameBehavior(KWFrame::Reconnect);
+ frame->setZOrder( m_doc->maxZOrder( frame->pageNumber(m_doc) ) + 1 ); // make sure it's on top
+ KWFrameDia frameDia( this, frame, m_doc, FT_TEXT );
+ frameDia.setCaption(i18n("Connect Frame"));
+ frameDia.exec();
+ if ( checkCurrentEdit(frame->frameSet(), true) )
+ emit currentFrameSetEditChanged();
+ }
+ setMouseMode( MM_EDIT );
+ m_doc->repaintAllViews();
+ emit docStructChanged(TextFrames);
+ emit currentFrameSetEditChanged();
+}
+
+void KWCanvas::mrCreatePixmap()
+{
+ // kdDebug() << "KWCanvas::mrCreatePixmap m_insRect=" << DEBUGRECT(m_insRect) << endl;
+ Q_ASSERT(m_insRect.width() > 0 && m_insRect.height() > 0);
+ // Make sure the pic is completely in document.
+ double ratio = m_insRect.width() / m_insRect.height();
+ KoRect picRect(m_doc->pageManager()->clipToDocument(m_insRect.topLeft()),
+ m_doc->pageManager()->clipToDocument(m_insRect.bottomRight()) );
+ picRect = picRect.normalize();
+
+ // Make sure it's completely on page.
+ KWPage *page = m_doc->pageManager()->page( picRect.bottom() );
+ KoRect pageRect = page->rect();
+ picRect = pageRect.intersect(picRect);
+
+ // make sure we keep ratio!
+ double height = picRect.width() / ratio ;
+ if(picRect.height() > height)
+ picRect.setBottom(picRect.top() + height);
+ else // moving bottom would make it bigger, so alter width
+ picRect.setRight(picRect.left() + ratio * picRect.height());
+
+ setMouseMode( MM_EDIT );
+ if ( !m_kopicture.isNull() ) {
+ KWPictureFrameSet *fs = new KWPictureFrameSet( m_doc, QString::null /*automatic name*/ );
+ fs->insertPicture( m_kopicture );
+ fs->setKeepAspectRatio( m_keepRatio );
+ KWFrame *frame = new KWFrame(fs, picRect.x(), picRect.y(), picRect.width(),
+ picRect.height() );
+ frame->setZOrder( m_doc->maxZOrder( page->pageNumber() ) +1 ); // make sure it's on top
+ fs->addFrame( frame, false );
+ m_doc->addFrameSet( fs );
+ KWCreateFrameCommand *cmd=new KWCreateFrameCommand( i18n("Insert Picture"), frame );
+ m_doc->addCommand(cmd);
+ m_doc->frameChanged( frame );
+ frameViewManager()->view(frame)->setSelected(true);
+ }
+ emit docStructChanged(Pictures);
+}
+
+void KWCanvas::mrCreatePart() // mouse release, when creating part
+{
+ m_insRect = m_insRect.normalize();
+ if ( !m_doc->snapToGrid() || ( m_insRect.width() > m_doc->gridX() && m_insRect.height() > m_doc->gridY() ) ) {
+ KWPartFrameSet *fs = m_doc->insertObject( m_insRect, m_partEntry, this );
+Q_ASSERT(viewMode()->canvas());
+ if(fs)
+ fs->updateChildGeometry(); // set initial coordinates of 'ch' correctly
+ }
+ setMouseMode( MM_EDIT );
+ emit docStructChanged(Embedded);
+}
+
+void KWCanvas::mrCreateFormula()
+{
+ m_insRect = m_insRect.normalize();
+ if ( !m_doc->snapToGrid() || ( m_insRect.width() > m_doc->gridX() && m_insRect.height() > m_doc->gridY() ) ) {
+ KWFormulaFrameSet *frameset = new KWFormulaFrameSet( m_doc, QString::null );
+ KWFrame *frame = new KWFrame(frameset, m_insRect.x(), m_insRect.y(), m_insRect.width(), m_insRect.height() );
+ frame->setZOrder( m_doc->maxZOrder( frame->pageNumber(m_doc) ) + 1 ); // make sure it's on top
+ frameset->addFrame( frame, false );
+ m_doc->addFrameSet( frameset );
+ KWCreateFrameCommand *cmd=new KWCreateFrameCommand( i18n("Create Formula Frame"), frame );
+ m_doc->addCommand(cmd);
+ m_doc->frameChanged( frame );
+ }
+ setMouseMode( MM_EDIT );
+ emit docStructChanged(FormulaFrames);
+}
+
+void KWCanvas::mrCreateTable()
+{
+ m_insRect = m_insRect.normalize();
+ if ( !m_doc->snapToGrid() || ( m_insRect.width() > m_doc->gridX() && m_insRect.height() > m_doc->gridY() ) ) {
+ if ( m_table.cols * s_minFrameWidth + m_insRect.x() > m_doc->pageManager()->pageLayout(0).ptWidth )
+ {
+ KMessageBox::sorry(0, i18n("KWord is unable to insert the table because there "
+ "is not enough space available."));
+ }
+ else {
+ KWTableFrameSet * table = createTable();
+ KMacroCommand *macroCmd = new KMacroCommand( i18n("Create Table") );
+
+ KWCreateTableCommand *cmd=new KWCreateTableCommand( "Create table", table );
+ macroCmd->addCommand(cmd);
+ if (m_table.tt) {
+ KWTableTemplateCommand *ttCmd=new KWTableTemplateCommand( "Apply template to table", table, m_table.tt );
+ macroCmd->addCommand(ttCmd);
+ }
+ m_doc->addCommand(macroCmd);
+ macroCmd->execute();
+
+ emit docStructChanged(Tables);
+ }
+ m_doc->updateAllFrames();
+ m_doc->layout();
+ repaintAll();
+
+ }
+ setMouseMode( MM_EDIT );
+}
+
+KWTableFrameSet * KWCanvas::createTable() // uses m_insRect and m_table to create the table
+{
+ KWTableFrameSet *table = new KWTableFrameSet( m_doc, QString::null /*automatic name*/ );
+ int pageNum = m_doc->pageManager()->pageNumber(m_insRect.topLeft());
+
+ // Create a set of cells with random-size frames.
+ for ( unsigned int i = 0; i < m_table.rows; i++ ) {
+ for ( unsigned int j = 0; j < m_table.cols; j++ ) {
+ KWTableFrameSet::Cell *cell = new KWTableFrameSet::Cell( table, i, j, QString::null /*automatic name*/ );
+ KWFrame *frame = new KWFrame(cell, 0, 0, 0, 0, KWFrame::RA_BOUNDINGRECT ); // pos and size will be set in setBoundingRect
+ frame->setZOrder( m_doc->maxZOrder( pageNum ) + 1 ); // make sure it's on top
+ cell->addFrame( frame, false );
+ frame->setFrameBehavior(KWFrame::AutoExtendFrame);
+ frame->setNewFrameBehavior(KWFrame::NoFollowup);
+ }
+ }
+ KWTableFrameSet::CellSize w;
+ w=static_cast<KWTableFrameSet::CellSize>( m_table.width );
+ if(m_frameInline) w=KWTableFrameSet::TblManual;
+ table->setBoundingRect( m_insRect , w, static_cast<KWTableFrameSet::CellSize>( m_table.height ));
+ return table;
+}
+
+void KWCanvas::contentsMouseReleaseEvent( QMouseEvent * e )
+{
+ if ( m_printing )
+ return;
+ if ( m_scrollTimer->isActive() )
+ m_scrollTimer->stop();
+ if ( m_mousePressed ) {
+ if ( m_deleteMovingRect )
+ deleteMovingRect();
+
+ QPoint normalPoint = m_viewMode->viewToNormal( e->pos() );
+ KoPoint docPoint = m_doc->unzoomPoint( normalPoint );
+
+ if(m_insRect.bottom()==0 && m_insRect.right()==0) {
+ // if the user did not drag, just click; make a 200x150 square for him.
+ int page = m_doc->pageManager()->pageNumber(docPoint);
+ if(page == -1)
+ return;
+ KoPageLayout pageLayout = m_doc->pageManager()->pageLayout(page);
+ m_insRect.setLeft(QMIN(m_insRect.left(), pageLayout.ptWidth - 200));
+ m_insRect.setTop(QMIN(m_insRect.top(), pageLayout.ptHeight - 150));
+ m_insRect.setBottom(m_insRect.top()+150);
+ m_insRect.setRight(m_insRect.left()+200);
+ }
+ MouseMode old_mouseMove = m_mouseMode;
+ switch ( m_mouseMode ) {
+ case MM_EDIT:
+ if ( m_currentFrameSetEdit )
+ m_currentFrameSetEdit->mouseReleaseEvent( e, normalPoint, docPoint );
+ else {
+ if ( m_mouseMeaning == MEANING_RESIZE_COLUMN )
+ {
+ KWResizeColumnCommand *cmd = new KWResizeColumnCommand( m_currentTable, m_rowColResized, m_previousTableSize, docPoint.x() );
+ m_doc->addCommand(cmd);
+ cmd->execute();
+ }
+ else if ( m_mouseMeaning == MEANING_RESIZE_ROW )
+ {
+ KWResizeRowCommand *cmd = new KWResizeRowCommand( m_currentTable, m_rowColResized, m_previousTableSize, docPoint.y() );
+ m_doc->addCommand(cmd);
+ cmd->execute();
+ }
+ else
+ mrEditFrame();
+ m_mouseMeaning = MEANING_NONE;
+ }
+ break;
+ case MM_CREATE_TEXT:
+ mrCreateText();
+ break;
+ case MM_CREATE_PIX:
+ mrCreatePixmap();
+ break;
+ case MM_CREATE_PART:
+ mrCreatePart();
+ break;
+ case MM_CREATE_TABLE:
+ mrCreateTable();
+ break;
+ case MM_CREATE_FORMULA:
+ mrCreateFormula();
+ break;
+ }
+
+ if ( old_mouseMove != MM_EDIT && !m_doc->showGrid() && m_doc->snapToGrid() )
+ repaintContents( FALSE ); //draw the grid over the whole canvas
+ m_mousePressed = false;
+ }
+}
+
+void KWCanvas::contentsMouseDoubleClickEvent( QMouseEvent * e )
+{
+ if ( m_printing )
+ return;
+ QPoint normalPoint = m_viewMode->viewToNormal( e->pos() );
+ KoPoint docPoint = m_doc->unzoomPoint( normalPoint );
+ switch ( m_mouseMode ) {
+ case MM_EDIT:
+ if ( m_currentFrameSetEdit )
+ {
+ m_mousePressed = true; // needed for the dbl-click + move feature.
+ m_scrollTimer->start( 50 );
+ m_currentFrameSetEdit->mouseDoubleClickEvent( e, normalPoint, docPoint );
+ }
+ else
+ {
+ // Double-click on an embedded object should edit it, not pop up the frame dialog
+ // So we have to test for that.
+ KWFrameView *view = m_frameViewManager->selectedFrame();
+ bool isPartFrameSet = view && dynamic_cast<KWPartFrameSet*>(view->frame()->frameSet());
+ if ( !isPartFrameSet )
+ editFrameProperties();
+ // KWDocumentChild::hitTest and KWView::slotChildActivated take care of embedded objects
+ m_mousePressed = false;
+ }
+ break;
+ default:
+ break;
+ }
+}
+
+void KWCanvas::setFrameBackgroundColor( const QBrush &_backColor )
+{
+ QValueList<KWFrameView*> selectedFrames = m_frameViewManager->selectedFrames();
+ if (selectedFrames.isEmpty())
+ return;
+ bool colorChanged=false;
+ QPtrList<FrameIndex> frameindexList;
+ QPtrList<QBrush> oldColor;
+
+ QValueListIterator<KWFrameView*> framesIterator = selectedFrames.begin();
+ while(framesIterator != selectedFrames.end()) {
+ KWFrame *frame = KWFrameSet::settingsFrame( (*framesIterator)->frame() );
+ FrameIndex *index=new FrameIndex( frame );
+ frameindexList.append(index);
+
+ QBrush *_color=new QBrush(frame->backgroundColor());
+ oldColor.append(_color);
+
+ if (frame->frameSet() && frame->frameSet()->type()!=FT_PICTURE && frame->frameSet()->type()!=FT_PART && _backColor!=frame->backgroundColor())
+ {
+ colorChanged=true;
+ frame->setBackgroundColor(_backColor);
+ }
+ ++framesIterator;
+ }
+ if(colorChanged)
+ {
+ KWFrameBackGroundColorCommand *cmd=new KWFrameBackGroundColorCommand(i18n("Change Frame Background Color"),frameindexList,oldColor,_backColor);
+ m_doc->addCommand(cmd);
+ m_doc->repaintAllViews();
+ }
+ else
+ {
+ frameindexList.setAutoDelete(true);
+ oldColor.setAutoDelete(true);
+ }
+}
+
+void KWCanvas::editFrameProperties( KWFrameSet * frameset )
+{
+ KWFrameDia *frameDia;
+ KWFrame *frame = frameset->frame(0);
+ frameDia = new KWFrameDia( this, frame );
+ frameDia->exec();
+ delete frameDia;
+}
+
+void KWCanvas::editFrameProperties()
+{
+ QValueList<KWFrameView*> selectedFrames = m_frameViewManager->selectedFrames();
+ if(selectedFrames.count()==0) return;
+
+ KWFrameDia *frameDia;
+ if(selectedFrames.count()==1)
+ frameDia = new KWFrameDia( this, selectedFrames[0]->frame());
+ else { // multi frame dia.
+ QPtrList<KWFrame> frames;
+ QValueListIterator<KWFrameView*> framesIterator = selectedFrames.begin();
+ for(;framesIterator != selectedFrames.end(); ++framesIterator)
+ frames.append( (*framesIterator)->frame() );
+ frameDia = new KWFrameDia( this, frames );
+ }
+ frameDia->exec();
+ delete frameDia;
+}
+
+void KWCanvas::selectAllFrames( bool select ) {
+ QValueList<KWFrameView*> frameViews = m_frameViewManager->frameViewsIterator();
+ QValueList<KWFrameView*>::iterator frames = frameViews.begin();
+ for(; frames != frameViews.end(); ++frames ) {
+ KWFrameSet *fs = (*frames)->frame()->frameSet();
+ if ( !fs->isVisible() ) continue;
+ if ( select && fs->isMainFrameset() )
+ continue; // "select all frames" shouldn't select the page
+ (*frames)->setSelected(select);
+ }
+}
+
+void KWCanvas::tableSelectCell(KWTableFrameSet *table, KWFrameSet *cell)
+{
+ terminateCurrentEdit();
+ m_frameViewManager->view(cell->frame(0))->setSelected(true);
+ m_currentTable = table;
+}
+
+void KWCanvas::editFrameSet( KWFrameSet * frameSet, bool onlyText /*=false*/ )
+{
+ selectAllFrames( false );
+ bool emitChanged = checkCurrentEdit( frameSet, onlyText );
+
+ if ( emitChanged ) // emitted after mousePressEvent [for tables]
+ emit currentFrameSetEditChanged();
+ emit updateRuler();
+}
+
+void KWCanvas::editTextFrameSet( KWFrameSet * fs, KoTextParag* parag, int index )
+{
+ selectAllFrames( false );
+
+#if 0
+ //active header/footer when it's possible
+ // DF: what is this code doing here?
+ if ( fs->isAHeader() && !m_doc->isHeaderVisible() && !(viewMode()->type()=="ModeText"))
+ m_doc->setHeaderVisible( true );
+ if ( fs->isAFooter() && !m_doc->isFooterVisible() && !(viewMode()->type()=="ModeText"))
+ m_doc->setFooterVisible( true );
+#endif
+
+ if ( !fs->isVisible( viewMode() ) )
+ return;
+ setMouseMode( MM_EDIT );
+ bool emitChanged = checkCurrentEdit( fs );
+
+ if ( m_currentFrameSetEdit && m_currentFrameSetEdit->frameSet()->type()==FT_TEXT ) {
+ if ( !parag )
+ {
+ KWTextDocument *tmp = static_cast<KWTextFrameSet*>(m_currentFrameSetEdit->frameSet())->kwTextDocument();
+ parag = tmp->firstParag();
+ }
+ // The _new_ cursor position must be visible.
+ KWTextFrameSetEdit *textedit = currentTextEdit();
+ if ( textedit ) {
+ textedit->hideCursor();
+ textedit->setCursor( parag, index );
+ textedit->showCursor();
+ textedit->ensureCursorVisible();
+ }
+ }
+ if ( emitChanged )
+ emit currentFrameSetEditChanged();
+ emit updateRuler();
+}
+
+void KWCanvas::ensureCursorVisible()
+{
+ Q_ASSERT( m_currentFrameSetEdit );
+ KWTextFrameSetEdit *textedit = currentTextEdit();
+ if ( textedit )
+ textedit->ensureCursorVisible();
+}
+
+bool KWCanvas::checkCurrentEdit( KWFrameSet * fs , bool onlyText )
+{
+ bool emitChanged = false;
+ if ( fs && m_currentFrameSetEdit && m_currentFrameSetEdit->frameSet() != fs )
+ {
+ KWTextFrameSet * tmp = dynamic_cast<KWTextFrameSet *>(fs );
+ if ( tmp && tmp->protectContent() && !m_doc->cursorInProtectedArea() )
+ return false;
+
+ KWTextFrameSetEdit *edit = currentTextEdit();
+ if(edit && onlyText)
+ {
+ // Don't use terminateCurrentEdit here, we want to emit changed only once
+ //don't remove selection in dnd
+ m_currentFrameSetEdit->terminate(false);
+ }
+ else
+ m_currentFrameSetEdit->terminate();
+ delete m_currentFrameSetEdit;
+ m_currentFrameSetEdit = 0L;
+ emitChanged = true;
+
+ }
+
+ // Edit the frameset "fs"
+ if ( fs && !m_currentFrameSetEdit )
+ {
+ KWTextFrameSet * tmp = dynamic_cast<KWTextFrameSet *>(fs );
+ if ( tmp && tmp->protectContent() && !m_doc->cursorInProtectedArea() )
+ return false;
+ // test for "text frameset only" if requested
+ if(fs->type()==FT_TABLE || fs->type()==FT_TEXT || !onlyText)
+ {
+ if ( fs->type() == FT_TABLE )
+ m_currentTable = static_cast<KWTableFrameSet *>(fs);
+ else if ( fs->type() == FT_TEXT )
+ m_currentTable = static_cast<KWTextFrameSet *>(fs)->groupmanager();
+ else
+ m_currentTable = 0L;
+ if ( m_currentTable ) {
+ m_currentFrameSetEdit = m_currentTable->createFrameSetEdit( this );
+ static_cast<KWTableFrameSetEdit *>( m_currentFrameSetEdit )->setCurrentCell( fs );
+ }
+ else
+ m_currentFrameSetEdit = fs->createFrameSetEdit( this );
+
+ if ( m_currentFrameSetEdit ) {
+ KWTextFrameSetEdit *edit = currentTextEdit();
+ if ( edit )
+ edit->setOverwriteMode( m_overwriteMode );
+ }
+ }
+ emitChanged = true;
+ }
+ return emitChanged;
+}
+
+void KWCanvas::terminateCurrentEdit()
+{
+ if(m_currentFrameSetEdit == 0)
+ return;
+ m_lastCaretPos = caretPos();
+ m_currentFrameSetEdit->terminate();
+ delete m_currentFrameSetEdit;
+ m_currentFrameSetEdit = 0L;
+ emit currentFrameSetEditChanged();
+ repaintAll();
+}
+
+void KWCanvas::terminateEditing( KWFrameSet *fs )
+{
+ if ( m_currentFrameSetEdit && m_currentFrameSetEdit->frameSet() == fs )
+ terminateCurrentEdit();
+ // Also deselect the frames from this frameset
+ QPtrListIterator<KWFrame> frameIt = fs->frameIterator();
+ for ( ; frameIt.current(); ++frameIt ) {
+ KWFrameView* view = m_frameViewManager->view(frameIt.current());
+ Q_ASSERT(view);
+ if(view) view->setSelected(false);
+ }
+}
+
+KWTextFrameSetEdit* KWCanvas::currentTextEdit() const
+{
+ if ( m_currentFrameSetEdit )
+ return dynamic_cast<KWTextFrameSetEdit *>(m_currentFrameSetEdit->currentTextEdit());
+ return 0;
+}
+
+void KWCanvas::setMouseMode( MouseMode newMouseMode )
+{
+ if ( m_mouseMode != newMouseMode )
+ {
+ selectAllFrames( false );
+
+ if ( newMouseMode != MM_EDIT )
+ terminateCurrentEdit();
+
+ m_mouseMode = newMouseMode;
+ if ( !m_doc->showGrid() && m_doc->snapToGrid() )
+ repaintContents( FALSE ); //draw the grid over the whole canvas
+ }
+ else
+ m_mouseMode = newMouseMode;
+ emit currentMouseModeChanged(m_mouseMode);
+
+ switch ( m_mouseMode ) {
+ case MM_EDIT: {
+ QPoint mousep = mapFromGlobal(QCursor::pos()) + QPoint( contentsX(), contentsY() );
+ QPoint normalPoint = m_viewMode->viewToNormal( mousep );
+ KoPoint docPoint = m_doc->unzoomPoint( normalPoint );
+ viewport()->setCursor( m_frameViewManager->mouseCursor( docPoint, 0 ) );
+ m_frameInline = false;
+ } break;
+ case MM_CREATE_TEXT:
+ case MM_CREATE_PIX:
+ case MM_CREATE_TABLE:
+ case MM_CREATE_FORMULA:
+ case MM_CREATE_PART:
+ viewport()->setCursor( crossCursor );
+ break;
+ }
+}
+
+void KWCanvas::insertPicture( const KoPicture& newPicture, QSize pixmapSize, bool _keepRatio )
+{
+ setMouseMode( MM_CREATE_PIX );
+ m_kopicture = newPicture;
+ m_pixmapSize = pixmapSize;
+ if ( pixmapSize.isEmpty() )
+ m_pixmapSize = newPicture.getOriginalSize();
+ m_keepRatio = _keepRatio;
+}
+
+void KWCanvas::insertPictureDirect( const KoPicture& picture, const KoPoint& pos, const QSize& sz )
+{
+ // Prepare things for mrCreatePixmap
+ m_pixmapSize = sz.isEmpty() ? picture.getOriginalSize() : sz;
+ m_kopicture = picture;
+ m_insRect = KoRect( pos.x(), pos.y(), m_doc->unzoomItX( m_pixmapSize.width() ), m_doc->unzoomItY( m_pixmapSize.height() ) );
+ m_keepRatio = true;
+ mrCreatePixmap();
+}
+
+void KWCanvas::insertPart( const KoDocumentEntry &entry )
+{
+ m_partEntry = entry;
+ if ( m_partEntry.isEmpty() )
+ {
+ setMouseMode( MM_EDIT );
+ return;
+ }
+ setMouseMode( MM_CREATE_PART );
+}
+
+void KWCanvas::contentsDragEnterEvent( QDragEnterEvent *e )
+{
+ int provides = KWView::checkClipboard( e );
+ if ( ( provides & KWView::ProvidesImage ) || KURLDrag::canDecode( e ) )
+ {
+ m_imageDrag = true;
+ e->acceptAction();
+ }
+ else
+ {
+ m_imageDrag = false;
+ if ( m_currentFrameSetEdit )
+ m_currentFrameSetEdit->dragEnterEvent( e );
+ }
+}
+
+void KWCanvas::contentsDragMoveEvent( QDragMoveEvent *e )
+{
+ if ( !m_imageDrag /*&& m_currentFrameSetEdit*/ )
+ {
+ QPoint normalPoint = m_viewMode->viewToNormal( e->pos() );
+ KoPoint docPoint = m_doc->unzoomPoint( normalPoint );
+ KWFrameView *view = m_frameViewManager->view(docPoint, KWFrameViewManager::frameOnTop);
+ KWFrame *frame = view ? view->frame() : 0;
+ KWFrameSet * fs = frame ? frame->frameSet() : 0L;
+ bool emitChanged = false;
+ if ( fs )
+ {
+ //kdDebug()<<"table :"<<table<<endl;
+ emitChanged = checkCurrentEdit( fs, true );
+ }
+ if ( m_currentFrameSetEdit )
+ {
+ m_currentFrameSetEdit->dragMoveEvent( e, normalPoint, docPoint );
+
+ if ( emitChanged ) // emitted after mousePressEvent [for tables]
+ emit currentFrameSetEditChanged();
+ }
+ }
+}
+
+void KWCanvas::contentsDragLeaveEvent( QDragLeaveEvent *e )
+{
+ if ( !m_imageDrag && m_currentFrameSetEdit )
+ m_currentFrameSetEdit->dragLeaveEvent( e );
+}
+
+void KWCanvas::contentsDropEvent( QDropEvent *e )
+{
+ QPoint normalPoint = m_viewMode->viewToNormal( e->pos() );
+ KoPoint docPoint = m_doc->unzoomPoint( normalPoint );
+
+ if ( QImageDrag::canDecode( e ) ) {
+ pasteImage( e, docPoint );
+ } else if ( KURLDrag::canDecode( e ) ) {
+
+ // TODO ask (with a popupmenu) between inserting a link and inserting the contents
+ // TODO fix khtml to export images when dragging an image+link (as it does when using "Copy")
+
+ KURL::List lst;
+ KURLDrag::decode( e, lst );
+
+ KURL::List::ConstIterator it = lst.begin();
+ for ( ; it != lst.end(); ++it ) {
+ const KURL &url( *it );
+
+ QString filename;
+ if ( !KIO::NetAccess::download( url, filename, this ) )
+ continue;
+
+ KMimeType::Ptr res = KMimeType::findByFileContent( filename );
+
+ if ( res && res->isValid() ) {
+ QString mimetype = res->name();
+ if ( mimetype.contains( "image" ) ) {
+ KoPictureKey key;
+ key.setKeyFromFile( filename );
+ KoPicture newKoPicture;
+ newKoPicture.setKey( key );
+ newKoPicture.loadFromFile( filename );
+ insertPictureDirect( newKoPicture, docPoint );
+ }
+ }
+ KIO::NetAccess::removeTempFile( filename );
+ }
+ }
+ else
+ {
+ if ( m_currentFrameSetEdit )
+ m_currentFrameSetEdit->dropEvent( e, normalPoint, docPoint, m_gui->getView() );
+ else
+ m_gui->getView()->pasteData( e, true );
+ }
+ m_mousePressed = false;
+ m_imageDrag = false;
+}
+
+void KWCanvas::pasteImage( QMimeSource *e, const KoPoint &docPoint )
+{
+ QImage i;
+ if ( !QImageDrag::decode(e, i) ) {
+ kdWarning() << "Couldn't decode image" << endl;
+ return;
+ }
+ KTempFile tmpFile( QString::null, ".png");
+ tmpFile.setAutoDelete( true );
+ if ( !i.save(tmpFile.name(), "PNG") ) {
+ kdWarning() << "Couldn't save image to " << tmpFile.name() << endl;
+ return;
+ }
+ m_pixmapSize = i.size();
+ // Prepare things for mrCreatePixmap
+ KoPictureKey key;
+ key.setKeyFromFile( tmpFile.name() );
+ KoPicture newKoPicture;
+ newKoPicture.setKey( key );
+ newKoPicture.loadFromFile( tmpFile.name() );
+ m_kopicture = newKoPicture;
+ m_insRect = KoRect( docPoint.x(), docPoint.y(), m_doc->unzoomItX( i.width() ), m_doc->unzoomItY( i.height() ) );
+ m_keepRatio = true;
+ mrCreatePixmap();
+}
+
+void KWCanvas::doAutoScroll()
+{
+ if ( !m_mousePressed )
+ {
+ m_scrollTimer->stop();
+ return;
+ }
+
+ // This code comes from khtml
+ QPoint pos( mapFromGlobal( QCursor::pos() ) );
+
+ pos = QPoint(pos.x() - viewport()->x(), pos.y() - viewport()->y());
+ if ( (pos.y() < 0) || (pos.y() > visibleHeight()) ||
+ (pos.x() < 0) || (pos.x() > visibleWidth()) )
+ {
+ int xm, ym;
+ viewportToContents(pos.x(), pos.y(), xm, ym);
+ if ( m_currentFrameSetEdit )
+ m_currentFrameSetEdit->focusOutEvent(); // Hide cursor
+ if ( m_deleteMovingRect )
+ deleteMovingRect();
+ ensureVisible( xm, ym, 0, 5 );
+ if ( m_currentFrameSetEdit )
+ m_currentFrameSetEdit->focusInEvent(); // Show cursor
+ }
+}
+
+void KWCanvas::slotContentsMoving( int cx, int cy )
+{
+ //QPoint nPointTop = m_viewMode->viewToNormal( QPoint( cx, cy ) );
+ QPoint nPointBottom = m_viewMode->viewToNormal( QPoint( cx + visibleWidth(), cy + visibleHeight() ) );
+ //kdDebug() << "KWCanvas::slotContentsMoving cx=" << cx << " cy=" << cy << endl;
+ //kdDebug() << " visibleWidth()=" << visibleWidth() << " visibleHeight()=" << visibleHeight() << endl;
+ // Update our "formatted paragraphs needs" in all the text framesets
+ QPtrList<KWTextFrameSet> textFrameSets = m_doc->allTextFramesets( false );
+ QPtrListIterator<KWTextFrameSet> fit( textFrameSets );
+ for ( ; fit.current() ; ++fit )
+ {
+ if(! fit.current()->isVisible()) continue;
+ fit.current()->updateViewArea( this, m_viewMode, nPointBottom );
+ }
+ // cx and cy contain the future values for contentsx and contentsy, so we need to
+ // pass them to updateRulerOffsets.
+ updateRulerOffsets( cx, cy );
+
+ // Tell KoView that the view transformations have changed (e.g. the centering of the page, or the scrolling offsets)
+ // so that it will reposition any active embedded object.
+ // This needs to be delayed since contents moving is emitted -before- moving,
+ // and from resizeEvent it's too early too.
+ QTimer::singleShot( 0, this, SIGNAL( viewTransformationsChanged() ) );
+}
+
+void KWCanvas::slotMainTextHeightChanged()
+{
+ // Check that the viewmode is a KWViewModeText, and that the rulers have been built already
+ if ( dynamic_cast<KWViewModeText *>(m_viewMode) && m_gui->getHorzRuler() )
+ {
+ slotNewContentsSize();
+ m_viewMode->setPageLayout( m_gui->getHorzRuler(), m_gui->getVertRuler(), KoPageLayout() /*unused*/ );
+ emit updateRuler();
+ }
+}
+
+void KWCanvas::slotNewContentsSize()
+{
+ QSize size = m_viewMode->contentsSize();
+ if ( size != QSize( contentsWidth(), contentsHeight() ) )
+ {
+ //kdDebug() << "KWCanvas::slotNewContentsSize " << size.width() << "x" << size.height() << endl;
+ resizeContents( size.width(), size.height() );
+ }
+}
+
+void KWCanvas::resizeEvent( QResizeEvent *e )
+{
+ slotContentsMoving( contentsX(), contentsY() );
+ QScrollView::resizeEvent( e );
+}
+
+void KWCanvas::scrollToOffset( const KoPoint & d )
+{
+ kdDebug() << "KWCanvas::scrollToOffset " << d.x() << "," << d.y() << endl;
+#if 0
+ bool blinking = blinkTimer.isActive();
+ if ( blinking )
+ stopBlinkCursor();
+#endif
+ QPoint nPoint = m_doc->zoomPoint( d );
+ QPoint cPoint = m_viewMode->normalToView( nPoint );
+ setContentsPos( cPoint.x(), cPoint.y() );
+
+#if 0
+ if ( blinking )
+ startBlinkCursor();
+#endif
+}
+
+void KWCanvas::updateRulerOffsets( int cx, int cy )
+{
+ if ( cx == -1 && cy == -1 )
+ {
+ cx = contentsX();
+ cy = contentsY();
+ }
+ // The offset is usually just the scrollview offset
+ // But we also need to offset to the current page, for the graduations
+ QPoint pc = m_viewMode->pageCorner();
+ //kdDebug() << "KWCanvas::updateRulerOffsets contentsX=" << cx << ", contentsY=" << cy << endl;
+ if (m_gui->getHorzRuler())
+ m_gui->getHorzRuler()->setOffset( cx - pc.x(), 0 );
+ if (m_gui->getVertRuler())
+ m_gui->getVertRuler()->setOffset( 0, cy - pc.y() );
+
+}
+
+bool KWCanvas::eventFilter( QObject *o, QEvent *e )
+{
+ if ( o == this || o == viewport() ) {
+
+ if(m_currentFrameSetEdit && o == this )
+ {
+ // Pass event to auto-hide-cursor code (see kcursor.h for details)
+ KCursor::autoHideEventFilter( o, e );
+ }
+
+ switch ( e->type() ) {
+ case QEvent::FocusIn:
+ // kdDebug() << "KWCanvas::eventFilter QEvent::FocusIn" << endl;
+ if ( m_currentFrameSetEdit && !m_printing )
+ m_currentFrameSetEdit->focusInEvent();
+ break;
+ case QEvent::FocusOut:
+ // kdDebug() << "KWCanvas::eventFilter QEvent::FocusOut" << endl;
+ if ( m_currentFrameSetEdit && !m_printing )
+ m_currentFrameSetEdit->focusOutEvent();
+ if ( m_scrollTimer->isActive() )
+ m_scrollTimer->stop();
+ m_mousePressed = false;
+ break;
+ case QEvent::AccelOverride: // was part of KeyPress - changed due to kdelibs BUG!
+ {
+ // kdDebug() << " KeyPress m_currentFrameSetEdit=" << m_currentFrameSetEdit << " isRW="<<m_doc->isReadWrite() << endl;
+ // kdDebug() << " m_printing=" << m_printing << " mousemode=" << m_mouseMode << " (MM_EDIT=" << MM_EDIT<<")"<<endl;
+ QKeyEvent * keyev = static_cast<QKeyEvent *>(e);
+#ifndef NDEBUG
+ // Debug keys
+ if ( ( keyev->state() & ControlButton ) && ( keyev->state() & ShiftButton ) )
+ {
+ switch ( keyev->key() ) {
+ case Qt::Key_P: // 'P' -> paragraph debug
+ printRTDebug( 0 );
+ keyev->accept();
+ break;
+ case Qt::Key_V: // 'V' -> verbose parag debug
+ printRTDebug( 1 );
+ keyev->accept();
+ break;
+ case Qt::Key_F: // 'F' -> frames debug
+ m_doc->printDebug();
+ kdDebug(32002) << "Current framesetedit: " << m_currentFrameSetEdit << " " <<
+ ( m_currentFrameSetEdit ? m_currentFrameSetEdit->frameSet()->className() : "" ) << endl;
+ keyev->accept();
+ break;
+ case Qt::Key_S: // 'S' -> styles debug
+ m_doc->printStyleDebug();
+ keyev->accept();
+ break;
+ case Qt::Key_M: // 'M' -> mark debug output
+ {
+ const QDateTime dtMark ( QDateTime::currentDateTime() );
+ kdDebug(32002) << "Developer mark: " << dtMark.toString("yyyy-MM-dd hh:mm:ss,zzz") << endl;
+ keyev->accept();
+ break;
+ }
+ default:
+ break;
+ };
+ // For some reason 'T' doesn't work (maybe kxkb)
+ }
+#endif
+ }
+ break;
+ case QEvent::KeyPress:
+ {
+ // kdDebug() << " KeyPress m_currentFrameSetEdit=" << m_currentFrameSetEdit << " isRW="<<m_doc->isReadWrite() << endl;
+ // kdDebug() << " m_printing=" << m_printing << " mousemode=" << m_mouseMode << " (MM_EDIT=" << MM_EDIT<<")"<<endl;
+ QKeyEvent * keyev = static_cast<QKeyEvent *>(e);
+ // By default PgUp and PgDown move the scrollbars and not the caret anymore - this is done here
+ if ( !m_doc->pgUpDownMovesCaret() && ( (keyev->state() & ShiftButton) == 0 )
+ && ( keyev->key() == Qt::Key_PageUp || keyev->key() == Key_PageDown ) )
+ {
+ viewportScroll( keyev->key() == Qt::Key_PageUp );
+ }
+ // Activate this code (and in focusNextPreviousChild() to allow Shift+Tab
+ // out of document window. Disabled because it conflicts with Shift+Tab inside a table.
+ // else if ( keyev->key() == Qt::Key_BackTab )
+ // return FALSE;
+ else if ( keyev->key() == KGlobalSettings::contextMenuKey() ) {
+ // The popups are not available in readonly mode, since the GUI isn't built...
+ if(!m_doc->isReadWrite()) return TRUE;
+ if (m_mouseMode != MM_EDIT) return TRUE;
+ KoPoint docPoint = m_doc->unzoomPoint( QCursor::pos() );
+
+ if ( viewMode()->type()=="ModeText") {
+ KWFrameView *view = m_frameViewManager->view(m_doc->frameSet( 0 )->frame(0));
+ view->showPopup(docPoint, m_gui->getView(), QCursor::pos());
+ }
+ else {
+ m_frameViewManager->showPopup( docPoint, m_gui->getView(), keyev->state(), pos());
+ }
+ return true;
+ }
+ else if ( keyev->key() == Qt::Key_Return && keyev->state() == 0
+ && (m_mouseMode != MM_EDIT || m_frameInline )) {
+ // When inserting an inline or non-line frame,
+ // simulate mouse press and release at caret position.
+ // In the case of a regular frame, the caret position was saved when
+ // they left edit mode. In the case of an inline frame,
+ // get current caret position, since user can type and move caret
+ // around before they click or hit Enter.
+ if (m_frameInline)
+ m_lastCaretPos = caretPos();
+ if (m_lastCaretPos.isNull()) return TRUE;
+ int page = m_doc->pageManager()->pageNumber(m_lastCaretPos);
+ if(page == -1) return TRUE;
+ QPoint normalPoint = m_doc->zoomPoint(m_lastCaretPos);
+ // Coordinate is at the very top of the caret. In the case of an
+ // inline frame, adjust slightly down and to the right in order
+ // to avoid "clicking" the frame border.
+ if (m_frameInline)
+ normalPoint += QPoint(2,2);
+ QPoint vP = m_viewMode->normalToView(normalPoint);
+ QPoint gP = mapToGlobal(vP);
+ QMouseEvent mevPress(QEvent::MouseButtonPress, vP,
+ gP, Qt::LeftButton, 0);
+ contentsMousePressEvent(&mevPress);
+ QMouseEvent mevRelease(QEvent::MouseButtonRelease, vP,
+ gP, Qt::LeftButton, 0);
+ contentsMouseReleaseEvent(&mevRelease);
+ }
+ else if ( keyev->key() == Qt::Key_Escape ) {
+ if ( m_mouseMode != MM_EDIT ) // Abort frame creation
+ setMouseMode( MM_EDIT );
+ else if(m_interactionPolicy) {
+ m_interactionPolicy->cancelInteraction();
+ delete(m_interactionPolicy);
+ m_interactionPolicy = 0;
+ m_mousePressed = false;
+
+ // reset cursor
+ QPoint mousep = mapFromGlobal(QCursor::pos()) + QPoint( contentsX(), contentsY() );
+ QPoint normalPoint = m_viewMode->viewToNormal( mousep );
+ KoPoint docPoint = m_doc->unzoomPoint( normalPoint );
+ viewport()->setCursor( m_frameViewManager->mouseCursor( docPoint, keyev->stateAfter() ) );
+ if ( !m_doc->showGrid() && m_doc->snapToGrid() )
+ repaintContents();
+ }
+ }
+ else if ( keyev->key() == Key_Insert && keyev->state() == 0 ) {
+ m_overwriteMode = !m_overwriteMode;
+ KWTextFrameSetEdit *edit = currentTextEdit();
+ if ( edit ) {
+ edit->setOverwriteMode( m_overwriteMode );
+ emit overwriteModeChanged( m_overwriteMode );
+ }
+ kdDebug()<<"Insert is pressed, overwrite mode: "<< m_overwriteMode << endl;
+ }
+ else // normal key processing
+ if ( m_currentFrameSetEdit && m_mouseMode == MM_EDIT && m_doc->isReadWrite() && !m_printing )
+ {
+ KWTextFrameSetEdit *edit = dynamic_cast<KWTextFrameSetEdit *>(m_currentFrameSetEdit );
+ if ( edit )
+ {
+ if ( !edit->textFrameSet()->textObject()->protectContent() || (keyev->text().length() == 0))
+ m_currentFrameSetEdit->keyPressEvent( keyev );
+ else if(keyev->text().length() > 0)
+ KMessageBox::information(this, i18n("Read-only content cannot be changed. No modifications will be accepted."));
+ }
+ else
+ m_currentFrameSetEdit->keyPressEvent( keyev );
+ return TRUE;
+ }
+
+ // Because of the dependency on the control key, we need to update the mouse cursor here
+ if ( keyev->key() == Qt::Key_Control )
+ {
+ QPoint mousep = mapFromGlobal(QCursor::pos()) + QPoint( contentsX(), contentsY() );
+ QPoint normalPoint = m_viewMode->viewToNormal( mousep );
+ KoPoint docPoint = m_doc->unzoomPoint( normalPoint );
+ viewport()->setCursor( m_frameViewManager->mouseCursor( docPoint, keyev->stateAfter() ) );
+ }
+ else if ( (keyev->key() == Qt::Key_Delete || keyev->key() ==Key_Backspace )
+ && m_frameViewManager->selectedFrame() && !m_printing )
+ m_gui->getView()->editDeleteFrame();
+ } break;
+ case QEvent::KeyRelease:
+ {
+ QKeyEvent * keyev = static_cast<QKeyEvent *>(e);
+ if ( keyev->key() == Qt::Key_Control )
+ {
+ QPoint mousep = mapFromGlobal(QCursor::pos()) + QPoint( contentsX(), contentsY() );
+ QPoint normalPoint = m_viewMode->viewToNormal( mousep );
+ KoPoint docPoint = m_doc->unzoomPoint( normalPoint );
+ viewport()->setCursor( m_frameViewManager->mouseCursor( docPoint, keyev->stateAfter() ) );
+ }
+
+ if ( m_currentFrameSetEdit && m_mouseMode == MM_EDIT && m_doc->isReadWrite() && !m_printing )
+ {
+ m_currentFrameSetEdit->keyReleaseEvent( keyev );
+ return TRUE;
+ }
+ }
+ break;
+ case QEvent::IMStart:
+ {
+ QIMEvent * imev = static_cast<QIMEvent *>(e);
+ m_currentFrameSetEdit->imStartEvent( imev );
+ }
+ break;
+ case QEvent::IMCompose:
+ {
+ QIMEvent * imev = static_cast<QIMEvent *>(e);
+ m_currentFrameSetEdit->imComposeEvent( imev );
+ }
+ break;
+ case QEvent::IMEnd:
+ {
+ QIMEvent * imev = static_cast<QIMEvent *>(e);
+ m_currentFrameSetEdit->imEndEvent( imev );
+ }
+ break;
+ default:
+ break;
+ }
+ }
+ return QScrollView::eventFilter( o, e );
+}
+
+bool KWCanvas::focusNextPrevChild( bool next)
+{
+ Q_UNUSED(next);
+ return TRUE; // Don't allow to go out of the canvas widget by pressing "Tab"
+ // Don't allow to go out of the canvas widget by pressing Tab, but do allow Shift+Tab.
+ // if (next) return TRUE;
+ // return QWidget::focusNextPrevChild( next );
+}
+
+void KWCanvas::updateCurrentFormat()
+{
+ KWTextFrameSetEdit * edit = dynamic_cast<KWTextFrameSetEdit *>(m_currentFrameSetEdit);
+ if ( edit )
+ edit->updateUI( true, true );
+}
+
+#ifndef NDEBUG
+void KWCanvas::printRTDebug( int info )
+{
+ KWTextFrameSet * textfs = 0L;
+ if ( m_currentFrameSetEdit ) {
+ KWTextFrameSetEdit* edit = currentTextEdit();
+ if ( edit ) {
+ textfs = dynamic_cast<KWTextFrameSet *>( edit->frameSet() );
+ Q_ASSERT( textfs );
+ }
+ }
+ if ( !textfs )
+ textfs = dynamic_cast<KWTextFrameSet *>(m_doc->frameSet( 0 ));
+ if ( textfs )
+ textfs->textObject()->printRTDebug( info );
+}
+#endif
+
+void KWCanvas::setXimPosition( int x, int y, int w, int h )
+{
+ /* Check for hasFocus() to avoid crashes in QXIMInputContext as in bug #123941.
+ This is only a workaround, the real problem might be in Qt. See also
+ http://lists.kde.org/?l=kde-core-devel&m=115770546313922&w=2 .
+ */
+ if (hasFocus())
+ QWidget::setMicroFocusHint( x - contentsX(), y - contentsY(), w, h );
+}
+
+void KWCanvas::inlinePictureStarted()
+{
+ m_frameInline=true;
+ m_frameInlineType=FT_PICTURE;
+}
+
+int KWCanvas::currentTableRow() const
+{
+ if ( !m_currentFrameSetEdit )
+ return -1;
+ KWTextFrameSetEdit *edit = currentTextEdit();
+ if ( !edit )
+ return -1;
+ KWTextFrameSet* textfs = edit->textFrameSet();
+ if ( textfs && textfs->groupmanager() )
+ return static_cast<KWTableFrameSet::Cell *>(textfs)->firstRow();
+ return -1;
+}
+
+int KWCanvas::currentTableCol() const
+{
+ if ( !m_currentFrameSetEdit )
+ return -1;
+ KWTextFrameSetEdit *edit = currentTextEdit();
+ if ( !edit )
+ return -1;
+ KWTextFrameSet* textfs = edit->textFrameSet();
+ if ( textfs && textfs->groupmanager() )
+ return static_cast<KWTableFrameSet::Cell *>(textfs)->firstColumn();
+ return -1;
+}
+
+void KWCanvas::viewportScroll( bool up )
+{
+ if ( up )
+ setContentsPos( contentsX(), contentsY() - visibleHeight() );
+ else
+ setContentsPos( contentsX(), contentsY() + visibleHeight() );
+}
+
+void KWCanvas::resetStatusBarText()
+{
+ if ( m_temporaryStatusBarTextShown )
+ {
+ gui()->getView()->updateFrameStatusBarItem();
+ m_temporaryStatusBarTextShown = false;
+ }
+}
+
+
+/* Returns the caret position in document coordinates.
+ The current frame must be editable, i.e., a caret is possible. */
+KoPoint KWCanvas::caretPos()
+{
+ if (!m_currentFrameSetEdit) return KoPoint();
+ KWTextFrameSetEdit* textEdit = currentTextEdit();
+ if (!textEdit) return KoPoint();
+ KoTextCursor* cursor = textEdit->cursor();
+ if (!cursor) return KoPoint();
+ KWTextFrameSet* textFrameset =
+ dynamic_cast<KWTextFrameSet *>(m_currentFrameSetEdit->frameSet());
+ if (!textFrameset) return KoPoint();
+ KWFrame* currentFrame = m_currentFrameSetEdit->currentFrame();
+ if (!currentFrame) return KoPoint();
+
+ QPoint viewP = textFrameset->cursorPos(cursor, this, currentFrame);
+ viewP.rx() += contentsX();
+ viewP.ry() += contentsY();
+ QPoint normalP = m_viewMode->viewToNormal(viewP);
+ KoPoint docP = m_doc->unzoomPoint(normalP);
+ return docP;
+}
+
+
+// ************** InteractionPolicy ***********************
+InteractionPolicy::InteractionPolicy(KWCanvas *parent, bool doInit, bool includeInlineFrames) {
+ m_gotDragEvents = false;
+ m_parent = parent;
+ if(doInit) {
+ QValueList<KWFrameView*> selectedFrames = m_parent->frameViewManager()->selectedFrames();
+ QValueListIterator<KWFrameView*> framesIterator = selectedFrames.begin();
+ for(;framesIterator != selectedFrames.end(); ++framesIterator) {
+ KWFrame *frame = (*framesIterator)->frame();
+ KWFrameSet *fs = frame->frameSet();
+ if(! fs) continue;
+ if(!fs->isVisible()) continue;
+ if(fs->isMainFrameset() ) continue;
+ if(fs->isFloating() && !includeInlineFrames) continue;
+ if(fs->isProtectSize() ) continue;
+ if(fs->type() == FT_TABLE ) continue;
+ if(fs->type() == FT_TEXT && fs->frameSetInfo() != KWFrameSet::FI_BODY ) continue;
+ m_frames.append( frame );
+ m_indexFrame.append( FrameIndex( frame ) );
+ }
+ }
+}
+
+InteractionPolicy* InteractionPolicy::createPolicy(KWCanvas *parent, MouseMeaning meaning, KoPoint &point, Qt::ButtonState buttonState, Qt::ButtonState keyState) {
+ if(buttonState & Qt::LeftButton || buttonState & Qt::RightButton) {
+ // little inner class to make sure we don't duplicate code
+ class Selector {
+ public:
+ Selector(KWCanvas *canvas, KoPoint &point, Qt::ButtonState buttonState, Qt::ButtonState keyState) :
+ m_canvas(canvas), m_point(point), m_state(keyState) {
+ m_leftClick = buttonState & Qt::LeftButton;
+ KWFrameView *view = canvas->frameViewManager()->view(point,
+ KWFrameViewManager::frameOnTop);
+ m_doSomething = (view && !view->selected());
+ }
+
+ void doSelect() {
+ if(! m_doSomething) return;
+ m_canvas->frameViewManager()->selectFrames(m_point, m_state, m_leftClick);
+ }
+ private:
+ KWCanvas *m_canvas;
+ KoPoint m_point;
+ Qt::ButtonState m_state;
+ bool m_leftClick, m_doSomething;
+ };
+
+ Selector selector(parent, point, buttonState, keyState);
+ switch(meaning) {
+ case MEANING_MOUSE_MOVE:
+ selector.doSelect();
+ return new FrameMovePolicy(parent, point);
+ case MEANING_TOPLEFT:
+ case MEANING_TOP:
+ case MEANING_TOPRIGHT:
+ case MEANING_RIGHT:
+ case MEANING_BOTTOMRIGHT:
+ case MEANING_BOTTOM:
+ case MEANING_BOTTOMLEFT:
+ case MEANING_LEFT:
+ selector.doSelect();
+ return new FrameResizePolicy(parent, meaning, point);
+ default:
+ FrameSelectPolicy *fsp = new FrameSelectPolicy(parent, meaning, point, buttonState, keyState);
+ if(fsp->isValid())
+ return fsp;
+ delete fsp;
+ }
+ }
+ return 0; // no interaction policy found
+}
+
+void InteractionPolicy::cancelInteraction() {
+ KCommand *cmd = createCommand();
+ if(cmd) {
+ cmd->unexecute();
+ delete cmd;
+ }
+}
+
+
+// ************** FrameResizePolicy ***********************
+FrameResizePolicy::FrameResizePolicy(KWCanvas *parent, MouseMeaning meaning, KoPoint &point) :
+ InteractionPolicy (parent, true, true), m_boundingRect() {
+
+ if( meaning == MEANING_TOPLEFT) {
+ m_top = true; m_bottom = false; m_left = true; m_right = false;
+ }
+ else if( meaning == MEANING_TOP) {
+ m_top = true; m_bottom = false; m_left = false; m_right = false;
+ }
+ else if( meaning == MEANING_TOPRIGHT) {
+ m_top = true; m_bottom = false; m_left = false; m_right = true;
+ }
+ else if( meaning == MEANING_RIGHT) {
+ m_top = false; m_bottom = false; m_left = false; m_right = true;
+ }
+ else if( meaning == MEANING_BOTTOMRIGHT) {
+ m_top = false; m_bottom = true; m_left = false; m_right = true;
+ }
+ else if( meaning == MEANING_BOTTOM) {
+ m_top = false; m_bottom = true; m_left = false; m_right = false;
+ }
+ else if( meaning == MEANING_BOTTOMLEFT) {
+ m_top = false; m_bottom = true; m_left = true; m_right = false;
+ }
+ else if( meaning == MEANING_LEFT) {
+ m_top = false; m_bottom = false; m_left = true; m_right = false;
+ }
+
+ QValueListConstIterator<KWFrame*> framesIterator = m_frames.begin();
+ for(;framesIterator != m_frames.end(); ++framesIterator) {
+ KWFrame *frame = *framesIterator;
+ FrameResizeStruct frs(*frame, frame->minimumFrameHeight(), *frame);
+ m_frameResize.append(frs);
+ m_boundingRect |= frame->outerKoRect();
+ }
+ m_hotSpot = point - m_boundingRect.topLeft();
+}
+
+void FrameResizePolicy::handleMouseMove(Qt::ButtonState keyState, const KoPoint &point) {
+ //kdDebug() << "handleMouseMove " << (m_top?"top ":"") << (m_bottom?"bottom ":"") << (m_left?"left ":"") << (m_right?"right":"") << endl;
+ //kdDebug() << " + point: " << point
+ // << " boundingrect: " << m_boundingRect << endl;
+
+ bool keepAspect = keyState & Qt::AltButton;
+ for(unsigned int i=0; !keepAspect && i < m_frames.count(); i++) {
+ KWPictureFrameSet *picFs = dynamic_cast<KWPictureFrameSet*>(m_frames[i]->frameSet());
+ if(picFs)
+ keepAspect = picFs->keepAspectRatio();
+ }
+
+ bool noGrid = keyState & Qt::ShiftButton;
+ bool scaleFromCenter = keyState & Qt::ControlButton;
+
+ KoPoint p( point.x() - (m_hotSpot.x() + m_boundingRect.x()),
+ point.y() - (m_hotSpot.y() + m_boundingRect.y()) );
+
+ if ( m_parent->kWordDocument()->snapToGrid() && !noGrid )
+ m_parent->applyGrid( p );
+
+ KoRect sizeRect = m_boundingRect;
+ if(m_top)
+ sizeRect.setY(sizeRect.y() + p.y());
+ if(m_bottom)
+ sizeRect.setBottom(sizeRect.bottom() + p.y());
+ if(m_left)
+ sizeRect.setX(sizeRect.left() + p.x());
+ if(m_right)
+ sizeRect.setRight(sizeRect.right() + p.x());
+ if(keepAspect) {
+ double ratio = m_boundingRect.width() / m_boundingRect.height();
+ double width = sizeRect.width();
+ double height = sizeRect.height();
+ int toLargestEdge = (m_bottom?1:0) + (m_top?1:0) + // should be false when only one
+ (m_left?1:0) + (m_right?1:0); // of the direction bools is set
+ bool horizontal = m_left || m_right;
+
+ if(toLargestEdge != 1) { // one of the corners.
+ if (width < height) // the biggest border is the one in control
+ width = height * ratio;
+ else
+ height = width / ratio;
+ } else {
+ if (horizontal)
+ height = width / ratio;
+ else
+ width = height * ratio;
+ }
+ if(m_bottom)
+ sizeRect.setBottom(sizeRect.top() + height);
+ else
+ sizeRect.setTop(sizeRect.bottom() - height);
+
+ if(m_left)
+ sizeRect.setLeft(sizeRect.right() - width);
+ else
+ sizeRect.setRight(sizeRect.left() + width);
+ }
+ if(scaleFromCenter) {
+ KoPoint origCenter(m_boundingRect.x() + m_boundingRect.width() / 2,
+ m_boundingRect.y() + m_boundingRect.height() / 2);
+ KoPoint newCenter(sizeRect.x() + sizeRect.width() / 2,
+ sizeRect.y() + sizeRect.height() / 2);
+ sizeRect.moveTopLeft(sizeRect.topLeft() + (origCenter - newCenter));
+ }
+ if(m_parent) {
+ KWPageManager *pageManager = m_parent->kWordDocument()->pageManager();
+ sizeRect.moveTopLeft(pageManager->clipToDocument(sizeRect.topLeft()));
+ sizeRect.moveBottomRight(pageManager->clipToDocument(sizeRect.bottomRight()));
+ sizeRect.setX( QMAX(0, sizeRect.x()) ); // otherwise it would get wider than the page
+ }
+
+ // each frame in m_frames should be reshaped from the original size stored in the
+ // m_frameResize data to a size that equals the reshaping of m_boundingrect to sizeRect
+ class Converter {
+ public:
+ Converter(KoRect &from, KoRect &to, KWViewMode *viewMode) {
+ m_from = from.topLeft();
+ m_to = to.topLeft();
+ m_viewMode = viewMode;
+ m_diffX = to.width() / from.width();
+ m_diffY = to.height() / from.height();
+ //kdDebug() << "Converter " << from << ", " << to << " x: " << m_diffX << ", y: " << m_diffY << endl;
+ }
+ void update(KWFrame *frame, KoRect &orig) {
+ QRect oldRect( m_viewMode->normalToView( frame->outerRect(m_viewMode) ) );
+ if(! frame->frameSet()->isFloating())
+ frame->moveTopLeft( convert( orig.topLeft() ) );
+ KoPoint bottomRight( convert( orig.bottomRight() ) );
+ frame->setBottom( bottomRight.y() );
+ frame->setRight( bottomRight.x() );
+
+ QRect newRect( frame->outerRect(m_viewMode) );
+ QRect frameRect( m_viewMode->normalToView( newRect ) );
+ // Repaint only the changed rects (oldRect U newRect)
+ m_repaintRegion += QRegion(oldRect).unite(frameRect).boundingRect();
+ }
+
+ QRegion repaintRegion() {
+ return m_repaintRegion;
+ }
+
+ private:
+ KoPoint convert(KoPoint point) {
+ double offsetX = point.x() - m_from.x();
+ double offsetY = point.y() - m_from.y();
+ KoPoint answer(m_to.x() + offsetX * m_diffX, m_to.y() + offsetY * m_diffY);
+ return answer;
+ }
+ private: // vars
+ KoPoint m_from, m_to;
+ KWViewMode *m_viewMode;
+ QRegion m_repaintRegion;
+ double m_diffX, m_diffY;
+ };
+
+ Converter converter(m_boundingRect, sizeRect, m_parent->viewMode());
+ for(unsigned int i=0; i < m_frames.count(); i++)
+ converter.update(m_frames[i], m_frameResize[i].oldRect);
+
+ if ( !m_parent->kWordDocument()->showGrid() && m_parent->kWordDocument()->snapToGrid() )
+ m_parent->repaintContents( false ); //draw the grid over the whole canvas
+ else
+ m_parent->repaintContents( converter.repaintRegion().boundingRect(), false );
+ m_parent->gui()->getView()->updateFrameStatusBarItem();
+}
+
+KCommand *FrameResizePolicy::createCommand() {
+ for(unsigned int i=0; i < m_frames.count(); i++) {
+ KWFrame *frame = m_frames[i];
+ FrameResizeStruct frs = m_frameResize[i];
+ frs.newRect = frame->rect();
+ frs.newMinHeight = frame->height();
+ m_frameResize[i] = frs;
+ }
+ return new KWFrameResizeCommand(i18n("Resize Frame"), m_indexFrame, m_frameResize);
+}
+
+void FrameResizePolicy::finishInteraction() {
+ KWFrameViewManager *frameViewManager = m_parent->frameViewManager();
+ for(unsigned int i=0; i < m_frames.count(); i++) {
+ KWFrame *frame = m_frames[i];
+ frame->setMinimumFrameHeight(frame->height());
+ frameViewManager->slotFrameResized(frame);
+ }
+}
+
+
+// *************** FrameMovePolicy ************************
+FrameMovePolicy::FrameMovePolicy(KWCanvas *parent, KoPoint &point) :
+ InteractionPolicy (parent), m_boundingRect() {
+
+ QValueListConstIterator<KWFrame*> framesIterator = m_frames.begin();
+ for(;framesIterator != m_frames.end(); ++framesIterator) {
+ KWFrame *frame = *framesIterator;
+ m_boundingRect |= frame->outerKoRect();
+ FrameMoveStruct fms(frame->topLeft(), KoPoint(0,0));
+ m_frameMove.append(fms);
+ }
+
+ m_hotSpot = point - m_boundingRect.topLeft();
+ m_startPoint = m_boundingRect.topLeft();
+}
+
+void FrameMovePolicy::handleMouseMove(Qt::ButtonState keyState, const KoPoint &point) {
+ bool noGrid = keyState & Qt::ShiftButton;
+ bool linearMove = (keyState & Qt::AltButton) || (keyState & Qt::ControlButton);
+
+ KWPageManager *pageManager = m_parent->kWordDocument()->pageManager();
+
+ KoRect oldBoundingRect = m_boundingRect;
+ //kdDebug() << "KWCanvas::mmEditFrameMove point: " << point
+ // << " boundingrect: " << m_boundingRect << endl;
+
+ KoPoint p( point.x() - m_hotSpot.x(), point.y() - m_hotSpot.y() );
+ if(linearMove) {
+ if(QABS(p.x() - m_startPoint.x()) < QABS(p.y() - m_startPoint.y()))
+ p.setX(m_startPoint.x());
+ else
+ p.setY(m_startPoint.y());
+ }
+ if ( m_parent->kWordDocument()->snapToGrid() && !noGrid )
+ m_parent->applyGrid( p );
+
+ p = pageManager->clipToDocument(p);
+ m_boundingRect.moveTopLeft( p );
+ m_boundingRect.moveBottomRight( pageManager->clipToDocument(m_boundingRect.bottomRight()) );
+
+ // Another annoying case is if the top and bottom points are not in the same page....
+ int topPage = pageManager->pageNumber( m_boundingRect.topLeft() );
+ int bottomPage = pageManager->pageNumber( m_boundingRect.bottomRight() );
+ //kdDebug() << "KWCanvas::mmEditFrameMove topPage=" << topPage << " bottomPage=" << bottomPage << endl;
+ if ( topPage != bottomPage ) {
+ // Choose the closest page...
+ Q_ASSERT( bottomPage == -1 || topPage + 1 == bottomPage ); // Not too sure what to do otherwise
+ double topPart = m_boundingRect.bottom() - pageManager->bottomOfPage(topPage);
+ if ( topPart < m_boundingRect.height() / 2 ) // Most of the rect is in the top page
+ p.setY( pageManager->bottomOfPage(topPage) - m_boundingRect.height() - 1 );
+ else // Most of the rect is in the bottom page
+ p.setY( pageManager->topOfPage(bottomPage) );
+ m_boundingRect.moveTopLeft( p );
+ m_boundingRect.moveBottomRight( pageManager->clipToDocument(m_boundingRect.bottomRight()) );
+ }
+
+ if( m_boundingRect.topLeft() == oldBoundingRect.topLeft() )
+ return; // nothing happened (probably due to the grid)
+
+ /*kdDebug() << "boundingRect moved by " << m_boundingRect.left() - oldBoundingRect.left() << ","
+ << m_boundingRect.top() - oldBoundingRect.top() << endl;
+ kdDebug() << " boundingX+hotspotX=" << m_boundingRect.left() + m_hotSpot.x() << endl;
+ kdDebug() << " point.x()=" << point.x() << endl; */
+
+ QPtrList<KWTableFrameSet> tablesMoved;
+ tablesMoved.setAutoDelete( FALSE );
+ QRegion repaintRegion;
+ KoPoint _move=m_boundingRect.topLeft() - oldBoundingRect.topLeft();
+
+ QValueListIterator<KWFrame*> framesIterator = m_frames.begin();
+ for(; framesIterator != m_frames.end(); ++framesIterator) {
+ KWFrame *frame = *framesIterator;
+ KWFrameSet *fs = frame->frameSet();
+
+ if ( fs->type() == FT_TABLE ) {
+ if ( tablesMoved.findRef( static_cast<KWTableFrameSet *> (fs) ) == -1 )
+ tablesMoved.append( static_cast<KWTableFrameSet *> (fs));
+ }
+ else {
+ QRect oldRect( m_parent->viewMode()->normalToView( frame->outerRect(m_parent->viewMode()) ) );
+ // Move the frame
+ frame->moveTopLeft( frame->topLeft() + _move );
+ // Calculate new rectangle for this frame
+ QRect newRect( frame->outerRect(m_parent->viewMode()) );
+
+ QRect frameRect( m_parent->viewMode()->normalToView( newRect ) );
+ // Repaint only the changed rects (oldRect U newRect)
+ repaintRegion += QRegion(oldRect).unite(frameRect).boundingRect();
+ }
+ }
+
+ if ( !tablesMoved.isEmpty() ) {
+ //kdDebug() << "KWCanvas::mmEditFrameMove TABLESMOVED" << endl;
+ for ( unsigned int i = 0; i < tablesMoved.count(); i++ ) {
+ KWTableFrameSet *table = tablesMoved.at( i );
+ for ( KWTableFrameSet::TableIter k(table) ; k ; ++k ) {
+ KWFrame * frame = k->frame( 0 );
+ QRect oldRect( m_parent->viewMode()->normalToView( frame->outerRect(m_parent->viewMode()) ) );
+ frame->moveTopLeft( frame->topLeft() + _move );
+ // Calculate new rectangle for this frame
+ QRect newRect( frame->outerRect(m_parent->viewMode()) );
+ QRect frameRect( m_parent->viewMode()->normalToView( newRect ) );
+ // Repaing only the changed rects (oldRect U newRect)
+ repaintRegion += QRegion(oldRect).unite(frameRect).boundingRect();
+ }
+ }
+ }
+
+ if ( !m_parent->kWordDocument()->showGrid() && m_parent->kWordDocument()->snapToGrid() )
+ m_parent->repaintContents( false ); //draw the grid over the whole canvas
+ else
+ m_parent->repaintContents( repaintRegion.boundingRect(), false );
+ m_parent->gui()->getView()->updateFrameStatusBarItem();
+}
+
+KCommand *FrameMovePolicy::createCommand() {
+ for(unsigned int i=0; i < m_frames.count(); i++) {
+ KWFrame *frame = m_frames[i];
+ FrameMoveStruct fms = m_frameMove[i];
+ fms.newPos = frame->topLeft();
+ m_frameMove[i] = fms;
+ }
+ return new KWFrameMoveCommand( i18n("Move Frame"), m_indexFrame, m_frameMove );
+}
+
+void FrameMovePolicy::finishInteraction() {
+ KWFrameViewManager *frameViewManager = m_parent->frameViewManager();
+ for(unsigned int i=0; i < m_frames.count(); i++) {
+ KWFrame *frame = m_frames[i];
+ frameViewManager->slotFrameMoved(frame, m_frameMove[i].oldPos.y());
+ }
+}
+
+
+// ************** FrameSelectPolicy ***********************
+FrameSelectPolicy::FrameSelectPolicy(KWCanvas *parent, MouseMeaning meaning, KoPoint &point, Qt::ButtonState buttonState, Qt::ButtonState keyState)
+ : InteractionPolicy(parent, false) {
+
+ bool leftButton = buttonState & Qt::LeftButton;
+ // this is a special case; if a frame that is curently being edited is 'selected' on the border
+ // we redirect that click to the text part of the frame.
+ // this means we give the user a lot more space to click on the left side of the frame to
+ // select the first characters.
+ KWFrameSetEdit *fse = parent->currentFrameSetEdit();
+ if(leftButton && fse) {
+ KWFrameView *view = m_parent->frameViewManager()->view(point,
+ KWFrameViewManager::unselected, true);
+ if(view && view->frame()->frameSet() == fse->frameSet()) {
+ // make sure 'point' is inside the frame
+ point.setX(QMAX(point.x(), view->frame()->left()));
+ point.setY(QMAX(point.y(), view->frame()->top()));
+ point.setX(QMIN(point.x(), view->frame()->right()));
+ point.setY(QMIN(point.y(), view->frame()->bottom()));
+
+ // convert point to the view coordinate system.
+ QPoint normalPoint = parent->kWordDocument()->zoomPoint(point);
+ QPoint mousePos = parent->viewMode()->normalToView(normalPoint);
+ QMouseEvent *me = new QMouseEvent(QEvent::MouseButtonPress, mousePos,
+ buttonState, keyState);
+ fse->mousePressEvent(me, normalPoint, point );
+ delete me;
+
+ m_validSelection = false;
+ return;
+ }
+ }
+
+ m_validSelection = meaning != MEANING_NONE;
+ m_parent->frameViewManager()->selectFrames(point, keyState, leftButton );
+}
+
+void FrameSelectPolicy::handleMouseMove(Qt::ButtonState keyState, const KoPoint &point) {
+ Q_UNUSED(keyState);
+ Q_UNUSED(point);
+}
+
+KCommand *FrameSelectPolicy::createCommand() {
+ return 0;
+}
+
+void FrameSelectPolicy::finishInteraction() {
+}
+
+#include "KWCanvas.moc"
diff --git a/kword/KWCanvas.h b/kword/KWCanvas.h
new file mode 100644
index 00000000..ffd1e85e
--- /dev/null
+++ b/kword/KWCanvas.h
@@ -0,0 +1,488 @@
+/* This file is part of the KDE project
+ Copyright (C) 1998, 1999 Reginald Stadlbauer <reggie@kde.org>
+ Copyright (C) 2002-2006 David Faure <faure@kde.org>
+ Copyright (C) 2005 Thomas Zander <zander@kde.org>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+
+#ifndef KWCANVAS_H
+#define KWCANVAS_H
+
+#include <kprinter.h>
+#include <KoRect.h>
+#include <qscrollview.h>
+#include <qstylesheet.h>
+#include <KoRichText.h>
+#include <KoQueryTrader.h>
+#include <KoPicture.h>
+
+#include "KWTextParag.h"
+#include "KWFrame.h"
+#include "KWVariable.h"
+#include "KWCommand.h"
+
+class KWTextFrameSetEdit;
+class KWDocument;
+class KWFrame;
+class KWFrameSet;
+class KWFrameSetEdit;
+class KWTableFrameSet;
+class KWFrameMoveCommand;
+class KWViewMode;
+class KWFrameViewManager;
+class KWGUI;
+class KWTableTemplate;
+class KoTextParag;
+class QTimer;
+class InteractionPolicy;
+class KWFrameView;
+
+/**
+ * Class: KWCanvas
+ * This class is responsible for the rendering of the frames to
+ * the screen as well as the interaction with the user via mouse
+ * and keyboard. There is one per view.
+ */
+class KWCanvas : public QScrollView
+{
+ Q_OBJECT
+
+public:
+ KWCanvas(const QString& viewMode, QWidget *parent, KWDocument *d, KWGUI *lGui);
+ virtual ~KWCanvas();
+
+ KWDocument * kWordDocument() const { return m_doc; }
+ KWGUI * gui() const { return m_gui; }
+ KWFrameViewManager* frameViewManager() { return m_frameViewManager; }
+ KWFrameSetEdit *currentFrameSetEdit() const { return m_currentFrameSetEdit; }
+
+ void switchViewMode( const QString& newViewMode );
+ KWViewMode *viewMode() const { return m_viewMode; }
+
+ void repaintAll( bool erase = false );
+ /**
+ * Only repaint the frameset @p fs.
+ * @p resetChanged should only be true for the last view
+ * (see KWFrameSet::drawContents)
+ */
+ void repaintChanged( KWFrameSet * fs, bool resetChanged );
+
+ /** We need to repaint if the window is resized. */
+ void viewportResizeEvent( QResizeEvent * );
+
+ void print( QPainter *painter, KPrinter *printer );
+ bool eventFilter( QObject *o, QEvent *e );
+ bool focusNextPrevChild( bool next);
+
+ void setFrameBackgroundColor( const QBrush &backColor );
+
+ void editFrameProperties();
+ void editFrameProperties( KWFrameSet * frameset );
+
+ void pasteFrames();
+
+ // Mouse press
+ void mpCreate( const QPoint& normalPoint, bool noGrid );
+ void mpCreatePixmap( const QPoint& normalPoint, bool noGrid );
+ // Mouse move
+ void mmCreate( const QPoint& normalPoint, bool noGrid );
+ // Mouse release
+ void mrEditFrame();
+ void mrCreateText();
+ void mrCreatePixmap();
+ void mrCreatePart();
+ void mrCreateFormula();
+ void mrCreateTable();
+
+ enum MouseMode {
+ MM_EDIT = 0,
+ MM_CREATE_TEXT = 2,
+ MM_CREATE_PIX = 3,
+ MM_CREATE_TABLE = 5,
+ MM_CREATE_FORMULA = 6,
+ MM_CREATE_PART = 7
+ };
+ void setMouseMode( MouseMode _mm );
+ MouseMode mouseMode()const { return m_mouseMode; }
+
+ // makes the user draw the rect for inserting the picture
+ void insertPicture( const KoPicture& newPicture, QSize pixmapSize, bool _keepRatio );
+ void insertPart( const KoDocumentEntry &entry );
+ void pasteImage( QMimeSource *e, const KoPoint &docPoint );
+ // insert a (non-inline) picture at the given position; used by dnd and dcop
+ void insertPictureDirect( const KoPicture& picture, const KoPoint& pos, const QSize& sz = QSize() );
+
+ void updateCurrentFormat();
+
+ void updateFrameFormat();
+
+ // Table creation support - methods used by KWView to reuse the last settings
+ unsigned int tableRows() const { return m_table.rows; }
+ void setTableRows( unsigned int rows ) { m_table.rows=rows; }
+ unsigned int tableCols() const { return m_table.cols; }
+ void setTableCols( unsigned int cols ) { m_table.cols=cols; }
+ int tableWidthMode()const { return m_table.width; }
+ int tableHeightMode()const { return m_table.height; }
+ bool tableIsFloating()const { return m_table.floating; }
+ int tableFormat()const { return m_table.format;}
+
+ void setTableFormat(int _nb){ m_table.format=_nb;}
+
+ QString tableTemplateName()const { return m_table.tableTemplateName;}
+ void setTableTemplateName(const QString &_name) { m_table.tableTemplateName=_name;}
+
+ void setPictureInline( bool _inline) { m_picture.pictureInline = _inline;}
+ bool pictureInline() const { return m_picture.pictureInline; }
+
+ void setPictureKeepRatio( bool _keep) { m_picture.keepRatio = _keep;}
+ bool pictureKeepRatio() const { return m_picture.keepRatio; }
+
+ void createTable( unsigned int rows, unsigned int cols,
+ int /*KWTableFrameSet::CellSize*/ wid, int /*KWTableFrameSet::CellSize*/ hei,
+ bool isFloating,
+ KWTableTemplate *tt=0L, int format=31 );
+
+ /// The current table (either because one or more cells are selected,
+ /// or because the cursor is in a table cell
+ KWTableFrameSet *getCurrentTable()const { return m_currentTable; }
+ /// When the cursor is in a table cell, this returns the row
+ int currentTableRow() const;
+ /// When the cursor is in a table cell, this returns the column
+ int currentTableCol() const;
+
+ //move canvas to show point dPoint (in doc coordinates)
+ void scrollToOffset( const KoPoint & dPoint );
+
+ //for KWTextFrameSetEdit
+ void dragStarted() { m_mousePressed = false; }
+
+ void setXimPosition( int x, int y, int w, int h );
+
+ void updateRulerOffsets( int cx = -1, int cy = -1 );
+
+ void inlinePictureStarted();
+
+ void ensureCursorVisible();
+
+ void editFrameSet( KWFrameSet * frameSet, bool onlyText = false );
+ /**
+ * Starting editing @p fs if we're not yet doing it.
+ * In all cases, position the cursor at @p parag and @p index.
+ */
+ void editTextFrameSet( KWFrameSet * fs, KoTextParag* parag, int index );
+ bool checkCurrentEdit( KWFrameSet * fs, bool onlyText = false);
+
+
+ NoteType footNoteType()const{return m_footEndNote.noteType;}
+ KWFootNoteVariable::Numbering numberingFootNoteType() const { return m_footEndNote.numberingType;}
+
+ void setFootNoteType( NoteType _type ) { m_footEndNote.noteType = _type; }
+ void setNumberingFootNoteType(KWFootNoteVariable::Numbering _type) { m_footEndNote.numberingType = _type; }
+
+ void tableSelectCell(KWTableFrameSet *table, KWFrameSet *cell);
+ void selectAllFrames( bool select );
+
+ KCommand * createTextBox(const KoRect & rect );
+
+ // Called by KWTextFrameSetEdit when pgup/pgdown can't go further
+ // or directly called by pgup/pgdown if not using 'moves caret' feature.
+ void viewportScroll( bool up );
+
+ /// Resets the status bar text
+ void resetStatusBarText();
+
+ /** Returns the caret position in document coordinates.
+ The current frame must be editable, i.e., a caret is possible. */
+ KoPoint caretPos();
+ void applyGrid( KoPoint &p );
+
+ bool overwriteMode() const { return m_overwriteMode; }
+
+ // Returns the current text edit object, or 0 if
+ // - no frame is being edited
+ // - a non-text frame is being edited
+ KWTextFrameSetEdit* currentTextEdit() const;
+
+ bool insertInlinePicture();
+
+protected:
+ void drawGrid( QPainter &p, const QRect& rect );
+
+ /**
+ * Reimplemented from QScrollView, to draw the contents of the canvas
+ */
+ virtual void drawContents( QPainter *p, int cx, int cy, int cw, int ch );
+ /**
+ * The main drawing method.
+ * @param painter guess
+ * @param crect the area to be repainted, in contents coordinates
+ * @param viewMode the view mode to be used (usually m_viewMode, except when printing)
+ */
+ void drawDocument( QPainter *painter, const QRect &crect, KWViewMode* viewMode );
+ /**
+ * Draw page borders, but also clear up the space between the frames and the page borders,
+ * draw the page shadow, and the gray area.
+ */
+ void drawPageBorders( QPainter * painter, const QRect & crect, const QRegion & emptySpaceRegion );
+
+ virtual void keyPressEvent( QKeyEvent *e );
+ virtual void contentsMousePressEvent( QMouseEvent *e );
+ virtual void contentsMouseMoveEvent( QMouseEvent *e );
+ virtual void contentsMouseReleaseEvent( QMouseEvent *e );
+ virtual void contentsMouseDoubleClickEvent( QMouseEvent *e );
+ virtual void contentsDragEnterEvent( QDragEnterEvent *e );
+ virtual void contentsDragMoveEvent( QDragMoveEvent *e );
+ virtual void contentsDragLeaveEvent( QDragLeaveEvent *e );
+ virtual void contentsDropEvent( QDropEvent *e );
+ virtual void resizeEvent( QResizeEvent *e );
+
+ KWTableFrameSet * createTable(); // uses m_insRect and m_table to create the table
+
+ void terminateCurrentEdit();
+ bool insertInlineTable();
+
+signals:
+ // Emitted when the current frameset edit changes
+ void currentFrameSetEditChanged();
+ // Emitted by the current frameset edit when its selection changes
+ void selectionChanged( bool hasSelection );
+ // Emitted when Mouse Mode changed
+ void currentMouseModeChanged(int newMouseMode);
+ // Emitted when frames have been selected or unselected (to disable/enable the UI in kwview)
+ void frameSelectedChanged();
+ // Emitted when the document structure has changed
+ // ### DF: IMHO this should be only emitted by KWDocument (e.g. addFrameSet)
+ void docStructChanged(int _type);
+ // Emitted when the insert key is pressed
+ void overwriteModeChanged( bool m_overwriteMode );
+
+ void viewTransformationsChanged();
+
+ void updateRuler();
+
+private slots:
+ void slotContentsMoving( int, int );
+ void slotNewContentsSize();
+ void slotMainTextHeightChanged();
+ void doAutoScroll();
+
+ //Terminate editing this frameset, if we were editing it.
+ void terminateEditing( KWFrameSet *fs );
+
+private:
+ /**
+ * Draw the contents of one frameset
+ * @param resetChanged whether the changed flag should be reset to false while redrawing
+ */
+ void drawFrameSet( KWFrameSet * frameset, QPainter * painter,
+ const QRect & crect, bool onlyChanged, bool resetChanged, KWViewMode* viewMode );
+
+ void drawMovingRect( QPainter & p );
+ void deleteMovingRect();
+ /**
+ * make the parag rectangle have the aspect ratio by changing either the height
+ * or the width of the ratio.
+ * @param ratio the ratio the rectangle should have afterwards.
+ * @param insRect the rectangle that is to be changed in-place
+ */
+ void applyAspectRatio( double ratio, KoRect& insRect );
+
+#ifndef NDEBUG
+ void printRTDebug( int );
+#endif
+
+ KWFrameViewManager *m_frameViewManager;
+ KWDocument *m_doc;
+ KWFrameSetEdit *m_currentFrameSetEdit;
+ KWGUI *m_gui;
+ QTimer *m_scrollTimer;
+ bool m_mousePressed;
+ bool m_printing;
+ bool m_imageDrag;
+
+ //define type of frame (for set inline frame)
+ bool m_frameInline;
+ FrameSetType m_frameInlineType;
+
+ // Warning: the viewmode is stored here for good design ;)
+ // but it's owned by the document, since we currently have one viewmode for all views.
+ KWViewMode *m_viewMode;
+
+ // Frame stuff
+ MouseMode m_mouseMode;
+ MouseMeaning m_mouseMeaning; // set by mousePress, used by mouseMove
+ KoRect m_resizedFrameInitialSize; // when resizing a frame
+ double m_resizedFrameInitialMinHeight; // when resizing a frame
+ KoRect m_insRect; ///< variable updated and painted to represent the to insert frame
+ bool m_deleteMovingRect;
+ KoPicture m_kopicture; // The picture
+ QSize m_pixmapSize; // size when inserting a picture (not necessarily the size of the picture)
+ bool m_keepRatio;//when inserting a picture
+ KoDocumentEntry m_partEntry; // when inserting a part
+ int m_rowColResized; // when resizing a row or column
+ bool m_temporaryStatusBarTextShown; // Indicates if the temporary is shown
+ double m_previousTableSize; //previous column or row size before resizing it
+ KoPoint m_lastCaretPos; // position of caret when editing stopped in document coordinates
+ bool m_overwriteMode;
+
+ // Table creation support.
+ // Having this as a member variable allows to remember and reuse the last settings
+ struct
+ {
+ unsigned int cols;
+ unsigned int rows;
+ int format;
+ int /*KWTableFrameSet::CellSize*/ width;
+ int /*KWTableFrameSet::CellSize*/ height;
+ bool floating;
+ QString tableTemplateName;
+ KWTableTemplate *tt;
+ } m_table;
+ KWTableFrameSet *m_currentTable;
+ InteractionPolicy *m_interactionPolicy;
+
+ struct
+ {
+ NoteType noteType;
+ KWFootNoteVariable::Numbering numberingType;
+ } m_footEndNote;
+
+ struct
+ {
+ bool pictureInline;
+ bool keepRatio;
+ }m_picture;
+};
+
+/**
+ * Interaction policy defines the behavior in case the user clicks or drags the mouse.
+ * The InteractionPolicy is created in the createPolicy() function which defines the
+ * resulting behavior and initiates a frame-move or a frame-resize, for example.
+ * The canvas forwards mouseMove events to the handleMouseMove() method and the interaction
+ * is either finished with finishInteraction() or cancelInteraction() (never both).
+ */
+class InteractionPolicy {
+ public:
+ /**
+ * Extending classes should implement this method to alter the frames or other data
+ * based on the new mouse position.
+ * @param keyState the orred-data of the Shift/Alt/Control buttons being held down
+ * during the mousemove.
+ * @param point the new point where the mouse if at. This is in the document (pt-based)
+ * coordinate system.
+ */
+ virtual void handleMouseMove(Qt::ButtonState keyState, const KoPoint &point) = 0;
+ /**
+ * For interactions that are undo-able this method should be implemented to return such
+ * a command. Implementations should return 0 otherwise.
+ * @return a command, or 0.
+ */
+ virtual KCommand* createCommand() = 0;
+ /**
+ * This method will undo frames based interactions by calling createCommand()
+ * and unexecuting that.
+ */
+ void cancelInteraction();
+ /**
+ * Override to make final changes to the data on the end of an interaction.
+ */
+ virtual void finishInteraction() = 0;
+
+ /**
+ * This instanciates a new policy object and decides which policy is created based on the params.
+ * @param parent the parent canvas for things like redraw commands.
+ * @param meaning the mouseMeaning of as it is at 'point'
+ * @param point the place where the mouseDown is registred.
+ * @param buttonState which button is used to click, like Qt::LeftButton
+ * @param keyState which keys are held down at the click, like Qt::ControlButton
+ */
+ static InteractionPolicy* createPolicy(KWCanvas *parent, MouseMeaning meaning, KoPoint &point, Qt::ButtonState buttonState, Qt::ButtonState keyState);
+
+ void hadDragEvents() { m_gotDragEvents = true; }
+ bool gotDragEvents() { return m_gotDragEvents; }
+
+ protected:
+ /**
+ * Constructor.
+ * @param parent the parent canvas.
+ * @param doInit if true this will initialize the m_frames and m_indexFrame variables.
+ * @param includeInlineFrames if true the m_frames will include inline frames
+ */
+ InteractionPolicy(KWCanvas *parent, bool doInit = true, bool includeInlineFrames = false);
+
+ QValueList<FrameIndex> m_indexFrame;
+ KWCanvas *m_parent;
+ QValueList<KWFrame*> m_frames;
+
+ private:
+ void init();
+ bool m_gotDragEvents;
+};
+
+/**
+ * A policy that handles resizes of any number of frames.
+ * Includes support for undo/redo and support for scale from center plus various other
+ * usability features.
+ */
+class FrameResizePolicy : public InteractionPolicy {
+ public:
+ FrameResizePolicy(KWCanvas *parent, MouseMeaning meaning, KoPoint &point);
+ void handleMouseMove(Qt::ButtonState keyState, const KoPoint &point);
+ KCommand *createCommand();
+ void finishInteraction();
+
+ private:
+ QValueList<FrameResizeStruct> m_frameResize;
+ bool m_top, m_bottom, m_left, m_right;
+ KoRect m_boundingRect;
+ KoPoint m_hotSpot;
+};
+
+/**
+ * A policy that handles frame moves of any number of frames.
+ * Includes support for undo/redo and linear moves (moves constrained to one axis)
+ * plus various other usability features.
+ */
+class FrameMovePolicy : public InteractionPolicy {
+ public:
+ FrameMovePolicy(KWCanvas *parent, KoPoint &point);
+ void handleMouseMove(Qt::ButtonState keyState, const KoPoint &point);
+ KCommand *createCommand();
+ void finishInteraction();
+ private:
+ QValueList<FrameMoveStruct> m_frameMove;
+ KoPoint m_hotSpot;
+ KoPoint m_startPoint;
+ KoRect m_boundingRect;
+};
+
+/**
+ * A policy to select frames.
+ */
+class FrameSelectPolicy : public InteractionPolicy {
+ public:
+ FrameSelectPolicy(KWCanvas *parent, MouseMeaning meaning, KoPoint &point, Qt::ButtonState state, Qt::ButtonState keyState);
+ void handleMouseMove(Qt::ButtonState keyState, const KoPoint &point);
+ KCommand *createCommand();
+ void finishInteraction();
+ bool isValid() { return m_validSelection; }
+
+ private:
+ bool m_validSelection;
+};
+
+#endif
diff --git a/kword/KWCollectFramesetsVisitor.cpp b/kword/KWCollectFramesetsVisitor.cpp
new file mode 100644
index 00000000..1b30e19b
--- /dev/null
+++ b/kword/KWCollectFramesetsVisitor.cpp
@@ -0,0 +1,41 @@
+/* This file is part of the KDE project
+ Copyright (C) 2004-2005 David Faure <faure@kde.org>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+*/
+
+#include <KoTextParag.h>
+#include "KWCollectFramesetsVisitor.h"
+#include "KWAnchor.h"
+
+bool KWCollectFramesetsVisitor::visit( KoTextParag *parag, int start, int end )
+{
+ KoTextString* str = parag->string();
+ for ( int i = start ; i < end ; ++i )
+ {
+ const KoTextStringChar& ch = str->at( i );
+ if ( ch.isCustom() )
+ {
+ KoTextCustomItem *customitem = ch.customItem();
+ KWAnchor *anchor = dynamic_cast<KWAnchor *>(customitem);
+ if (anchor)
+ {
+ m_framesets.append(anchor->frameSet());
+ }
+ }
+ }
+ return true; //always return true, i.e. keep going
+}
diff --git a/kword/KWCollectFramesetsVisitor.h b/kword/KWCollectFramesetsVisitor.h
new file mode 100644
index 00000000..e2eb84f6
--- /dev/null
+++ b/kword/KWCollectFramesetsVisitor.h
@@ -0,0 +1,41 @@
+/* This file is part of the KDE project
+ Copyright (C) 2004-2005 David Faure <faure@kde.org>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+*/
+
+#ifndef KWORD_PARAGVISITORS_H
+#define KWORD_PARAGVISITORS_H
+
+#include <KoTextDocument.h>
+class KWFrameSet;
+template <class T> class QValueList;
+
+// This paragraph visitor collects the inline framesets (found via KWAnchor)
+// found in a text selection.
+class KWCollectFramesetsVisitor : public KoParagVisitor // see kotextdocument.h
+{
+public:
+ KWCollectFramesetsVisitor() : KoParagVisitor() {}
+ virtual bool visit( KoTextParag *parag, int start, int end );
+
+ const QValueList<KWFrameSet *>& frameSets() const { return m_framesets; }
+
+private:
+ QValueList<KWFrameSet *> m_framesets;
+};
+
+#endif /* KWORD_PARAGVISITORS_H */
diff --git a/kword/KWCommand.cpp b/kword/KWCommand.cpp
new file mode 100644
index 00000000..52383db4
--- /dev/null
+++ b/kword/KWCommand.cpp
@@ -0,0 +1,2094 @@
+/* This file is part of the KDE project
+ Copyright (C) 2001 David Faure <faure@kde.org>
+ Copyright (C) 2005 Thomas Zander <zander@kde.org>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+*/
+
+#include "KWCommand.h"
+#include "KWDocument.h"
+#include "KWTextFrameSet.h"
+#include "KWTableStyle.h"
+#include "KWTableTemplate.h"
+#include "KWTableFrameSet.h"
+#include "KWPartFrameSet.h"
+#include "KWTextDocument.h"
+#include "KWTextParag.h"
+#include "KWAnchor.h"
+#include "KWVariable.h"
+#include "KWOasisLoader.h"
+#include "KWFrameList.h"
+#include "KWFrameSet.h"
+#include "KWPictureFrameSet.h"
+#include "KWPageManager.h"
+#include "KWPage.h"
+
+#include <KoTextObject.h>
+#include <KoOasisStyles.h>
+#include <KoOasisContext.h>
+#include <KoXmlNS.h>
+#include <KoDom.h>
+#include <KoStore.h>
+#include <KoOasisStore.h>
+
+#include <klocale.h>
+#include <kdebug.h>
+
+#include <qxml.h>
+#include <qbuffer.h>
+#include <algorithm>
+
+// Helper class for deleting all custom items
+// (KWTextFrameset::removeSelectedText and readFormats do that already,
+// but with undo/redo, and copying all formatting etc.)
+class KWDeleteCustomItemVisitor : public KoParagVisitor // see kotextdocument.h
+{
+public:
+ KWDeleteCustomItemVisitor() : KoParagVisitor() { }
+ virtual bool visit( KoTextParag *parag, int start, int end )
+ {
+ kdDebug(32001) << "KWPasteTextCommand::execute " << parag->paragId() << " " << start << " " << end << endl;
+ for ( int i = start ; i < end ; ++i )
+ {
+ KoTextStringChar * ch = parag->at( i );
+ if ( ch->isCustom() ) {
+ KoTextCustomItem* item = ch->customItem();
+ item->setDeleted( true );
+ parag->removeCustomItem(i);
+ KCommand* itemCmd = item->deleteCommand();
+ if ( itemCmd )
+ itemCmd->execute();
+ }
+ }
+ return true;
+ }
+};
+
+#if 0 // kept for comparison with KWOasisPasteCommand
+KWPasteTextCommand::KWPasteTextCommand( KoTextDocument *d, int parag, int idx,
+ const QCString & data )
+ : KoTextDocCommand( d ), m_parag( parag ), m_idx( idx ), m_data( data ), m_oldParagLayout( 0 )
+{
+}
+
+KoTextCursor * KWPasteTextCommand::execute( KoTextCursor *c )
+{
+ KoTextParag *firstParag = doc->paragAt( m_parag );
+ if ( !firstParag ) {
+ qWarning( "can't locate parag at %d, last parag: %d", m_parag, doc->lastParag()->paragId() );
+ return 0;
+ }
+ //kdDebug() << "KWPasteTextCommand::execute m_parag=" << m_parag << " m_idx=" << m_idx
+ // << " firstParag=" << firstParag << " " << firstParag->paragId() << endl;
+ cursor.setParag( firstParag );
+ cursor.setIndex( m_idx );
+ c->setParag( firstParag );
+ c->setIndex( m_idx );
+ QDomDocument domDoc;
+ domDoc.setContent( m_data );
+ QDomElement elem = domDoc.documentElement();
+ KWTextDocument * textdoc = static_cast<KWTextDocument *>(doc);
+ KWTextFrameSet * textFs = textdoc->textFrameSet();
+ // We iterate twice over the list of paragraphs.
+ // First time to gather the text,
+ // second time to apply the character & paragraph formatting
+ QString text;
+
+ QValueList<QDomElement> listParagraphs;
+ QDomElement paragraph = elem.firstChild().toElement();
+ for ( ; !paragraph.isNull() ; paragraph = paragraph.nextSibling().toElement() )
+ {
+ if ( paragraph.tagName() == "PARAGRAPH" )
+ {
+ QString s = paragraph.namedItem( "TEXT" ).toElement().text();
+ //kdDebug() << "KWPasteTextCommand::execute Inserting text: '" << s << "'" << endl;
+ c->insert( s, false /*newline=linebreak, not new parag*/ );
+
+ if ( !paragraph.nextSibling().isNull() ) // Not for last parag
+ {
+ // Create new parag
+ // Lowlevel method:
+ c->splitAndInsertEmptyParag( FALSE, TRUE );
+ // Highlevel method:
+ //c->insert( "\n", true );
+ }
+ listParagraphs.append( paragraph );
+ }
+ }
+
+ // Redo the parag lookup because if firstParag was empty, insert() has
+ // shifted it down (side effect of splitAndInsertEmptyParag)
+ firstParag = doc->paragAt( m_parag );
+ KWTextParag * parag = static_cast<KWTextParag *>(firstParag);
+ //kdDebug() << "KWPasteTextCommand::execute starting at parag " << parag << " " << parag->paragId() << endl;
+ uint count = listParagraphs.count();
+ QValueList<QDomElement>::Iterator it = listParagraphs.begin();
+ QValueList<QDomElement>::Iterator end = listParagraphs.end();
+ for ( uint item = 0 ; it != end ; ++it, ++item )
+ {
+ if (!parag)
+ {
+ kdWarning() << "KWPasteTextCommand: parag==0L ! KWord bug, please report." << endl;
+ break;
+ }
+ QDomElement paragElem = *it;
+ // First line (if appending to non-empty line) : apply offset to formatting, don't apply parag layout
+ if ( item == 0 && m_idx > 0 )
+ {
+ // First load the default format, but only apply it to our new chars
+ QDomElement layout = paragElem.namedItem( "LAYOUT" ).toElement();
+ if ( !layout.isNull() )
+ {
+ QDomElement formatElem = layout.namedItem( "FORMAT" ).toElement();
+ if ( !formatElem.isNull() )
+ {
+ KoTextFormat f = parag->loadFormat( formatElem, 0L, QFont(), KGlobal::locale()->language(),false );
+ KoTextFormat * defaultFormat = doc->formatCollection()->format( &f );
+ // Last paragraph (i.e. only one in all) : some of the text might be from before the paste
+ int endIndex = (item == count-1) ? c->index() : parag->string()->length() - 1;
+ parag->setFormat( m_idx, endIndex - m_idx, defaultFormat, TRUE );
+ }
+ }
+
+ parag->loadFormatting( paragElem, m_idx, (textFs->isMainFrameset()));
+ }
+ else
+ {
+ if ( item == 0 ) // This paragraph existed, store its parag layout
+ {
+ delete m_oldParagLayout;
+ m_oldParagLayout = new KoParagLayout( parag->paragLayout() );
+ }
+ parag->loadLayout( paragElem );
+ // Last paragraph: some of the text might be from before the paste
+ int len = (item == count-1) ? c->index() : parag->string()->length();
+ // Apply default format
+ parag->setFormat( 0, len, parag->paragFormat(), TRUE );
+ parag->loadFormatting( paragElem, 0, (textFs->isMainFrameset()) );
+ }
+ parag->invalidate(0); // the formatting will be done by caller (either KWTextFrameSet::pasteOasis or KoTextObject::undo/redo)
+ parag->setChanged( TRUE );
+ parag = static_cast<KWTextParag *>(parag->next());
+ //kdDebug() << "KWPasteTextCommand::execute going to next parag: " << parag << endl;
+ }
+ textFs->textObject()->setNeedSpellCheck( true );
+ // In case loadFormatting queued any image request
+ KWDocument * doc = textFs->kWordDocument();
+ doc->processPictureRequests();
+
+ //kdDebug() << "KWPasteTextCommand::execute calling doc->pasteFrames" << endl;
+ // In case of any inline frameset
+ doc->pasteFrames( elem, 0,
+ true /*don't change footnote attribute*/ ,
+ (textFs->isMainFrameset()) /*load footnotes if mainframeset*/,
+ false /*don't select frames*/ );
+ doc->completePasting();
+
+ m_lastParag = c->parag()->paragId();
+ m_lastIndex = c->index();
+ return c;
+}
+
+KoTextCursor * KWPasteTextCommand::unexecute( KoTextCursor *c )
+{
+ KoTextParag *firstParag = doc->paragAt( m_parag );
+ if ( !firstParag ) {
+ qWarning( "can't locate parag at %d, last parag: %d", m_parag, doc->lastParag()->paragId() );
+ return 0;
+ }
+ cursor.setParag( firstParag );
+ cursor.setIndex( m_idx );
+ doc->setSelectionStart( KoTextDocument::Temp, &cursor );
+
+ KoTextParag *lastParag = doc->paragAt( m_lastParag );
+ if ( !lastParag ) {
+ qWarning( "can't locate parag at %d, last parag: %d", m_lastParag, doc->lastParag()->paragId() );
+ return 0;
+ }
+ Q_ASSERT( lastParag->document() );
+ KWTextDocument * textdoc = static_cast<KWTextDocument *>(doc);
+
+ //kdDebug() << "Undoing paste: deleting from (" << firstParag->paragId() << "," << m_idx << ")"
+ // << " to (" << lastParag->paragId() << "," << m_lastIndex << ")" << endl;
+
+ cursor.setParag( lastParag );
+ cursor.setIndex( m_lastIndex );
+ doc->setSelectionEnd( KoTextDocument::Temp, &cursor );
+ // Delete all custom items
+ KWDeleteCustomItemVisitor visitor;
+ doc->visitSelection( KoTextDocument::Temp, &visitor );
+
+ doc->removeSelectedText( KoTextDocument::Temp, c /* sets c to the correct position */ );
+
+ KWTextFrameSet * textFs = textdoc->textFrameSet();
+
+ textFs->renumberFootNotes();
+ if ( m_idx == 0 ) {
+ Q_ASSERT( m_oldParagLayout );
+ if ( m_oldParagLayout )
+ firstParag->setParagLayout( *m_oldParagLayout );
+ }
+ return c;
+}
+#endif
+
+KWOasisPasteCommand::KWOasisPasteCommand( KoTextDocument *d, int parag, int idx,
+ const QByteArray& data )
+ : KoTextDocCommand( d ), m_parag( parag ), m_idx( idx ), m_data( data ), m_oldParagLayout( 0 )
+{
+}
+
+KoTextCursor * KWOasisPasteCommand::execute( KoTextCursor *c )
+{
+ KoTextParag *firstParag = doc->paragAt( m_parag );
+ if ( !firstParag ) {
+ qWarning( "can't locate parag at %d, last parag: %d", m_parag, doc->lastParag()->paragId() );
+ return c;
+ }
+ //kdDebug() << "KWOasisPasteCommand::execute m_parag=" << m_parag << " m_idx=" << m_idx
+ // << " firstParag=" << firstParag << " " << firstParag->paragId() << endl;
+ cursor.setParag( firstParag );
+ cursor.setIndex( m_idx );
+ c->setParag( firstParag );
+ c->setIndex( m_idx );
+
+ KWTextDocument * textdoc = static_cast<KWTextDocument *>(doc);
+
+ QBuffer buffer( m_data );
+
+ KoStore * store = KoStore::createStore( &buffer, KoStore::Read );
+ KWDocument* kwdoc = textdoc->textFrameSet()->kWordDocument();
+ KWOasisLoader loader( kwdoc );
+ loader.insertOasisData( store, c );
+
+ delete store;
+
+ m_lastParag = c->parag()->paragId();
+ m_lastIndex = c->index();
+ return c;
+}
+
+KoTextCursor * KWOasisPasteCommand::unexecute( KoTextCursor *c )
+{
+ KoTextParag *firstParag = doc->paragAt( m_parag );
+ if ( !firstParag ) {
+ qWarning( "can't locate parag at %d, last parag: %d", m_parag, doc->lastParag()->paragId() );
+ return 0;
+ }
+ cursor.setParag( firstParag );
+ cursor.setIndex( m_idx );
+ doc->setSelectionStart( KoTextDocument::Temp, &cursor );
+
+ KoTextParag *lastParag = doc->paragAt( m_lastParag );
+ if ( !lastParag ) {
+ qWarning( "can't locate parag at %d, last parag: %d", m_lastParag, doc->lastParag()->paragId() );
+ return 0;
+ }
+ Q_ASSERT( lastParag->document() );
+ // Get hold of the document before deleting the parag
+ KWTextDocument * textdoc = static_cast<KWTextDocument *>(doc);
+
+ //kdDebug() << "Undoing paste: deleting from (" << firstParag->paragId() << "," << m_idx << ")"
+ // << " to (" << lastParag->paragId() << "," << m_lastIndex << ")" << endl;
+
+ cursor.setParag( lastParag );
+ cursor.setIndex( m_lastIndex );
+ doc->setSelectionEnd( KoTextDocument::Temp, &cursor );
+ // Delete all custom items
+ KWDeleteCustomItemVisitor visitor;
+ doc->visitSelection( KoTextDocument::Temp, &visitor );
+
+ doc->removeSelectedText( KoTextDocument::Temp, c /* sets c to the correct position */ );
+
+ KWTextFrameSet * textFs = textdoc->textFrameSet();
+
+ textFs->renumberFootNotes();
+#if 0
+ if ( m_idx == 0 ) {
+ Q_ASSERT( m_oldParagLayout );
+ if ( m_oldParagLayout )
+ firstParag->setParagLayout( *m_oldParagLayout );
+ }
+#endif
+ return c;
+}
+
+
+KWTextDeleteCommand::KWTextDeleteCommand( KoTextDocument *d, int i, int idx, const QMemArray<KoTextStringChar> &str,
+ const CustomItemsMap & customItemsMap,
+ const QValueList<KoParagLayout> & oldParagLayouts )
+ :KoTextDeleteCommand(d, i, idx, str, customItemsMap, oldParagLayouts)
+{
+ //createBookmarkList();
+}
+
+void KWTextDeleteCommand::createBookmarkList()
+{
+#if 0
+ KoTextParag *s = doc ? doc->paragAt( id ) : parag;
+ if ( !s ) {
+ qWarning( "can't locate parag at %d, last parag: %d", id, doc->lastParag()->paragId() );
+ return;
+ }
+
+ // Now restore the parag layouts (i.e. libkotext specific stuff)
+ QValueList<KoParagLayout>::Iterator lit = m_oldParagLayouts.begin();
+ kdDebug(32500) << "KWTextDeleteCommand::createBookmarkList " << m_oldParagLayouts.count() << " parag layouts. First parag=" << s->paragId() << endl;
+ Q_ASSERT( id == s->paragId() );
+ KoTextParag *p = s;
+ while ( p ) {
+ if ( lit != m_oldParagLayouts.end() )
+ {
+ kdDebug(32500) << "KWTextDeleteCommand::unexecute find bookmark in parag " << p->paragId() << endl;
+ //p->setParagLayout( *lit );
+ }
+ else
+ break;
+ p = p->next();
+ ++lit;
+ }
+#endif
+}
+
+KoTextCursor *KWTextDeleteCommand::execute( KoTextCursor *c )
+{
+ return KoTextDeleteCommand::execute( c );
+}
+
+KoTextCursor *KWTextDeleteCommand::unexecute( KoTextCursor *c )
+{
+ return KoTextDeleteCommand::unexecute( c );
+}
+
+////////////////////////// Frame commands ////////////////////////////////
+
+FrameIndex::FrameIndex( KWFrame *frame )
+{
+ m_pFrameSet=frame->frameSet();
+ m_iFrameIndex=m_pFrameSet->frameFromPtr(frame);
+}
+
+KWFrameBorderCommand::KWFrameBorderCommand( const QString &name, QPtrList<FrameIndex> &_listFrameIndex, QPtrList<FrameBorderTypeStruct> &_frameTypeBorder,const KoBorder & _newBorder):
+ KNamedCommand(name),
+ m_indexFrame(_listFrameIndex),
+ m_oldBorderFrameType(_frameTypeBorder),
+ m_newBorder( _newBorder)
+{
+}
+
+KWFrameBorderCommand::~KWFrameBorderCommand()
+{
+ m_indexFrame.setAutoDelete( true);
+ m_oldBorderFrameType.setAutoDelete( true);
+}
+
+void KWFrameBorderCommand::execute()
+{
+ FrameIndex *tmp;
+ KWDocument *doc = 0L;
+ for ( tmp=m_indexFrame.first(); tmp != 0; tmp=m_indexFrame.next() )
+ {
+ KWFrameSet *frameSet =tmp->m_pFrameSet;
+ doc = frameSet->kWordDocument();
+ KWFrame *frame=frameSet->frame(tmp->m_iFrameIndex);
+ KWTableFrameSet::Cell *cell = dynamic_cast<KWTableFrameSet::Cell *>(frame->frameSet());
+ FrameBorderTypeStruct *tmpFrameStruct=m_oldBorderFrameType.at(m_indexFrame.find(tmp));
+
+ switch( tmpFrameStruct->m_EFrameType)
+ {
+ case KoBorder::LeftBorder:
+ if(cell) // is a table cell
+ cell->setLeftBorder(m_newBorder);
+ else
+ frame->setLeftBorder(m_newBorder);
+ break;
+ case KoBorder::RightBorder:
+ if(cell) // is a table cell
+ cell->setRightBorder(m_newBorder);
+ else
+ frame->setRightBorder(m_newBorder);
+ break;
+ case KoBorder::TopBorder:
+ if(cell) // is a table cell
+ cell->setTopBorder(m_newBorder);
+ else
+ frame->setTopBorder(m_newBorder);
+ break;
+ case KoBorder::BottomBorder:
+ if(cell) // is a table cell
+ cell->setBottomBorder(m_newBorder);
+ else
+ frame->setBottomBorder(m_newBorder);
+ break;
+ default:
+ break;
+ }
+
+ if (!cell) {
+ frame->frameBordersChanged();
+ //fixme frameBorderChanged for table cells here too ?
+ }
+ }
+
+
+ if ( doc )
+ {
+ doc->repaintAllViews();
+ }
+}
+
+void KWFrameBorderCommand::unexecute()
+{
+ FrameIndex *tmp;
+ KWDocument *doc = 0L;
+ for ( tmp=m_indexFrame.first(); tmp != 0; tmp=m_indexFrame.next() )
+ {
+ KWFrameSet *frameSet =tmp->m_pFrameSet;
+ doc = frameSet->kWordDocument();
+ KWFrame *frame=frameSet->frame(tmp->m_iFrameIndex);
+ KWTableFrameSet::Cell *cell = dynamic_cast<KWTableFrameSet::Cell *>(frame->frameSet());
+ FrameBorderTypeStruct *tmpFrameStruct=m_oldBorderFrameType.at(m_indexFrame.find(tmp));
+ switch(tmpFrameStruct->m_EFrameType)
+ {
+ case KoBorder::LeftBorder:
+ if(cell) // is a table cell
+ cell->setLeftBorder(tmpFrameStruct->m_OldBorder);
+ else
+ frame->setLeftBorder(tmpFrameStruct->m_OldBorder);
+ break;
+ case KoBorder::RightBorder:
+ if(cell) // is a table cell
+ cell->setRightBorder(tmpFrameStruct->m_OldBorder);
+ else
+ frame->setRightBorder(tmpFrameStruct->m_OldBorder);
+ break;
+ case KoBorder::TopBorder:
+ if(cell) // is a table cell
+ cell->setTopBorder(tmpFrameStruct->m_OldBorder);
+ else
+ frame->setTopBorder(tmpFrameStruct->m_OldBorder);
+ break;
+ case KoBorder::BottomBorder:
+ if(cell) // is a table cell
+ cell->setBottomBorder(tmpFrameStruct->m_OldBorder);
+ else
+ frame->setBottomBorder(tmpFrameStruct->m_OldBorder);
+ break;
+ default:
+ break;
+ }
+ if (!cell) {
+ frame->frameBordersChanged();
+ //fixme frameBorderChanged for table cells here too ?
+ }
+ }
+
+
+
+ if ( doc )
+ {
+ //update frames
+ doc->repaintAllViews();
+ }
+}
+
+KWFrameBackGroundColorCommand::KWFrameBackGroundColorCommand( const QString &name, QPtrList<FrameIndex> &_listFrameIndex, QPtrList<QBrush> &_oldBrush,const QBrush & _newColor ):
+ KNamedCommand(name),
+ m_indexFrame(_listFrameIndex),
+ m_oldBackGroundColor(_oldBrush),
+ m_newColor( _newColor)
+{
+}
+
+KWFrameBackGroundColorCommand::~KWFrameBackGroundColorCommand()
+{
+ m_indexFrame.setAutoDelete(true);
+ m_oldBackGroundColor.setAutoDelete(true);
+}
+
+
+void KWFrameBackGroundColorCommand::execute()
+{
+ FrameIndex *tmp;
+ KWDocument * doc = 0L;
+ for ( tmp=m_indexFrame.first(); tmp != 0; tmp=m_indexFrame.next() )
+ {
+ KWFrameSet *frameSet =tmp->m_pFrameSet;
+ if ( frameSet && (frameSet->type() != FT_PICTURE) && (frameSet->type() != FT_PART))
+ {
+ doc = frameSet->kWordDocument();
+ KWFrame *frame=frameSet->frame(tmp->m_iFrameIndex);
+ frame->setBackgroundColor(m_newColor);
+ }
+ }
+ //update frame
+ if ( doc )
+ doc->repaintAllViews();
+}
+
+void KWFrameBackGroundColorCommand::unexecute()
+{
+ FrameIndex *tmp;
+ KWDocument * doc = 0L;
+ for ( tmp=m_indexFrame.first(); tmp != 0; tmp=m_indexFrame.next() )
+ {
+ KWFrameSet *frameSet =tmp->m_pFrameSet;
+ if ( frameSet && (frameSet->type() != FT_PICTURE) && (frameSet->type() != FT_PART) )
+ {
+ doc = frameSet->kWordDocument();
+ KWFrame *frame=frameSet->frame(tmp->m_iFrameIndex);
+ QBrush *tmpFrameStruct=m_oldBackGroundColor.at(m_indexFrame.find(tmp));
+ frame->setBackgroundColor(*tmpFrameStruct);
+ }
+ }
+
+ //update frames
+ if ( doc )
+ doc->repaintAllViews();
+}
+
+KWFrameStyleCommand::KWFrameStyleCommand( const QString &name, KWFrame *_frame, KWFrameStyle *_fs, bool _repaintViews ) :
+ KNamedCommand( name )
+{
+ m_frame = _frame;
+ m_fs = _fs;
+ repaintViews = _repaintViews;
+
+ m_oldValues = new KWFrameStyle( "Old", m_frame );
+}
+
+void KWFrameStyleCommand::execute()
+{
+ applyFrameStyle( m_fs);
+}
+
+void KWFrameStyleCommand::unexecute()
+{
+ applyFrameStyle( m_oldValues);
+}
+
+void KWFrameStyleCommand::applyFrameStyle( KWFrameStyle * _sty )
+{
+ if ( m_frame->frameSet() && (m_frame->frameSet()->type() != FT_PICTURE)&& (m_frame->frameSet()->type() != FT_PART))
+ m_frame->setBackgroundColor( _sty->backgroundColor() );
+ m_frame->setLeftBorder( _sty->leftBorder() );
+ m_frame->setRightBorder( _sty->rightBorder() );
+ m_frame->setTopBorder( _sty->topBorder() );
+ m_frame->setBottomBorder( _sty->bottomBorder() );
+
+ m_frame->frameBordersChanged();
+ if ( repaintViews )
+ m_frame->frameSet()->kWordDocument()->repaintAllViews();
+}
+
+
+KWTableStyleCommand::KWTableStyleCommand( const QString &name, KWFrame *_frame, KWTableStyle *_ts, bool _repaintViews ) :
+ KNamedCommand( name )
+{
+ m_frame = _frame;
+ m_ts = _ts;
+ repaintViews = _repaintViews;
+
+ // No need for i18n because it will never be displayed.
+ m_fsc = new KWFrameStyleCommand( "Apply Framestyle to Frame", m_frame, m_ts->frameStyle(), repaintViews );
+ m_sc = 0L;
+}
+
+KWTableStyleCommand::~KWTableStyleCommand()
+{
+ delete m_fsc;
+ delete m_sc;
+}
+
+void KWTableStyleCommand::execute()
+{
+ if (m_fsc)
+ m_fsc->execute();
+
+ if ( (m_ts) && ( m_frame->frameSet()->type() == FT_TEXT ) && ( m_ts->paragraphStyle() ) )
+ {
+ KoTextObject *textObject = ((KWTextFrameSet*)m_frame->frameSet())->textObject();
+ textObject->textDocument()->selectAll( KoTextDocument::Temp );
+ m_sc = textObject->applyStyleCommand( 0L, m_ts->paragraphStyle(), KoTextDocument::Temp, KoParagLayout::All, KoTextFormat::Format, true, false );
+ textObject->textDocument()->removeSelection( KoTextDocument::Temp );
+ }
+
+ m_frame->frameBordersChanged();
+ if ( repaintViews )
+ m_frame->frameSet()->kWordDocument()->repaintAllViews();
+
+}
+
+void KWTableStyleCommand::unexecute()
+{
+ if (m_fsc)
+ m_fsc->unexecute();
+ if (m_sc)
+ m_sc->unexecute();
+
+ m_frame->frameBordersChanged();
+ if ( repaintViews )
+ m_frame->frameSet()->kWordDocument()->repaintAllViews();
+}
+
+KWTableTemplateCommand::KWTableTemplateCommand( const QString &name, KWTableFrameSet *_table, KWTableTemplate *_tt ) :
+ KNamedCommand( name )
+{
+ m_table = _table;
+ m_tt = _tt;
+
+ // No need for i18n because it will never be displayed.
+ m_tableCommands = new KMacroCommand( "Apply Tablestyles to Table" );
+
+
+ KWTableStyle *cell = 0L;
+ unsigned int rows = m_table->getRows();
+ unsigned int cols = m_table->getColumns();
+
+ for ( unsigned int i = 0; i < rows; i++ )
+ {
+ for ( unsigned int j = 0; j < cols; j++ )
+ {
+ if ( (i==0) && (j==0) ) // TOP LEFT CORNER
+ cell = m_tt->pTopLeftCorner();
+ else
+ if ( (i==0) && ( j==(cols-1) ) ) // TOP RIGHT CORNER
+ cell = m_tt->pTopRightCorner();
+ else
+ if ( ( i==(rows-1) ) && (j==0) ) // BOTTOM LEFT CORNER
+ cell = m_tt->pBottomLeftCorner();
+ else
+ if ( ( i==(rows-1) ) && ( j==(cols-1) ) ) // BOTTOM RIGHT CORNER
+ cell = m_tt->pBottomRightCorner();
+ else
+ if ( ( i==0 ) && ( j>0 ) && ( j<(cols-1) ) ) // FIRST ROW
+ cell = m_tt->pFirstRow();
+ else
+ if ( ( j==0 ) && ( i>0 ) && ( i<(rows-1) ) ) // FIRST COL
+ cell = m_tt->pFirstCol();
+ else
+ if ( ( i==(rows-1) ) && ( j>0 ) && ( j<(cols-1) ) ) // LAST ROW
+ cell = m_tt->pLastRow();
+ else
+ if ( ( j==(cols-1) ) && ( i>0 ) && ( i<(rows-1) ) ) // LAST COL
+ cell = m_tt->pLastCol();
+ else
+ if ( (i>0) && (j>0) && (i<(rows-1)) && (j<(cols-1)) ) // BODY
+ cell = m_tt->pBodyCell();
+
+ m_tableCommands->addCommand( new KWTableStyleCommand( "Apply tablestyle to cell", m_table->cell(i,j)->frame(0),cell, false ) );
+ }
+ }
+}
+
+KWTableTemplateCommand::~KWTableTemplateCommand()
+{
+ delete m_tableCommands;
+}
+
+void KWTableTemplateCommand::execute()
+{
+ m_tableCommands->execute();
+ m_table->kWordDocument()->repaintAllViews();
+}
+
+void KWTableTemplateCommand::unexecute()
+{
+ m_tableCommands->unexecute();
+ m_table->kWordDocument()->repaintAllViews();
+}
+
+
+KWFrameResizeCommand::KWFrameResizeCommand(const QString &name, const QValueList<FrameIndex> &frameIndex, const QValueList<FrameResizeStruct> &frameResize )
+ : KNamedCommand(name), m_indexFrame(frameIndex), m_frameResize(frameResize) {
+ Q_ASSERT(m_indexFrame.count() == m_frameResize.count());
+}
+KWFrameResizeCommand::KWFrameResizeCommand(const QString &name, FrameIndex frameIndex, const FrameResizeStruct &frameResize )
+ : KNamedCommand(name) {
+ m_indexFrame.append(frameIndex);
+ m_frameResize.append(frameResize);
+}
+
+void KWFrameResizeCommand::execute()
+{
+ QValueList<FrameResizeStruct>::Iterator resizeIter = m_frameResize.begin();
+ QValueList<FrameIndex>::Iterator iter = m_indexFrame.begin();
+ for(; iter != m_indexFrame.end() && resizeIter != m_frameResize.end(); ++resizeIter, ++iter ) {
+ FrameIndex index = *iter;
+ FrameResizeStruct frs = *resizeIter;
+
+ KWFrameSet *frameSet = index.m_pFrameSet;
+ Q_ASSERT( frameSet );
+ KWFrame *frame = frameSet->frame(index.m_iFrameIndex);
+ Q_ASSERT( frame );
+ frame->setCoords(frs.newRect.left(),frs.newRect.top(),frs.newRect.right(),frs.newRect.bottom());
+ frame->setMinimumFrameHeight(frs.newMinHeight);
+ KWTableFrameSet *table = frameSet->groupmanager();
+ if (table) {
+ KWTableFrameSet::Cell *cell=dynamic_cast<KWTableFrameSet::Cell *>(frameSet);
+ if(cell) {
+ table->recalcCols(cell->firstColumn(), cell->firstRow());
+ table->recalcRows(cell->firstColumn(), cell->firstRow());
+ }
+ else {
+ table->recalcCols(0, 0);
+ table->recalcRows(0, 0);
+ }
+ }
+
+ KWDocument * doc = frameSet->kWordDocument();
+ if ( frameSet->frameSetInfo() != KWFrameSet::FI_BODY ) // header/footer/footnote
+ doc->recalcFrames();
+
+ //update frames
+ doc->frameChanged( frame );
+ }
+}
+
+void KWFrameResizeCommand::unexecute()
+{
+ QValueList<FrameResizeStruct>::Iterator resizeIter = m_frameResize.begin();
+ QValueList<FrameIndex>::Iterator iter = m_indexFrame.begin();
+ for(; iter != m_indexFrame.end() && resizeIter != m_frameResize.end(); ++resizeIter, ++iter ) {
+ FrameIndex index = *iter;
+ FrameResizeStruct frs = *resizeIter;
+ KWFrameSet *frameSet =index.m_pFrameSet;
+ Q_ASSERT( frameSet );
+ KWFrame *frame=frameSet->frame(index.m_iFrameIndex);
+ Q_ASSERT( frame );
+ frame->setCoords(frs.oldRect.left(),frs.oldRect.top(),frs.oldRect.right(),frs.oldRect.bottom());
+ frame->setMinimumFrameHeight(frs.oldMinHeight);
+ KWTableFrameSet *table = frameSet->groupmanager();
+ if (table) {
+ KWTableFrameSet::Cell *cell=dynamic_cast<KWTableFrameSet::Cell *>(frameSet);
+ if(cell) {
+ table->recalcCols(cell->firstColumn(), cell->firstRow());
+ table->recalcRows(cell->firstColumn(), cell->firstRow());
+ }
+ else {
+ table->recalcCols(0, 0);
+ table->recalcRows(0, 0);
+ }
+ }
+ KWDocument * doc = frameSet->kWordDocument();
+ if ( frameSet->frameSetInfo() != KWFrameSet::FI_BODY ) // header/footer/footnote
+ doc->recalcFrames();
+
+ frame->updateRulerHandles();
+
+ //update frames
+ doc->frameChanged( frame );
+ }
+}
+
+KWFrameChangePictureCommand::KWFrameChangePictureCommand( const QString &name, FrameIndex _frameIndex, const KoPictureKey & _oldKey, const KoPictureKey & _newKey ) :
+ KNamedCommand(name),
+ m_indexFrame(_frameIndex),
+ m_oldKey(_oldKey),
+ m_newKey(_newKey)
+{
+}
+
+void KWFrameChangePictureCommand::execute()
+{
+ KWFrameSet *frameSet = m_indexFrame.m_pFrameSet;
+ Q_ASSERT( frameSet );
+ KWFrame *frame = frameSet->frame(m_indexFrame.m_iFrameIndex);
+ Q_ASSERT( frame );
+ KWDocument * doc = frameSet->kWordDocument();
+ KWPictureFrameSet *frameset = static_cast<KWPictureFrameSet *>(frame->frameSet());
+ frameset->reloadPicture( m_newKey );
+ frameSet->kWordDocument()->refreshDocStructure( frameSet->type() );
+ doc->frameChanged( frame );
+}
+
+void KWFrameChangePictureCommand::unexecute()
+{
+ KWFrameSet *frameSet =m_indexFrame.m_pFrameSet;
+ KWFrame *frame=frameSet->frame(m_indexFrame.m_iFrameIndex);
+ KWDocument * doc = frameSet->kWordDocument();
+ KWPictureFrameSet *frameset = static_cast<KWPictureFrameSet *>(frame->frameSet());
+ frameset->reloadPicture( m_oldKey );
+ frameSet->kWordDocument()->refreshDocStructure( frameSet->type() );
+ doc->frameChanged( frame );
+}
+
+
+KWFramePartMoveCommand::KWFramePartMoveCommand( const QString &name, FrameIndex _frameIndex, FrameResizeStruct _frameMove ) :
+ KNamedCommand(name),
+ m_indexFrame(_frameIndex),
+ m_frameMove(_frameMove)
+{
+}
+
+void KWFramePartMoveCommand::execute()
+{
+ KWFrameSet *frameSet = m_indexFrame.m_pFrameSet;
+ Q_ASSERT( frameSet );
+ KWFrame *frame = frameSet->frame(m_indexFrame.m_iFrameIndex);
+ Q_ASSERT( frame );
+ frame->setCoords(m_frameMove.newRect.left(),m_frameMove.newRect.top(),m_frameMove.newRect.right(),m_frameMove.newRect.bottom());
+
+ KWDocument * doc = frameSet->kWordDocument();
+
+ frame->updateRulerHandles();
+ doc->frameChanged( frame );
+}
+
+void KWFramePartMoveCommand::unexecute()
+{
+ KWFrameSet *frameSet =m_indexFrame.m_pFrameSet;
+ KWFrame *frame=frameSet->frame(m_indexFrame.m_iFrameIndex);
+ frame->setCoords(m_frameMove.oldRect.left(),m_frameMove.oldRect.top(),m_frameMove.oldRect.right(),m_frameMove.oldRect.bottom());
+
+ KWDocument * doc = frameSet->kWordDocument();
+ frame->updateRulerHandles();
+
+ //update frames
+ doc->frameChanged( frame );
+}
+
+bool KWFramePartMoveCommand::frameMoved()
+{
+ return (m_frameMove.oldRect!=m_frameMove.newRect);
+}
+
+KWFramePartInternalCommand::KWFramePartInternalCommand( const QString &name, KWPartFrameSet *part ) :
+ KNamedCommand(name),
+ m_part(part)
+{
+ m_url = m_part->getChild()->document()->url();
+}
+
+void KWFramePartInternalCommand::execute()
+{
+ m_part->getChild()->document()->setStoreInternal(true);
+}
+
+void KWFramePartInternalCommand::unexecute()
+{
+ m_part->getChild()->document()->setStoreInternal(false);
+ m_part->getChild()->document()->setURL( m_url );
+}
+
+
+KWFramePartExternalCommand::KWFramePartExternalCommand( const QString &name, KWPartFrameSet *part ) :
+ KNamedCommand(name),
+ m_part(part)
+{
+}
+
+void KWFramePartExternalCommand::execute()
+{
+ m_part->getChild()->document()->setStoreInternal(false);
+}
+
+void KWFramePartExternalCommand::unexecute()
+{
+ m_part->getChild()->document()->setStoreInternal(true);
+}
+
+
+KWFrameMoveCommand::KWFrameMoveCommand( const QString &name,
+ const QValueList<FrameIndex> & _frameIndex,
+ const QValueList<FrameMoveStruct> & _frameMove ) :
+ KNamedCommand(name),
+ m_indexFrame(_frameIndex),
+ m_frameMove(_frameMove)
+{
+}
+
+void KWFrameMoveCommand::execute()
+{
+ bool needRelayout = false;
+ KWDocument * doc = 0L;
+ QValueList<FrameMoveStruct>::Iterator moveIt = m_frameMove.begin();
+ QValueList<FrameIndex>::Iterator tmp = m_indexFrame.begin();
+ for( ; tmp != m_indexFrame.end() && moveIt != m_frameMove.end(); ++tmp, ++moveIt )
+ {
+ KWFrameSet *frameSet = (*tmp).m_pFrameSet;
+ doc = frameSet->kWordDocument();
+ KWFrame *frame = frameSet->frame((*tmp).m_iFrameIndex);
+ frame->moveTopLeft( (*moveIt).newPos );
+
+ frame->updateRulerHandles();
+ needRelayout = needRelayout || ( frame->runAround() != KWFrame::RA_NO );
+ }
+ if ( doc )
+ {
+ doc->updateAllFrames();
+ if ( needRelayout )
+ doc->layout();
+
+ doc->updateRulerFrameStartEnd();
+ doc->repaintAllViews();
+ }
+}
+
+void KWFrameMoveCommand::unexecute()
+{
+ bool needRelayout = false;
+ KWDocument * doc = 0L;
+ QValueList<FrameMoveStruct>::Iterator moveIt = m_frameMove.begin();
+ QValueList<FrameIndex>::Iterator tmp = m_indexFrame.begin();
+ for( ; tmp != m_indexFrame.end() && moveIt != m_frameMove.end(); ++tmp, ++moveIt )
+ {
+ KWFrameSet *frameSet = (*tmp).m_pFrameSet;
+ doc = frameSet->kWordDocument();
+ KWFrame *frame = frameSet->frame((*tmp).m_iFrameIndex);
+ frame->moveTopLeft( (*moveIt).oldPos );
+
+ frame->updateRulerHandles();
+ needRelayout = needRelayout || ( frame->runAround() != KWFrame::RA_NO );
+ }
+
+ if ( doc )
+ {
+ doc->updateAllFrames();
+ if ( needRelayout )
+ doc->layout();
+ doc->updateRulerFrameStartEnd();
+ doc->repaintAllViews();
+ }
+}
+
+KWFramePropertiesCommand::KWFramePropertiesCommand( const QString &name, KWFrame *_frameBefore, KWFrame *_frameAfter ) :
+ KNamedCommand(name),
+ m_frameIndex( _frameAfter ),
+ m_frameBefore(_frameBefore),
+ m_frameAfter(_frameAfter->getCopy())
+{
+}
+
+KWFramePropertiesCommand::~KWFramePropertiesCommand()
+{
+ delete m_frameBefore;
+ delete m_frameAfter;
+}
+
+void KWFramePropertiesCommand::execute()
+{
+ kdDebug(32001) << "KWFrameChangeParamCommand::execute" << endl;
+ KWFrameSet *frameSet = m_frameIndex.m_pFrameSet;
+ Q_ASSERT( frameSet );
+
+ KWFrame *frame = frameSet->frame( m_frameIndex.m_iFrameIndex );
+ Q_ASSERT( frame );
+ frame->copySettings(m_frameAfter);
+ frame->frameStack()->update();
+
+ KWDocument * doc = frameSet->kWordDocument();
+ if(doc)
+ {
+ doc->frameChanged( frame );
+ doc->updateAllFrames();
+ doc->layout();
+ doc->repaintAllViews();
+ doc->updateRulerFrameStartEnd();
+ }
+}
+
+void KWFramePropertiesCommand::unexecute()
+{
+ kdDebug(32001) << "KWFrameChangeParamCommand::unexecute" << endl;
+ KWFrameSet *frameSet = m_frameIndex.m_pFrameSet;
+ Q_ASSERT( frameSet );
+
+ KWFrame *frame = frameSet->frame( m_frameIndex.m_iFrameIndex );
+ Q_ASSERT( frame );
+ frame->copySettings(m_frameBefore);
+ frame->frameStack()->update();
+ KWDocument * doc = frameSet->kWordDocument();
+ if(doc)
+ {
+ doc->frameChanged( frame );
+ doc->updateAllFrames();
+ doc->layout();
+ doc->repaintAllViews();
+ doc->updateRulerFrameStartEnd();
+ }
+}
+
+
+KWFrameSetInlineCommand::KWFrameSetInlineCommand( const QString &name, KWFrameSet *frameset, bool value ) :
+ KNamedCommand(name),
+ m_pFrameSet( frameset ),
+ m_value( value )
+{
+ m_oldValue = m_pFrameSet->isFloating();
+}
+
+void KWFrameSetInlineCommand::setValue( bool value )
+{
+ kdDebug(32001) << "KWFrameSetInlineCommand::execute" << endl;
+ if ( value )
+ {
+ // Make frame(set) floating
+ m_pFrameSet->setFloating();
+ // ## We might want to store a list of anchors in the command, and reuse them
+ // in execute/unexecute. Currently setFixed forgets the anchors and setFloating recreates new ones...
+ }
+ else
+ {
+ // Make frame(set) non-floating
+ m_pFrameSet->setFixed();
+ }
+
+ m_pFrameSet->kWordDocument()->updateAllFrames();
+}
+
+void KWFrameSetInlineCommand::execute()
+{
+ setValue( m_value );
+}
+
+void KWFrameSetInlineCommand::unexecute()
+{
+ setValue( m_oldValue );
+}
+
+KWPageLayoutCommand::KWPageLayoutCommand( const QString &name,KWDocument *_doc,KWPageLayoutStruct &_oldLayout, KWPageLayoutStruct &_newLayout ) :
+ KNamedCommand(name),
+ m_pDoc(_doc),
+ m_oldLayout(_oldLayout),
+ m_newLayout(_newLayout)
+{
+}
+
+void KWPageLayoutCommand::execute()
+{
+ m_pDoc->setPageLayout( m_newLayout._pgLayout, m_newLayout._cl, m_newLayout._hf );
+}
+
+void KWPageLayoutCommand::unexecute()
+{
+ m_pDoc->setPageLayout( m_oldLayout._pgLayout, m_oldLayout._cl, m_oldLayout._hf);
+}
+
+
+KWDeleteFrameCommand::KWDeleteFrameCommand( const QString &name, KWFrame * frame ):
+ KNamedCommand(name),
+ m_frameIndex( frame ),
+ m_copyFrame( frame->getCopy() )
+{
+}
+
+KWDeleteFrameCommand::KWDeleteFrameCommand( const FrameIndex &frameIndex) :
+ KNamedCommand("")
+{
+ m_frameIndex = frameIndex;
+ m_copyFrame = m_frameIndex.m_pFrameSet->frame(m_frameIndex.m_iFrameIndex)->getCopy();
+}
+
+KWDeleteFrameCommand::~KWDeleteFrameCommand()
+{
+ delete m_copyFrame;
+}
+
+
+void KWDeleteFrameCommand::execute()
+{
+ KWFrameSet *frameSet = m_frameIndex.m_pFrameSet;
+ Q_ASSERT( frameSet );
+
+ KWFrame *frame = frameSet->frame( m_frameIndex.m_iFrameIndex );
+ Q_ASSERT( frame );
+
+kdDebug() << "delete frame " << m_frameIndex.m_iFrameIndex << " of " << frameSet->name() << endl;
+ KWDocument* doc = frameSet->kWordDocument();
+ doc->terminateEditing( frameSet );
+ doc->frameChanged( frame );
+ frameSet->deleteFrame( m_frameIndex.m_iFrameIndex );
+
+/* KWTextFrameSet * textfs = dynamic_cast<KWTextFrameSet *>(fs);
+ if(textfs) { TODO
+ // if content does not fit; change properties of previous frame to be 'do not show'
+ }
+*/
+
+ doc->refreshDocStructure( frameSet->type() );
+ doc->updateTextFrameSetEdit();
+}
+
+void KWDeleteFrameCommand::unexecute()
+{
+ KWFrameSet *frameSet = m_frameIndex.m_pFrameSet;
+ KWFrame * frame = m_copyFrame->getCopy();
+ frame->setFrameSet( frameSet );
+ frameSet->addFrame( frame );
+
+ KWPartFrameSet * partfs = dynamic_cast<KWPartFrameSet *>( frameSet );
+ if ( partfs )
+ partfs->setDeleted( false );
+
+ KWTextFrameSet * textfs = dynamic_cast<KWTextFrameSet *>( frameSet );
+ if ( textfs )
+ textfs->textObject()->formatMore( 2 );
+ KWDocument* doc = frameSet->kWordDocument();
+ doc->frameChanged( frame );
+ // could have been the last frame on a page, so undeleting it needs to recreate the page
+ doc->recalcFrames( frame->pageNumber() );
+ doc->refreshDocStructure(frameSet->type());
+ doc->updateRulerFrameStartEnd();
+}
+
+KWCreateFrameCommand::KWCreateFrameCommand( const QString &name, KWFrame * frame ) :
+ KWDeleteFrameCommand( name, frame )
+{}
+
+
+KWUngroupTableCommand::KWUngroupTableCommand( const QString &name, KWTableFrameSet * _table ):
+ KNamedCommand(name),
+ m_pTable(_table)
+{
+ m_ListFrame.clear();
+ for ( KWTableFrameSet::TableIter i(m_pTable); i ; ++i ) {
+ m_ListFrame.append( i.current() );
+ }
+}
+
+void KWUngroupTableCommand::execute()
+{
+ KWDocument * doc = m_pTable->kWordDocument();
+ for ( KWTableFrameSet::TableIter i(m_pTable) ; i ; ++i ) {
+ i->setGroupManager( 0L );
+ doc->addFrameSet( i.current() );
+ }
+ m_pTable->ungroup();
+ doc->removeFrameSet(m_pTable);
+
+ //when you ungroup a table
+ // you must remove table item in docstruct
+ // create items in text item in docstruct
+
+ int refresh=0;
+ refresh |=Tables;
+ refresh |=TextFrames;
+ doc->refreshDocStructure(refresh);
+
+ doc->updateAllFrames();
+ doc->repaintAllViews();
+}
+
+void KWUngroupTableCommand::unexecute()
+{
+ Q_ASSERT(m_pTable);
+ m_pTable->group();
+ KWDocument * doc = m_pTable->kWordDocument();
+ KWFrameSet *tmp;
+ for ( tmp=m_ListFrame.first(); tmp != 0; tmp=m_ListFrame.next() )
+ {
+ tmp->setGroupManager(m_pTable);
+ doc->removeFrameSet(tmp);
+ KWTableFrameSet::Cell *cell=static_cast<KWTableFrameSet::Cell *>(tmp);
+ Q_ASSERT(cell);
+ m_pTable->addCell( cell );
+ }
+ doc->addFrameSet(m_pTable);
+
+ int refresh=0;
+ refresh |=Tables;
+ refresh |=TextFrames;
+ doc->refreshDocStructure(refresh);
+
+
+ doc->updateAllFrames();
+ doc->repaintAllViews();
+}
+
+
+KWDeleteTableCommand::KWDeleteTableCommand( const QString &name, KWTableFrameSet * _table ):
+ KNamedCommand(name),
+ m_pTable(_table)
+{
+ Q_ASSERT(m_pTable);
+}
+
+void KWDeleteTableCommand::execute()
+{
+ kdDebug(32001) << "KWDeleteTableCommand::execute" << endl;
+ KWDocument * doc = m_pTable->kWordDocument();
+ doc->removeFrameSet(m_pTable);
+ m_pTable->setVisible( false );
+ doc->refreshDocStructure((int)Tables);
+ doc->updateAllFrames();
+ m_pTable->updateFrames(); // not in the doc list anymore, so the above call didn't do it!
+ doc->layout();
+ doc->repaintAllViews();
+ doc->updateRulerFrameStartEnd();
+
+}
+
+void KWDeleteTableCommand::unexecute()
+{
+ kdDebug(32001) << "KWDeleteTableCommand::unexecute" << endl;
+ KWDocument * doc = m_pTable->kWordDocument();
+ m_pTable->setVisible( true );
+ doc->addFrameSet(m_pTable);
+ doc->refreshDocStructure((int)Tables);
+ doc->updateAllFrames();
+ doc->layout();
+ doc->repaintAllViews();
+ doc->updateRulerFrameStartEnd();
+}
+
+
+KWInsertColumnCommand::KWInsertColumnCommand( const QString &name, KWTableFrameSet * _table, int _col, double _maxRight ):
+ KNamedCommand(name),
+ m_pTable(_table),
+ m_rc(new RemovedColumn()),
+ m_colPos(_col),
+ m_maxRight(_maxRight),
+ m_oldWidth(0)
+{
+ Q_ASSERT(m_pTable);
+}
+
+KWInsertColumnCommand::~KWInsertColumnCommand()
+{
+ delete m_rc;
+}
+
+void KWInsertColumnCommand::execute()
+{
+ kdDebug(32001) << "KWInsertColumnCommand::execute" << endl;
+ KWDocument * doc = m_pTable->kWordDocument();
+ // a insert column = KWTableFrameSet::m_sDefaultColWidth, see kwtableframeset.cc
+ if (m_pTable->boundingRect().right() + KWTableFrameSet::m_sDefaultColWidth >= static_cast<int>(m_maxRight))
+ { // must create space (resize the table)
+ m_oldWidth = m_pTable->boundingRect().width();
+ // here we calculate the new table size for a table that would take the
+ // entire width of the page, which what the user wants 99% of the time.
+ double newTableWidth =m_maxRight - m_pTable->boundingRect().left();
+ double newColSize = newTableWidth / (m_pTable->getColumns()+1);
+ double resizeTableWidth = m_maxRight - m_pTable->boundingRect().left();
+ m_pTable->resizeWidth(resizeTableWidth - newColSize);
+ m_pTable->insertNewColumn(m_colPos, newColSize);
+ }
+ else
+ { // simply insert the column without asking for a specific size :
+ m_pTable->insertNewColumn(m_colPos);
+ }
+ Q_ASSERT(m_pTable->boundingRect().right() <= m_maxRight);
+ doc->updateAllFrames();
+ doc->layout();
+ doc->repaintAllViews();
+}
+
+void KWInsertColumnCommand::unexecute()
+{
+ kdDebug(32001) << "KWInsertColumnCommand::unexecute" << endl;
+ KWDocument * doc = m_pTable->kWordDocument();
+ doc->terminateEditing(m_pTable);
+ m_pTable->deleteColumn(m_colPos, *m_rc);
+ // now undo the resize of the table if necessary:
+ if (m_oldWidth) {
+ // yes, the table was resized, let's undo that :
+ m_pTable->resizeWidth(m_oldWidth);
+ }
+ doc->updateAllFrames();
+ doc->layout();
+ doc->repaintAllViews();
+}
+
+
+
+KWInsertRowCommand::KWInsertRowCommand( const QString &name, KWTableFrameSet * _table, int _row ):
+ KNamedCommand(name),
+ m_pTable(_table),
+ m_rr(new RemovedRow()),
+ m_rowPos(_row),
+ m_inserted(false)
+{
+ Q_ASSERT(m_pTable);
+}
+
+KWInsertRowCommand::~KWInsertRowCommand()
+{
+ delete m_rr;
+}
+
+void KWInsertRowCommand::execute()
+{
+ kdDebug(32001) << "KWInsertRowCommand::execute" << endl;
+ KWDocument * doc = m_pTable->kWordDocument();
+ if(m_inserted)
+ m_pTable->reInsertRow(*m_rr);
+ else {
+ m_inserted = true;
+ m_pTable->insertNewRow(m_rowPos); //only happens the first time
+ }
+ doc->updateAllFrames();
+ doc->layout();
+ doc->repaintAllViews();
+}
+
+void KWInsertRowCommand::unexecute()
+{
+ kdDebug(32001) << "KWInsertRowCommand::unexecute" << endl;
+ KWDocument * doc = m_pTable->kWordDocument();
+
+ doc->terminateEditing(m_pTable);
+ m_pTable->deleteRow( m_rowPos, *m_rr);
+
+ doc->updateAllFrames();
+ doc->layout();
+}
+
+
+KWRemoveRowCommand::KWRemoveRowCommand( const QString &name, KWTableFrameSet * _table, int _row ):
+ KNamedCommand(name),
+ m_pTable(_table),
+ m_rr(new RemovedRow()),
+ m_rowPos(_row)
+{
+ Q_ASSERT(m_pTable);
+}
+
+KWRemoveRowCommand::~KWRemoveRowCommand()
+{
+ delete m_rr;
+}
+
+void KWRemoveRowCommand::execute()
+{
+ kdDebug(32001) << "KWRemoveRowCommand::execute" << endl;
+ KWDocument * doc = m_pTable->kWordDocument();
+ doc->terminateEditing(m_pTable);
+
+ m_pTable->deleteRow( m_rowPos, *m_rr);
+
+ doc->updateAllFrames();
+ doc->layout();
+}
+
+void KWRemoveRowCommand::unexecute()
+{
+ kdDebug(32001) << "KWRemoveRowCommand::unexecute" << endl;
+ KWDocument * doc = m_pTable->kWordDocument();
+ m_pTable->reInsertRow(*m_rr);
+ doc->updateAllFrames();
+ doc->layout();
+ doc->repaintAllViews();
+}
+
+KWRemoveColumnCommand::KWRemoveColumnCommand( const QString &name, KWTableFrameSet * _table, int _col ):
+ KNamedCommand(name),
+ m_pTable(_table),
+ m_rc(new RemovedColumn()),
+ m_colPos(_col)
+{
+ Q_ASSERT(m_pTable);
+}
+
+KWRemoveColumnCommand::~KWRemoveColumnCommand()
+{
+ delete m_rc;
+}
+
+void KWRemoveColumnCommand::execute()
+{
+ kdDebug(32001) << "KWRemoveColumnCommand::execute" << endl;
+ KWDocument * doc = m_pTable->kWordDocument();
+ doc->terminateEditing(m_pTable);
+
+ m_pTable->deleteColumn( m_colPos, *m_rc);
+ doc->updateAllFrames();
+ doc->layout();
+}
+
+void KWRemoveColumnCommand::unexecute()
+{
+ kdDebug(32001) << "KWRemoveColumnCommand::unexecute" << endl;
+ KWDocument * doc = m_pTable->kWordDocument();
+ m_pTable->reInsertColumn(*m_rc);
+ doc->updateAllFrames();
+ doc->layout();
+ doc->repaintAllViews();
+}
+
+
+
+KWSplitCellCommand::KWSplitCellCommand( const QString &name, KWTableFrameSet * _table,unsigned int colBegin,unsigned int rowBegin, unsigned int colEnd,unsigned int rowEnd ):
+ KNamedCommand(name),
+ m_pTable(_table),
+ m_colBegin(colBegin),
+ m_rowBegin(rowBegin),
+ m_colEnd(colEnd),
+ m_rowEnd(rowEnd)
+{
+ Q_ASSERT(m_pTable);
+}
+
+void KWSplitCellCommand::execute()
+{
+ kdDebug(32001) << "KWSplitCellCommand::execute" << endl;
+ KWDocument * doc = m_pTable->kWordDocument();
+ doc->terminateEditing(m_pTable);
+ //kdDebug()<<"split Cell m_colBegin :"<<m_colBegin<<" m_colEnd :"<<m_colEnd<<" m_rowBegin :"<<m_rowBegin<<" m_colEnd :"<<m_colEnd<<endl;
+ m_pTable->splitCell(m_rowEnd, m_colEnd,m_colBegin,m_rowBegin,m_ListFrameSet);
+ doc->updateAllFrames();
+ doc->layout();
+}
+
+void KWSplitCellCommand::unexecute()
+{
+ kdDebug(32001) << "KWSplitCellCommand::unexecute" << endl;
+ KWDocument * doc = m_pTable->kWordDocument();
+ doc->terminateEditing(m_pTable);
+
+ //kdDebug()<<"Join Cell m_colBegin :"<<m_colBegin<<" m_colEnd :"<<m_colBegin+m_colEnd-1<<" m_rowBegin :"<<m_rowBegin<<" m_rowEnd :"<<m_rowBegin+m_rowEnd-1<<endl;
+
+ if(m_ListFrameSet.isEmpty())
+ {
+ for ( unsigned int i = 0; i < m_pTable->getColumns(); i++ )
+ {
+ for ( unsigned int j = 0; j < m_pTable->getRows(); j++ )
+ {
+ if(j>=m_rowBegin && j<=(m_rowBegin+m_rowEnd-1)
+ && i>=m_colBegin && i<=(m_colEnd+m_colBegin-1))
+ {
+ //don't store first cell
+ if( !(j==m_rowBegin && i==m_colBegin))
+ {
+ kdDebug(32001)<<"store cell row :"<<j<<" col :"<<i<<endl;
+ KWTableFrameSet::Cell *cell=static_cast<KWTableFrameSet::Cell *>(m_pTable->cell( j,i ));
+ m_ListFrameSet.append(cell);
+ }
+ }
+
+ }
+ }
+ }
+ KWTableFrameSet::Cell *cell=static_cast<KWTableFrameSet::Cell *>(m_pTable->cell( m_rowBegin,m_colBegin ));
+ m_pTable->joinCells(m_colBegin, m_rowBegin, m_colEnd+m_colBegin-1+cell->columnSpan()-1,
+ m_rowBegin+m_rowEnd-1+cell->rowSpan()-1);
+
+ doc->updateAllFrames();
+ doc->layout();
+}
+
+
+
+KWJoinCellCommand::KWJoinCellCommand( const QString &name, KWTableFrameSet * _table,unsigned int colBegin,unsigned int rowBegin, unsigned int colEnd,unsigned int rowEnd, QPtrList<KWFrameSet> listFrameSet,QPtrList<KWFrame> listCopyFrame):
+ KNamedCommand(name),
+ m_pTable(_table),
+ m_colBegin(colBegin),
+ m_rowBegin(rowBegin),
+ m_colEnd(colEnd),
+ m_rowEnd(rowEnd),
+ m_ListFrameSet(listFrameSet),
+ m_copyFrame(listCopyFrame)
+{
+ Q_ASSERT(m_pTable);
+}
+KWJoinCellCommand::~KWJoinCellCommand()
+{
+ m_copyFrame.setAutoDelete( true );
+}
+
+void KWJoinCellCommand::execute()
+{
+ kdDebug(32001) << "KWJoinCellCommand::execute" << endl;
+ KWDocument * doc = m_pTable->kWordDocument();
+ doc->terminateEditing(m_pTable);
+ m_pTable->joinCells(m_colBegin,m_rowBegin,m_colEnd,m_rowEnd);
+ doc->updateAllFrames();
+ doc->layout();
+}
+
+void KWJoinCellCommand::unexecute()
+{
+ kdDebug(32001) << "KWJoinCellCommand::unexecute" << endl;
+ KWDocument * doc = m_pTable->kWordDocument();
+ doc->terminateEditing(m_pTable);
+ m_pTable->splitCell(m_rowEnd-m_rowBegin+1, m_colEnd-m_colBegin+1,m_colBegin,m_rowBegin,m_ListFrameSet,m_copyFrame);
+ doc->updateAllFrames();
+ doc->layout();
+}
+
+
+KWChangeStartingPageCommand::KWChangeStartingPageCommand( const QString &name, KWDocument *_doc, int _oldStartingPage, int _newStartingPage):
+ KNamedCommand(name),
+ m_doc(_doc),
+ oldStartingPage(_oldStartingPage),
+ newStartingPage(_newStartingPage)
+{
+}
+
+void KWChangeStartingPageCommand::execute()
+{
+ m_doc->variableCollection()->variableSetting()->setStartingPageNumber(newStartingPage);
+ m_doc->recalcVariables( VT_PGNUM );
+}
+
+void KWChangeStartingPageCommand::unexecute()
+{
+ m_doc->variableCollection()->variableSetting()->setStartingPageNumber(oldStartingPage);
+ m_doc->recalcVariables( VT_PGNUM );
+}
+
+KWChangeVariableSettingsCommand::KWChangeVariableSettingsCommand( const QString &name, KWDocument *_doc, bool _oldValue, bool _newValue, VariableProperties _type):
+ KNamedCommand(name),
+ m_doc(_doc),
+ type(_type),
+ m_bOldValue(_oldValue),
+ m_bNewValue(_newValue)
+{
+}
+
+void KWChangeVariableSettingsCommand::changeValue( bool b )
+{
+ switch(type)
+ {
+ case VS_DISPLAYLINK:
+ m_doc->variableCollection()->variableSetting()->setDisplayLink(b);
+ m_doc->recalcVariables( VT_LINK );
+ break;
+ case VS_UNDERLINELINK:
+ m_doc->variableCollection()->variableSetting()->setUnderlineLink(b);
+ m_doc->recalcVariables( VT_LINK );
+ break;
+ case VS_DISPLAYCOMMENT:
+ m_doc->variableCollection()->variableSetting()->setDisplayComment(b);
+ m_doc->recalcVariables( VT_NOTE );
+ break;
+ case VS_DISPLAYFIELDCODE:
+ m_doc->variableCollection()->variableSetting()->setDisplayFieldCode(b);
+ //hack necessary otherwise footnote frameset is not refreshing
+ //and footnote is not resize.
+ m_doc->displayFootNoteFieldCode();
+ m_doc->recalcVariables( VT_ALL );
+ break;
+ }
+}
+
+void KWChangeVariableSettingsCommand::execute()
+{
+ changeValue(m_bNewValue);
+}
+
+void KWChangeVariableSettingsCommand::unexecute()
+{
+ changeValue(m_bOldValue);
+}
+
+KWChangeCustomVariableValue::KWChangeCustomVariableValue( const QString &name, KWDocument *_doc,const QString & _oldValue, const QString & _newValue,KoCustomVariable *var):
+ KNamedCommand(name),
+ m_doc(_doc),
+ newValue(_newValue),
+ oldValue(_oldValue),
+ m_var(var)
+{
+}
+
+KWChangeCustomVariableValue::~KWChangeCustomVariableValue()
+{
+}
+
+void KWChangeCustomVariableValue::execute()
+{
+ Q_ASSERT(m_var);
+ m_var->setValue(newValue);
+ m_doc->recalcVariables( VT_CUSTOM );
+}
+
+void KWChangeCustomVariableValue::unexecute()
+{
+ Q_ASSERT(m_var);
+ m_var->setValue(oldValue);
+ m_doc->recalcVariables( VT_CUSTOM );
+}
+
+KWChangeVariableNoteText::KWChangeVariableNoteText( const QString &name, KWDocument *_doc,
+ const QString &_oldValue,const QString &_newValue,
+ KoNoteVariable *var):
+ KNamedCommand(name),
+ m_doc(_doc),
+ newValue(_newValue),
+ oldValue(_oldValue),
+ m_var(var)
+{
+}
+
+KWChangeVariableNoteText::~KWChangeVariableNoteText()
+{
+}
+
+void KWChangeVariableNoteText::execute()
+{
+ Q_ASSERT(m_var);
+ m_var->setNote(newValue);
+}
+
+void KWChangeVariableNoteText::unexecute()
+{
+ Q_ASSERT(m_var);
+ m_var->setNote(oldValue);
+}
+
+// TODO: move to libkotext to remove code duplication with kpresenter
+KWChangeLinkVariable::KWChangeLinkVariable( const QString &name, KWDocument *_doc,const QString & _oldHref, const QString & _newHref, const QString & _oldLink,const QString &_newLink, KoLinkVariable *var):
+ KNamedCommand(name),
+ m_doc(_doc),
+ oldHref(_oldHref),
+ newHref(_newHref),
+ oldLink(_oldLink),
+ newLink(_newLink),
+ m_var(var)
+{
+}
+
+
+void KWChangeLinkVariable::execute()
+{
+ m_var->setLink(newLink,newHref);
+ m_doc->recalcVariables(VT_LINK);
+}
+
+void KWChangeLinkVariable::unexecute()
+{
+ m_var->setLink(oldLink,oldHref);
+ m_doc->recalcVariables(VT_LINK);
+}
+
+KWHideShowHeader::KWHideShowHeader( const QString &name, KWDocument *_doc, bool _newValue):
+ KNamedCommand(name),
+ m_doc(_doc),
+ newValue(_newValue)
+{
+}
+
+
+void KWHideShowHeader::execute()
+{
+ m_doc->setHeaderVisible(newValue );
+ m_doc->updateHeaderButton();
+
+}
+
+void KWHideShowHeader::unexecute()
+{
+ m_doc->setHeaderVisible(!newValue );
+ m_doc->updateHeaderButton();
+}
+
+KWHideShowFooter::KWHideShowFooter( const QString &name, KWDocument *_doc, bool _newValue):
+ KNamedCommand(name),
+ m_doc(_doc),
+ newValue(_newValue)
+{
+}
+
+
+void KWHideShowFooter::execute()
+{
+ m_doc->setFooterVisible( newValue );
+ m_doc->updateFooterButton();
+}
+
+void KWHideShowFooter::unexecute()
+{
+ m_doc->setFooterVisible( !newValue );
+ m_doc->updateFooterButton();
+}
+
+
+KWProtectContentCommand::KWProtectContentCommand( const QString &name, KWTextFrameSet*frameset, bool _protect):
+ KNamedCommand(name),
+ m_pFrameSet(frameset),
+ m_bProtect(_protect)
+{
+}
+
+
+void KWProtectContentCommand::execute()
+{
+ m_pFrameSet->setProtectContent(m_bProtect);
+ m_pFrameSet->kWordDocument()->updateTextFrameSetEdit();
+ m_pFrameSet->kWordDocument()->testAndCloseAllFrameSetProtectedContent();
+ m_pFrameSet->kWordDocument()->updateRulerInProtectContentMode();
+
+}
+
+void KWProtectContentCommand::unexecute()
+{
+ m_pFrameSet->setProtectContent(!m_bProtect);
+ m_pFrameSet->kWordDocument()->updateTextFrameSetEdit();
+ m_pFrameSet->kWordDocument()->testAndCloseAllFrameSetProtectedContent();
+ m_pFrameSet->kWordDocument()->updateRulerInProtectContentMode();
+
+}
+
+KWInsertRemovePageCommand::KWInsertRemovePageCommand( KWDocument *_doc, Command cmd, int pgNum)
+ : KCommand(), m_doc(_doc), m_cmd(cmd), m_pgNum(pgNum)
+{}
+
+KWInsertRemovePageCommand::~KWInsertRemovePageCommand() {
+ QValueListIterator<KCommand*> cmdIter = childCommands.begin();
+ for(;cmdIter != childCommands.end(); ++ cmdIter)
+ delete (*cmdIter);
+}
+
+QString KWInsertRemovePageCommand::name() const
+{
+ return m_cmd == Insert ? i18n("Insert Page") // problem with after/before page
+ : i18n("Delete Page %1").arg(m_pgNum);
+}
+
+void KWInsertRemovePageCommand::execute() {
+ if ( m_cmd == Insert )
+ doInsert(m_pgNum);
+ else
+ doRemove(m_pgNum);
+}
+
+void KWInsertRemovePageCommand::unexecute() {
+ if ( m_cmd == Insert )
+ // remove the page that was inserted
+ doRemove(m_pgNum+1);
+ else
+ // Re-insert the page that was deleted
+ doInsert(m_pgNum-1);
+}
+
+void KWInsertRemovePageCommand::doRemove(int pageNumber) {
+ bool firstRun = childCommands.count() == 0;
+ if(firstRun) {
+ QValueVector<FrameIndex> indexes;
+ QPtrList<KWFrame> frames = m_doc->framesInPage(pageNumber, false);
+ QPtrListIterator<KWFrame> framesIter(frames);
+ for(; framesIter.current(); ++framesIter)
+ indexes.append(FrameIndex(*framesIter));
+
+ // we sort them to make sure frames are deleted in order and indexes are not going
+ // to get mixed up when there is more then one frame of a frameset on the page
+ std::sort(indexes.begin(), indexes.end(), compareIndex);
+
+ QValueVector<FrameIndex>::iterator iter = indexes.begin();
+ for(; iter != indexes.end(); ++iter)
+ childCommands.append(new KWDeleteFrameCommand(*iter));
+ }
+ QValueListIterator<KCommand*> cmdIter = childCommands.begin();
+ for(;cmdIter != childCommands.end(); ++ cmdIter)
+ (*cmdIter)->execute();
+
+ // next move all frames up that are on higher pagenumbers
+ KWPage* page = m_doc->pageManager()->page(pageNumber);
+ Q_ASSERT(page);
+ if(! page) return; // hack to work around bug #125998
+ const double pageHeight = page->height();
+ const double topOfPage = m_doc->pageManager()->topOfPage(pageNumber);
+ m_doc->pageManager()->removePage( pageNumber );
+
+ if(firstRun && m_doc->lastPage() >= pageNumber) { // only walk frames when there was a page
+ // after the deleted one
+ QValueList<FrameIndex> indexes;
+ QValueList<FrameMoveStruct> moveStructs;
+ QPtrListIterator<KWFrameSet> fss = m_doc->framesetsIterator();
+ for(;fss.current(); ++fss) {
+ KWFrameSet *fs = *fss;
+ if(fs->isMainFrameset()) continue;
+ if(fs->isHeaderOrFooter()) continue;
+ if(fs->isFootEndNote()) continue;
+ if(! fs->isVisible()) continue;
+ QPtrList<KWFrame> frames = fs->frameIterator();
+ QPtrListIterator<KWFrame> framesIter(frames);
+ for(; framesIter.current(); ++framesIter) {
+ KWFrame *frame = *framesIter;
+ if(frame->top() > topOfPage) {
+ indexes.append(FrameIndex(frame));
+ KoPoint before = frame->topLeft();
+ frame->moveBy(0, -pageHeight);
+ moveStructs.append(FrameMoveStruct(before, frame->topLeft()));
+ }
+ }
+ }
+ KCommand *cmd = new KWFrameMoveCommand("", indexes, moveStructs);
+ childCommands.append(cmd);
+ }
+ m_doc->afterRemovePages();
+}
+
+bool KWInsertRemovePageCommand::compareIndex(const FrameIndex &index1, const FrameIndex &index2) {
+ if(index1.m_pFrameSet == index2.m_pFrameSet)
+ return index1.m_iFrameIndex >= index2.m_iFrameIndex;
+ return index1.m_pFrameSet >= index2.m_pFrameSet; // I don't care about frameset order,
+ // so just sort on pointers..
+}
+
+void KWInsertRemovePageCommand::doInsert(int pageNumber) {
+ m_doc->pageManager()->insertPage( pageNumber );
+ for(int i=childCommands.count()-1; i > 0; i--) // reverse order
+ childCommands[i]->unexecute();
+ m_doc->afterInsertPage( pageNumber );
+}
+
+FramePaddingStruct::FramePaddingStruct( KWFrame *frame )
+{
+ topPadding = frame->paddingTop();
+ bottomPadding= frame->paddingBottom();
+ leftPadding = frame->paddingLeft();
+ rightPadding= frame->paddingRight();
+}
+
+FramePaddingStruct::FramePaddingStruct( double _left, double _top, double _right, double _bottom ):
+ topPadding(_top),
+ bottomPadding(_bottom),
+ leftPadding(_left),
+ rightPadding(_right)
+{
+}
+
+
+KWFrameChangeFramePaddingCommand::KWFrameChangeFramePaddingCommand( const QString &name, FrameIndex _frameIndex, FramePaddingStruct _framePaddingBegin, FramePaddingStruct _framePaddingEnd ) :
+ KNamedCommand(name),
+ m_indexFrame(_frameIndex),
+ m_framePaddingBegin(_framePaddingBegin),
+ m_framePaddingEnd(_framePaddingEnd)
+{
+}
+
+void KWFrameChangeFramePaddingCommand::execute()
+{
+ KWFrameSet *frameSet = m_indexFrame.m_pFrameSet;
+ Q_ASSERT( frameSet );
+ KWFrame *frame = frameSet->frame(m_indexFrame.m_iFrameIndex);
+ Q_ASSERT( frame );
+ frame->setFramePadding( m_framePaddingEnd.leftPadding,m_framePaddingEnd.topPadding , m_framePaddingEnd.rightPadding, m_framePaddingEnd.bottomPadding);
+ frameSet->kWordDocument()->frameChanged( frame );
+}
+
+void KWFrameChangeFramePaddingCommand::unexecute()
+{
+ KWFrameSet *frameSet = m_indexFrame.m_pFrameSet;
+ Q_ASSERT( frameSet );
+ KWFrame *frame = frameSet->frame(m_indexFrame.m_iFrameIndex);
+ Q_ASSERT( frame );
+ frame->setFramePadding( m_framePaddingBegin.leftPadding,m_framePaddingBegin.topPadding , m_framePaddingBegin.rightPadding, m_framePaddingBegin.bottomPadding);
+ frameSet->kWordDocument()->frameChanged( frame );
+}
+
+KWChangeFootEndNoteSettingsCommand::KWChangeFootEndNoteSettingsCommand( const QString &name, KoParagCounter _oldCounter, KoParagCounter _newCounter ,bool _footNote ,KWDocument *_doc):
+ KNamedCommand(name),
+ m_oldCounter(_oldCounter),
+ m_newCounter(_newCounter),
+ m_footNote( _footNote ),
+ m_doc(_doc)
+{
+}
+
+void KWChangeFootEndNoteSettingsCommand::execute()
+{
+ changeCounter( m_newCounter);
+}
+
+void KWChangeFootEndNoteSettingsCommand::unexecute()
+{
+ changeCounter( m_oldCounter);
+}
+
+void KWChangeFootEndNoteSettingsCommand::changeCounter( KoParagCounter counter)
+{
+ if (m_footNote )
+ {
+ static_cast<KWVariableSettings*>(m_doc->variableCollection()->variableSetting())->changeFootNoteCounter(counter );
+ }
+ else
+ {
+ static_cast<KWVariableSettings*>(m_doc->variableCollection()->variableSetting())->changeEndNoteCounter(counter );
+ }
+ m_doc->changeFootNoteConfig();
+}
+
+
+KWChangeTabStopValueCommand::KWChangeTabStopValueCommand( const QString &name, double _oldValue, double _newValue, KWDocument *_doc):
+ KNamedCommand(name),
+ m_doc( _doc ),
+ m_oldValue(_oldValue),
+ m_newValue(_newValue)
+{
+}
+
+void KWChangeTabStopValueCommand::execute()
+{
+ m_doc->setTabStopValue ( m_newValue );
+}
+
+void KWChangeTabStopValueCommand::unexecute()
+{
+ m_doc->setTabStopValue ( m_oldValue );
+}
+
+
+
+FootNoteParameter::FootNoteParameter( KWFootNoteVariable *_var )
+{
+ noteType = _var->noteType();
+ numberingType = _var->numberingType();
+ manualString = _var->manualString();
+}
+
+FootNoteParameter::FootNoteParameter( NoteType _noteType, KWFootNoteVariable::Numbering _numberingType, const QString &_manualString)
+{
+ noteType= _noteType;
+ numberingType = _numberingType;
+ manualString = _manualString;
+}
+
+KWChangeFootNoteParametersCommand::KWChangeFootNoteParametersCommand( const QString &name, KWFootNoteVariable * _var, FootNoteParameter _oldParameter, FootNoteParameter _newParameter, KWDocument *_doc):
+ KNamedCommand(name),
+ m_doc( _doc ),
+ m_var( _var ),
+ m_oldParameter( _oldParameter ),
+ m_newParameter( _newParameter)
+{
+}
+
+void KWChangeFootNoteParametersCommand::execute()
+{
+ changeVariableParameter( m_newParameter );
+}
+
+void KWChangeFootNoteParametersCommand::unexecute()
+{
+ changeVariableParameter( m_oldParameter );
+}
+
+void KWChangeFootNoteParametersCommand::changeVariableParameter( FootNoteParameter _param )
+{
+ m_var->setNoteType( _param.noteType );
+ m_var->setNumberingType( _param.numberingType );
+ m_var->setManualString( _param.manualString );
+ m_var->setNumDisplay( -1 ); // force renumberFootNotes to recalc
+ if ( m_var->numberingType()== KWFootNoteVariable::Manual)
+ {
+ m_var->resize();
+ m_var->paragraph()->invalidate(0);
+ m_var->paragraph()->setChanged( true );
+ }
+
+ KWTextFrameSet * frameset = dynamic_cast<KWTextFrameSet *>( m_doc->frameSet( 0 ));
+ Q_ASSERT( frameset );
+ if ( frameset)
+ frameset->renumberFootNotes();
+
+ // Re-layout the footnote/endnote frame
+ KWFrame* footNoteFrame = m_var->frameSet()->frame( 0 );
+ int framePage = footNoteFrame->pageNumber();
+ m_doc->recalcFrames( framePage, -1 );
+
+ // Repaint
+ m_doc->delayedRepaintAllViews();
+}
+
+
+KWChangeFootNoteLineSeparatorParametersCommand::KWChangeFootNoteLineSeparatorParametersCommand( const QString &name, SeparatorLinePos _oldValuePos, SeparatorLinePos _newValuePos, int _oldLength, int _newLength, double _oldWidth, double _newWidth, SeparatorLineLineType _oldLineType, SeparatorLineLineType _newLineType, KWDocument *_doc):
+ KNamedCommand(name),
+ m_doc( _doc ),
+ m_oldValuePos(_oldValuePos),
+ m_newValuePos(_newValuePos),
+ m_oldLength(_oldLength),
+ m_newLength(_newLength),
+ m_oldWidth(_oldWidth),
+ m_newWidth(_newWidth),
+ m_oldLineType(_oldLineType),
+ m_newLineType(_newLineType)
+
+{
+}
+
+void KWChangeFootNoteLineSeparatorParametersCommand::execute()
+{
+ changeLineSeparatorParameter( m_newValuePos, m_newLength, m_newWidth,m_newLineType );
+}
+
+void KWChangeFootNoteLineSeparatorParametersCommand::unexecute()
+{
+ changeLineSeparatorParameter( m_oldValuePos, m_oldLength, m_oldWidth, m_oldLineType);
+}
+
+void KWChangeFootNoteLineSeparatorParametersCommand::changeLineSeparatorParameter( SeparatorLinePos _pos, int _length, double _width, SeparatorLineLineType _type)
+{
+ m_doc->setFootNoteSeparatorLinePosition( _pos );
+ m_doc->setFootNoteSeparatorLineLength( _length);
+ m_doc->setFootNoteSeparatorLineWidth(_width );
+ m_doc->setFootNoteSeparatorLineType( _type );
+ m_doc->repaintAllViews();
+}
+
+
+KWRenameBookmarkCommand::KWRenameBookmarkCommand( const QString &name, const QString & _oldname, const QString & _newName, KWDocument *_doc):
+ KNamedCommand(name),
+ m_doc( _doc ),
+ m_oldName( _oldname),
+ m_newName( _newName)
+{
+}
+
+void KWRenameBookmarkCommand::execute()
+{
+ m_doc->renameBookmark( m_oldName, m_newName);
+}
+
+void KWRenameBookmarkCommand::unexecute()
+{
+ m_doc->renameBookmark( m_newName, m_oldName);
+}
+
+KWResizeColumnCommand::KWResizeColumnCommand( KWTableFrameSet *table, int col, double oldSize, double newSize ):
+ KNamedCommand( i18n("Resize Column") ),
+ m_table( table ),
+ m_oldSize( oldSize ),
+ m_newSize( newSize ),
+ m_col( col )
+{
+}
+
+void KWResizeColumnCommand::execute()
+{
+ m_table->resizeColumn(m_col, m_newSize);
+ m_table->kWordDocument()->layout();
+ m_table->kWordDocument()->repaintAllViews();
+}
+
+void KWResizeColumnCommand::unexecute()
+{
+ m_table->resizeColumn(m_col, m_oldSize);
+ m_table->kWordDocument()->layout();
+ m_table->kWordDocument()->repaintAllViews();
+}
+
+KWResizeRowCommand::KWResizeRowCommand( KWTableFrameSet *table, int row, double oldSize, double newSize ):
+ KNamedCommand( i18n("Resize Row") ),
+ m_table( table ),
+ m_oldSize( oldSize ),
+ m_newSize( newSize ),
+ m_row( row )
+{
+}
+
+void KWResizeRowCommand::execute()
+{
+ m_table->resizeRow( m_row, m_newSize );
+ m_table->kWordDocument()->repaintAllViews();
+}
+
+void KWResizeRowCommand::unexecute()
+{
+ m_table->resizeRow( m_row, m_oldSize );
+ m_table->kWordDocument()->repaintAllViews();
+}
diff --git a/kword/KWCommand.h b/kword/KWCommand.h
new file mode 100644
index 00000000..02d58f9a
--- /dev/null
+++ b/kword/KWCommand.h
@@ -0,0 +1,901 @@
+/* This file is part of the KDE project
+ Copyright (C) 2001 David Faure <faure@kde.org>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+*/
+
+#ifndef KWORD_COMMAND_H
+#define KWORD_COMMAND_H
+#include <kcommand.h>
+#include <kurl.h>
+#include <KoCommandHistory.h>
+#include <KoPageLayout.h>
+#include <KoRect.h>
+#include <KoBorder.h>
+#include <KoParagLayout.h>
+#include <KoParagCounter.h>
+#include "KWFrameStyle.h"
+#include <KoTextCommand.h>
+#include "KWVariable.h"
+#include <KoPoint.h>
+#include <KoPictureKey.h>
+
+class KWFrameSet;
+class KWTableStyle;
+class KWTableTemplate;
+class KWTableFrameSet;
+class RemovedRow;
+class RemovedColumn;
+class KWPartFrameSet;
+class KWDocument;
+class KoCustomVariable;
+class KoLinkVariable;
+class KWFieldVariable;
+class KWTimeVariable;
+class KWDateVariable;
+class KWPgNumVariable;
+class KWFootNoteVariable;
+
+// TODO: change most KNamedCommands into KCommands, removing name arguments
+// and implementing name() instead (less memory used).
+
+/**
+ * Command created when pasting oasis-formatted text
+ */
+class KWOasisPasteCommand : public KoTextDocCommand
+{
+public:
+ KWOasisPasteCommand( KoTextDocument *d, int parag, int idx,
+ const QByteArray & data );
+ KoTextCursor *execute( KoTextCursor *c );
+ KoTextCursor *unexecute( KoTextCursor *c );
+protected:
+ int m_parag;
+ int m_idx;
+ QByteArray m_data;
+ // filled in by execute(), for unexecute()
+ int m_lastParag;
+ int m_lastIndex;
+ KoParagLayout* m_oldParagLayout;
+};
+
+struct ParagBookmark {
+ QString m_bookName;
+ int m_startParagIndex;
+ int m_endParagIndex;
+};
+
+class KWTextDeleteCommand : public KoTextDeleteCommand
+{
+public:
+ KWTextDeleteCommand( KoTextDocument *d, int i, int idx, const QMemArray<KoTextStringChar> &str,
+ const CustomItemsMap & customItemsMap,
+ const QValueList<KoParagLayout> & oldParagLayouts );
+ KoTextCursor *execute( KoTextCursor *c );
+ KoTextCursor *unexecute( KoTextCursor *c );
+ void createBookmarkList();
+private:
+ QValueList<ParagBookmark> m_listParagBookmark;
+};
+
+
+////////////////////////// Frame commands ////////////////////////////////
+
+/// Identifies a frame
+struct FrameIndex {
+ FrameIndex() {}
+ FrameIndex( KWFrame *frame );
+
+ KWFrameSet * m_pFrameSet;
+ unsigned int m_iFrameIndex;
+};
+
+
+/**
+ * Command created when changing frame border
+ */
+class KWFrameBorderCommand : public KNamedCommand
+{
+public:
+ //enum FrameBorderType { FBLeft=0, FBRight=1, FBTop=2, FBBottom=3};
+ struct FrameBorderTypeStruct {
+ KoBorder::BorderType m_EFrameType;
+ KoBorder m_OldBorder;
+ };
+
+ KWFrameBorderCommand( const QString &name, QPtrList<FrameIndex> &_listFrameIndex, QPtrList<FrameBorderTypeStruct> &_frameTypeBorder,const KoBorder & _newBorder ) ;
+ ~ KWFrameBorderCommand();
+
+ void execute();
+ void unexecute();
+
+protected:
+ QPtrList<FrameIndex> m_indexFrame;
+ QPtrList<FrameBorderTypeStruct> m_oldBorderFrameType;
+ KoBorder m_newBorder;
+};
+
+/**
+ * Command created when changing background color of one or more frames
+ */
+class KWFrameBackGroundColorCommand : public KNamedCommand
+{
+public:
+ KWFrameBackGroundColorCommand( const QString &name, QPtrList<FrameIndex> &_listFrameIndex, QPtrList<QBrush> &_oldBrush, const QBrush & _newColor ) ;
+ ~KWFrameBackGroundColorCommand();
+
+ void execute();
+ void unexecute();
+
+protected:
+ QPtrList<FrameIndex> m_indexFrame;
+ QPtrList<QBrush> m_oldBackGroundColor;
+ QBrush m_newColor;
+};
+
+/**
+ * Command created when applying a framestyle
+ */
+class KWFrameStyleCommand : public KNamedCommand
+{
+public:
+ KWFrameStyleCommand( const QString &name, KWFrame *_frame, KWFrameStyle *_fs, bool _repaintViews = true );
+ ~ KWFrameStyleCommand() { if (m_oldValues) delete m_oldValues; }
+
+ void execute();
+ void unexecute();
+
+protected:
+ void applyFrameStyle( KWFrameStyle * _sty );
+ KWFrame *m_frame ;
+ KWFrameStyle * m_fs;
+ KWFrameStyle * m_oldValues;
+ bool repaintViews;
+};
+
+
+/**
+ * Command created when applying a tablestyle
+ */
+class KWTableStyleCommand : public KNamedCommand
+{
+public:
+ KWTableStyleCommand( const QString &name, KWFrame *_frame, KWTableStyle *_ts, bool _repaintViews = true );
+ ~ KWTableStyleCommand();
+
+ void execute();
+ void unexecute();
+
+protected:
+ KWFrame *m_frame ;
+ KWTableStyle * m_ts;
+ KWFrameStyleCommand * m_fsc;
+ KCommand * m_sc;
+ bool repaintViews;
+};
+
+/**
+ * Command created when applying a tabletemplate
+ */
+class KWTableTemplateCommand : public KNamedCommand
+{
+public:
+ KWTableTemplateCommand( const QString &name, KWTableFrameSet *_table, KWTableTemplate *_tt );
+ ~ KWTableTemplateCommand();
+
+ void execute();
+ void unexecute();
+
+protected:
+ KWTableFrameSet *m_table;
+ KWTableTemplate * m_tt;
+ KMacroCommand * m_tableCommands;
+};
+
+struct FrameResizeStruct {
+ // Note that the new "minimum frame height" is always s2.height(),
+ // since this is called when the user manually resizes a frame (not when
+ // some text changes the size of a frame).
+ FrameResizeStruct() { } // default constructor;
+ FrameResizeStruct( const KoRect& s1, double min1, const KoRect& s2 )
+ : oldRect(s1), oldMinHeight(min1),
+ newRect( s2), newMinHeight(s2.height()) {
+ }
+ KoRect oldRect;
+ double oldMinHeight;
+ KoRect newRect;
+ double newMinHeight;
+};
+
+/**
+ * Command created when a frame is resized
+ * (or "moved and resized" as for KWPartFrameSet)
+ */
+class KWFrameResizeCommand : public KNamedCommand
+{
+public:
+ KWFrameResizeCommand(const QString &name, const QValueList<FrameIndex> &frameIndex, const QValueList<FrameResizeStruct> &frameResize );
+ KWFrameResizeCommand(const QString &name, FrameIndex frameIndex, const FrameResizeStruct &frameResize );
+ ~KWFrameResizeCommand() {}
+
+ void execute();
+ void unexecute();
+
+protected:
+ QValueList<FrameIndex> m_indexFrame;
+ QValueList<FrameResizeStruct> m_frameResize;
+};
+
+/**
+ * Command created when we changed a clipart or picture
+ */
+class KWFrameChangePictureCommand : public KNamedCommand
+{
+public:
+ KWFrameChangePictureCommand( const QString &name, FrameIndex _frameIndex, const KoPictureKey & _oldFile, const KoPictureKey & _newFile) ;
+ ~KWFrameChangePictureCommand() {}
+
+ void execute();
+ void unexecute();
+
+protected:
+ FrameIndex m_indexFrame;
+ KoPictureKey m_oldKey;
+ KoPictureKey m_newKey;
+};
+
+struct FrameMoveStruct {
+ FrameMoveStruct() {} // for QValueList
+ FrameMoveStruct( const KoPoint& p1, const KoPoint& p2 )
+ : oldPos(p1), newPos(p2) {
+ }
+ KoPoint oldPos;
+ KoPoint newPos;
+};
+
+/**
+ * Command created when one or more frames are moved
+ */
+class KWFrameMoveCommand : public KNamedCommand
+{
+public:
+ KWFrameMoveCommand( const QString &name,
+ const QValueList<FrameIndex> & _frameIndex,
+ const QValueList<FrameMoveStruct> & _frameMove );
+ ~KWFrameMoveCommand() {}
+
+ void execute();
+ void unexecute();
+ QValueList<FrameMoveStruct> & listFrameMoved() { return m_frameMove; }
+protected:
+ QValueList<FrameIndex> m_indexFrame;
+ QValueList<FrameMoveStruct> m_frameMove;
+};
+
+/**
+ * Command created when the properties of a frame are changed
+ * (e.g. using frame dialog).
+ * In the long run, KWFrameBackGroundColorCommand, KWFrameBorderCommand etc.
+ * could be removed and KWFramePropertiesCommand could be used instead.
+ * #### This solution is memory eating though, since all settings of the frame
+ * are copied. TODO: evaluate using graphite's GenericCommand instead.
+ */
+class KWFramePropertiesCommand : public KNamedCommand
+{
+public:
+ /** A copy of frameAfter is done internally.
+ * But make sure frameBefore is already a copy, its ownership is moved to the command.
+ */
+ KWFramePropertiesCommand( const QString &name, KWFrame *_frameBefore, KWFrame *_frameAfter );
+ ~KWFramePropertiesCommand();
+ void execute();
+ void unexecute();
+protected:
+ FrameIndex m_frameIndex;
+ KWFrame *m_frameBefore;
+ KWFrame *m_frameAfter;
+};
+
+
+/**
+ * Command created when one part is moved or resized
+ */
+class KWFramePartMoveCommand : public KNamedCommand
+{
+public:
+ KWFramePartMoveCommand( const QString &name,FrameIndex _frameIndex,FrameResizeStruct _frameMove ) ;
+ ~KWFramePartMoveCommand() {}
+
+ void execute();
+ void unexecute();
+ FrameResizeStruct & listFrameMoved() { return m_frameMove; }
+ bool frameMoved();
+protected:
+ FrameIndex m_indexFrame;
+ FrameResizeStruct m_frameMove;
+};
+
+/**
+ * Command created when a part with an external document is changed to be stored internal
+ */
+class KWFramePartInternalCommand : public KNamedCommand
+{
+public:
+ KWFramePartInternalCommand( const QString &name, KWPartFrameSet *part ) ;
+ ~KWFramePartInternalCommand() {}
+
+ void execute();
+ void unexecute();
+protected:
+ KWPartFrameSet *m_part;
+ KURL m_url;
+};
+
+/**
+ * Command created when a part with an external document is changed to be stored internal
+ */
+class KWFramePartExternalCommand : public KNamedCommand
+{
+public:
+ KWFramePartExternalCommand( const QString &name, KWPartFrameSet *part ) ;
+ ~KWFramePartExternalCommand() {}
+
+ void execute();
+ void unexecute();
+protected:
+ KWPartFrameSet *m_part;
+};
+
+/**
+ * This command makes a frameset floating and non-floating
+ */
+class KWFrameSetInlineCommand : public KNamedCommand
+{
+public:
+ KWFrameSetInlineCommand( const QString &name, KWFrameSet *frameset,
+ bool value );
+ ~KWFrameSetInlineCommand() {}
+
+ void execute();
+ void unexecute();
+
+protected:
+ void setValue( bool value );
+
+ KWFrameSet* m_pFrameSet;
+ bool m_value;
+ bool m_oldValue;
+};
+
+///////////////////////////////layout command///////////////////////////
+struct KWPageLayoutStruct {
+ KWPageLayoutStruct( const KoPageLayout& pgLayout, const KoColumns& cl, const KoKWHeaderFooter& hf )
+ : _pgLayout(pgLayout), _cl(cl), _hf(hf) {
+ }
+ KoPageLayout _pgLayout;
+ KoColumns _cl;
+ KoKWHeaderFooter _hf;
+};
+
+/**
+ * Command created when changing the page layout
+ */
+class KWPageLayoutCommand : public KNamedCommand
+{
+public:
+ KWPageLayoutCommand( const QString &name, KWDocument *_doc, KWPageLayoutStruct &_oldLayout, KWPageLayoutStruct &_newLayout);
+ ~KWPageLayoutCommand() {}
+
+ void execute();
+ void unexecute();
+protected:
+ KWDocument *m_pDoc;
+ KWPageLayoutStruct m_oldLayout;
+ KWPageLayoutStruct m_newLayout;
+};
+
+
+/**
+ * Command created when deleting a frame
+ */
+class KWDeleteFrameCommand : public KNamedCommand
+{
+public:
+ KWDeleteFrameCommand( const QString &name, KWFrame * frame) ;
+ /**
+ * Constructor to be used for chaining commands, i.e. inside another command.
+ * @param frameIndex a frameIndex object that specifies which frame to delete
+ */
+ KWDeleteFrameCommand( const FrameIndex &frameIndex) ;
+ ~KWDeleteFrameCommand();
+
+ void execute();
+ void unexecute();
+protected:
+ FrameIndex m_frameIndex;
+ KWFrame *m_copyFrame;
+};
+
+/**
+ * Command created when creating a frame
+ */
+class KWCreateFrameCommand : public KWDeleteFrameCommand
+{
+public:
+ KWCreateFrameCommand( const QString &name, KWFrame * frame);
+ ~KWCreateFrameCommand() {}
+
+ void execute() { KWDeleteFrameCommand::unexecute(); }
+ void unexecute() { KWDeleteFrameCommand::execute(); }
+};
+
+/**
+ * Command created when ungrouping a table
+ */
+class KWUngroupTableCommand : public KNamedCommand
+{
+public:
+ KWUngroupTableCommand( const QString &name, KWTableFrameSet * _table) ;
+ ~KWUngroupTableCommand() {}
+
+ void execute();
+ void unexecute();
+protected:
+ KWTableFrameSet *m_pTable;
+ QPtrList<KWFrameSet> m_ListFrame;
+};
+
+/**
+ * Command created when deleting a table
+ */
+class KWDeleteTableCommand : public KNamedCommand
+{
+public:
+ KWDeleteTableCommand( const QString &name, KWTableFrameSet * _table) ;
+ ~KWDeleteTableCommand() {}
+
+ void execute();
+ void unexecute();
+protected:
+ KWTableFrameSet *m_pTable;
+};
+
+
+/**
+ * Command created when creating a table
+ */
+class KWCreateTableCommand : public KWDeleteTableCommand
+{
+public:
+ KWCreateTableCommand( const QString &name, KWTableFrameSet * _table)
+ : KWDeleteTableCommand( name, _table ) {}
+ ~KWCreateTableCommand() {}
+
+ void execute() { KWDeleteTableCommand::unexecute(); }
+ void unexecute() { KWDeleteTableCommand::execute(); }
+};
+
+/**
+ * Command created when inserting a column
+ */
+class KWInsertColumnCommand : public KNamedCommand
+{
+public:
+ /* for the last parameter, _maxRight, you should pass the maximum offset that the table can use at its right (normally m_maxRight - m_pTable->boundingRect().left())*/
+ KWInsertColumnCommand( const QString &name, KWTableFrameSet * _table, int _pos, double _maxRight);
+ ~KWInsertColumnCommand();
+
+ void execute();
+ void unexecute();
+protected:
+ KWTableFrameSet *m_pTable;
+ RemovedColumn *m_rc;
+ unsigned int m_colPos;
+ double m_maxRight; // this is the maximum x of the right part of the table (used so that the table does no go off the page)
+ double m_oldWidth; // will be 0 after execute() if the width of the table was not changed by the operation
+ bool m_inserted;
+};
+
+
+/**
+ * Command created when inserting a row
+ */
+class KWInsertRowCommand : public KNamedCommand
+{
+public:
+ KWInsertRowCommand( const QString &name, KWTableFrameSet * _table, int _pos);
+ ~KWInsertRowCommand();
+
+ void execute();
+ void unexecute();
+protected:
+ KWTableFrameSet *m_pTable;
+ RemovedRow *m_rr;
+ unsigned int m_rowPos;
+ bool m_inserted;
+};
+
+/**
+ * Command created when removing a row
+ */
+class KWRemoveRowCommand : public KNamedCommand
+{
+public:
+ KWRemoveRowCommand( const QString &name, KWTableFrameSet * _table, int _pos);
+ ~KWRemoveRowCommand();
+
+ void execute();
+ void unexecute();
+protected:
+ KWTableFrameSet *m_pTable;
+ RemovedRow *m_rr;
+ uint m_rowPos;
+};
+
+/**
+ * Command created when removing a column
+ */
+class KWRemoveColumnCommand : public KNamedCommand
+{
+public:
+ KWRemoveColumnCommand( const QString &name, KWTableFrameSet * _table, int _pos);
+ ~KWRemoveColumnCommand();
+
+ void execute();
+ void unexecute();
+protected:
+ KWTableFrameSet *m_pTable;
+ RemovedColumn *m_rc;
+ uint m_colPos;
+};
+
+/**
+ * Command created when splitting a cell
+ */
+class KWSplitCellCommand : public KNamedCommand
+{
+public:
+ KWSplitCellCommand( const QString &name, KWTableFrameSet * _table,unsigned int colBegin,unsigned int rowBegin, unsigned int colEnd,unsigned int rowEnd );
+ ~KWSplitCellCommand() {}
+
+ void execute();
+ void unexecute();
+protected:
+ KWTableFrameSet *m_pTable;
+ unsigned int m_colBegin;
+ unsigned int m_rowBegin;
+ unsigned int m_colEnd;
+ unsigned int m_rowEnd;
+ QPtrList<KWFrameSet> m_ListFrameSet;
+};
+
+/**
+ * Command created when joining cells
+ */
+class KWJoinCellCommand : public KNamedCommand
+{
+public:
+ KWJoinCellCommand( const QString &name, KWTableFrameSet * _table,unsigned int colBegin,unsigned int rowBegin, unsigned int colEnd,unsigned int rowEnd, QPtrList<KWFrameSet> listFrameSet,QPtrList<KWFrame> listCopyFrame);
+ ~KWJoinCellCommand();
+
+ void execute();
+ void unexecute();
+protected:
+ KWTableFrameSet *m_pTable;
+ unsigned int m_colBegin;
+ unsigned int m_rowBegin;
+ unsigned int m_colEnd;
+ unsigned int m_rowEnd;
+ QPtrList<KWFrameSet> m_ListFrameSet;
+ QPtrList<KWFrame> m_copyFrame;
+};
+
+/**
+ * Command to starting page setting
+ */
+class KWChangeStartingPageCommand : public KNamedCommand
+{
+public:
+ KWChangeStartingPageCommand( const QString &name, KWDocument *_doc, int _oldStartingPage, int _newStartingPage);
+ ~KWChangeStartingPageCommand(){}
+
+ void execute();
+ void unexecute();
+protected:
+ KWDocument *m_doc;
+ int oldStartingPage;
+ int newStartingPage;
+};
+
+/**
+ * Command to display link setting
+ */
+class KWChangeVariableSettingsCommand : public KNamedCommand
+{
+public:
+ enum VariableProperties { VS_DISPLAYLINK, VS_UNDERLINELINK, VS_DISPLAYCOMMENT, VS_DISPLAYFIELDCODE};
+ KWChangeVariableSettingsCommand( const QString &name, KWDocument *_doc, bool _oldDisplay, bool _newDisplay, VariableProperties _type);
+ ~KWChangeVariableSettingsCommand(){}
+
+ void execute();
+ void unexecute();
+protected:
+ void changeValue( bool b );
+ KWDocument *m_doc;
+ VariableProperties type;
+ bool m_bOldValue;
+ bool m_bNewValue;
+};
+
+class KWChangeCustomVariableValue : public KNamedCommand
+{
+ public:
+ KWChangeCustomVariableValue( const QString &name, KWDocument *_doc,const QString & _oldValue, const QString & _newValue, KoCustomVariable *var);
+ ~KWChangeCustomVariableValue();
+ void execute();
+ void unexecute();
+ protected:
+ KWDocument *m_doc;
+ QString newValue;
+ QString oldValue;
+ KoCustomVariable *m_var;
+};
+
+class KWChangeVariableNoteText : public KNamedCommand
+{
+ public:
+ KWChangeVariableNoteText( const QString &name, KWDocument *_doc, const QString &_oldValue,const QString &_newValue, KoNoteVariable *var);
+ ~KWChangeVariableNoteText();
+ void execute();
+ void unexecute();
+ protected:
+ KWDocument *m_doc;
+ QString newValue;
+ QString oldValue;
+ KoNoteVariable *m_var;
+};
+
+class KWChangeLinkVariable : public KNamedCommand
+{
+ public:
+ KWChangeLinkVariable( const QString &name, KWDocument *_doc,const QString & _oldHref, const QString & _newHref, const QString & _oldLink,const QString &_newLink, KoLinkVariable *var);
+ ~KWChangeLinkVariable(){};
+ void execute();
+ void unexecute();
+ protected:
+ KWDocument *m_doc;
+ QString oldHref;
+ QString newHref;
+ QString oldLink;
+ QString newLink;
+ KoLinkVariable *m_var;
+};
+
+class KWHideShowHeader : public KNamedCommand
+{
+ public:
+ KWHideShowHeader( const QString &name, KWDocument *_doc, bool _newValue);
+ ~KWHideShowHeader(){};
+ void execute();
+ void unexecute();
+ protected:
+ KWDocument *m_doc;
+ bool newValue;
+};
+
+class KWHideShowFooter : public KNamedCommand
+{
+ public:
+ KWHideShowFooter( const QString &name, KWDocument *_doc, bool _newValue);
+ ~KWHideShowFooter(){};
+ void execute();
+ void unexecute();
+ protected:
+ KWDocument *m_doc;
+ bool newValue;
+};
+
+
+class KWProtectContentCommand : public KNamedCommand
+{
+public:
+ KWProtectContentCommand( const QString &name, KWTextFrameSet*frameset,bool protect );
+ ~KWProtectContentCommand() {}
+
+ void execute();
+ void unexecute();
+
+protected:
+ KWTextFrameSet* m_pFrameSet;
+ bool m_bProtect;
+};
+
+class KWInsertRemovePageCommand : public KCommand
+{
+ public:
+ enum Command { Insert, Remove };
+ KWInsertRemovePageCommand( KWDocument *_doc, Command cmd, int pgNum);
+ ~KWInsertRemovePageCommand();
+ virtual QString name() const;
+ void execute();
+ void unexecute();
+ protected:
+ KWDocument *m_doc;
+ Command m_cmd;
+ int m_pgNum;
+ QValueList<KCommand*> childCommands;
+
+ void doRemove(int pageNumber);
+ void doInsert(int pageNumber);
+
+ private:
+ static bool compareIndex(const FrameIndex &index1, const FrameIndex &index2);
+};
+
+struct FramePaddingStruct {
+ FramePaddingStruct() {}
+ FramePaddingStruct( KWFrame *frame );
+ FramePaddingStruct( double _left, double top, double right, double bottom );
+ double topPadding;
+ double bottomPadding;
+ double leftPadding;
+ double rightPadding;
+};
+
+class KWFrameChangeFramePaddingCommand :public KNamedCommand
+{
+public:
+ KWFrameChangeFramePaddingCommand( const QString &name, FrameIndex _frameIndex, FramePaddingStruct _framePaddingBegin, FramePaddingStruct _framePaddingEnd );
+ ~KWFrameChangeFramePaddingCommand() {}
+ void execute();
+ void unexecute();
+protected:
+ FrameIndex m_indexFrame;
+ FramePaddingStruct m_framePaddingBegin;
+ FramePaddingStruct m_framePaddingEnd;
+};
+
+
+class KWChangeFootEndNoteSettingsCommand : public KNamedCommand
+{
+public:
+ KWChangeFootEndNoteSettingsCommand( const QString &name, KoParagCounter _oldCounter, KoParagCounter _newCounter ,bool _footNote ,KWDocument *_doc );
+ ~KWChangeFootEndNoteSettingsCommand() {}
+
+ void execute();
+ void unexecute();
+
+protected:
+ void changeCounter( KoParagCounter counter);
+ KoParagCounter m_oldCounter;
+ KoParagCounter m_newCounter;
+ bool m_footNote;
+ KWDocument *m_doc;
+};
+
+class KWChangeTabStopValueCommand : public KNamedCommand
+{
+public:
+ KWChangeTabStopValueCommand( const QString &name, double _oldValue, double _newValue, KWDocument *_doc);
+
+ ~KWChangeTabStopValueCommand() {}
+
+ virtual void execute();
+ virtual void unexecute();
+protected:
+ KWDocument *m_doc;
+ double m_oldValue;
+ double m_newValue;
+};
+
+
+struct FootNoteParameter {
+ FootNoteParameter() {}
+ FootNoteParameter( KWFootNoteVariable *_var );
+ FootNoteParameter( NoteType _noteType, KWFootNoteVariable::Numbering _numberingType, const QString &_manualString);
+ NoteType noteType;
+ KWFootNoteVariable::Numbering numberingType;
+ QString manualString;
+};
+
+class KWChangeFootNoteParametersCommand : public KNamedCommand
+{
+public:
+ KWChangeFootNoteParametersCommand( const QString &name, KWFootNoteVariable * _var, FootNoteParameter _oldParameter, FootNoteParameter _newParameter, KWDocument *_doc);
+
+ ~KWChangeFootNoteParametersCommand() {}
+
+ virtual void execute();
+ virtual void unexecute();
+protected:
+ void changeVariableParameter( FootNoteParameter _param );
+ KWDocument *m_doc;
+ KWFootNoteVariable *m_var;
+ FootNoteParameter m_oldParameter;
+ FootNoteParameter m_newParameter;
+};
+
+
+class KWChangeFootNoteLineSeparatorParametersCommand : public KNamedCommand
+{
+public:
+ KWChangeFootNoteLineSeparatorParametersCommand( const QString &name, SeparatorLinePos _oldValuePos, SeparatorLinePos _newValuePos, int _oldLength, int _newLength, double _oldWidth, double _newWidth,SeparatorLineLineType _oldLineType, SeparatorLineLineType _newLineType, KWDocument *_doc);
+
+ ~KWChangeFootNoteLineSeparatorParametersCommand() {}
+
+ virtual void execute();
+ virtual void unexecute();
+protected:
+ void changeLineSeparatorParameter( SeparatorLinePos _pos, int length, double _width, SeparatorLineLineType _type);
+ KWDocument *m_doc;
+ SeparatorLinePos m_oldValuePos;
+ SeparatorLinePos m_newValuePos;
+ int m_oldLength;
+ int m_newLength;
+ double m_oldWidth;
+ double m_newWidth;
+ SeparatorLineLineType m_oldLineType;
+ SeparatorLineLineType m_newLineType;
+};
+
+class KWRenameBookmarkCommand : public KNamedCommand
+{
+public:
+ KWRenameBookmarkCommand( const QString &name, const QString & _oldname, const QString & _newName, KWDocument *_doc);
+
+ ~KWRenameBookmarkCommand() {}
+
+ virtual void execute();
+ virtual void unexecute();
+protected:
+ KWDocument *m_doc;
+ QString m_oldName;
+ QString m_newName;
+};
+
+class KWResizeColumnCommand : public KNamedCommand
+{
+public:
+ KWResizeColumnCommand( KWTableFrameSet *table, int col, double oldSize, double newSize );
+
+ ~KWResizeColumnCommand() {}
+
+ virtual void execute();
+ virtual void unexecute();
+protected:
+ KWTableFrameSet *m_table;
+ double m_oldSize;
+ double m_newSize;
+ int m_col;
+};
+
+class KWResizeRowCommand : public KNamedCommand
+{
+ public:
+ KWResizeRowCommand( KWTableFrameSet *table, int row, double oldSize, double newSize );
+
+ ~KWResizeRowCommand() {}
+
+ virtual void execute();
+ virtual void unexecute();
+ protected:
+ KWTableFrameSet *m_table;
+ double m_oldSize;
+ double m_newSize;
+ int m_row;
+};
+
+#endif
diff --git a/kword/KWConfig.cpp b/kword/KWConfig.cpp
new file mode 100644
index 00000000..3819bd61
--- /dev/null
+++ b/kword/KWConfig.cpp
@@ -0,0 +1,1118 @@
+/* This file is part of the KDE project
+ Copyright (C) 2001 Montel Laurent <lmontel@mandrakesoft.com>
+ Copyright (C) 2005 Thomas Zander <zander@kde.org>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+*/
+
+#include <kconfig.h>
+#include <kiconloader.h>
+#include <klocale.h>
+#include <KoUnitWidgets.h>
+#include <knuminput.h>
+#include <knumvalidator.h>
+#include <kfontdialog.h>
+#include <kdebug.h>
+
+#include <qcheckbox.h>
+#include <qlabel.h>
+#include <qvbox.h>
+#include <qcombobox.h>
+#include <qwhatsthis.h>
+#include <qvgroupbox.h>
+#include <qpushbutton.h>
+#include <qlistbox.h>
+#include <qlineedit.h>
+#include <qlayout.h>
+
+#include "KWConfig.h"
+#include "KWView.h"
+#include "KWFrameSet.h"
+#include "KWDocument.h"
+#include "KWCanvas.h"
+#include "KWViewMode.h"
+#include "KWCommand.h"
+#include "KWVariable.h"
+#include "KoEditPath.h"
+#include "KWPageManager.h"
+#include "KWPage.h"
+#include "KoSpeaker.h"
+
+#include <KoVariable.h>
+#include <kformulaconfigpage.h>
+
+#include <kspell2/configwidget.h>
+#include <kspell2/settings.h>
+#include <kspell2/broker.h>
+using namespace KSpell2;
+
+#include <float.h>
+#include <kmessagebox.h>
+#include <klistview.h>
+#include <kstandarddirs.h>
+#include <kglobalsettings.h>
+#include <kglobal.h>
+#include <kurlrequesterdlg.h>
+#include <kfiledialog.h>
+#include <qtabwidget.h>
+#include <keditlistbox.h>
+#include <KoGlobal.h>
+
+// little helper stolen from kmail
+// (Note: KDialogBase should have version of the methods that take a QString for the icon name)
+static inline QPixmap loadIcon( const char * name ) {
+ return KGlobal::instance()->iconLoader()
+ ->loadIcon( QString::fromLatin1(name), KIcon::NoGroup, KIcon::SizeMedium );
+}
+
+KWConfig::KWConfig( KWView* parent )
+ : KDialogBase(KDialogBase::IconList,i18n("Configure KWord") ,
+ KDialogBase::Ok | KDialogBase::Apply | KDialogBase::Cancel| KDialogBase::Default,
+ KDialogBase::Ok, parent)
+
+{
+ QVBox *page2 = addVBoxPage( i18n("Interface"), i18n("Interface Settings"),
+ loadIcon("configure") );
+ m_interfacePage=new ConfigureInterfacePage(parent, page2);
+
+ QVBox *page4 = addVBoxPage( i18n("Document"), i18n("Document Settings"),
+ loadIcon("kword_kwd") );
+
+ m_defaultDocPage=new ConfigureDefaultDocPage(parent, page4);
+
+ QVBox *page = addVBoxPage( i18n("Spelling"), i18n("Spell Checker Behavior"),
+ loadIcon("spellcheck") );
+ m_spellPage = new ConfigureSpellPage(parent, page);
+
+ QVBox *page5 = addVBoxPage( i18n("Formula"), i18n("Formula Defaults"),
+ loadIcon("kformula") );
+ m_formulaPage=new KFormula::ConfigurePage( parent->kWordDocument()->formulaDocument( false ),
+ this, KWFactory::instance()->config(), page5 );
+
+ QVBox *page3 = addVBoxPage( i18n("Misc"), i18n("Misc Settings"),
+ loadIcon("misc") );
+ m_miscPage=new ConfigureMiscPage(parent, page3);
+
+ QVBox *page6 = addVBoxPage( i18n("Path"), i18n("Path Settings"),
+ loadIcon("path") );
+ m_pathPage=new ConfigurePathPage(parent, page6);
+
+ if (KoSpeaker::isKttsdInstalled()) {
+ QVBox *page7 = addVBoxPage( i18n("Abbreviation for Text-to-Speech", "TTS"),
+ i18n("Text-to-Speech Settings"), loadIcon("access") );
+ m_ttsPage=new ConfigureTTSPage(parent, page7);
+ } else m_ttsPage = 0;
+
+ m_doc = parent->kWordDocument();
+ connect(this, SIGNAL(okClicked()),this,SLOT(slotApply()));
+
+ connect( m_interfacePage, SIGNAL( unitChanged( int ) ), SLOT( unitChanged( int ) ) );
+ unitChanged( parent->kWordDocument()->unit() );
+}
+
+void KWConfig::unitChanged( int u )
+{
+ KoUnit::Unit unit = static_cast<KoUnit::Unit>(u);
+ //m_spellPage->setUnit( unit );
+ m_interfacePage->setUnit( unit );
+ m_miscPage->setUnit( unit );
+ m_defaultDocPage->setUnit( unit );
+ //m_formulaPage->setUnit( unit );
+ //m_pathPage->setUnit( unit );
+}
+
+void KWConfig::openPage(int flags)
+{
+ if(flags & KW_KSPELL)
+ showPage( 2 );
+ else if(flags & KP_INTERFACE)
+ showPage(0 );
+ else if(flags & KP_MISC)
+ showPage(4);
+ else if(flags & KP_DOCUMENT)
+ showPage(2 );
+ else if(flags & KP_FORMULA)
+ showPage(3);
+ else if ( flags & KP_PATH )
+ showPage(4);
+}
+
+void KWConfig::slotApply()
+{
+ KMacroCommand *macro = 0L;
+ if (m_spellPage) m_spellPage->apply();
+ m_interfacePage->apply();
+ m_pathPage->apply();
+ KCommand * cmd = m_miscPage->apply();
+ if ( cmd )
+ {
+ if ( !macro )
+ macro = new KMacroCommand( i18n("Change Config"));
+ macro->addCommand(cmd);
+ }
+
+ cmd=m_defaultDocPage->apply();
+ if ( cmd )
+ {
+ if ( !macro )
+ macro = new KMacroCommand( i18n("Change Config"));
+
+ macro->addCommand( cmd );
+ }
+ m_formulaPage->apply();
+ if (m_ttsPage) m_ttsPage->apply();
+ if (macro)
+ m_doc->addCommand( macro );
+ KWFactory::instance()->config()->sync();
+}
+
+void KWConfig::slotDefault()
+{
+ switch(activePageIndex())
+ {
+ case 0:
+ m_interfacePage->slotDefault();
+ break;
+ case 1:
+ m_defaultDocPage->slotDefault();
+ break;
+ case 2:
+ if (m_spellPage) m_spellPage->slotDefault();
+ break;
+ case 3:
+ m_formulaPage->slotDefault();
+ break;
+ case 4:
+ m_miscPage->slotDefault();
+ break;
+ case 5:
+ m_pathPage->slotDefault();
+ break;
+ case 6:
+ m_ttsPage->slotDefault();
+ default:
+ break;
+ }
+}
+
+////
+
+ConfigureSpellPage::ConfigureSpellPage( KWView *view, QVBox *box, char *name )
+ : QObject( box->parent(), name )
+{
+ m_pView=view;
+ config = KWFactory::instance()->config();
+ m_spellConfigWidget = new ConfigWidget( view->broker(), box );
+ m_spellConfigWidget->setBackgroundCheckingButtonShown( true );
+ m_spellConfigWidget->layout()->setMargin( 0 );
+}
+
+void ConfigureSpellPage::apply()
+{
+ KWDocument* doc = m_pView->kWordDocument();
+
+ m_spellConfigWidget->save();
+
+ m_pView->kWordDocument()->setSpellCheckIgnoreList(
+ m_pView->broker()->settings()->currentIgnoreList() );
+ //FIXME reactivate just if there are changes.
+ doc->enableBackgroundSpellCheck( m_pView->broker()->settings()->backgroundCheckerEnabled() );
+ doc->reactivateBgSpellChecking();
+}
+
+void ConfigureSpellPage::slotDefault()
+{
+ m_spellConfigWidget->slotDefault();
+}
+
+ConfigureInterfacePage::ConfigureInterfacePage( KWView *view, QVBox *box, char *name )
+ : QObject( box->parent(), name )
+{
+ m_pView=view;
+ config = KWFactory::instance()->config();
+ QVGroupBox* gbInterfaceGroup = new QVGroupBox( i18n("Interface"), box, "GroupBox" );
+ gbInterfaceGroup->setMargin( KDialog::marginHint() );
+ gbInterfaceGroup->setInsideSpacing( KDialog::spacingHint() );
+
+ double ptGridX=MM_TO_POINT(5.0 );
+ double ptGridY=MM_TO_POINT(5.0 );
+ double ptIndent = MM_TO_POINT(10.0);
+ bool oldShowStatusBar = true;
+ bool oldPgUpDownMovesCaret = false;
+ bool oldShowScrollBar = true;
+ oldNbRecentFiles=10;
+ int nbPagePerRow=4;
+ KoUnit::Unit unit = m_pView->kWordDocument()->unit();
+ if( config->hasGroup("Interface") )
+ {
+ config->setGroup( "Interface" );
+ ptGridX=config->readDoubleNumEntry("GridX", ptGridX);
+ ptGridY=config->readDoubleNumEntry("GridY", ptGridY);
+ ptIndent = config->readDoubleNumEntry("Indent", ptIndent);
+ oldNbRecentFiles=config->readNumEntry("NbRecentFile", oldNbRecentFiles);
+ nbPagePerRow=config->readNumEntry("nbPagePerRow", nbPagePerRow);
+ oldShowStatusBar = config->readBoolEntry( "ShowStatusBar", true );
+ oldPgUpDownMovesCaret = config->readBoolEntry( "PgUpDownMovesCaret", false );
+ oldShowScrollBar = config->readBoolEntry("ShowScrollBar", true);
+ }
+
+ QHBox *hbUnit = new QHBox(gbInterfaceGroup);
+ hbUnit->setSpacing(KDialog::spacingHint());
+ QLabel *unitLabel= new QLabel(i18n("&Units:"),hbUnit);
+
+ m_unitCombo = new QComboBox( hbUnit );
+ m_unitCombo->insertStringList( KoUnit::listOfUnitName() );
+ connect(m_unitCombo, SIGNAL(activated(int)), this, SIGNAL(unitChanged(int)));
+ unitLabel->setBuddy( m_unitCombo );
+ QString unitHelp = i18n("Select the unit type used every time a distance or width/height "
+ "is displayed or entered. This one setting is for the whole of KWord: all dialogs, the rulers etc. "
+ "Note that KWord documents specify the unit which was used to create them, so this setting "
+ "only affects this document and all documents that will be created later.");
+ QWhatsThis::add( unitLabel, unitHelp );
+ QWhatsThis::add( m_unitCombo, unitHelp );
+
+ showStatusBar = new QCheckBox(i18n("Show &status bar"),gbInterfaceGroup);
+ showStatusBar->setChecked(oldShowStatusBar);
+ QWhatsThis::add( showStatusBar, i18n("Show or hide the status bar. If enabled, the status bar is shown at the bottom, which displays various information."));
+
+ showScrollBar = new QCheckBox( i18n("Show s&crollbar"), gbInterfaceGroup);
+ showScrollBar->setChecked(oldShowScrollBar);
+ QWhatsThis::add( showScrollBar, i18n("Show or hide the scroll bar. If enabled, the scroll bar is shown on the right and lets you scroll up and down, which is useful for navigating through the document."));
+
+ pgUpDownMovesCaret = new QCheckBox(i18n("PageUp/PageDown &moves the caret"),gbInterfaceGroup);
+ pgUpDownMovesCaret->setChecked(oldPgUpDownMovesCaret);
+ QWhatsThis::add( pgUpDownMovesCaret, i18n(
+ "If this option is enabled, the PageUp and PageDown keys "
+ "move the text caret, as in other KDE applications. "
+ "If it is disabled, they move the scrollbars, as in most other word processors." ) );
+
+ QHBox* hbRecent = new QHBox( gbInterfaceGroup );
+ QString recentHelp = i18n("The number of files remembered in the file open dialog and in the "
+ "recent files menu item.");
+ QLabel* labelRecent = new QLabel( i18n("Number of recent &files:"), hbRecent );
+ QWhatsThis::add( labelRecent, recentHelp );
+ recentFiles=new KIntNumInput( oldNbRecentFiles, hbRecent );
+ recentFiles->setRange(1, 20, 1);
+ labelRecent->setBuddy( recentFiles );
+ QWhatsThis::add( recentFiles, recentHelp );
+
+ QHBox* hbGridX = new QHBox( gbInterfaceGroup );
+ QString gridxHelp = i18n("The grid size on which frames, tabs and other content snaps while "
+ "moving and scaling.");
+ QLabel* labelGridX = new QLabel( i18n("&Horizontal grid size:"), hbGridX );
+ QWhatsThis::add( labelGridX, gridxHelp );
+ gridX=new KoUnitDoubleSpinBox( hbGridX,
+ 0.1,
+ 50,
+ 0.1,
+ ptGridX,
+ unit );
+ labelGridX->setBuddy( gridX );
+ QWhatsThis::add( gridX, gridxHelp );
+
+ QHBox* hbGridY = new QHBox( gbInterfaceGroup );
+ QString gridyHelp = i18n("The grid size on which frames and other content snaps while "
+ "moving and scaling.");
+ QLabel* labelGridY = new QLabel( i18n("&Vertical grid size:"), hbGridY );
+ QWhatsThis::add( labelGridY, gridyHelp );
+ gridY=new KoUnitDoubleSpinBox( hbGridY,
+ 0.1,
+ 50,
+ 0.1,
+ ptGridY,
+ unit );
+ labelGridY->setBuddy( gridY );
+
+ QWhatsThis::add( gridY, gridyHelp );
+
+ QHBox* hbIndent = new QHBox( gbInterfaceGroup );
+ QString indentHelp = i18n("Configure the indent width used when using the 'Increase' "
+ "or 'Decrease' indentation buttons on a paragraph.<p>The lower the value, "
+ "the more often the buttons will have to be pressed to gain the same "
+ "indentation.");
+ QLabel* labelIndent = new QLabel( i18n("&Paragraph indent by toolbar buttons:"), hbIndent );
+ QWhatsThis::add( labelIndent, indentHelp );
+ indent = new KoUnitDoubleSpinBox( hbIndent,
+ 0.1,
+ 5000,
+ 0.1,
+ ptIndent,
+ unit );
+ labelIndent->setBuddy( indent );
+ QWhatsThis::add( indent, indentHelp );
+
+ QHBox* hbPagePerRow = new QHBox( gbInterfaceGroup );
+ QString pagePerRowHelp = i18n("After selecting Preview Mode (from the \"View\" menu,) "
+ "this is the number of pages KWord will "
+ "position on one horizontal row.");
+ QLabel* labelPagePerRow = new QLabel( i18n("Number of pa&ges per row in preview mode:" ), hbPagePerRow );
+ QWhatsThis::add( labelPagePerRow, pagePerRowHelp );
+ m_nbPagePerRow=new KIntNumInput( 0, nbPagePerRow, hbPagePerRow );
+ m_nbPagePerRow->setRange(1, 10, 1);
+ labelPagePerRow->setBuddy( m_nbPagePerRow );
+ hbPagePerRow->setStretchFactor( m_nbPagePerRow, 1 );
+ QWhatsThis::add(m_nbPagePerRow , pagePerRowHelp );
+}
+
+void ConfigureInterfacePage::apply()
+{
+ KWDocument * doc = m_pView->kWordDocument();
+ double valX = QMAX( 0.1, gridX->value() );
+ double valY = QMAX( 0.1, gridY->value() );
+ int nbRecent=recentFiles->value();
+
+ bool statusBar=showStatusBar->isChecked();
+ bool scrollBar = showScrollBar->isChecked();
+ config->setGroup( "Interface" );
+ bool updateView = false;
+ if(valX!=doc->gridX())
+ {
+ config->writeEntry( "GridX", valX, true, false, 'g', DBL_DIG /* 6 is not enough */ );
+ doc->setGridX(valX);
+ updateView= true;
+ }
+ if(valY!=doc->gridY())
+ {
+ config->writeEntry( "GridY", valY, true, false, 'g', DBL_DIG /* 6 is not enough */ );
+ doc->setGridY(valY);
+ updateView= true;
+ }
+ double newIndent = indent->value();
+ if( newIndent != doc->indentValue() )
+ {
+ config->writeEntry( "Indent", newIndent, true, false, 'g', DBL_DIG /* 6 is not enough */ );
+ doc->setIndentValue( newIndent );
+ }
+ if(nbRecent!=oldNbRecentFiles)
+ {
+ config->writeEntry( "NbRecentFile", nbRecent);
+ m_pView->changeNbOfRecentFiles(nbRecent);
+ }
+ bool refreshGUI= false;
+
+ if( statusBar != doc->showStatusBar() )
+ {
+ config->writeEntry( "ShowStatusBar", statusBar );
+ doc->setShowStatusBar( statusBar );
+ refreshGUI=true;
+ }
+
+ if( scrollBar != doc->showScrollBar() )
+ {
+ config->writeEntry( "ShowScrollBar", scrollBar );
+ doc->setShowScrollBar( scrollBar );
+ refreshGUI=true;
+ }
+
+ bool b = pgUpDownMovesCaret->isChecked();
+ if ( b != doc->pgUpDownMovesCaret() )
+ {
+ config->writeEntry( "PgUpDownMovesCaret", b );
+ doc->setPgUpDownMovesCaret( b );
+ }
+
+ if( refreshGUI )
+ doc->reorganizeGUI();
+
+
+ int nbPageByRow=m_nbPagePerRow->value();
+ if(nbPageByRow!=doc->nbPagePerRow())
+ {
+ config->writeEntry("nbPagePerRow",nbPageByRow);
+ m_pView->getGUI()->canvasWidget()->viewMode()->setPagesPerRow(nbPageByRow);
+ doc->setNbPagePerRow(nbPageByRow);
+ //m_pView->getGUI()->canvasWidget()->refreshViewMode();
+ //necessary to recreate new view because in switchViewMode
+ //we delete viewmode that we want to apply (LM)
+ // This needs to be cleaned up .... (DF)
+ doc->switchViewMode( doc->viewModeType() ); // force a refresh
+ }
+
+ config->setGroup( "Misc" );
+ KoUnit::Unit unit = static_cast<KoUnit::Unit>( m_unitCombo->currentItem() );
+ // It's already been set in the document, see unitChanged
+ config->writeEntry( "Units", KoUnit::unitName( unit ) );
+ if ( updateView )
+ doc->repaintAllViews(false);
+}
+
+void ConfigureInterfacePage::setUnit( KoUnit::Unit unit )
+{
+ m_unitCombo->blockSignals( true );
+ m_unitCombo->setCurrentItem( unit );
+ m_unitCombo->blockSignals( false );
+ // We need to set it in the doc immediately, because much code here uses doc->unit()
+ m_pView->kWordDocument()->setUnit( unit );
+
+ gridX->setUnit( unit );
+ gridY->setUnit( unit );
+ indent->setUnit( unit );
+}
+
+void ConfigureInterfacePage::slotDefault()
+{
+ KWDocument * doc = m_pView->kWordDocument();
+ m_unitCombo->setCurrentItem( KoUnit::U_CM );
+ emit unitChanged( m_unitCombo->currentItem() );
+ gridX->setValue( KoUnit::toUserValue( MM_TO_POINT( 5.0 ),doc->unit() ) );
+ gridY->setValue( KoUnit::toUserValue( MM_TO_POINT( 5.0 ),doc->unit() ) );
+ m_nbPagePerRow->setValue(4);
+ double newIndent = KoUnit::toUserValue( MM_TO_POINT( 10 ), doc->unit() );
+ indent->setValue( newIndent );
+ recentFiles->setValue(10);
+ showStatusBar->setChecked(true);
+ pgUpDownMovesCaret->setChecked(false);
+ showScrollBar->setChecked( true);
+}
+
+////
+
+ConfigureMiscPage::ConfigureMiscPage( KWView *view, QVBox *box, char *name )
+ : QObject( box->parent(), name )
+{
+ m_pView=view;
+ config = KWFactory::instance()->config();
+ QVGroupBox* gbMiscGroup = new QVGroupBox( i18n("Misc"), box, "GroupBox" );
+ gbMiscGroup->setMargin( KDialog::marginHint() );
+ gbMiscGroup->setInsideSpacing( KDialog::spacingHint() );
+
+ m_oldNbRedo=30;
+
+ // Don't load the unit from config file because the unit can come from the kword file
+ // => unit can be different from config file
+
+ if( config->hasGroup("Misc") )
+ {
+ config->setGroup( "Misc" );
+ m_oldNbRedo=config->readNumEntry("UndoRedo",m_oldNbRedo);
+ }
+
+ QHBox* hbUndoRedo = new QHBox( gbMiscGroup );
+ QLabel* labelUndoRedo = new QLabel( i18n("Undo/&redo limit:"), hbUndoRedo );
+ QString undoHelp = i18n("Limit the number of undo/redo actions remembered. "
+ "A lower value helps to save memory, a higher value allows "
+ "you to undo and redo more editing steps.");
+ m_undoRedoLimit=new KIntNumInput( m_oldNbRedo, hbUndoRedo );
+ m_undoRedoLimit->setRange(1, 100, 1);
+ labelUndoRedo->setBuddy( m_undoRedoLimit );
+ QWhatsThis::add( m_undoRedoLimit, undoHelp );
+ QWhatsThis::add( labelUndoRedo, undoHelp );
+
+ KWDocument* doc = m_pView->kWordDocument();
+ m_displayLink=new QCheckBox(i18n("Display &links"),gbMiscGroup);
+ m_displayLink->setChecked(doc->variableCollection()->variableSetting()->displayLink());
+ QWhatsThis::add( m_displayLink, i18n("If enabled, a link is highlighted as such and is clickable.\n\n"
+ "You can insert a link from the Insert menu."));
+ m_underlineLink=new QCheckBox(i18n("&Underline all links"),gbMiscGroup);
+ m_underlineLink->setChecked(doc->variableCollection()->variableSetting()->underlineLink());
+ QWhatsThis::add( m_underlineLink, i18n("If enabled, a link is underlined."));
+
+ m_displayComment=new QCheckBox(i18n("Display c&omments"),gbMiscGroup);
+ m_displayComment->setChecked(doc->variableCollection()->variableSetting()->displayComment());
+ QWhatsThis::add( m_displayComment, i18n("If enabled, comments are indicated by a small yellow box.\n\n"
+ "You can show and edit a comment from the context menu."));
+
+ m_displayFieldCode=new QCheckBox(i18n("Display field code"),gbMiscGroup);
+ m_displayFieldCode->setChecked(doc->variableCollection()->variableSetting()->displayFieldCode());
+ QWhatsThis::add( m_displayFieldCode, i18n("If enabled, the type of link is displayed instead "
+ "of displaying the link text.\n\n"
+ "There are various types of link that can be inserted, "
+ "such as hyperlinks, files, mail, news and bookmarks."));
+
+
+ QVGroupBox* gbViewFormatting = new QVGroupBox( i18n("View Formatting"), box, "view_formatting" );
+ QWhatsThis::add( gbViewFormatting, i18n("These settings can be used to select the formatting "
+ "characters that should be shown.\n\n"
+ "Note that the selected formatting characters are only "
+ "shown if formatting characters are enabled in general, "
+ "which can be done from the View menu."));
+ gbViewFormatting->setMargin( KDialog::marginHint() );
+ gbViewFormatting->setInsideSpacing( KDialog::spacingHint() );
+
+ m_oldFormattingEndParag = doc->viewFormattingEndParag();
+ m_oldFormattingSpace = doc->viewFormattingSpace();
+ m_oldFormattingTabs = doc->viewFormattingTabs();
+ m_oldFormattingBreak = doc->viewFormattingBreak();
+
+ m_cbViewFormattingEndParag = new QCheckBox( i18n("View formatting end paragraph"), gbViewFormatting);
+ m_cbViewFormattingEndParag->setChecked(m_oldFormattingEndParag);
+
+ m_cbViewFormattingSpace = new QCheckBox( i18n("View formatting space"), gbViewFormatting);
+ m_cbViewFormattingSpace->setChecked(m_oldFormattingSpace);
+
+ m_cbViewFormattingTabs = new QCheckBox( i18n("View formatting tabs"), gbViewFormatting);
+ m_cbViewFormattingTabs->setChecked(m_oldFormattingTabs);
+
+ m_cbViewFormattingBreak = new QCheckBox( i18n("View formatting break"), gbViewFormatting);
+ m_cbViewFormattingBreak->setChecked(m_oldFormattingBreak);
+}
+
+ConfigureDefaultDocPage::~ConfigureDefaultDocPage()
+{
+ delete font;
+}
+
+KCommand *ConfigureMiscPage::apply()
+{
+ KWDocument * doc = m_pView->kWordDocument();
+ config->setGroup( "Misc" );
+ int newUndo=m_undoRedoLimit->value();
+ if(newUndo!=m_oldNbRedo)
+ {
+ config->writeEntry("UndoRedo",newUndo);
+ doc->setUndoRedoLimit(newUndo);
+ m_oldNbRedo=newUndo;
+ }
+ KMacroCommand * macroCmd=0L;
+ bool b=m_displayLink->isChecked();
+ if(doc->variableCollection()->variableSetting()->displayLink()!=b)
+ {
+ if(!macroCmd)
+ {
+ macroCmd=new KMacroCommand(i18n("Change Display Link Command"));
+ }
+ KWChangeVariableSettingsCommand *cmd=new KWChangeVariableSettingsCommand( i18n("Change Display Link Command"), doc, doc->variableCollection()->variableSetting()->displayLink() ,b, KWChangeVariableSettingsCommand::VS_DISPLAYLINK);
+
+ cmd->execute();
+ macroCmd->addCommand(cmd);
+ }
+ b=m_underlineLink->isChecked();
+ if(doc->variableCollection()->variableSetting()->underlineLink()!=b)
+ {
+ if(!macroCmd)
+ {
+ macroCmd=new KMacroCommand(i18n("Change Display Link Command"));
+ }
+ KWChangeVariableSettingsCommand *cmd=new KWChangeVariableSettingsCommand( i18n("Change Display Link Command"), doc, doc->variableCollection()->variableSetting()->underlineLink() ,b, KWChangeVariableSettingsCommand::VS_UNDERLINELINK);
+ cmd->execute();
+ macroCmd->addCommand(cmd);
+ }
+
+ b=m_displayComment->isChecked();
+ if(doc->variableCollection()->variableSetting()->displayComment()!=b)
+ {
+ if(!macroCmd)
+ {
+ macroCmd=new KMacroCommand(i18n("Change Display Link Command"));
+ }
+ KWChangeVariableSettingsCommand *cmd=new KWChangeVariableSettingsCommand( i18n("Change Display Link Command"), doc, doc->variableCollection()->variableSetting()->displayComment() ,b, KWChangeVariableSettingsCommand::VS_DISPLAYCOMMENT);
+ cmd->execute();
+ macroCmd->addCommand(cmd);
+ }
+ b=m_displayFieldCode->isChecked();
+ if(doc->variableCollection()->variableSetting()->displayFieldCode()!=b)
+ {
+ if(!macroCmd)
+ {
+ macroCmd=new KMacroCommand(i18n("Change Display Field Code Command"));
+ }
+ KWChangeVariableSettingsCommand *cmd=new KWChangeVariableSettingsCommand( i18n("Change Display Field Code Command"), doc, doc->variableCollection()->variableSetting()->displayFieldCode() ,b, KWChangeVariableSettingsCommand::VS_DISPLAYFIELDCODE);
+ cmd->execute();
+ macroCmd->addCommand(cmd);
+ }
+
+ bool state =m_cbViewFormattingEndParag->isChecked();
+ bool needRepaint = false;
+ if ( state != m_oldFormattingEndParag )
+ {
+ doc->setViewFormattingEndParag(state);
+ needRepaint = true;
+ m_oldFormattingEndParag = state;
+ }
+ state = m_cbViewFormattingSpace->isChecked();
+ if ( state != m_oldFormattingSpace)
+ {
+ doc->setViewFormattingSpace(state);
+ needRepaint = true;
+ m_oldFormattingSpace = state;
+ }
+ state = m_cbViewFormattingBreak->isChecked();
+ if ( state != m_oldFormattingBreak)
+ {
+ doc->setViewFormattingBreak(state);
+ needRepaint = true;
+ m_oldFormattingBreak = state;
+ }
+ state = m_cbViewFormattingTabs->isChecked();
+ if ( state != m_oldFormattingTabs )
+ {
+ doc->setViewFormattingTabs(state);
+ needRepaint = true;
+ m_oldFormattingTabs= state;
+ }
+ if ( needRepaint )
+ {
+ doc->layout();
+ doc->repaintAllViews();
+ }
+ return macroCmd;
+}
+
+void ConfigureMiscPage::slotDefault()
+{
+ m_undoRedoLimit->setValue(30);
+ m_displayLink->setChecked(true);
+ m_displayComment->setChecked(true);
+ m_underlineLink->setChecked(true);
+ m_cbViewFormattingEndParag->setChecked(true);
+ m_cbViewFormattingSpace->setChecked(true);
+ m_cbViewFormattingTabs->setChecked(true);
+ m_cbViewFormattingBreak->setChecked(true);
+ m_displayFieldCode->setChecked( false );
+}
+
+void ConfigureMiscPage::setUnit( KoUnit::Unit )
+{
+}
+
+////
+
+ConfigureDefaultDocPage::ConfigureDefaultDocPage( KWView *view, QVBox *box, char *name )
+ : QObject( box->parent(), name )
+{
+ m_pView=view;
+ KWDocument * doc = m_pView->kWordDocument();
+ config = KWFactory::instance()->config();
+ QVGroupBox* gbDocumentDefaults = new QVGroupBox( i18n("Document Defaults"), box, "GroupBox" );
+ gbDocumentDefaults->setMargin( KDialog::marginHint() );
+ gbDocumentDefaults->setInsideSpacing( KDialog::spacingHint() );
+
+ double ptColumnSpacing=3;
+ KoUnit::Unit unit = doc->unit();
+ if( config->hasGroup("Document defaults") )
+ {
+ config->setGroup( "Document defaults" );
+ ptColumnSpacing=config->readDoubleNumEntry("ColumnSpacing",ptColumnSpacing);
+ // loaded by kwdoc already defaultFont=config->readEntry("DefaultFont",defaultFont);
+ }
+
+
+ QHBox* hbColumnSpacing = new QHBox( gbDocumentDefaults );
+ QLabel* columnSpacingLabel = new QLabel( i18n("Default column spacing:"), hbColumnSpacing );
+ m_columnSpacing = new KoUnitDoubleSpinBox( hbColumnSpacing,
+ 0.1,
+ 50,
+ 0.1,
+ ptColumnSpacing,
+ unit );
+ columnSpacingLabel->setBuddy( m_columnSpacing );
+ QWhatsThis::add( m_columnSpacing, i18n("When setting a document to use more than one column "
+ "this distance will be used to separate the columns. This value is merely a default "
+ "setting as the column spacing can be changed per document") );
+
+ QWidget *fontContainer = new QWidget(gbDocumentDefaults);
+ QGridLayout * fontLayout = new QGridLayout(fontContainer, 1, 3);
+
+ fontLayout->setSpacing(KDialog::spacingHint());
+ fontLayout->setColStretch(0, 0);
+ fontLayout->setColStretch(1, 1);
+ fontLayout->setColStretch(2, 0);
+
+ QLabel *fontTitle = new QLabel(i18n("Default font:"), fontContainer);
+
+ font= new QFont( doc->defaultFont() );
+
+ QString labelName = font->family() + ' ' + QString::number(font->pointSize());
+ fontName = new QLabel(labelName, fontContainer);
+ fontName->setFont(*font);
+ fontName->setFrameStyle(QFrame::StyledPanel | QFrame::Sunken);
+
+ QPushButton *chooseButton = new QPushButton(i18n("Choose..."), fontContainer);
+ connect(chooseButton, SIGNAL(clicked()), this, SLOT(selectNewDefaultFont()));
+
+ fontLayout->addWidget(fontTitle, 0, 0);
+ fontLayout->addWidget(fontName, 0, 1);
+ fontLayout->addWidget(chooseButton, 0, 2);
+
+
+ oldAutoSaveValue=KoDocument::defaultAutoSave() / 60;
+ m_oldLanguage = doc->globalLanguage();
+ m_oldHyphenation = doc->globalHyphenation();
+ if( config->hasGroup("Interface") )
+ {
+ config->setGroup( "Interface" );
+ oldAutoSaveValue=config->readNumEntry("AutoSave",oldAutoSaveValue);
+ m_oldLanguage = config->readEntry( "language", m_oldLanguage);
+ m_oldHyphenation = config->readBoolEntry( "hyphenation", m_oldHyphenation);
+ }
+
+
+ QWidget *languageContainer = new QWidget(gbDocumentDefaults);
+ QGridLayout * languageLayout = new QGridLayout(languageContainer, 1, 3);
+
+ languageLayout->setSpacing(KDialog::spacingHint());
+ languageLayout->setColStretch(0, 0);
+ languageLayout->setColStretch(1, 1);
+
+ QLabel *languageTitle = new QLabel(i18n("Global language:"), languageContainer);
+
+ m_globalLanguage = new QComboBox( languageContainer );
+ m_globalLanguage->insertStringList( KoGlobal::listOfLanguages() );
+ m_globalLanguage->setCurrentText( KoGlobal::languageFromTag( m_oldLanguage ) );
+
+ languageLayout->addWidget(languageTitle, 0, 0);
+ languageLayout->addWidget(m_globalLanguage, 0, 1);
+
+ m_autoHyphenation = new QCheckBox( i18n("Automatic hyphenation"), gbDocumentDefaults);
+ m_autoHyphenation->setChecked( m_oldHyphenation );
+
+ QVGroupBox* gbDocumentSettings = new QVGroupBox( i18n("Document Settings"), box );
+ gbDocumentSettings->setMargin( KDialog::marginHint() );
+ gbDocumentSettings->setInsideSpacing( KDialog::spacingHint() );
+
+ QHBox* hbAutoSave = new QHBox( gbDocumentSettings );
+ QLabel* labelAutoSave = new QLabel( i18n("Autosave every (min):"), hbAutoSave );
+ autoSave = new KIntNumInput( oldAutoSaveValue, hbAutoSave );
+ autoSave->setRange(0, 60, 1);
+ labelAutoSave->setBuddy(autoSave);
+ QWhatsThis::add( autoSave, i18n("A backup copy of the current document is created when a change "
+ "has been made. The interval used to create backup documents is set here.") );
+ autoSave->setSpecialValueText(i18n("No autosave"));
+ autoSave->setSuffix(i18n(" min"));
+
+ m_oldBackupFile = true;
+ if( config->hasGroup("Interface") )
+ {
+ config->setGroup( "Interface" );
+ m_oldBackupFile=config->readBoolEntry("BackupFile",m_oldBackupFile);
+ }
+
+ m_createBackupFile = new QCheckBox( i18n("Create backup file"), gbDocumentSettings);
+ m_createBackupFile->setChecked( m_oldBackupFile );
+
+ QHBox* hbStartingPage = new QHBox( gbDocumentSettings );
+ QLabel* labelStartingPage = new QLabel(i18n("Starting page number:"), hbStartingPage);
+
+ m_oldStartingPage=doc->variableCollection()->variableSetting()->startingPageNumber();
+ m_variableNumberOffset=new KIntNumInput(hbStartingPage);
+ m_variableNumberOffset->setRange(-1000, 9999, 1, false);
+ m_variableNumberOffset->setValue(m_oldStartingPage);
+ labelStartingPage->setBuddy( m_variableNumberOffset );
+
+ QHBox* hbTabStop = new QHBox( gbDocumentSettings );
+ tabStop = new QLabel(i18n("Tab stop (%1):").arg(doc->unitName()), hbTabStop);
+ m_tabStopWidth = new KoUnitDoubleSpinBox( hbTabStop,
+ MM_TO_POINT(2),
+ doc->pageManager()->page(doc->startPage())->width(),
+ 0.1,
+ doc->tabStopValue(),
+ unit );
+ m_oldTabStopWidth = doc->tabStopValue();
+
+ QVGroupBox* gbDocumentCursor = new QVGroupBox( i18n("Cursor"), box );
+ gbDocumentCursor->setMargin( KDialog::marginHint() );
+ gbDocumentCursor->setInsideSpacing( KDialog::spacingHint() );
+
+ m_cursorInProtectedArea= new QCheckBox(i18n("Cursor in protected area"),gbDocumentCursor);
+ m_cursorInProtectedArea->setChecked(doc->cursorInProtectedArea());
+
+// m_directInsertCursor= new QCheckBox(i18n("Direct insert cursor"),gbDocumentCursor);
+// m_directInsertCursor->setChecked(doc->insertDirectCursor());
+}
+
+KCommand *ConfigureDefaultDocPage::apply()
+{
+ config->setGroup( "Document defaults" );
+ KWDocument * doc = m_pView->kWordDocument();
+ double colSpacing = m_columnSpacing->value();
+ if ( colSpacing != doc->defaultColumnSpacing() )
+ {
+ config->writeEntry( "ColumnSpacing", colSpacing , true, false, 'g', DBL_DIG );
+ doc->setDefaultColumnSpacing(colSpacing);
+ }
+ config->writeEntry("DefaultFont",font->toString());
+
+ config->setGroup( "Interface" );
+ int autoSaveVal=autoSave->value();
+ if(autoSaveVal!=oldAutoSaveValue)
+ {
+ config->writeEntry( "AutoSave", autoSaveVal );
+ doc->setAutoSave(autoSaveVal*60);
+ oldAutoSaveValue=autoSaveVal;
+ }
+
+ bool state =m_createBackupFile->isChecked();
+ if(state!=m_oldBackupFile)
+ {
+ config->writeEntry( "BackupFile", state );
+ doc->setBackupFile( state);
+ m_oldBackupFile=state;
+ }
+
+ state = m_cursorInProtectedArea->isChecked();
+ if ( state != doc->cursorInProtectedArea() )
+ {
+ config->writeEntry( "cursorInProtectArea", state );
+ doc->setCursorInProtectedArea( state );
+ }
+
+// state = m_directInsertCursor->isChecked();
+// if ( state != doc->insertDirectCursor() )
+// doc->setInsertDirectCursor( state );
+
+ //Laurent Todo add a message box to inform user that
+ //global language will change after re-launch kword
+ QString lang = KoGlobal::tagOfLanguage( m_globalLanguage->currentText() );
+ config->writeEntry( "language" , lang);
+ m_oldLanguage = lang;
+ //don't call this fiunction otherwise we can have a textobject with
+ // a default language and other textobject with other default language.
+ //doc->setGlobalLanguage( lang );
+
+ state = m_autoHyphenation->isChecked();
+ config->writeEntry( "hyphenation", state );
+ m_oldHyphenation = state;
+
+ KMacroCommand * macroCmd=0L;
+ int newStartingPage=m_variableNumberOffset->value();
+ if(newStartingPage!=m_oldStartingPage)
+ {
+ macroCmd=new KMacroCommand(i18n("Change Starting Page Number"));
+ KWChangeStartingPageCommand *cmd = new KWChangeStartingPageCommand( i18n("Change Starting Page Number"), doc, m_oldStartingPage,newStartingPage );
+ cmd->execute();
+ macroCmd->addCommand(cmd);
+ m_oldStartingPage=newStartingPage;
+ }
+ double newTabStop = m_tabStopWidth->value();
+ if ( newTabStop != m_oldTabStopWidth)
+ {
+ if ( !macroCmd )
+ macroCmd=new KMacroCommand(i18n("Change Tab Stop Value"));
+
+
+ KWChangeTabStopValueCommand *cmd = new KWChangeTabStopValueCommand( i18n("Change Tab Stop Value"), m_oldTabStopWidth, newTabStop, doc);
+ cmd->execute();
+ macroCmd->addCommand(cmd);
+ m_oldTabStopWidth = newTabStop;
+ }
+
+ return macroCmd;
+}
+
+void ConfigureDefaultDocPage::slotDefault()
+{
+ m_columnSpacing->setValue( 3 );
+ autoSave->setValue( KoDocument::defaultAutoSave() / 60 );
+ m_variableNumberOffset->setValue(1);
+ m_cursorInProtectedArea->setChecked(true);
+ m_tabStopWidth->setValue( MM_TO_POINT(15) );
+ m_createBackupFile->setChecked( true );
+// m_directInsertCursor->setChecked( false );
+ m_globalLanguage->setCurrentText( KoGlobal::languageFromTag( KGlobal::locale()->language() ) );
+ m_autoHyphenation->setChecked( false );
+}
+
+void ConfigureDefaultDocPage::selectNewDefaultFont() {
+ QStringList list;
+ KFontChooser::getFontList(list, KFontChooser::SmoothScalableFonts);
+ KFontDialog dlg( (QWidget *)this->parent(), "Font Selector", false, true, list, true );
+ dlg.setFont(*font);
+ int result = dlg.exec();
+ if (KDialog::Accepted == result) {
+ delete font;
+ font = new QFont(dlg.font());
+ fontName->setText(font->family() + ' ' + QString::number(font->pointSize()));
+ fontName->setFont(*font);
+ m_pView->kWordDocument()->setDefaultFont( *font );
+ }
+}
+
+void ConfigureDefaultDocPage::setUnit( KoUnit::Unit unit )
+{
+ m_columnSpacing->setUnit( unit );
+ m_tabStopWidth->setUnit( unit );
+ tabStop->setText( i18n( "Tab stop:" ) );
+}
+
+////
+
+ConfigurePathPage::ConfigurePathPage( KWView *view, QVBox *box, char *name )
+ : QObject( box->parent(), name )
+{
+ m_pView=view;
+ KWDocument * doc = m_pView->kWordDocument();
+ config = KWFactory::instance()->config();
+ QVGroupBox* gbPathGroup = new QVGroupBox( i18n("Path"), box, "GroupBox" );
+ gbPathGroup->setMargin( KDialog::marginHint() );
+ gbPathGroup->setInsideSpacing( KDialog::spacingHint() );
+
+ m_pPathView = new KListView( gbPathGroup );
+ m_pPathView->setResizeMode(QListView::NoColumn);
+ m_pPathView->addColumn( i18n( "Type" ) );
+ m_pPathView->addColumn( i18n( "Path" ), 400 ); // not too big by default
+ (void) new QListViewItem( m_pPathView, i18n("Personal Expression"), doc->personalExpressionPath().join(";") );
+ (void) new QListViewItem( m_pPathView, i18n("Backup Path"),doc->backupPath() );
+
+ m_modifyPath = new QPushButton( i18n("Modify Path..."), gbPathGroup);
+ connect( m_modifyPath, SIGNAL( clicked ()), this, SLOT( slotModifyPath()));
+ connect( m_pPathView, SIGNAL( doubleClicked (QListViewItem *, const QPoint &, int )), this, SLOT( slotModifyPath()));
+ connect( m_pPathView, SIGNAL( selectionChanged ( QListViewItem * )), this, SLOT( slotSelectionChanged(QListViewItem * )));
+ slotSelectionChanged(m_pPathView->currentItem());
+}
+
+void ConfigurePathPage::slotSelectionChanged(QListViewItem * item)
+{
+ m_modifyPath->setEnabled( item );
+}
+
+void ConfigurePathPage::slotModifyPath()
+{
+ QListViewItem *item = m_pPathView->currentItem ();
+ if ( item )
+ {
+ if ( item->text(0)==i18n("Personal Expression"))
+ {
+ KoEditPathDia * dlg = new KoEditPathDia( item->text( 1), 0L, "editpath");
+ if (dlg->exec() )
+ item->setText(1, dlg->newPath());
+ delete dlg;
+ }
+ if ( item->text(0)==i18n("Backup Path"))
+ {
+ KoChangePathDia *dlg = new KoChangePathDia( item->text(1), 0L, "backup path" );
+ if (dlg->exec() )
+ item->setText(1, dlg->newPath());
+ delete dlg;
+ }
+ }
+}
+
+void ConfigurePathPage::slotDefault()
+{
+ QListViewItem * item = m_pPathView->findItem(i18n("Personal Expression"), 0);
+ if ( item )
+ item->setText(1, KWFactory::instance()->dirs()->resourceDirs("expression").join(";"));
+ item = m_pPathView->findItem(i18n("Backup Path"), 0);
+ if ( item )
+ item->setText(1, QString::null );
+}
+
+void ConfigurePathPage::apply()
+{
+ QListViewItem * item = m_pPathView->findItem(i18n("Personal Expression"), 0);
+ if ( item )
+ {
+ QStringList lst = QStringList::split(QString(";"), item->text(1));
+ if ( lst != m_pView->kWordDocument()->personalExpressionPath())
+ {
+ m_pView->kWordDocument()->setPersonalExpressionPath(lst);
+ config->setGroup( "Kword Path" );
+ config->writePathEntry( "expression path", lst);
+ }
+ }
+ item = m_pPathView->findItem(i18n("Backup Path"), 0);
+ if ( item )
+ {
+ QString res = item->text(1 );
+ if ( res != m_pView->kWordDocument()->backupPath())
+ {
+ config->setGroup( "Kword Path" );
+ m_pView->kWordDocument()->setBackupPath( res );
+ config->writePathEntry( "backup path",res );
+ }
+ }
+
+}
+
+////
+
+ConfigureTTSPage::ConfigureTTSPage( KWView *view, QVBox *box, char *name )
+ : QObject( box->parent(), name )
+{
+ Q_UNUSED(view);
+ // m_pView=_view;
+ // KWDocument * doc = m_pView->kWordDocument();
+
+ m_cbSpeakPointerWidget = new QCheckBox(i18n("Speak widget under &mouse pointer"), box);
+ m_cbSpeakFocusWidget = new QCheckBox(i18n("Speak widget with &focus"), box);
+ m_gbScreenReaderOptions = new QVGroupBox("", box);
+ m_gbScreenReaderOptions->setMargin( KDialog::marginHint() );
+ m_gbScreenReaderOptions->setInsideSpacing( KDialog::spacingHint() );
+ m_cbSpeakTooltips = new QCheckBox(i18n("Speak &tool tips"), m_gbScreenReaderOptions);
+ m_cbSpeakWhatsThis = new QCheckBox(i18n("Speak &What's This"), m_gbScreenReaderOptions);
+ m_cbSpeakDisabled = new QCheckBox(i18n("Verbal indication if widget is disabled (grayed)",
+ "&Say whether disabled"), m_gbScreenReaderOptions);
+ m_cbSpeakAccelerators = new QCheckBox(i18n("Spea&k accelerators"), m_gbScreenReaderOptions);
+ QHBox* hbAcceleratorPrefix = new QHBox(m_gbScreenReaderOptions);
+ QWidget* spacer = new QWidget(hbAcceleratorPrefix);
+ spacer->setMinimumWidth(2 * KDialog::marginHint());
+ m_lblAcceleratorPrefix =
+ new QLabel(i18n("A word spoken before another word", "Pr&efaced by the word:"),
+ hbAcceleratorPrefix);
+ m_leAcceleratorPrefixWord = new QLineEdit(i18n("Keyboard accelerator, such as Alt+F", "Accelerator"),
+ hbAcceleratorPrefix);
+ m_lblAcceleratorPrefix->setBuddy(m_leAcceleratorPrefixWord);
+ QHBox* hbPollingInterval = new QHBox(m_gbScreenReaderOptions);
+ hbPollingInterval->setMargin( 0 );
+ QLabel* lblPollingInterval = new QLabel(i18n("&Polling interval:"), hbPollingInterval);
+ m_iniPollingInterval = new KIntNumInput(hbPollingInterval);
+ m_iniPollingInterval->setSuffix(" ms");
+ m_iniPollingInterval->setRange(100, 5000, 100, true);
+ lblPollingInterval->setBuddy(m_iniPollingInterval);
+
+ config = KWFactory::instance()->config();
+ config->setGroup("TTS");
+ m_cbSpeakPointerWidget->setChecked(config->readBoolEntry("SpeakPointerWidget", false));
+ m_cbSpeakFocusWidget->setChecked(config->readBoolEntry("SpeakFocusWidget", false));
+ m_cbSpeakTooltips->setChecked(config->readBoolEntry("SpeakTooltips", true));
+ m_cbSpeakWhatsThis->setChecked(config->readBoolEntry("SpeakWhatsThis", false));
+ m_cbSpeakDisabled->setChecked(config->readBoolEntry("SpeakDisabled", true));
+ m_cbSpeakAccelerators->setChecked(config->readBoolEntry("SpeakAccelerators", true));
+ m_leAcceleratorPrefixWord->setText(config->readEntry("AcceleratorPrefixWord",
+ i18n("Keyboard accelerator, such as Alt+F", "Accelerator")));
+ m_iniPollingInterval->setValue(config->readNumEntry("PollingInterval", 600));
+
+ screenReaderOptionChanged();
+ connect(m_cbSpeakPointerWidget, SIGNAL(toggled(bool)), this, SLOT(screenReaderOptionChanged()));
+ connect(m_cbSpeakFocusWidget, SIGNAL(toggled(bool)), this, SLOT(screenReaderOptionChanged()));
+ connect(m_cbSpeakAccelerators, SIGNAL(toggled(bool)), this, SLOT(screenReaderOptionChanged()));
+}
+
+void ConfigureTTSPage::slotDefault()
+{
+ m_cbSpeakPointerWidget->setChecked(false);
+ m_cbSpeakFocusWidget->setChecked(false);
+ m_cbSpeakTooltips->setChecked(true);
+ m_cbSpeakWhatsThis->setChecked(false);
+ m_cbSpeakDisabled->setChecked(true);
+ m_cbSpeakAccelerators->setChecked(true);
+ m_leAcceleratorPrefixWord->setText(i18n("Keyboard accelerator, such as Alt+F", "Accelerator"));
+ m_iniPollingInterval->setValue(600);
+}
+
+void ConfigureTTSPage::apply()
+{
+ config->setGroup("TTS");
+ config->writeEntry("SpeakPointerWidget", m_cbSpeakPointerWidget->isChecked());
+ config->writeEntry("SpeakFocusWidget", m_cbSpeakFocusWidget->isChecked());
+ config->writeEntry("SpeakTooltips", m_cbSpeakTooltips->isChecked());
+ config->writeEntry("SpeakWhatsThis", m_cbSpeakWhatsThis->isChecked());
+ config->writeEntry("SpeakDisabled", m_cbSpeakDisabled->isChecked());
+ config->writeEntry("SpeakAccelerators", m_cbSpeakAccelerators->isChecked());
+ config->writeEntry("AcceleratorPrefixWord", m_leAcceleratorPrefixWord->text());
+ config->writeEntry("PollingInterval", m_iniPollingInterval->value());
+ if (kospeaker) kospeaker->readConfig(config);
+}
+
+void ConfigureTTSPage::screenReaderOptionChanged()
+{
+ m_gbScreenReaderOptions->setEnabled(
+ m_cbSpeakPointerWidget->isChecked() | m_cbSpeakFocusWidget->isChecked());
+ m_leAcceleratorPrefixWord->setEnabled(m_cbSpeakAccelerators->isChecked());
+ m_lblAcceleratorPrefix->setEnabled(m_cbSpeakAccelerators->isChecked());
+}
+
+#include "KWConfig.moc"
diff --git a/kword/KWConfig.h b/kword/KWConfig.h
new file mode 100644
index 00000000..1b563f92
--- /dev/null
+++ b/kword/KWConfig.h
@@ -0,0 +1,203 @@
+/* This file is part of the KDE project
+ Copyright (C) 2001 Montel Laurent <lmontel@mandrakesoft.com>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+*/
+
+#ifndef __kwconfig__
+#define __kwconfig__
+
+#include <kdialogbase.h>
+
+namespace KFormula {
+ class ConfigurePage;
+}
+
+class KWView;
+class QCheckBox;
+class KIntNumInput;
+class KoUnitDoubleSpinBox;
+class KConfig;
+class QComboBox;
+class KIntNumInput;
+class KCommand;
+class KWDocument;
+class KListView;
+class QVGroupBox;
+class QLabel;
+
+namespace KSpell2 {
+ class ConfigWidget;
+}
+
+class ConfigureSpellPage : public QObject
+{
+ Q_OBJECT
+public:
+ ConfigureSpellPage( KWView *view, QVBox *box, char *name = 0 );
+ void apply();
+ void slotDefault();
+private:
+ KWView* m_pView;
+ KConfig* config;
+ KSpell2::ConfigWidget *m_spellConfigWidget;
+};
+
+class ConfigureInterfacePage : public QObject
+{
+ Q_OBJECT
+public:
+ ConfigureInterfacePage( KWView *view, QVBox *box, char *name = 0 );
+ void apply();
+ void slotDefault();
+ void setUnit( KoUnit::Unit unit );
+
+signals:
+ // For KWConfig
+ void unitChanged( int );
+private:
+ KWView* m_pView;
+ KConfig* config;
+ QComboBox *m_unitCombo;
+ KoUnitDoubleSpinBox* gridX,*gridY;
+ KoUnitDoubleSpinBox* indent;
+ KIntNumInput* recentFiles;
+ QCheckBox *showStatusBar, *showScrollBar, *pgUpDownMovesCaret;
+ int oldNbRecentFiles;
+ KIntNumInput *m_nbPagePerRow;
+};
+
+class ConfigureMiscPage : public QObject
+{
+ Q_OBJECT
+public:
+ ConfigureMiscPage( KWView *view, QVBox *box, char *name = 0 );
+ KCommand* apply();
+ void slotDefault();
+ void setUnit( KoUnit::Unit unit );
+private:
+ KWView* m_pView;
+ KConfig* config;
+ KIntNumInput* m_undoRedoLimit;
+ int m_oldNbRedo;
+ bool m_oldFormattingEndParag, m_oldFormattingSpace, m_oldFormattingTabs, m_oldFormattingBreak;
+ QCheckBox* m_displayLink, *m_displayComment, *m_underlineLink, *m_displayFieldCode;
+ QCheckBox* m_cbViewFormattingEndParag, *m_cbViewFormattingSpace;
+ QCheckBox* m_cbViewFormattingTabs, *m_cbViewFormattingBreak;
+};
+
+class ConfigureDefaultDocPage : public QObject
+{
+ Q_OBJECT
+public:
+ ConfigureDefaultDocPage( KWView *view, QVBox *box, char *name = 0 );
+ ~ConfigureDefaultDocPage();
+ KCommand* apply();
+ void slotDefault();
+ void setUnit( KoUnit::Unit unit );
+public slots:
+ void selectNewDefaultFont();
+private:
+ KWView* m_pView;
+ KConfig* config;
+ QFont *font;
+ QLabel *fontName;
+ QLabel *tabStop;
+
+ KoUnitDoubleSpinBox* m_columnSpacing;
+
+ KIntNumInput* autoSave;
+ int oldAutoSaveValue;
+ double m_oldTabStopWidth;
+
+ int m_oldStartingPage;
+ bool m_oldBackupFile;
+ KIntNumInput* m_variableNumberOffset;
+ KoUnitDoubleSpinBox *m_tabStopWidth;
+ QCheckBox *m_cursorInProtectedArea;
+ QCheckBox *m_createBackupFile;
+// QCheckBox *m_directInsertCursor;
+ QCheckBox *m_autoHyphenation;
+ QComboBox *m_globalLanguage;
+ QString m_oldLanguage;
+ bool m_oldHyphenation;
+};
+
+class ConfigurePathPage : public QObject
+{
+ Q_OBJECT
+public:
+ ConfigurePathPage( KWView *view, QVBox *box, char *name = 0 );
+ void slotDefault();
+ void apply();
+private slots:
+ void slotModifyPath();
+ void slotSelectionChanged(QListViewItem *);
+private:
+ KWView* m_pView;
+ KConfig* config;
+ KListView* m_pPathView;
+ QPushButton *m_modifyPath;
+};
+
+class ConfigureTTSPage : public QObject
+{
+ Q_OBJECT
+public:
+ ConfigureTTSPage( KWView *view, QVBox *box, char *name = 0 );
+ void slotDefault();
+ void apply();
+private slots:
+ void screenReaderOptionChanged();
+private:
+ KConfig* config;
+ QCheckBox* m_cbSpeakPointerWidget;
+ QCheckBox* m_cbSpeakFocusWidget;
+ QVGroupBox* m_gbScreenReaderOptions;
+ QCheckBox* m_cbSpeakTooltips;
+ QCheckBox* m_cbSpeakWhatsThis;
+ QCheckBox* m_cbSpeakDisabled;
+ QCheckBox* m_cbSpeakAccelerators;
+ QLabel* m_lblAcceleratorPrefix;
+ QLineEdit* m_leAcceleratorPrefixWord;
+ KIntNumInput* m_iniPollingInterval;
+};
+
+class KWConfig : public KDialogBase
+{
+ Q_OBJECT
+public:
+ enum { KW_KSPELL=1,KP_INTERFACE=2,KP_MISC=4, KP_DOCUMENT=8, KP_FORMULA=16, KP_PATH = 32};
+ KWConfig( KWView* parent );
+ void openPage(int flags);
+public slots:
+ void slotApply();
+ void slotDefault();
+ void unitChanged( int );
+private:
+ ConfigureSpellPage *m_spellPage;
+ ConfigureInterfacePage *m_interfacePage;
+ ConfigureMiscPage *m_miscPage;
+ ConfigureDefaultDocPage *m_defaultDocPage;
+ KFormula::ConfigurePage *m_formulaPage;
+ ConfigurePathPage *m_pathPage;
+ ConfigureTTSPage *m_ttsPage;
+ KWDocument *m_doc;
+};
+
+
+
+#endif
diff --git a/kword/KWConfigFootNoteDia.cpp b/kword/KWConfigFootNoteDia.cpp
new file mode 100644
index 00000000..f2d606c6
--- /dev/null
+++ b/kword/KWConfigFootNoteDia.cpp
@@ -0,0 +1,216 @@
+/* This file is part of the KDE project
+ Copyright (C) 2002 Montel Laurent <lmontel@mandrakesoft.com>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+*/
+
+#include "KWDocument.h"
+#include "KWConfigFootNoteDia.h"
+#include "KWConfigFootNoteDia.moc"
+#include "KWVariable.h"
+#include "KWCommand.h"
+#include "KWFrameSet.h"
+
+#include <KoParagDia.h>
+#include <KoUnitWidgets.h>
+
+#include <klocale.h>
+#include <knuminput.h>
+
+#include <qradiobutton.h>
+#include <qwhatsthis.h>
+#include <qvbuttongroup.h>
+#include <qlabel.h>
+#include <qvbox.h>
+#include <qlayout.h>
+#include <qcombobox.h>
+
+
+KWConfigFootNoteDia::KWConfigFootNoteDia( QWidget *parent, const char *name, KWDocument *doc )
+ : KDialogBase(Tabbed, QString::null, Ok | Cancel , Ok, parent, name, true)
+{
+ setCaption( i18n("Configure Endnote/Footnote") );
+ m_doc = doc;
+
+ resize( 510, 310 );
+ setupTab1();
+ setupTab2();
+ setupTab3();
+}
+
+void KWConfigFootNoteDia::setupTab1()
+{
+ QVBox * page = addVBoxPage( i18n( "Footnotes" ) );
+ m_footNoteConfig = new KoCounterStyleWidget( false, true, false, page );
+ //m_footNoteConfig->numTypeChanged( KoParagCounter::NUM_LIST );
+ m_footNoteConfig->setCounter (static_cast<KWVariableSettings*>(m_doc->variableCollection()->variableSetting())->footNoteCounter() );
+}
+
+void KWConfigFootNoteDia::setupTab2()
+{
+ QVBox * page = addVBoxPage( i18n( "Endnotes" ) );
+ m_endNoteConfig = new KoCounterStyleWidget( false, true/*onlyStyleLetter*/,false, page );
+ //m_endNoteConfig->numTypeChanged( KoParagCounter::NUM_LIST );
+ m_endNoteConfig->setCounter (static_cast<KWVariableSettings*>(m_doc->variableCollection()->variableSetting())->endNoteCounter() );
+}
+
+
+void KWConfigFootNoteDia::setupTab3()
+{
+ QFrame * page = addPage( i18n( "Separator Line" ) );
+ QString comment= i18n ("Configure the separator line. The separator line "
+ "is drawn directly above the frame for the footnotes.");
+ QWhatsThis::add(page, comment);
+ QVBoxLayout *pageLayout= new QVBoxLayout( page, 0, KDialog::spacingHint());
+
+ QButtonGroup *positionGroupBox = new QButtonGroup( i18n( "Position"), page );
+ comment= i18n ("The separator can be positioned horizontally by picking one "
+ "of the three alignments.");
+ QWhatsThis::add(positionGroupBox, comment);
+ positionGroupBox->setColumnLayout(0, Qt::Vertical );
+ QVBoxLayout *positionLayout = new QVBoxLayout( positionGroupBox->layout() );
+ positionLayout->setAlignment( Qt::AlignTop );
+
+ // i18n context information necessary for gender considerations (e.g. in Polish)
+ rbPosLeft = new QRadioButton( i18n("Position", "Left"), positionGroupBox, "rbPosLeft" );
+ positionLayout->addWidget( rbPosLeft );
+
+ rbPosCentered = new QRadioButton( i18n("Position", "Centered"), positionGroupBox, "rbPosCentered" );
+ positionLayout->addWidget( rbPosCentered );
+
+ rbPosRight = new QRadioButton( i18n("Position", "Right"), positionGroupBox, "rbPosRight" );
+ positionLayout->addWidget( rbPosRight );
+ pageLayout->addWidget( positionGroupBox );
+ switch( m_doc->footNoteSeparatorLinePosition() ) {
+ case SLP_LEFT:
+ rbPosLeft->setChecked( true);
+ break;
+ case SLP_CENTERED:
+ rbPosCentered->setChecked( true);
+ break;
+ case SLP_RIGHT:
+ rbPosRight->setChecked( true);
+ break;
+ }
+
+ QGridLayout *layout = new QGridLayout( 0, 1, 1, 0, KDialog::spacingHint());
+
+ spWidth = new KoUnitDoubleSpinBox(page, 0, 5, 0.5, m_doc->footNoteSeparatorLineWidth(), m_doc->unit(), 1);
+
+ layout->addWidget( spWidth, 1, 1 );
+
+ spLength = new KIntNumInput( page, "spLength" );
+ spLength->setRange( 1, 100, 1,false );
+ spLength->setValue( m_doc->footNoteSeparatorLineLength());
+ spLength->setSuffix(i18n(" %"));
+ layout->addWidget( spLength, 0, 1 );
+
+ QLabel *lSize = new QLabel( i18n( "&Width:"), page );
+ lSize->setBuddy( spWidth );
+ comment= i18n ("The width is the thickness of the separator line, set to 0 for no separator line.");
+ QWhatsThis::add(lSize, comment);
+ QWhatsThis::add(spWidth, comment);
+ layout->addWidget( lSize, 1, 0 );
+
+ QSpacerItem* spacer = new QSpacerItem( 0, 0, QSizePolicy::Expanding, QSizePolicy::Minimum );
+ layout->addMultiCell( spacer, 0, 1, 2, 2 );
+
+ QLabel *lWidth = new QLabel( i18n("&Size on page:"), page, "lWidth" );
+ lWidth->setBuddy( spLength );
+ comment= i18n ("The size of the separator line can be defined as a percentage of the width of the page.");
+ QWhatsThis::add(spLength, comment);
+ QWhatsThis::add(lWidth, comment);
+ layout->addWidget( lWidth, 0, 0 );
+ pageLayout->addLayout( layout );
+
+ QHBoxLayout *styleLayout = new QHBoxLayout( 0, 0, KDialog::spacingHint(), "styleLayout");
+
+ QLabel *styleLabel = new QLabel( i18n("Style:"), page );
+ styleLayout->addWidget( styleLabel );
+
+ m_cbLineType = new QComboBox( page );
+ QStringList lst;
+ lst <<i18n("Solid");
+ lst <<i18n("Dash Line");
+ lst <<i18n("Dot Line");
+ lst <<i18n("Dash Dot Line");
+ lst <<i18n("Dash Dot Dot Line");
+ m_cbLineType->insertStringList( lst );
+ m_cbLineType->setCurrentItem( static_cast<int>(m_doc->footNoteSeparatorLineType()));
+ comment= i18n ("The separator line can be drawn as a solid line or as a line which has a "
+ "pattern; the pattern can be set in the style-type.");
+ QWhatsThis::add(styleLabel, comment);
+ QWhatsThis::add(m_cbLineType, comment);
+ styleLayout->addWidget( m_cbLineType );
+
+ QSpacerItem* spacer_2 = new QSpacerItem( 0, 0, QSizePolicy::Expanding, QSizePolicy::Minimum );
+ styleLayout->addItem( spacer_2 );
+ pageLayout->addLayout( styleLayout );
+ QSpacerItem* spacer_3 = new QSpacerItem( 0, 0, QSizePolicy::Minimum, QSizePolicy::Expanding );
+ pageLayout->addItem( spacer_3 );
+}
+
+
+void KWConfigFootNoteDia::slotOk()
+{
+ KMacroCommand * macro = 0L;
+ KCommand *cmd = 0L;
+ KoParagCounter counter =static_cast<KWVariableSettings*>(m_doc->variableCollection()->variableSetting())->footNoteCounter();
+ if (counter != m_footNoteConfig->counter() )
+ {
+ macro = new KMacroCommand(i18n("Change End-/Footnote Variable Settings"));
+ cmd= new KWChangeFootEndNoteSettingsCommand( i18n("Change End-/Footnote Variable Settings") , counter, m_footNoteConfig->counter() ,true ,m_doc);
+ macro->addCommand(cmd );
+ }
+ counter = static_cast<KWVariableSettings*>(m_doc->variableCollection()->variableSetting())->endNoteCounter();
+ if (counter != m_endNoteConfig->counter() )
+ {
+ if ( !macro )
+ macro = new KMacroCommand(i18n("Change End-/Footnote Variable Settings"));
+ cmd= new KWChangeFootEndNoteSettingsCommand( i18n("Change End-/Footnote Variable Settings") , counter, m_endNoteConfig->counter() ,false ,m_doc);
+ macro->addCommand(cmd );
+ }
+
+ int val =spLength->value();
+ double width = spWidth->value();
+ SeparatorLinePos tmp = SLP_LEFT;
+ SeparatorLineLineType type = static_cast<SeparatorLineLineType>(m_cbLineType->currentItem());
+ if ( rbPosRight->isChecked())
+ tmp = SLP_RIGHT;
+ else if ( rbPosCentered->isChecked())
+ tmp = SLP_CENTERED;
+ else if ( rbPosLeft->isChecked())
+ tmp = SLP_LEFT;
+
+ if ( (val != m_doc->footNoteSeparatorLineLength())||
+ tmp != m_doc->footNoteSeparatorLinePosition()||
+ width!= m_doc->footNoteSeparatorLineWidth() ||
+ type != m_doc->footNoteSeparatorLineType())
+ {
+ if ( !macro )
+ macro = new KMacroCommand(i18n("Change Footnote Line Separator Settings"));
+ cmd = new KWChangeFootNoteLineSeparatorParametersCommand( i18n("Change Footnote Line Separator Settings") , m_doc->footNoteSeparatorLinePosition(), tmp, m_doc->footNoteSeparatorLineLength(), val,m_doc->footNoteSeparatorLineWidth(), width, m_doc->footNoteSeparatorLineType(), type, m_doc);
+ macro->addCommand( cmd );
+ }
+
+ if ( macro )
+ {
+ macro->execute();
+ m_doc->addCommand( macro );
+ }
+
+ KDialogBase::slotOk();
+}
diff --git a/kword/KWConfigFootNoteDia.h b/kword/KWConfigFootNoteDia.h
new file mode 100644
index 00000000..7ec62eb4
--- /dev/null
+++ b/kword/KWConfigFootNoteDia.h
@@ -0,0 +1,58 @@
+/* This file is part of the KDE project
+ Copyright (C) 2002 Montel Laurent <lmontel@mandrakesoft.com>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+*/
+
+#ifndef configfootnotedia_h
+#define configfootnotedia_h
+
+#include <kdialogbase.h>
+
+class KWDocument;
+class QWidget;
+class KoCounterStyleWidget;
+class QRadioButton;
+class KIntNumInput;
+class QComboBox;
+class KoUnitDoubleSpinBox;
+
+class KWConfigFootNoteDia : public KDialogBase
+{
+ Q_OBJECT
+public:
+ KWConfigFootNoteDia( QWidget *parent, const char *name, KWDocument *doc );
+protected:
+ void setupTab1();
+ void setupTab2();
+ void setupTab3();
+private:
+ KoCounterStyleWidget *m_footNoteConfig;
+ KoCounterStyleWidget *m_endNoteConfig;
+ KWDocument *m_doc;
+ QRadioButton *rbPosLeft;
+ QRadioButton *rbPosCentered;
+ QRadioButton *rbPosRight;
+ KIntNumInput *spLength;
+ KoUnitDoubleSpinBox *spWidth;
+ QComboBox *m_cbLineType;
+protected slots:
+ virtual void slotOk();
+};
+
+#endif
+
+
diff --git a/kword/KWCreateBookmarkDia.cpp b/kword/KWCreateBookmarkDia.cpp
new file mode 100644
index 00000000..2bc3a1c7
--- /dev/null
+++ b/kword/KWCreateBookmarkDia.cpp
@@ -0,0 +1,155 @@
+/* This file is part of the KDE project
+ Copyright (C) 2002 Montel Laurent <lmontel@mandrakesoft.com>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+*/
+
+#include <klocale.h>
+#include "KWDocument.h"
+#include <qvbox.h>
+#include <qlayout.h>
+#include <qlineedit.h>
+#include <qpushbutton.h>
+#include <qlistbox.h>
+#include <kmessagebox.h>
+#include "KWCommand.h"
+#include "KWCreateBookmarkDia.h"
+#include "KWCreateBookmarkDiaBase.h"
+#include "KWFrame.h"
+#include "KWFrameSet.h"
+
+KWCreateBookmarkDia::KWCreateBookmarkDia( const QStringList & _list, QWidget *parent, const char *name )
+ : KDialogBase( parent, name , true, "", Ok|Cancel, Ok, true )
+{
+ setCaption( i18n("Create New Bookmark") );
+ listBookMark = _list;
+ init();
+}
+
+KWCreateBookmarkDia::KWCreateBookmarkDia( const QStringList & _list, const QString & _name, QWidget *parent, const char *name )
+ : KDialogBase( parent, name , true, "", Ok|Cancel, Ok, true )
+{
+ setCaption( i18n("Rename Bookmark") );
+ listBookMark = _list;
+ init();
+ m_bookmarkName->setText(_name);
+}
+
+void KWCreateBookmarkDia::init()
+{
+ KWCreateBookmarkDiaBase *dia = new KWCreateBookmarkDiaBase( this );
+ m_bookmarkName = dia->m_bookmarkName;
+ enableButtonOK( false );
+ connect( m_bookmarkName, SIGNAL(textChanged ( const QString & )), this, SLOT(nameChanged( const QString &)));
+ setMainWidget( dia );
+ m_bookmarkName->setFocus();
+}
+
+void KWCreateBookmarkDia::slotOk()
+{
+ if ( listBookMark.findIndex(m_bookmarkName->text() ) != -1 )
+ {
+ KMessageBox::error(this, i18n("That name already exists, please choose another name."));
+ }
+ else
+ KDialogBase::slotOk();
+}
+
+QString KWCreateBookmarkDia::bookmarkName()const
+{
+ return m_bookmarkName->text();
+}
+
+void KWCreateBookmarkDia::nameChanged( const QString &text)
+{
+ enableButtonOK( !text.isEmpty() );
+}
+
+
+/* **************************** */
+KWSelectBookmarkDia::KWSelectBookmarkDia( const QStringList & _list, KWDocument *_doc, QWidget *parent, const char *name )
+ : KDialogBase( parent, name , true, "", Ok|Cancel, Ok, true )
+{
+ m_doc=_doc;
+ setCaption( i18n("Select Bookmark") );
+ QWidget *page = new QWidget( this );
+ setMainWidget(page);
+
+ QGridLayout * grid = new QGridLayout(page, 5, 2, KDialog::marginHint(), KDialog::spacingHint());
+ m_bookmarkList = new QListBox( page );
+ grid->addMultiCellWidget(m_bookmarkList, 0, 4, 0, 0);
+ m_bookmarkList->insertStringList(_list);
+
+ connect(m_bookmarkList, SIGNAL( selectionChanged ()), this, SLOT(slotSelectionChanged()));
+ connect(m_bookmarkList, SIGNAL(doubleClicked ( QListBoxItem * )), this, SLOT(slotOk()));
+ connect(m_bookmarkList, SIGNAL(returnPressed ( QListBoxItem * )), this, SLOT(slotOk()));
+
+ m_pbRename = new QPushButton( i18n("Rename Bookmark"), page );
+ grid->addWidget( m_pbRename, 0, 1);
+ connect( m_pbRename, SIGNAL(clicked()), this, SLOT(slotRenameBookmark()));
+
+ m_pbDelete = new QPushButton( i18n("Delete Bookmark"), page );
+ grid->addWidget( m_pbDelete, 1, 1);
+
+ connect( m_pbDelete, SIGNAL(clicked()), this, SLOT(slotDeleteBookmark()));
+
+ m_bookmarkList->setFocus();
+ slotSelectionChanged();
+}
+
+void KWSelectBookmarkDia::slotRenameBookmark()
+{
+ QString tmp =m_bookmarkList->currentText();
+ if ( tmp.isEmpty() )
+ return;
+ //all bookmark name
+ QStringList lst =m_doc->listOfBookmarkName(0L);
+ lst.remove( tmp );
+ KWCreateBookmarkDia dia( lst, tmp, this, 0 );
+ if ( dia.exec() ) {
+ QString newName = dia.bookmarkName();
+ KWRenameBookmarkCommand *cmd = new KWRenameBookmarkCommand( i18n("Rename Bookmark"), tmp, newName, m_doc);
+ m_doc->addCommand( cmd );
+ cmd->execute();
+ m_bookmarkList->changeItem ( newName, m_bookmarkList->currentItem() );
+ }
+}
+
+void KWSelectBookmarkDia::slotDeleteBookmark()
+{
+ QString tmp =m_bookmarkList->currentText();
+ if ( !tmp.isEmpty())
+ {
+ m_doc->deleteBookmark(tmp);
+ m_bookmarkList->removeItem(m_bookmarkList->currentItem());
+ }
+}
+
+
+QString KWSelectBookmarkDia::bookmarkSelected()const
+{
+ return m_bookmarkList->currentText();
+}
+
+void KWSelectBookmarkDia::slotSelectionChanged()
+{
+ bool state =!m_bookmarkList->currentText().isEmpty();
+ enableButtonOK( state );
+ m_pbRename->setEnabled( state);
+ m_pbDelete->setEnabled( state && m_doc->isReadWrite());
+}
+
+#include "KWCreateBookmarkDia.moc"
diff --git a/kword/KWCreateBookmarkDia.h b/kword/KWCreateBookmarkDia.h
new file mode 100644
index 00000000..cd5f732c
--- /dev/null
+++ b/kword/KWCreateBookmarkDia.h
@@ -0,0 +1,65 @@
+/* This file is part of the KDE project
+ Copyright (C) 2002 Montel Laurent <lmontel@mandrakesoft.com>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+*/
+
+#ifndef __KWCreateBookmarkDia__
+#define __KWCreateBookmarkDia__
+
+#include <kdialogbase.h>
+#include <qstringlist.h>
+class QLineEdit;
+class QListBox;
+class KWDocument;
+class QPushButton;
+
+class KWCreateBookmarkDia : public KDialogBase
+{
+ Q_OBJECT
+public:
+ KWCreateBookmarkDia( const QStringList & _list, QWidget *parent, const char *name );
+ KWCreateBookmarkDia( const QStringList & _list, const QString & _name, QWidget *parent, const char *name );
+ QString bookmarkName()const;
+
+protected slots:
+ virtual void slotOk();
+ void nameChanged( const QString &text);
+
+protected:
+ void init();
+ QStringList listBookMark;
+ QLineEdit *m_bookmarkName;
+};
+
+class KWSelectBookmarkDia : public KDialogBase
+{
+ Q_OBJECT
+public:
+ KWSelectBookmarkDia( const QStringList & _list, KWDocument *_doc, QWidget *parent, const char *name );
+ QString bookmarkSelected()const;
+protected slots:
+ void slotSelectionChanged();
+ void slotRenameBookmark();
+ void slotDeleteBookmark();
+private:
+ QListBox *m_bookmarkList;
+ KWDocument *m_doc;
+ QPushButton *m_pbDelete;
+ QPushButton *m_pbRename;
+};
+
+#endif
diff --git a/kword/KWCreateBookmarkDiaBase.ui b/kword/KWCreateBookmarkDiaBase.ui
new file mode 100644
index 00000000..08c7b05d
--- /dev/null
+++ b/kword/KWCreateBookmarkDiaBase.ui
@@ -0,0 +1,57 @@
+<!DOCTYPE UI><UI version="3.2" stdsetdef="1">
+<class>KWCreateBookmarkDiaBase</class>
+<widget class="QWidget">
+ <property name="name">
+ <cstring>createBookmarkDia</cstring>
+ </property>
+ <property name="geometry">
+ <rect>
+ <x>0</x>
+ <y>0</y>
+ <width>496</width>
+ <height>104</height>
+ </rect>
+ </property>
+ <property name="caption">
+ <string>Create New Bookmark</string>
+ </property>
+ <grid>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="QLayoutWidget" row="1" column="0">
+ <property name="name">
+ <cstring>layout2</cstring>
+ </property>
+ <hbox>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="QLabel">
+ <property name="name">
+ <cstring>lName</cstring>
+ </property>
+ <property name="text">
+ <string>Name:</string>
+ </property>
+ </widget>
+ <widget class="QLineEdit">
+ <property name="name">
+ <cstring>m_bookmarkName</cstring>
+ </property>
+ </widget>
+ </hbox>
+ </widget>
+ <widget class="QLabel" row="0" column="0">
+ <property name="name">
+ <cstring>lExplain</cstring>
+ </property>
+ <property name="text">
+ <string>Bookmarks allow you to jump between parts of your document.
+Please provide the name of your bookmark.</string>
+ </property>
+ </widget>
+ </grid>
+</widget>
+<layoutdefaults spacing="6" margin="6"/>
+</UI>
diff --git a/kword/KWDeleteDia.cpp b/kword/KWDeleteDia.cpp
new file mode 100644
index 00000000..ab447cc6
--- /dev/null
+++ b/kword/KWDeleteDia.cpp
@@ -0,0 +1,90 @@
+/* This file is part of the KDE project
+ Copyright (C) 1998, 1999 Reginald Stadlbauer <reggie@kde.org>
+ Copyright (C) 2005 Thomas Zander <zander@kde.org>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+*/
+
+#include "KWTableFrameSet.h"
+#include "KWDeleteDia.h"
+#include "KWView.h"
+
+#include <klocale.h>
+#include <qlabel.h>
+#include <qlayout.h>
+
+KWDeleteDia::KWDeleteDia( KWView *parent, KWTableFrameSet *table, DeleteType type, QValueList<uint> remove)
+ : KDialogBase( Plain, (type==deleteRow?i18n("Delete Row") : i18n("Delete Column")), Ok | Cancel, Ok, parent, "Delete Table items dialog", true )
+{
+ Q_ASSERT(type == deleteRow || type == deleteColumn);
+ m_type = type;
+ m_table = table;
+ m_toRemove = remove;
+ m_view = parent;
+
+ setupTab1();
+ setButtonOK( KGuiItem(
+ i18n("&Delete"), "editdelete", type == deleteRow ?
+ i18n("Delete the row from the table.") :
+ i18n("Delete the column from the table.")) );
+}
+
+void KWDeleteDia::setupTab1() {
+ QWidget *tab1 = plainPage();
+ QGridLayout *grid1 = new QGridLayout( tab1, 4, 1, 0, spacingHint() );
+ unsigned int count = m_toRemove.count();
+ Q_ASSERT(count > 0);
+
+ QString message;
+ if ( count == ( (m_type == deleteRow) ? m_table->getRows() : m_table->getColumns() ) )
+ // all the columns are selected and the user asked to remove columns or the same with rows
+ // => we want to delete the whole table
+ message = i18n("Delete the whole table?");
+ else if ( count > 10 )
+ // do not display hugely long dialogs if many rows/cells are selected
+ message = m_type == deleteRow ? i18n("Delete all selected rows?") : i18n("Delete all selected cells?");
+ else if ( count == 1 ) {
+ message = m_type == deleteRow ? i18n( "Delete row number %1?" ) : i18n( "Delete column number %1?" );
+ message = message.arg( m_toRemove.first() + 1 ); // +1 because humans count from 1
+ }
+ else {
+ message = m_type == deleteRow ? i18n( "Delete rows: %1 ?" ) : i18n( "Delete columns: %1 ?" );
+
+ QValueListIterator<uint> items = m_toRemove.begin();
+ QString rows;
+ for(;items != m_toRemove.end(); ++items) {
+ if(! rows.isEmpty())
+ rows += ", ";
+ rows += QString().setNum((*items) +1);
+ }
+ message = message.arg( rows );
+ }
+
+ QLabel *rc = new QLabel( message , tab1 );
+ rc->resize( rc->sizeHint() );
+ rc->setAlignment( AlignLeft | AlignBottom );
+ grid1->addWidget( rc, 1, 0 );
+}
+
+void KWDeleteDia::slotOk() {
+ if(m_type == deleteRow)
+ m_view->tableDeleteRow(m_toRemove);
+ else
+ m_view->tableDeleteCol(m_toRemove);
+ KDialogBase::slotOk();
+}
+
+#include "KWDeleteDia.moc"
diff --git a/kword/KWDeleteDia.h b/kword/KWDeleteDia.h
new file mode 100644
index 00000000..9a2ad6d5
--- /dev/null
+++ b/kword/KWDeleteDia.h
@@ -0,0 +1,65 @@
+/* This file is part of the KDE project
+ Copyright (C) 1998, 1999 Reginald Stadlbauer <reggie@kde.org>
+ Copyright (C) 2005 Thomas Zander <zander@kde.org>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+*/
+
+#ifndef deldia_h
+#define deldia_h
+
+#include <kdialogbase.h>
+
+class KWTableFrameSet;
+class KWView;
+
+/******************************************************************/
+/* Class: KWDeleteDia */
+/******************************************************************/
+
+class KWDeleteDia : public KDialogBase
+{
+ Q_OBJECT
+
+public:
+ enum DeleteType {deleteRow, deleteColumn};
+
+ /**
+ * Constructor for the ok-to-delete dialog.
+ * @param parent the parent widget
+ * @param name the internal name for the widget
+ * @param table the table the rows or columns are to be deleted from
+ * @param type the type of dialog this should become, either deleteRow or deleteColumn
+ * @param remove a list of all the rows or columns that should be deleted.
+ */
+ KWDeleteDia( KWView *parent, KWTableFrameSet *table, DeleteType type, QValueList<uint> remove);
+
+protected:
+ void setupTab1();
+
+ KWView *m_view;
+ KWTableFrameSet *m_table;
+ DeleteType m_type;
+
+ QValueList<uint> m_toRemove;
+
+protected slots:
+ virtual void slotOk();
+};
+
+#endif
+
+
diff --git a/kword/KWDocStruct.cpp b/kword/KWDocStruct.cpp
new file mode 100644
index 00000000..f32e4181
--- /dev/null
+++ b/kword/KWDocStruct.cpp
@@ -0,0 +1,1264 @@
+/* This file is part of the KDE project
+ Copyright (C) 1998, 1999 Reginald Stadlbauer <reggie@kde.org>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+*/
+
+// KWord includes.
+#include "KWDocument.h"
+#include "KWView.h"
+#include "KWCanvas.h"
+#include "KWDocStruct.h"
+#include "KWDocStruct.moc"
+#include "KWTableFrameSet.h"
+#include "KWPartFrameSet.h"
+#include "KWFormulaFrameSet.h"
+#include "KWPictureFrameSet.h"
+#include "KWTextDocument.h"
+
+// KOffice includes.
+#include <KoParagCounter.h>
+#include <KoSpeaker.h>
+
+// KDE includes.
+#include <klocale.h>
+#include <kiconloader.h>
+#include <kdebug.h>
+#include <klistviewsearchline.h>
+#include <kglobalsettings.h>
+#include <kglobal.h>
+#include <kpixmap.h>
+#include <ktoolbar.h>
+#include <ktoolbarbutton.h>
+
+#include <qlayout.h>
+
+/******************************************************************/
+/* Class: KWOrderedFrameSet */
+/******************************************************************/
+
+KWOrderedFrameSet::KWOrderedFrameSet(KWFrameSet* fs) :
+ m_frameset(fs) { }
+
+KWOrderedFrameSet::KWOrderedFrameSet() :
+ m_frameset(0) { }
+
+bool KWOrderedFrameSet::operator<( KWOrderedFrameSet ofs )
+{
+ if (!m_frameset) return false;
+ KWFrame* frame1 = m_frameset->frame(0);
+ if (!frame1) return false;
+ KWFrameSet* frameset2 = ofs.frameSet();
+ if (!frameset2) return false;
+ KWFrame* frame2 = frameset2->frame(0);
+ if (!frame2) return false;
+ KoPoint p1 = frame1->topLeft();
+ KoPoint p2 = frame2->topLeft();
+ return (p1.y() < p2.y() || (p1.y() == p2.y() && p1.x() < p2.x()));
+}
+
+/******************************************************************/
+/* Class: KWDocDocListViewItem */
+/******************************************************************/
+
+KWDocListViewItem::KWDocListViewItem(QListViewItem* parent, const QString& text)
+ : KListViewItem(parent, text)
+{
+}
+
+KWDocListViewItem::KWDocListViewItem(QListViewItem* parent, QListViewItem* after, const QString& text )
+ :KListViewItem(parent, after, text)
+{
+}
+
+KWDocListViewItem::KWDocListViewItem(QListView* parent, const QString& text)
+ :KListViewItem(parent, text)
+{
+}
+
+void KWDocListViewItem::deleteAllChildren()
+{
+ if ( childCount() > 0 )
+ {
+ QListViewItem *child = firstChild();
+ QListViewItem *delChild;
+
+ while( child )
+ {
+ delChild = child;
+ child = child->nextSibling();
+ delete delChild;
+ }
+ }
+}
+
+KWDocument* KWDocListViewItem::doc()
+{
+ return dynamic_cast<KWDocStructTree *>(listView())->doc();
+}
+
+KWGUI* KWDocListViewItem::gui()
+{
+ return dynamic_cast<KWDocStructTree *>(listView())->gui();
+}
+
+
+/******************************************************************/
+/* Class: KWDocStructParagItem */
+/******************************************************************/
+
+KWDocStructParagItem::KWDocStructParagItem(QListViewItem* parent, const QString& text, KWTextParag* parag )
+ : KWDocListViewItem(parent, text), m_parag(parag)
+{
+}
+
+KWDocStructParagItem::KWDocStructParagItem(QListViewItem* parent, QListViewItem* after,
+ const QString& text, KWTextParag* parag )
+ : KWDocListViewItem(parent, after, text), m_parag(parag)
+{
+}
+
+void KWDocStructParagItem::contextMenu(QListViewItem* item, const QPoint& p, int )
+{
+ if (item == this)
+ {
+ KWTextFrameSet* fs = m_parag->kwTextDocument()->textFrameSet();
+ gui()->getView()->openDocStructurePopupMenu(p, fs, m_parag);
+ }
+}
+
+void KWDocStructParagItem::selectItem()
+{
+ KWTextFrameSet* fs = m_parag->kwTextDocument()->textFrameSet();
+ QPoint iPoint = m_parag->rect().topLeft(); // small bug if a paragraph is cut between two pages.
+ KoPoint dPoint;
+ fs->internalToDocument(iPoint, dPoint);
+ QPoint nPoint = fs->kWordDocument()->zoomPoint(dPoint);
+ gui()->canvasWidget()->scrollToOffset(fs->kWordDocument()->unzoomPoint(nPoint));
+
+}
+
+void KWDocStructParagItem::editItem()
+{
+ gui()->canvasWidget()->editTextFrameSet(m_parag->kwTextDocument()->textFrameSet(), m_parag, 0);
+}
+
+void KWDocStructParagItem::deleteItem()
+{
+ // TODO
+}
+
+void KWDocStructParagItem::editProperties()
+{
+ gui()->canvasWidget()->editTextFrameSet(m_parag->kwTextDocument()->textFrameSet(), m_parag, 0);
+ gui()->getView()->formatParagraph();
+}
+
+void KWDocStructParagItem::speakItem()
+{
+ QString text;
+ KoParagCounter* tmpCounter = m_parag->counter();
+ if (tmpCounter)
+ text = tmpCounter->text(m_parag) + " ";
+ text += m_parag->toString();
+ if (!text.isEmpty()) {
+ kospeaker->queueSpeech(text, m_parag->paragraphFormat()->language(), true);
+ kospeaker->startSpeech();
+ }
+}
+
+
+/******************************************************************/
+/* Class: KWDocStructTextFrameItem */
+/******************************************************************/
+
+KWDocStructTextFrameItem::KWDocStructTextFrameItem(QListViewItem* parent, const QString& text,
+ KWTextFrameSet* frameset, KWFrame* frame)
+ : KWDocListViewItem(parent, text), m_frame(frame), m_frameset(frameset)
+{
+}
+
+KWDocStructTextFrameItem::KWDocStructTextFrameItem(QListViewItem* parent, QListViewItem* after,
+ const QString& text, KWTextFrameSet* frameset, KWFrame* frame)
+ : KWDocListViewItem(parent, after, text), m_frame(frame), m_frameset(frameset)
+{
+}
+
+void KWDocStructTextFrameItem::setupTextParags()
+{
+ // Build a list of pointers to paragraphs.
+ QPtrList<KWTextParag> paragPtrs;
+ paragPtrs.setAutoDelete(false);
+ KoTextParag* textParag = 0;
+ KoTextParag* lastParag = 0;
+ int index = 0;
+ // Get upper left corner of the frame and get coordinates just inside it.
+ KoPoint dPoint = m_frame->topLeft() + KoPoint(2,2);
+ // Get the first paragraph of the frame.
+ m_frameset->findPosition(dPoint, textParag, index);
+ // Get lower right corner of the frame and get coordinate just inside it.
+ dPoint = m_frame->bottomRight() - KoPoint(2,2);
+ // Get the last paragraph of the frame.
+ m_frameset->findPosition(dPoint, lastParag, index);
+ if (lastParag) {
+ while (textParag) {
+ KWTextParag* parag = dynamic_cast<KWTextParag *>(textParag);
+ if (parag) {
+ // Don't display an empty paragraph.
+ QString text = parag->toString().stripWhiteSpace();
+ if ( text.length() > 0)
+ paragPtrs.append(parag);
+ }
+ if (textParag == lastParag)
+ textParag = 0;
+ else
+ textParag = textParag->next();
+ }
+ }
+
+ // Remove deleted paragraphs from the listview.
+ KWDocStructParagItem* item = dynamic_cast<KWDocStructParagItem *>(firstChild());
+ KWDocStructParagItem* delItem;
+ while (item) {
+ delItem = item;
+ item = dynamic_cast<KWDocStructParagItem *>(item->nextSibling());
+ if (paragPtrs.containsRef(delItem->parag()) == 0) delete delItem;
+ }
+
+ // Add new paragraphs to the list or update existing ones.
+ KWDocStructParagItem* after = 0;
+ for (uint j = 0; j < paragPtrs.count(); j++) {
+ KWTextParag* parag = paragPtrs.at(j);
+ QString text = parag->toString().stripWhiteSpace();
+ QString name = text.left(20);
+ KoParagCounter* tmpCounter = parag->counter();
+ if (tmpCounter)
+ name.prepend(tmpCounter->text(parag) + " ");
+ KWDocStructParagItem* child = findTextParagItem(parag);
+ if (child)
+ child->setText(0, name);
+ else {
+ if (after)
+ child = new KWDocStructParagItem(this, after, name, parag);
+ else
+ child = new KWDocStructParagItem(this, name, parag);
+ }
+ after = child;
+ }
+}
+
+void KWDocStructTextFrameItem::contextMenu(QListViewItem* item, const QPoint& p, int )
+{
+ if (item == this)
+ gui()->getView()->openDocStructurePopupMenu(p, m_frameset, 0);
+}
+
+void KWDocStructTextFrameItem::selectItem()
+{
+ gui()->canvasWidget()->scrollToOffset(m_frame->topLeft());
+}
+
+void KWDocStructTextFrameItem::editItem()
+{
+ KoTextParag* parag = 0L;
+ int index = 0;
+ // Get upperleft corner of the frame and get coordinates just inside it.
+ KoPoint dPoint = m_frame->topLeft() + KoPoint(2,2);
+ m_frameset->findPosition(dPoint, parag, index);
+ gui()->canvasWidget()->editTextFrameSet(m_frameset, parag, 0);
+}
+
+void KWDocStructTextFrameItem::deleteItem()
+{
+ gui()->getView()->deleteFrameSet(m_frameset);
+}
+
+void KWDocStructTextFrameItem::editProperties()
+{
+ gui()->canvasWidget()->editFrameProperties(m_frameset);
+}
+
+void KWDocStructTextFrameItem::speakItem()
+{
+ KoTextParag* textParag = 0;
+ KoTextParag* lastParag = 0;
+ int index = 0;
+ // Get upper left corner of the frame and get coordinates just inside it.
+ KoPoint dPoint = m_frame->topLeft() + KoPoint(2,2);
+ // Get the first paragraph of the frame.
+ m_frameset->findPosition(dPoint, textParag, index);
+ // Get lower right corner of the frame and get coordinate just inside it.
+ dPoint = m_frame->bottomRight() - KoPoint(2,2);
+ // Get the last paragraph of the frame.
+ m_frameset->findPosition(dPoint, lastParag, index);
+ bool first = true;
+ if (textParag && lastParag) {
+ while (textParag) {
+ KWTextParag* parag = dynamic_cast<KWTextParag *>(textParag);
+ if (parag) {
+ // Don't speak an empty paragraph.
+ QString text = parag->toString().stripWhiteSpace();
+ if ( text.length() > 0) {
+ kospeaker->queueSpeech(text, parag->paragraphFormat()->language(), first);
+ first = false;
+ }
+ }
+ if (textParag == lastParag)
+ textParag = 0;
+ else
+ textParag = textParag->next();
+ }
+ kospeaker->startSpeech();
+ }
+}
+
+KWDocStructParagItem* KWDocStructTextFrameItem::findTextParagItem(const KWTextParag* parag)
+{
+ if ( childCount() > 0 )
+ {
+ QListViewItem *child = firstChild();
+ while( child )
+ {
+ if (dynamic_cast<KWDocStructParagItem *>(child)->parag() == parag)
+ return dynamic_cast<KWDocStructParagItem *>(child);
+ child = child->nextSibling();
+ }
+ }
+ return 0;
+}
+
+
+/******************************************************************/
+/* Class: KWDocStructTextFrameSetItem */
+/******************************************************************/
+
+KWDocStructTextFrameSetItem::KWDocStructTextFrameSetItem(QListViewItem* parent, const QString& text,
+ KWTextFrameSet* frameset)
+ : KWDocListViewItem(parent, text ), m_frameset(frameset)
+{
+}
+
+KWDocStructTextFrameSetItem::KWDocStructTextFrameSetItem(QListViewItem* parent, QListViewItem* after,
+ const QString& text, KWTextFrameSet* frameset)
+ : KWDocListViewItem(parent, after, text), m_frameset(frameset)
+{
+}
+
+void KWDocStructTextFrameSetItem::setupTextFrames()
+{
+ // TODO: KWTextFrameSet::frame() method returns frames in screen order?
+ // Build a list of frame pointers.
+ QPtrList<KWFrame> framePtrs;
+ framePtrs.setAutoDelete(false);
+ for (uint j = 0; j < m_frameset->frameCount(); j++)
+ framePtrs.append(m_frameset->frame(j));
+
+ // Remove deleted frames from the listview.
+ KWDocStructTextFrameItem* item = dynamic_cast<KWDocStructTextFrameItem *>(firstChild());
+ KWDocStructTextFrameItem* delItem;
+ while (item) {
+ delItem = item;
+ item = dynamic_cast<KWDocStructTextFrameItem *>(item->nextSibling());
+ if (framePtrs.containsRef(delItem->frame()) == 0) delete delItem;
+ }
+
+ // Add new frames to the list or update existing ones.
+ KWDocument* dok = doc();
+ KWDocStructTextFrameItem* after = 0;
+ for (uint j = 0; j < framePtrs.count(); j++)
+ {
+ KWFrame* frame = framePtrs.at(j);
+ QString name;
+ if ( KListViewItem::parent()->firstChild() == this && dok->processingType() == KWDocument::WP )
+ {
+ if ( dok->numColumns() == 1 )
+ name=i18n( "Page %1" ).arg(QString::number(j + 1));
+ else
+ name=i18n( "Column %1" ).arg(QString::number(j + 1));
+ }
+ else
+ name=i18n( "Text Frame %1" ).arg(QString::number(j + 1));
+ KWDocStructTextFrameItem* child = findTextFrameItem(frame);
+ if (child)
+ child->setText(0, name);
+ else {
+ if (after)
+ child = new KWDocStructTextFrameItem(this, after, name, m_frameset, frame);
+ else
+ child = new KWDocStructTextFrameItem(this, name, m_frameset, frame);
+ }
+ child->setupTextParags();
+ after = child;
+ }
+}
+
+void KWDocStructTextFrameSetItem::contextMenu(QListViewItem* item, const QPoint& p, int )
+{
+ if (item == this)
+ gui()->getView()->openDocStructurePopupMenu(p, m_frameset, 0);
+}
+
+void KWDocStructTextFrameSetItem::selectItem()
+{
+ KWFrame* frame = m_frameset->frame(0);
+ if (!frame) return;
+ gui()->canvasWidget()->scrollToOffset(frame->topLeft());
+}
+
+void KWDocStructTextFrameSetItem::editItem()
+{
+ gui()->canvasWidget()->editTextFrameSet(m_frameset, 0L, 0);
+}
+
+void KWDocStructTextFrameSetItem::deleteItem()
+{
+ gui()->getView()->deleteFrameSet(m_frameset);
+}
+
+void KWDocStructTextFrameSetItem::editProperties()
+{
+ gui()->canvasWidget()->editFrameProperties(m_frameset);
+}
+
+void KWDocStructTextFrameSetItem::speakItem()
+{
+ KoTextParag* parag = m_frameset->textDocument()->firstParag();
+ kospeaker->queueSpeech(parag->toString(), parag->paragraphFormat()->language(), true);
+ parag = parag->next();
+ for ( ; parag ; parag = parag->next() )
+ kospeaker->queueSpeech(parag->toString(), parag->paragraphFormat()->language(), false);
+ kospeaker->startSpeech();
+}
+
+KWDocStructTextFrameItem* KWDocStructTextFrameSetItem::findTextFrameItem(const KWFrame* frame)
+{
+ if ( childCount() > 0 )
+ {
+ QListViewItem *child = firstChild();
+ while( child )
+ {
+ if (dynamic_cast<KWDocStructTextFrameItem *>(child)->frame() == frame)
+ return dynamic_cast<KWDocStructTextFrameItem *>(child);
+ child = child->nextSibling();
+ }
+ }
+ return 0;
+}
+
+
+/******************************************************************/
+/* Class: KWDocStructTableItem */
+/******************************************************************/
+
+KWDocStructTableItem::KWDocStructTableItem(QListViewItem* parent, const QString& text,
+ KWTableFrameSet* table)
+ :KWDocListViewItem(parent, text), m_table(table)
+{
+}
+
+KWDocStructTableItem::KWDocStructTableItem(QListViewItem* parent, QListViewItem* after,
+ const QString& text, KWTableFrameSet* table)
+ :KWDocListViewItem(parent, after, text), m_table(table)
+{
+}
+
+void KWDocStructTableItem::setupCells()
+{
+ // TODO: KWTableFrameSet::cell() method returns cells in screen order?
+ // Build a list of cell pointers.
+ QPtrList<KWTextFrameSet> cellPtrs;
+ cellPtrs.setAutoDelete(false);
+ for (uint row = 0; row < m_table->getRows(); ++row)
+ for (uint col = 0; col < m_table->getColumns(); ++ col) {
+ KWTextFrameSet* cell = m_table->cell(row, col);
+ if (cell)
+ cellPtrs.append(cell);
+ }
+
+ // Remove deleted cells from the listview.
+ KWDocStructTextFrameItem* item = dynamic_cast<KWDocStructTextFrameItem *>(firstChild());
+ KWDocStructTextFrameItem* delItem;
+ while (item) {
+ delItem = item;
+ item = dynamic_cast<KWDocStructTextFrameItem *>(item->nextSibling());
+ if (cellPtrs.containsRef(delItem->frameSet()) == 0) delete delItem;
+ }
+
+ // Add new cells to the list or update existing ones.
+ // Note we skip over the frameset and add the frame instead,
+ // as every cell has exactly one frame in the frameset.
+ KWDocStructTextFrameItem* child;
+ KWDocStructTextFrameItem* after = 0;
+ for (uint j = 0; j < cellPtrs.count(); j++)
+ {
+ KWTextFrameSet* cell = cellPtrs.at(j);
+ KWFrame* frame = cell->frame(0);
+ if (frame) {
+ QString name = cell->name();
+ child = findCellItem(cell);
+ if (child)
+ child->setText(0, name);
+ else {
+ if (after)
+ child = new KWDocStructTextFrameItem(this, after, name, cell, frame);
+ else
+ child = new KWDocStructTextFrameItem(this, name, cell, frame);
+ }
+ child->setupTextParags();
+ after = child;
+ }
+ }
+}
+
+void KWDocStructTableItem::contextMenu(QListViewItem* item, const QPoint& p, int )
+{
+ if (item == this)
+ gui()->getView()->openDocStructurePopupMenu(p, m_table, 0);
+}
+
+void KWDocStructTableItem::selectItem()
+{
+ KWFrame* frame = m_table->cell( 0, 0 )->frame( 0 );
+ gui()->canvasWidget()->scrollToOffset(frame->topLeft());
+}
+
+void KWDocStructTableItem::editItem()
+{
+ //activate the first cell
+ gui()->canvasWidget()->editTextFrameSet(m_table->cell(0,0), 0L, 0);
+}
+
+void KWDocStructTableItem::deleteItem()
+{
+ // TODO: The following statement isn't working for some reason.
+ gui()->getView()->deselectAllFrames();
+ gui()->getView()->deleteFrameSet(m_table);
+}
+
+void KWDocStructTableItem::editProperties()
+{
+ gui()->canvasWidget()->editFrameProperties(m_table);
+}
+
+void KWDocStructTableItem::speakItem()
+{
+ bool first = true;
+ for (uint row = 0; row < m_table->getRows(); ++row) {
+ for (uint col = 0; col < m_table->getColumns(); ++ col) {
+ KoTextParag* parag = m_table->cell(row, col)->textDocument()->firstParag();
+ kospeaker->queueSpeech(parag->toString(), parag->paragraphFormat()->language(), first);
+ first = false;
+ parag = parag->next();
+ for ( ; parag ; parag = parag->next() )
+ kospeaker->queueSpeech(parag->toString(), parag->paragraphFormat()->language(), false);
+ }
+ }
+ kospeaker->startSpeech();
+}
+
+KWDocStructTextFrameItem* KWDocStructTableItem::findCellItem(const KWTextFrameSet* cell)
+{
+ if ( childCount() > 0 )
+ {
+ QListViewItem *child = firstChild();
+ while( child )
+ {
+ if (dynamic_cast<KWDocStructTextFrameItem *>(child)->frameSet() == cell)
+ return dynamic_cast<KWDocStructTextFrameItem *>(child);
+ child = child->nextSibling();
+ }
+ }
+ return 0;
+}
+
+
+/******************************************************************/
+/* Class: KWDocStructPictureItem */
+/******************************************************************/
+
+KWDocStructPictureItem::KWDocStructPictureItem(QListViewItem* parent, const QString& text,
+ KWPictureFrameSet* pic)
+ : KWDocListViewItem(parent, text), m_pic(pic)
+{
+}
+
+void KWDocStructPictureItem::contextMenu(QListViewItem* item, const QPoint& p, int )
+{
+ if (item == this)
+ gui()->getView()->openDocStructurePopupMenu(p, m_pic, 0);
+}
+
+
+void KWDocStructPictureItem::selectItem()
+{
+ KWFrame *frame = m_pic->frame(0);
+ gui()->canvasWidget()->scrollToOffset(frame->topLeft() );
+
+}
+
+void KWDocStructPictureItem::editItem()
+{
+ // Pictures cannot be edited. Edit Properties instead.
+ editProperties();
+}
+
+void KWDocStructPictureItem::deleteItem()
+{
+ gui()->getView()->deleteFrameSet(m_pic);
+}
+
+void KWDocStructPictureItem::editProperties()
+{
+ gui()->canvasWidget()->editFrameProperties(m_pic);
+}
+
+/******************************************************************/
+/* Class: KWDocStructFormulaItem */
+/******************************************************************/
+
+KWDocStructFormulaItem::KWDocStructFormulaItem(QListViewItem* parent, const QString& text,
+ KWFormulaFrameSet* form)
+ : KWDocListViewItem(parent, text), m_form(form)
+{
+}
+
+void KWDocStructFormulaItem::contextMenu(QListViewItem* item, const QPoint& p, int )
+{
+ if (item == this)
+ gui()->getView()->openDocStructurePopupMenu(p, m_form, 0);
+}
+
+void KWDocStructFormulaItem::selectItem()
+{
+ KWFrame* frame = m_form->frame( 0 );
+ gui()->canvasWidget()->scrollToOffset(frame->topLeft());
+}
+
+void KWDocStructFormulaItem::editItem()
+{
+ // TODO: Formula has to be selected first to bring it into view. Bug?
+ selectItem();
+ gui()->canvasWidget()->editFrameSet(m_form);
+
+}
+
+void KWDocStructFormulaItem::deleteItem()
+{
+ gui()->getView()->deleteFrameSet(m_form);
+}
+
+void KWDocStructFormulaItem::editProperties()
+{
+ gui()->canvasWidget()->editFrameProperties(m_form);
+}
+
+void KWDocStructFormulaItem::speakItem()
+{
+ // TODO
+}
+
+
+/******************************************************************/
+/* Class: KWDocStructPartItem */
+/******************************************************************/
+
+KWDocStructPartItem::KWDocStructPartItem(QListViewItem* parent, const QString& text,
+ KWPartFrameSet* part)
+ : KWDocListViewItem(parent, text), m_part(part)
+{
+}
+
+void KWDocStructPartItem::contextMenu(QListViewItem* item, const QPoint& p, int )
+{
+ if (item == this)
+ gui()->getView()->openDocStructurePopupMenu(p, m_part, 0);
+}
+
+
+void KWDocStructPartItem::selectItem()
+{
+ KWFrame* frame = m_part->frame(0);
+ gui()->canvasWidget()->scrollToOffset(frame->topLeft());
+}
+
+void KWDocStructPartItem::editItem()
+{
+ // TODO:
+ // part->startEditing();
+ editProperties();
+}
+
+void KWDocStructPartItem::deleteItem()
+{
+ gui()->getView()->deleteFrameSet(m_part);
+}
+
+void KWDocStructPartItem::editProperties()
+{
+ gui()->canvasWidget()->editFrameProperties(m_part);
+}
+
+/******************************************************************/
+/* Class: KWDocStructRootItem */
+/******************************************************************/
+
+KWDocStructRootItem::KWDocStructRootItem(QListView* parent, const QString& text,
+ TypeStructDocItem type )
+ : KWDocListViewItem(parent, text), m_type(type)
+{
+ switch ( type ) {
+ case Arrangement: {
+ setPixmap( 0, KGlobal::iconLoader()->loadIcon( "tree_arrange", KIcon::Small ) );
+ } break;
+ case TextFrames: {
+ setPixmap( 0, KGlobal::iconLoader()->loadIcon( "frame_text", KIcon::Small ) );
+ } break;
+ case FormulaFrames: {
+ setPixmap( 0, KGlobal::iconLoader()->loadIcon( "frame_formula", KIcon::Small ) );
+ }break;
+ case Tables: {
+ setPixmap( 0, KGlobal::iconLoader()->loadIcon( "inline_table", KIcon::Small ) );
+ } break;
+ case Pictures: {
+ setPixmap( 0, KGlobal::iconLoader()->loadIcon( "frame_image", KIcon::Small ) );
+ } break;
+ case Embedded: {
+ setPixmap( 0, KGlobal::iconLoader()->loadIcon( "frame_query", KIcon::Small ) );
+ } break;
+ }
+}
+
+void KWDocStructRootItem::setOpen(bool o)
+{
+ if ( o )
+ {
+ switch (m_type)
+ {
+ case Arrangement:
+ setupArrangement();
+ break;
+ case TextFrames:
+ setupTextFrameSets();
+ break;
+ case FormulaFrames:
+ setupFormulaFrames();
+ break;
+ case Tables:
+ setupTables();
+ break;
+ case Pictures:
+ setupPictures();
+ break;
+ case Embedded:
+ setupEmbedded();
+ break;
+ }
+ }
+ QListViewItem::setOpen(o);
+}
+
+void KWDocStructRootItem::setupArrangement()
+{
+ deleteAllChildren();
+
+ QIntDict<KWDocStructParagItem> parags;
+ parags.setAutoDelete( false );
+
+ KWFrameSet* frameset = 0L;
+ KWTextParag* parag = 0L;
+ KoTextDocument* textdoc = 0L;
+
+ KWDocument* dok = doc();
+ KWDocStructTextFrameSetItem *item = 0L;
+ QString _name;
+
+ for ( int i = dok->frameSetCount() - 1; i >= 0; i-- )
+ {
+ frameset = dok->frameSet( i );
+ if ( frameset->type() == FT_TEXT && frameset->frameSetInfo() == KWFrameSet::FI_BODY && !frameset->groupmanager() && frameset->frameCount()>0)
+ {
+ KWTextFrameSet *tmpParag = dynamic_cast<KWTextFrameSet*> (frameset) ;
+ item = new KWDocStructTextFrameSetItem( this, frameset->name(), tmpParag);
+ textdoc= tmpParag->textDocument();
+ parag = static_cast<KWTextParag *>(textdoc->firstParag());
+ while ( parag )
+ {
+ KoParagCounter *tmpCounter = parag->counter();
+ if (tmpCounter !=0 && (tmpCounter->style() != KoParagCounter::STYLE_NONE) && (tmpCounter->numbering() == KoParagCounter::NUM_CHAPTER) )
+ {
+ int _depth = tmpCounter->depth();
+ if ( _depth == 0 )
+ {
+ if ( item->childCount() == 0 )
+ parags.replace( _depth, new KWDocStructParagItem( item,QString( tmpCounter->text(parag) + " " +parag->string()->toString().mid( 0, parag->string()->length() ) ),parag) );
+ else
+ parags.replace( _depth, new KWDocStructParagItem( item, parags[ _depth ],QString( tmpCounter->text(parag) + " " +parag->string()->toString().mid( 0, parag->string()->length() ) ),parag) );
+ }
+ else
+ {
+ if (parags[ _depth - 1 ]==0)
+ parags.replace( _depth, new KWDocStructParagItem( item,QString( tmpCounter->text(parag) + " " +parag->string()->toString().mid( 0, parag->string()->length() ) ), parag) );
+ else if ( parags[ _depth - 1 ]->childCount() == 0 )
+ parags.replace( _depth, new KWDocStructParagItem( parags[ _depth - 1 ],QString( tmpCounter->text(parag) + " " +parag->string()->toString().mid( 0, parag->string()->length() ) ), parag) );
+ else
+ parags.replace( _depth, new KWDocStructParagItem( parags[ _depth - 1 ], parags[ _depth ],QString( tmpCounter->text(parag) + " " +parag->string()->toString().mid( 0, parag->string()->length() ) ), parag) );
+ }
+ }
+ parag = static_cast<KWTextParag *>(parag->next());
+ }
+ }
+ }
+
+ if ( childCount() == 0 )
+ ( void )new KListViewItem( this, i18n( "Empty" ) );
+
+}
+
+void KWDocStructRootItem::setupTextFrameSets()
+{
+
+ // Delete Empty item from list.
+ QListViewItem* lvItem = firstChild();
+ if (lvItem && (lvItem->text(0) == i18n("Empty"))) delete lvItem;
+
+ // Build a list of framesets ordered by their screen position (top left corner).
+ KWDocument* dok = doc();
+ QValueList<KWOrderedFrameSet> orderedFrameSets;
+ for ( int i = dok->frameSetCount() - 1; i >= 0; i-- ) {
+ KWFrameSet* frameset = dok->frameSet(i);
+ if ( frameset->type() == FT_TEXT && frameset->frameSetInfo() == KWFrameSet::FI_BODY &&
+ !frameset->groupmanager() && frameset->frameCount()>0)
+
+ orderedFrameSets.append(KWOrderedFrameSet(frameset));
+ }
+ qHeapSort(orderedFrameSets);
+
+ // Build a list of frameset pointers from the sorted list.
+ QPtrList<KWTextFrameSet> frameSetPtrs;
+ frameSetPtrs.setAutoDelete(false);
+ for ( uint i = 0; i < orderedFrameSets.count(); i++ )
+ frameSetPtrs.append(dynamic_cast<KWTextFrameSet *>(orderedFrameSets[i].frameSet()));
+
+ // Remove deleted framesets from the listview.
+ KWDocStructTextFrameSetItem* item = dynamic_cast<KWDocStructTextFrameSetItem *>(firstChild());
+ KWDocStructTextFrameSetItem* delItem;
+ while (item) {
+ delItem = item;
+ item = dynamic_cast<KWDocStructTextFrameSetItem *>(item->nextSibling());
+ if (frameSetPtrs.containsRef(delItem->frameSet()) == 0) delete delItem;
+ }
+
+ // Add new framesets to the list or update existing ones.
+ KWDocStructTextFrameSetItem* after = 0L;
+ for ( uint i = 0; i < orderedFrameSets.count(); i++ )
+ {
+ KWTextFrameSet* textFrameset = dynamic_cast<KWTextFrameSet *>(orderedFrameSets[i].frameSet());
+ item = findTextFrameSetItem(textFrameset);
+ if (item)
+ item->setText(0, textFrameset->name());
+ else {
+ if (after)
+ item = new KWDocStructTextFrameSetItem(
+ this, after, textFrameset->name(), textFrameset);
+ else
+ item = new KWDocStructTextFrameSetItem(this, textFrameset->name(), textFrameset);
+ }
+ after = item;
+ item->setupTextFrames();
+ }
+
+ if ( childCount() == 0 )
+ ( void )new KListViewItem( this, i18n( "Empty" ) );
+}
+
+void KWDocStructRootItem::setupFormulaFrames()
+{
+ deleteAllChildren();
+
+ KWFrameSet* frameset = 0L;
+ QString _name;
+ KWDocStructFormulaItem* child;
+ KWDocument* dok = doc();
+
+ for ( int i = dok->frameSetCount() - 1; i >= 0; i-- )
+ {
+ frameset = dok->frameSet( i );
+ if ( frameset->type() == FT_FORMULA &&
+ frameset->frameCount()>0 )
+ {
+ _name=i18n("Formula Frame %1").arg(QString::number(i+1));
+ child = new KWDocStructFormulaItem(this, _name, dynamic_cast<KWFormulaFrameSet*>( frameset ));
+ }
+ }
+
+ if ( childCount() == 0 )
+ ( void )new KListViewItem( this, i18n( "Empty" ) );
+}
+
+void KWDocStructRootItem::setupTables()
+{
+ // Delete Empty item from list.
+ QListViewItem* lvItem = firstChild();
+ if (lvItem && (lvItem->text(0) == i18n("Empty"))) delete lvItem;
+
+ // Build a list of framesets ordered by their screen position (top left corner).
+ KWDocument* dok = doc();
+ QValueList<KWOrderedFrameSet> orderedFrameSets;
+ for ( int i = dok->frameSetCount() - 1; i >= 0; i-- ) {
+ KWFrameSet* frameset = dok->frameSet(i);
+ if ( frameset->type() == FT_TABLE)
+ orderedFrameSets.append(KWOrderedFrameSet(frameset));
+ }
+ qHeapSort(orderedFrameSets);
+
+ // Build a list of table pointers from the sorted list.
+ QPtrList<KWTableFrameSet> frameSetPtrs;
+ frameSetPtrs.setAutoDelete(false);
+ for ( uint i = 0; i < orderedFrameSets.count(); i++ )
+ frameSetPtrs.append(dynamic_cast<KWTableFrameSet *>(orderedFrameSets[i].frameSet()));
+
+ // Remove deleted tables from the listview.
+ KWDocStructTableItem* item = dynamic_cast<KWDocStructTableItem *>(firstChild());
+ KWDocStructTableItem* delItem;
+ while (item) {
+ delItem = item;
+ item = dynamic_cast<KWDocStructTableItem *>(item->nextSibling());
+ if (frameSetPtrs.containsRef(delItem->table()) == 0) delete delItem;
+ }
+
+ // Add new framesets to the list or update existing ones.
+ KWDocStructTableItem* after = 0L;
+ for ( uint i = 0; i < orderedFrameSets.count(); i++ )
+ {
+ KWTableFrameSet* tableFrameset = dynamic_cast<KWTableFrameSet *>(orderedFrameSets[i].frameSet());
+ item = findTableItem(tableFrameset);
+ if (item)
+ item->setText(0, tableFrameset->name());
+ else {
+ if (after)
+ item = new KWDocStructTableItem(
+ this, after, tableFrameset->name(), tableFrameset);
+ else
+ item = new KWDocStructTableItem(this, tableFrameset->name(), tableFrameset);
+ }
+ after = item;
+ item->setupCells();
+ }
+
+ if ( childCount() == 0 )
+ ( void )new KListViewItem( this, i18n( "Empty" ) );
+}
+
+void KWDocStructRootItem::setupPictures()
+{
+ deleteAllChildren();
+
+ KWFrameSet* frameset = 0L;
+ QString _name;
+ KWDocStructPictureItem* child;
+ KWDocument* dok = doc();
+
+ int j = 0;
+ for ( int i = dok->frameSetCount() - 1; i >= 0; i-- )
+ {
+ frameset = dok->frameSet( i );
+ if ( frameset->type() == FT_PICTURE && frameset->frameCount()>0)
+ {
+ _name=i18n("Picture (%1) %2").arg(dynamic_cast<KWPictureFrameSet*>( frameset )->key().filename()).arg(++j);
+ child = new KWDocStructPictureItem(this, _name, dynamic_cast<KWPictureFrameSet*>( frameset ));
+ }
+ }
+
+ if ( childCount() == 0 )
+ ( void )new KListViewItem( this, i18n( "Empty" ) );
+}
+
+void KWDocStructRootItem::setupEmbedded()
+{
+ deleteAllChildren();
+
+ KWFrameSet* frameset = 0L;
+ QString _name;
+ KWDocStructPartItem* child;
+ KWDocument* dok = doc();
+
+ for ( int i = dok->frameSetCount() - 1; i >= 0; i-- )
+ {
+ frameset = dok->frameSet( i );
+ if ( frameset->type() == FT_PART && frameset->frameCount()>0)
+ {
+ // Use the name of the frameset as the entry for the object.
+ _name=frameset->name();
+ child = new KWDocStructPartItem(this, _name, dynamic_cast<KWPartFrameSet*>( frameset ));
+ }
+ }
+
+ if ( childCount() == 0 )
+ ( void )new KListViewItem( this, i18n( "Empty" ) );
+}
+
+KWDocStructTextFrameSetItem* KWDocStructRootItem::findTextFrameSetItem(const KWFrameSet* frameset)
+{
+ if ( childCount() > 0 )
+ {
+ QListViewItem *child = firstChild();
+ while( child )
+ {
+ if (dynamic_cast<KWDocStructTextFrameSetItem *>(child)->frameSet() == frameset)
+ return dynamic_cast<KWDocStructTextFrameSetItem *>(child);
+ child = child->nextSibling();
+ }
+ }
+ return 0;
+}
+
+KWDocStructTableItem* KWDocStructRootItem::findTableItem(const KWFrameSet* frameset)
+{
+ if ( childCount() > 0 )
+ {
+ QListViewItem *child = firstChild();
+ while( child )
+ {
+ if (dynamic_cast<KWDocStructTableItem *>(child)->table() == frameset)
+ return dynamic_cast<KWDocStructTableItem *>(child);
+ child = child->nextSibling();
+ }
+ }
+ return 0;
+}
+
+
+
+/******************************************************************/
+/* Class: KWDocStructTree */
+/******************************************************************/
+
+KWDocStructTree::KWDocStructTree(QWidget* parent, KWDocument* doc, KWGUI* gui)
+ : KListView(parent), m_doc(doc), m_gui(gui)
+{
+ embedded = new KWDocStructRootItem( this, i18n( "Embedded Objects" ), Embedded);
+ formulafrms = new KWDocStructRootItem( this, i18n( "Formula Frames" ), FormulaFrames);
+ tables = new KWDocStructRootItem( this, i18n( "Tables" ), Tables);
+ pictures = new KWDocStructRootItem( this, i18n( "Pictures" ), Pictures);
+ textfrms = new KWDocStructRootItem( this, i18n( "Text Frames/Frame Sets" ), TextFrames);
+ // arrangement = new KWDocStructRootItem( this, i18n( "Arrangement" ), Arrangement);
+
+ addColumn( i18n( "Document Structure" ) );
+ setFullWidth( true );
+
+ connect( this, SIGNAL( doubleClicked(QListViewItem*) ),
+ this, SLOT( slotDoubleClicked(QListViewItem*)) );
+ connect( this, SIGNAL( returnPressed(QListViewItem*) ),
+ this, SLOT( slotReturnPressed(QListViewItem* )) );
+ connect( this, SIGNAL(rightButtonClicked(QListViewItem*, const QPoint&,int)),
+ this, SLOT( slotRightButtonClicked(QListViewItem *, const QPoint&, int)));
+ connect( this, SIGNAL(contextMenu(KListView*, QListViewItem*, const QPoint&)),
+ this, SLOT(slotContextMenu(KListView*, QListViewItem*, const QPoint&)) );
+}
+
+KWDocStructTree::~KWDocStructTree()
+{
+ delete embedded;
+ delete formulafrms;
+ delete tables;
+ delete pictures;
+ delete textfrms;
+ // delete arrangement;
+}
+
+void KWDocStructTree::setup()
+{
+ setRootIsDecorated( true );
+ setSorting( -1 );
+ refreshTree((int)(TextFrames | FormulaFrames | Tables | Pictures | Embedded));
+}
+
+void KWDocStructTree::refreshTree(int type)
+{
+ // TODO: Saving current position by listview item text doesn't work if an item is renamed.
+ QString curItemText;
+ if (currentItem()) curItemText = currentItem()->text(0);
+ // if(((int)Arrangement) & type)
+ // arrangement->setupArrangement();
+ if(((int)TextFrames) & type)
+ textfrms->setupTextFrameSets();
+ if(((int)FormulaFrames) & type)
+ formulafrms->setupFormulaFrames();
+ if(((int)Tables) & type)
+ tables->setupTables();
+ if(((int)Pictures) & type)
+ pictures->setupPictures();
+ if(((int)Embedded) & type)
+ embedded->setupEmbedded();
+ if (!curItemText.isEmpty()) {
+ QListViewItem* item = findItem(curItemText, 0);
+ if (item) setCurrentItem(item);
+ }
+}
+
+void KWDocStructTree::selectItem()
+{
+ QListViewItem* select = currentItem ();
+ KWDocListViewItem* tmp = dynamic_cast<KWDocListViewItem *>(select);
+ if ( tmp )
+ tmp->selectItem();
+}
+
+void KWDocStructTree::editItem()
+{
+ QListViewItem* select = currentItem();
+ KWDocListViewItem* tmp = dynamic_cast<KWDocListViewItem *>(select);
+ if ( tmp )
+ tmp->editItem();
+}
+
+
+void KWDocStructTree::deleteItem()
+{
+ QListViewItem* select = currentItem();
+ KWDocListViewItem *tmp = dynamic_cast<KWDocListViewItem *>(select);
+ if ( tmp )
+ tmp->deleteItem();
+}
+
+void KWDocStructTree::editProperties()
+{
+ QListViewItem* select = currentItem();
+ KWDocListViewItem* tmp = dynamic_cast<KWDocListViewItem *>(select);
+ if ( tmp )
+ tmp->editProperties();
+}
+
+void KWDocStructTree::speakItem()
+{
+ QListViewItem* select = currentItem();
+ KWDocListViewItem* tmp = dynamic_cast<KWDocListViewItem *>(select);
+ if ( tmp )
+ tmp->speakItem();
+}
+
+void KWDocStructTree::slotContextMenu(KListView* lv, QListViewItem* i, const QPoint& p)
+{
+ if (lv != this)
+ return;
+ KWDocListViewItem *item = dynamic_cast<KWDocListViewItem *>(i);
+ if (item)
+ item->contextMenu(item, p, 0);
+}
+
+void KWDocStructTree::slotRightButtonClicked(QListViewItem* i, const QPoint& p, int)
+{
+ KWDocListViewItem* item = dynamic_cast<KWDocListViewItem *>(i);
+ if (item)
+ item->contextMenu(item, p, 0);
+}
+
+void KWDocStructTree::slotDoubleClicked(QListViewItem* i)
+{
+ KWDocListViewItem* item = dynamic_cast<KWDocListViewItem *>(i);
+ if (item)
+ item->selectItem();
+}
+
+void KWDocStructTree::slotReturnPressed(QListViewItem* i)
+{
+ KWDocListViewItem* item = dynamic_cast<KWDocListViewItem *>(i);
+ if (item) {
+ item->editItem();
+ //return focus to canvas.
+ m_gui->canvasWidget()->setFocus();
+ }
+}
+
+
+/******************************************************************/
+/* Class: KWDocStruct */
+/******************************************************************/
+
+KWDocStruct::KWDocStruct(QWidget* parent, KWDocument* doc, KWGUI* gui)
+ : QWidget(parent), m_doc(doc), m_gui(gui)
+{
+ m_layout = new QVBoxLayout( this );
+
+ KToolBar* searchBar = new KToolBar( this );
+ searchBar->setFlat( true );
+ searchBar->setMovingEnabled( false );
+
+ KToolBarButton* eraseButton = new KToolBarButton( "locationbar_erase", 0, searchBar );
+ m_tree = new KWDocStructTree( this, doc, gui );
+ m_tree->setAlternateBackground( KGlobalSettings::alternateBackgroundColor() );
+ KListViewSearchLine* searchLine = new KListViewSearchLine( searchBar, m_tree );
+ searchBar->setStretchableWidget( searchLine );
+ connect( eraseButton, SIGNAL( clicked() ), searchLine, SLOT( clear() ) );
+
+ m_layout->addWidget(searchBar);
+ m_layout->addWidget(m_tree);
+ m_tree->setup();
+ dirtyTreeTypes = 0;
+}
+
+void KWDocStruct::paintEvent (QPaintEvent* ev)
+{
+ if (dirtyTreeTypes) {
+ m_tree->refreshTree(dirtyTreeTypes);
+ dirtyTreeTypes = 0;
+ }
+ QWidget::paintEvent(ev);
+}
+
+void KWDocStruct::refreshTree(int type)
+{
+ if ((dirtyTreeTypes | type) != dirtyTreeTypes) {
+ dirtyTreeTypes |= type;
+ update();
+ }
+}
+
+void KWDocStruct::refreshEntireTree()
+{
+ refreshTree((int)(TextFrames | FormulaFrames | Tables | Pictures | Embedded));
+}
+
+void KWDocStruct::setFocusHere()
+{
+ if (m_tree)
+ if (m_tree->isVisible()) m_tree->setFocus();
+}
+
+void KWDocStruct::selectItem()
+{
+ m_tree->selectItem();
+}
+
+void KWDocStruct::editItem()
+{
+ m_tree->editItem();
+}
+
+void KWDocStruct::deleteItem()
+{
+ m_tree->deleteItem();
+}
+
+void KWDocStruct::editProperties()
+{
+ m_tree->editProperties();
+}
+
+void KWDocStruct::speakItem()
+{
+ m_tree->speakItem();
+}
diff --git a/kword/KWDocStruct.h b/kword/KWDocStruct.h
new file mode 100644
index 00000000..fdf4d92f
--- /dev/null
+++ b/kword/KWDocStruct.h
@@ -0,0 +1,353 @@
+/* This file is part of the KDE project
+ Copyright (C) 1998, 1999 Reginald Stadlbauer <reggie@kde.org>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+*/
+
+#ifndef docstruct_h
+#define docstruct_h
+
+#include <klistview.h>
+#include <qwidget.h>
+
+class KWDocument;
+class KWFormulaFrameSet;
+class KWPictureFrameSet;
+class KWPartFrameSet;
+class KWGUI;
+class QWidget;
+class QVBoxLayout;
+class KWFrame;
+class KWFrameSet;
+class KWTextParag;
+
+/******************************************************************/
+/* Class: KWOrderedFrameSet */
+/******************************************************************/
+
+/** Provides a way to sort framesets using a QValueList based on their top left corner. */
+class KWOrderedFrameSet
+{
+public:
+ KWOrderedFrameSet(KWFrameSet* fs);
+ KWOrderedFrameSet(); // default constructor
+ bool operator<( KWOrderedFrameSet ofs);
+ KWFrameSet* frameSet() { return m_frameset; }
+
+private:
+ KWFrameSet* m_frameset;
+};
+
+class KWDocListViewItem : public KListViewItem
+{
+public:
+ enum ItemType {
+ IT_BASE = FT_BASE,
+ IT_TEXT = FT_TEXT,
+ IT_PICTURE = FT_PICTURE,
+ IT_PART = FT_PART,
+ IT_FORMULA = FT_FORMULA,
+ IT_CLIPART = FT_CLIPART,
+ IT_TABLE = FT_TABLE,
+ IT_ROOT = 11,
+ IT_TEXTFRAME = 12,
+ IT_PARAG = 13
+ };
+
+ KWDocListViewItem(QListViewItem *_parent, const QString &_text);
+ KWDocListViewItem(QListViewItem *_parent, QListViewItem *_after, const QString &_text);
+ KWDocListViewItem(QListView *_parent, const QString &_text);
+ virtual ItemType itemType() { return IT_BASE; }
+ virtual void selectItem() {}
+ virtual void editItem() {}
+ virtual void deleteItem() {}
+ virtual void editProperties() {}
+ virtual void speakItem() {}
+ virtual void contextMenu(QListViewItem *, const QPoint &, int) {}
+
+protected:
+ KWDocument* doc();
+ KWGUI* gui();
+ void deleteAllChildren();
+};
+
+/******************************************************************/
+/* Class: KWDocStructParagItem */
+/******************************************************************/
+
+class KWDocStructParagItem : public KWDocListViewItem
+{
+public:
+ KWDocStructParagItem(QListViewItem* parent, const QString& text, KWTextParag* parag);
+ KWDocStructParagItem(QListViewItem* parent, QListViewItem* after, const QString& text, KWTextParag* parag);
+ virtual ItemType itemType() { return IT_PARAG; }
+ virtual void selectItem();
+ virtual void editItem();
+ virtual void deleteItem();
+ virtual void editProperties();
+ virtual void speakItem();
+ virtual void contextMenu(QListViewItem* item, const QPoint& p, int);
+
+ KWTextParag* parag() const { return m_parag; }
+
+protected:
+ KWTextParag* m_parag;
+};
+
+/******************************************************************/
+/* Class: KWDocStructTextFrameItem */
+/******************************************************************/
+
+class KWDocStructTextFrameItem : public KWDocListViewItem
+{
+public:
+ KWDocStructTextFrameItem(QListViewItem* parent, const QString& text,
+ KWTextFrameSet* frameset, KWFrame* frame );
+ KWDocStructTextFrameItem(QListViewItem* parent, QListViewItem* after, const QString& text,
+ KWTextFrameSet* frameset, KWFrame* frame );
+ virtual int ItemType() { return IT_TEXTFRAME; }
+ virtual void selectItem();
+ virtual void editItem();
+ virtual void deleteItem();
+ virtual void editProperties();
+ virtual void speakItem();
+ virtual void contextMenu(QListViewItem* item, const QPoint& p, int);
+
+ KWFrame* frame() const { return m_frame; }
+ KWTextFrameSet* frameSet() const { return m_frameset; };
+ void setupTextParags();
+ KWDocStructParagItem* findTextParagItem(const KWTextParag* parag);
+
+protected:
+ KWFrame* m_frame;
+ KWTextFrameSet* m_frameset;
+};
+
+
+/******************************************************************/
+/* Class: KWDocStructTextFrameSetItem */
+/******************************************************************/
+
+class KWDocStructTextFrameSetItem : public KWDocListViewItem
+{
+public:
+ KWDocStructTextFrameSetItem(QListViewItem* parent, const QString& text, KWTextFrameSet* frameset);
+ KWDocStructTextFrameSetItem(QListViewItem* parent, QListViewItem* after, const QString& text,
+ KWTextFrameSet* frameset );
+ virtual int ItemType() { return IT_TEXT; }
+ virtual void selectItem();
+ virtual void editItem();
+ virtual void deleteItem();
+ virtual void editProperties();
+ virtual void speakItem();
+ virtual void contextMenu(QListViewItem* item, const QPoint& p, int);
+
+ KWTextFrameSet* frameSet() const { return m_frameset; };
+ void setupTextFrames();
+ KWDocStructTextFrameItem* findTextFrameItem(const KWFrame* frame);
+
+protected:
+ KWTextFrameSet* m_frameset;
+
+};
+
+/******************************************************************/
+/* Class: KWDocStructTableItem */
+/******************************************************************/
+
+class KWDocStructTableItem : public KWDocListViewItem
+{
+public:
+ KWDocStructTableItem(QListViewItem* parent, const QString& text, KWTableFrameSet* table );
+ KWDocStructTableItem(QListViewItem* parent, QListViewItem* after, const QString& text,
+ KWTableFrameSet* table );
+ virtual int ItemType() { return IT_TABLE; }
+ virtual void selectItem();
+ virtual void editItem();
+ virtual void deleteItem();
+ virtual void editProperties();
+ virtual void speakItem();
+ virtual void contextMenu(QListViewItem* item, const QPoint& p, int);
+
+ KWTableFrameSet* table() const { return m_table; };
+ void setupCells();
+ KWDocStructTextFrameItem* findCellItem(const KWTextFrameSet* cell);
+
+protected:
+ KWTableFrameSet* m_table;
+};
+
+/******************************************************************/
+/* Class: KWDocStructFormulaItem */
+/******************************************************************/
+
+class KWDocStructFormulaItem : public KWDocListViewItem
+{
+public:
+ KWDocStructFormulaItem(QListViewItem* parent, const QString& text, KWFormulaFrameSet* form);
+ virtual int ItemType() { return IT_FORMULA; }
+ virtual void selectItem();
+ virtual void editItem();
+ virtual void deleteItem();
+ virtual void editProperties();
+ virtual void speakItem();
+ virtual void contextMenu(QListViewItem* item, const QPoint& p, int);
+
+protected:
+ KWFormulaFrameSet* m_form;
+};
+
+
+/******************************************************************/
+/* Class: KWDocStructPictureItem */
+/******************************************************************/
+
+class KWDocStructPictureItem : public KWDocListViewItem
+{
+public:
+ KWDocStructPictureItem(QListViewItem* parent, const QString& text, KWPictureFrameSet* pic);
+ virtual int ItemType() { return IT_PICTURE; }
+ virtual void selectItem();
+ virtual void editItem();
+ virtual void deleteItem();
+ virtual void editProperties();
+ virtual void contextMenu(QListViewItem* item, const QPoint& p, int);
+
+protected:
+ KWPictureFrameSet* m_pic;
+};
+
+/******************************************************************/
+/* Class: KWDocStructPartItem */
+/******************************************************************/
+
+class KWDocStructPartItem : public KWDocListViewItem
+{
+public:
+ KWDocStructPartItem(QListViewItem* parent, const QString& text, KWPartFrameSet* part);
+ virtual int ItemType() { return IT_PART; }
+ virtual void selectItem();
+ virtual void editItem();
+ virtual void deleteItem();
+ virtual void editProperties();
+ virtual void contextMenu(QListViewItem* item, const QPoint& p, int);
+
+protected:
+ KWPartFrameSet* m_part;
+};
+
+/******************************************************************/
+/* Class: KWDocStructRootItem */
+/******************************************************************/
+
+class KWDocStructRootItem : public KWDocListViewItem
+{
+public:
+ KWDocStructRootItem(QListView* parent, const QString& text, TypeStructDocItem type);
+
+ virtual int ItemType() { return IT_ROOT; }
+ void setupArrangement();
+ void setupTextFrameSets();
+ void setupTables();
+ void setupPictures();
+ void setupEmbedded();
+ void setupFormulaFrames();
+ virtual void setOpen(bool o);
+
+protected:
+ KWDocStructTextFrameSetItem* findTextFrameSetItem(const KWFrameSet* frameset);
+ KWDocStructTableItem* findTableItem(const KWFrameSet* frameset);
+
+ TypeStructDocItem m_type;
+
+};
+
+/******************************************************************/
+/* Class: KWDocStructTree */
+/******************************************************************/
+
+class KWDocStructTree : public KListView
+{
+ Q_OBJECT
+
+public:
+ KWDocStructTree( QWidget* parent, KWDocument* doc, KWGUI* gui );
+ ~KWDocStructTree();
+
+ void setup();
+ void refreshTree(int _type);
+ QSize minimumSizeHint() const {
+ return QSize( 0, 0 );
+ }
+ void selectItem();
+ void editItem();
+ void deleteItem();
+ void editProperties();
+ void speakItem();
+
+ KWDocument* doc() { return m_doc; };
+ KWGUI* gui() { return m_gui; };
+
+public slots:
+ void slotContextMenu(KListView* l, QListViewItem* i, const QPoint& p);
+ void slotRightButtonClicked(QListViewItem*, const QPoint&, int);
+ void slotDoubleClicked(QListViewItem* item);
+ void slotReturnPressed(QListViewItem* item);
+
+protected:
+ KWDocument* m_doc;
+ KWGUI* m_gui;
+
+ KWDocStructRootItem *arrangement, *tables, *pictures, *textfrms, *embedded, *formulafrms;
+};
+
+/******************************************************************/
+/* Class: KWDocStruct */
+/******************************************************************/
+
+class KWDocStruct : public QWidget
+{
+ Q_OBJECT
+
+public:
+ KWDocStruct( QWidget* parent, KWDocument* doc, KWGUI* gui );
+ void selectItem();
+ void editItem();
+ void deleteItem();
+ void editProperties();
+ void speakItem();
+ /** Refresh the specified branches of the tree. Actual refreshing is deferred
+ until the paint event. */
+ void refreshTree(int _type);
+ /** Set focus to the tree, if visible. */
+ void setFocusHere();
+
+public slots:
+ /** Refresh the entire tree. */
+ void refreshEntireTree();
+
+protected:
+ KWDocStructTree* m_tree;
+ QVBoxLayout* m_layout;
+
+ virtual void paintEvent(QPaintEvent* ev);
+
+ KWDocument* m_doc;
+ KWGUI* m_gui;
+ int dirtyTreeTypes;
+};
+
+#endif
diff --git a/kword/KWDocument.cpp b/kword/KWDocument.cpp
new file mode 100644
index 00000000..a1bf0c89
--- /dev/null
+++ b/kword/KWDocument.cpp
@@ -0,0 +1,5466 @@
+/* This file is part of the KDE project
+ Copyright (C) 1998, 1999 Reginald Stadlbauer <reggie@kde.org>
+ Copyright (C) 2002-2006 David Faure <faure@kde.org>
+ Copyright (C) 2005 Thomas Zander <zander@kde.org>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+*/
+
+#include "KWDocument.h"
+
+#include "KWordDocIface.h"
+#include "KWBgSpellCheck.h"
+#include "KoTextBookmark.h"
+#include "KWCanvas.h"
+#include "KWCommand.h"
+#include "KWFormulaFrameSet.h"
+#include "KWFrameLayout.h"
+#include "KWPictureFrameSet.h"
+#include "KWPartFrameSet.h"
+#include "KWTableFrameSet.h"
+#include "KWTableStyle.h"
+#include "KWTableTemplate.h"
+#include "KWTextImage.h"
+#include "KWVariable.h"
+#include "KWView.h"
+#include "KWViewMode.h"
+#include "KWMailMergeDataBase.h"
+#include "KWLoadingInfo.h"
+#include "KWCollectFramesetsVisitor.h"
+#include "KWOasisLoader.h"
+#include "KWOasisSaver.h"
+#include "KWFrameList.h"
+#include "KWPageManager.h"
+#include "KWPage.h"
+#include "KWFrameView.h"
+#include "KWFrameViewManager.h"
+#include "KWStartupWidget.h"
+
+#include <KoPictureCollection.h>
+#include <KoTemplateChooseDia.h>
+#include <KoMainWindow.h>
+#include <KoDocumentInfo.h>
+#include <KoGlobal.h>
+#include <KoParagCounter.h>
+#include <KoTextObject.h>
+#include <KoAutoFormat.h>
+#include <KoVariable.h>
+#include <kformuladocument.h>
+#include <KoApplication.h>
+#include <KoOasisContext.h>
+#include <KoCommandHistory.h>
+#include <KoGenStyles.h>
+#include <KoStore.h>
+#include <KoStoreDrag.h>
+#include <KoStoreDevice.h>
+#include <KoXmlWriter.h>
+#include <KoOasisStore.h>
+#include <KoOasisStyles.h>
+#include <KoXmlNS.h>
+#include <KoDom.h>
+
+#include <kcursor.h>
+#include <kdebug.h>
+#include <kglobalsettings.h>
+#include <klibloader.h>
+#include <kmultipledrag.h>
+#include <klocale.h>
+#include <kmessagebox.h>
+#include <kspell.h>
+#include <kstandarddirs.h>
+
+#include <kspell2/settings.h>
+
+#include <qfileinfo.h>
+#include <qregexp.h>
+#include <qtimer.h>
+#include <qbuffer.h>
+
+#include <unistd.h>
+#include <math.h>
+
+//#define DEBUG_PAGES
+//#define DEBUG_SPEED
+
+// Make sure an appropriate DTD is available in www/koffice/DTD if changing this value
+static const char * CURRENT_DTD_VERSION = "1.2";
+
+/******************************************************************/
+/* Class: KWCommandHistory */
+/******************************************************************/
+class KWCommandHistory : public KoCommandHistory
+{
+public:
+ KWCommandHistory( KWDocument * doc ) : KoCommandHistory( doc->actionCollection(), true ), m_pDoc( doc ) {}
+public /*slots*/: // They are already slots in the parent. Running moc on the inherited class shouldn't be necessary AFAICS.
+ virtual void undo();
+ virtual void redo();
+private:
+ KWDocument * m_pDoc;
+};
+
+void KWCommandHistory::undo()
+{
+ m_pDoc->clearUndoRedoInfos();
+ KoCommandHistory::undo();
+}
+
+void KWCommandHistory::redo()
+{
+ m_pDoc->clearUndoRedoInfos();
+ KoCommandHistory::redo();
+}
+
+/******************************************************************/
+/* Class: KWDocument */
+/******************************************************************/
+void KWDocument::clearUndoRedoInfos()
+{
+ QPtrListIterator<KWFrameSet> fit = framesetsIterator();
+ for ( ; fit.current() ; ++fit )
+ {
+ KWTextFrameSet *fs = dynamic_cast<KWTextFrameSet *>( fit.current() );
+ if ( fs )
+ fs->clearUndoRedoInfo();
+ }
+}
+
+/**
+ * Temporary storage for the initial edition info
+ * (activeFrameset, cursorParagraph and cursorIndex attributes of the XML)
+ */
+class KWDocument::InitialEditing {
+public:
+ QString m_initialFrameSet;
+ int m_initialCursorParag;
+ int m_initialCursorIndex;
+};
+
+const int KWDocument::CURRENT_SYNTAX_VERSION = 3;
+
+KWDocument::KWDocument(QWidget *parentWidget, const char *widname, QObject* parent, const char* name, bool singleViewMode )
+ : KoDocument( parentWidget, widname, parent, name, singleViewMode ),
+ m_urlIntern()
+{
+ KWStatisticVariable::setExtendedType( true );
+ dcop = 0;
+ m_framesChangedHandler = 0;
+ m_pageManager = new KWPageManager();
+ m_pageManager->appendPage();
+ m_loadingInfo = 0L;
+ m_tabStop = MM_TO_POINT( 15.0 );
+ m_processingType = WP;
+
+// varFormats.setAutoDelete(true);
+ m_lstFrameSet.setAutoDelete( true );
+ // m_textImageRequests does not create or delete the KWTextImage classes
+ m_textImageRequests.setAutoDelete(false);
+
+ m_styleColl = new KoStyleCollection();
+ m_frameStyleColl = new KWFrameStyleCollection();
+ m_tableStyleColl = new KWTableStyleCollection();
+ m_tableTemplateColl = new KWTableTemplateCollection();
+ m_pictureCollection = new KoPictureCollection();
+
+ m_personalExpressionPath = KWFactory::instance()->dirs()->resourceDirs("expression");
+
+ m_bShowGrid = false;
+ m_bSnapToGrid = false;
+
+
+ setInstance( KWFactory::instance(), false );
+ setTemplateType( "kword_template" );
+
+ m_gridX = m_gridY = MM_TO_POINT(5.0 );
+ m_indent = MM_TO_POINT( 10.0 );
+
+ m_iNbPagePerRow = 4;
+ m_maxRecentFiles = 10;
+ m_bShowRuler = true;
+
+ m_footNoteSeparatorLinePos=SLP_LEFT;
+
+ m_viewFormattingChars = false;
+
+ m_viewFormattingEndParag = true;
+ m_viewFormattingSpace = true;
+ m_viewFormattingTabs = true;
+ m_viewFormattingBreak = true;
+
+ m_viewFrameBorders = true;
+ m_repaintAllViewsPending = false;
+ m_recalcFramesPending = -1;
+ m_bShowDocStruct = true;
+ m_bShowRuler = true;
+ m_bShowStatusBar = true;
+ m_bAllowAutoFormat = true;
+ m_pgUpDownMovesCaret = true;
+ m_bShowScrollBar = true;
+ m_cursorInProtectectedArea = true;
+ m_bHasEndNotes = false;
+
+ m_bInsertDirectCursor=false;
+ m_globalLanguage = KGlobal::locale()->language();
+ m_bGlobalHyphenation = false;
+ m_bGeneratingPreview = false;
+ m_viewModeType="ModeNormal";
+ m_layoutViewMode = 0;
+
+ m_commandHistory = new KWCommandHistory( this );
+ connect( m_commandHistory, SIGNAL( documentRestored() ), this, SLOT( slotDocumentRestored() ) );
+ connect( m_commandHistory, SIGNAL( commandExecuted() ), this, SLOT( slotCommandExecuted() ) );
+
+ //styleMask = U_FONT_FAMILY_ALL_SIZE | U_COLOR | U_BORDER | U_INDENT |
+ // U_NUMBERING | U_ALIGN | U_TABS | U_SMART;
+ m_headerVisible = false;
+ m_footerVisible = false;
+
+ m_pasteFramesetsMap = 0L;
+ m_initialEditing = 0L;
+ m_bufPixmap = 0L;
+ m_varFormatCollection = new KoVariableFormatCollection;
+ m_varColl = new KWVariableCollection( new KWVariableSettings(), m_varFormatCollection );
+
+ m_autoFormat = new KoAutoFormat(this,m_varColl,m_varFormatCollection );
+ m_bgSpellCheck = new KWBgSpellCheck(this);
+ m_slDataBase = new KWMailMergeDataBase( this );
+ m_bookmarkList = new KoTextBookmarkList;
+ slRecordNum = -1;
+
+ m_syntaxVersion = CURRENT_SYNTAX_VERSION;
+
+ m_hasTOC=false;
+
+ // It's important to call this to have the kformula actions
+ // created. The real document is still to be created if needed.
+ m_formulaDocumentWrapper =
+ new KFormula::DocumentWrapper( instance()->config(),
+ actionCollection(),
+ m_commandHistory );
+
+ setEmpty();
+ setModified(false);
+
+ initConfig();
+
+ // Get default font from the KWord config file
+ KConfig *config = KWFactory::instance()->config();
+ config->setGroup("Document defaults" );
+ QString defaultFontname=config->readEntry("DefaultFont");
+ if ( !defaultFontname.isEmpty() )
+ m_defaultFont.fromString( defaultFontname );
+ // If not found, we automatically fallback to the application font (the one from KControl's font module)
+
+ // Try to force a scalable font.
+ m_defaultFont.setStyleStrategy( QFont::ForceOutline );
+
+ int ptSize = m_defaultFont.pointSize();
+ if ( ptSize == -1 ) // specified with a pixel size ?
+ ptSize = QFontInfo(m_defaultFont).pointSize();
+
+ //kdDebug() << "Default font: requested family: " << m_defaultFont.family() << endl;
+ //kdDebug() << "Default font: real family: " << QFontInfo(m_defaultFont).family() << endl;
+
+ if ( name )
+ dcopObject();
+}
+
+DCOPObject* KWDocument::dcopObject()
+{
+ if ( !dcop )
+ dcop = new KWordDocIface( this );
+ return dcop;
+}
+
+KWDocument::~KWDocument()
+{
+ //don't save config when kword is embedded into konqueror
+ if(isReadWrite())
+ saveConfig();
+ // formula frames have to be deleted before m_formulaDocumentWrapper
+ m_lstFrameSet.clear();
+ delete m_loadingInfo;
+ delete m_autoFormat;
+ delete m_formulaDocumentWrapper;
+ delete m_commandHistory;
+ delete m_varColl;
+ delete m_varFormatCollection;
+ delete m_slDataBase;
+ delete dcop;
+ delete m_bgSpellCheck;
+ delete m_styleColl;
+ delete m_frameStyleColl;
+ delete m_tableStyleColl;
+ delete m_tableTemplateColl;
+ delete m_layoutViewMode;
+ delete m_bufPixmap;
+ delete m_pictureCollection;
+ delete m_pageManager;
+ delete m_bookmarkList;
+}
+
+void KWDocument::initConfig()
+{
+ KConfig *config = KWFactory::instance()->config();
+ if( config->hasGroup("KSpell kword" ) )
+ {
+ config->setGroup( "KSpell kword" );
+
+ // Default is false for spellcheck, but the spell-check config dialog
+ // should write out "true" when the user configures spell checking.
+ if ( isReadWrite() )
+ m_bgSpellCheck->setEnabled(config->readBoolEntry( "SpellCheck", false ));
+ else
+ m_bgSpellCheck->setEnabled( false );
+ }
+
+ if(config->hasGroup("Interface" ) )
+ {
+ config->setGroup( "Interface" );
+ setGridY(QMAX( config->readDoubleNumEntry("GridY",MM_TO_POINT(5.0) ), 0.1));
+ setGridX(QMAX( config->readDoubleNumEntry("GridX",MM_TO_POINT(5.0) ), 0.1));
+ setCursorInProtectedArea( config->readBoolEntry( "cursorInProtectArea", true ));
+ // Config-file value in mm, default 10 pt
+ double indent = config->readDoubleNumEntry("Indent", MM_TO_POINT(10.0) ) ;
+ setIndentValue(indent);
+ setShowRuler(config->readBoolEntry("Rulers",true));
+ int defaultAutoSave = KoDocument::defaultAutoSave()/60; // in minutes
+ setAutoSave(config->readNumEntry("AutoSave",defaultAutoSave)*60); // read key in minutes, call setAutoSave(seconds)
+ setBackupFile( config->readBoolEntry("BackupFile", true) );
+
+ setNbPagePerRow(config->readNumEntry("nbPagePerRow",4));
+ m_maxRecentFiles = config->readNumEntry( "NbRecentFile", 10 );
+
+ m_viewFormattingChars = config->readBoolEntry( "ViewFormattingChars", false );
+ m_viewFormattingBreak = config->readBoolEntry( "ViewFormattingBreaks", true );
+ m_viewFormattingSpace = config->readBoolEntry( "ViewFormattingSpace", true );
+ m_viewFormattingEndParag = config->readBoolEntry( "ViewFormattingEndParag", true );
+ m_viewFormattingTabs = config->readBoolEntry( "ViewFormattingTabs", true );
+
+ m_viewFrameBorders = config->readBoolEntry( "ViewFrameBorders", true );
+
+ m_zoom = config->readNumEntry( "Zoom", 100 );
+ m_zoomMode = static_cast<KoZoomMode::Mode> (
+ config->readNumEntry( "ZoomMode", KoZoomMode::ZOOM_CONSTANT )
+ );
+
+ m_bShowDocStruct = config->readBoolEntry( "showDocStruct", true );
+ m_viewModeType = config->readEntry( "viewmode", "ModeNormal" );
+ setShowStatusBar( config->readBoolEntry( "ShowStatusBar" , true ) );
+ setAllowAutoFormat( config->readBoolEntry( "AllowAutoFormat" , true ) );
+ setShowScrollBar( config->readBoolEntry( "ShowScrollBar", true ) );
+ if ( isEmbedded() )
+ m_bShowDocStruct = false; // off by default for embedded docs, but still toggleable
+ m_pgUpDownMovesCaret = config->readBoolEntry( "PgUpDownMovesCaret", true );
+ m_bInsertDirectCursor= config->readBoolEntry( "InsertDirectCursor", false );
+ m_globalLanguage=config->readEntry("language", KGlobal::locale()->language());
+ m_bGlobalHyphenation=config->readBoolEntry("hyphenation", false);
+
+ setShowGrid( config->readBoolEntry( "ShowGrid" , false ));
+ setSnapToGrid( config->readBoolEntry( "SnapToGrid", false ));
+ setGridX( config->readDoubleNumEntry( "ResolutionX", MM_TO_POINT( 5.0 ) ));
+ setGridY( config->readDoubleNumEntry( "ResolutionY", MM_TO_POINT( 5.0 ) ));
+ }
+ else
+ {
+ m_zoom = 100;
+ m_zoomMode = KoZoomMode::ZOOM_WIDTH;
+ }
+ int undo=30;
+ if(config->hasGroup("Misc" ) )
+ {
+ config->setGroup( "Misc" );
+ undo=config->readNumEntry("UndoRedo",-1);
+
+ //load default unit setting - this is only used for new files (from templates) or empty files
+ if ( config->hasKey( "Units" ) )
+ setUnit( KoUnit::unit( config->readEntry("Units") ) );
+ m_defaultColumnSpacing = config->readDoubleNumEntry( "ColumnSpacing", 3.0 );
+ }
+
+ if(undo!=-1)
+ setUndoRedoLimit(undo);
+
+ setZoomAndResolution( m_zoom, KoGlobal::dpiX(), KoGlobal::dpiY() );
+
+ //text mode view is not a good default for a readonly document...
+ if ( !isReadWrite() && m_viewModeType =="ModeText" )
+ m_viewModeType= "ModeNormal";
+
+ m_layoutViewMode = KWViewMode::create( m_viewModeType, this, 0 /*no canvas*/);
+
+ if(config->hasGroup("Kword Path" ) )
+ {
+ config->setGroup( "Kword Path" );
+ if ( config->hasKey( "expression path" ) )
+ m_personalExpressionPath = config->readPathListEntry( "expression path" );
+ setBackupPath(config->readPathEntry( "backup path" ));
+ }
+
+ // Load personal dict
+ KConfigGroup group( KoGlobal::kofficeConfig(), "Spelling" );
+ m_spellCheckPersonalDict = group.readListEntry( "PersonalDict" );
+}
+
+void KWDocument::saveConfig()
+{
+ if ( !isReadWrite() )
+ return;
+ KConfigGroup group( KoGlobal::kofficeConfig(), "Spelling" );
+ group.writeEntry( "PersonalDict", m_spellCheckPersonalDict );
+
+ if ( !isEmbedded() )
+ {
+ // Only save the config that is manipulated by the UI directly.
+ // The config from the config dialog is saved by the dialog itself.
+ KConfig *config = KWFactory::instance()->config();
+ config->setGroup( "Interface" );
+ config->writeEntry( "ViewFormattingChars", m_viewFormattingChars );
+ config->writeEntry( "ViewFormattingBreaks", m_viewFormattingBreak );
+ config->writeEntry( "ViewFormattingEndParag", m_viewFormattingEndParag );
+ config->writeEntry( "ViewFormattingTabs", m_viewFormattingTabs );
+ config->writeEntry( "ViewFormattingSpace", m_viewFormattingSpace );
+ config->writeEntry( "ViewFrameBorders", m_viewFrameBorders );
+ config->writeEntry( "Zoom", m_zoom );
+ config->writeEntry( "ZoomMode", m_zoomMode );
+ config->writeEntry( "showDocStruct", m_bShowDocStruct );
+ config->writeEntry( "Rulers", m_bShowRuler );
+ config->writeEntry( "viewmode", m_viewModeType) ;
+ config->writeEntry( "AllowAutoFormat", m_bAllowAutoFormat );
+ config->writeEntry( "ShowGrid" , m_bShowGrid );
+ config->writeEntry( "SnapToGrid" , m_bSnapToGrid );
+ config->writeEntry( "ResolutionX", m_gridX );
+ config->writeEntry( "ResolutionY", m_gridY );
+ }
+}
+
+void KWDocument::setZoomAndResolution( int zoom, int dpiX, int dpiY )
+{
+ KoTextZoomHandler::setZoomAndResolution( zoom, dpiX, dpiY );
+ if ( KFormula::Document* formulaDocument = m_formulaDocumentWrapper->document() )
+ formulaDocument->setZoomAndResolution( zoom, dpiX, dpiY );
+}
+
+KWTextFrameSet * KWDocument::textFrameSet ( unsigned int num ) const
+{
+ unsigned int i=0;
+ QPtrListIterator<KWFrameSet> fit = framesetsIterator();
+ for ( ; fit.current() ; ++fit )
+ {
+ if(fit.current()->isDeleted()) continue;
+ if(fit.current()->type()==FT_TEXT)
+ {
+ if(i==num)
+ return static_cast<KWTextFrameSet*>(fit.current());
+ i++;
+ }
+ }
+ return static_cast<KWTextFrameSet*>(m_lstFrameSet.getFirst());
+}
+
+void KWDocument::newZoomAndResolution( bool updateViews, bool forPrint )
+{
+ if ( KFormula::Document* formulaDocument = m_formulaDocumentWrapper->document() )
+ formulaDocument->newZoomAndResolution( updateViews,forPrint );
+#if 0
+ QPtrListIterator<KWFrameSet> fit = framesetsIterator();
+ for ( ; fit.current() ; ++fit )
+ fit.current()->zoom( forPrint );
+#endif
+
+ // First recalc all frames (including the kotextdocument width)
+ updateAllFrames();
+ // Then relayout the text inside the frames
+ layout();
+ if ( updateViews )
+ {
+ emit newContentsSize();
+ repaintAllViews( true );
+ }
+}
+
+bool KWDocument::initDoc(InitDocFlags flags, QWidget* parentWidget)
+{
+ m_pageColumns.columns = 1;
+ m_pageColumns.ptColumnSpacing = m_defaultColumnSpacing;
+
+ m_pageHeaderFooter.header = HF_SAME;
+ m_pageHeaderFooter.footer = HF_SAME;
+ m_pageHeaderFooter.ptHeaderBodySpacing = 10;
+ m_pageHeaderFooter.ptFooterBodySpacing = 10;
+ m_pageHeaderFooter.ptFootNoteBodySpacing = 10;
+
+ bool ok = FALSE;
+
+ if ( isEmbedded() )
+ {
+ QString fileName( locate( "kword_template", "Normal/.source/Embedded.kwt" , KWFactory::instance() ) );
+ resetURL();
+ ok = loadNativeFormat( fileName );
+ if ( !ok )
+ showLoadingErrorDialog();
+ setEmpty();
+ setModified( FALSE );
+ return ok;
+ }
+ else if (flags==KoDocument::InitDocEmpty)
+ {
+ QString fileName( locate( "kword_template", "Normal/.source/PlainText.kwt" , KWFactory::instance() ) );
+ resetURL();
+ ok = loadNativeFormat( fileName );
+ if ( !ok )
+ showLoadingErrorDialog();
+ setEmpty();
+ setModified( FALSE );
+ return ok;
+ }
+
+ KoTemplateChooseDia::DialogType dlgtype;
+
+ if (flags != KoDocument::InitDocFileNew)
+ dlgtype = KoTemplateChooseDia::Everything;
+ else
+ dlgtype = KoTemplateChooseDia::OnlyTemplates;
+
+
+ QString file;
+ KoTemplateChooseDia::ReturnType ret = KoTemplateChooseDia::choose(
+ KWFactory::instance(), file,
+ dlgtype, "kword_template", parentWidget );
+ if ( ret == KoTemplateChooseDia::Template ) {
+ resetURL();
+ ok = loadNativeFormat( file );
+ if ( !ok )
+ showLoadingErrorDialog();
+ setEmpty();
+ } else if ( ret == KoTemplateChooseDia::File ) {
+ KURL url( file );
+ //kdDebug() << "KWDocument::initDoc opening URL " << url.prettyURL() << endl;
+ ok = openURL( url );
+ } else if ( ret == KoTemplateChooseDia::Empty ) {
+ QString fileName( locate( "kword_template", "Normal/.source/PlainText.kwt" , KWFactory::instance() ) );
+ resetURL();
+ ok = loadNativeFormat( fileName );
+ if ( !ok )
+ showLoadingErrorDialog();
+ setEmpty();
+ }
+ setModified( FALSE );
+ return ok;
+}
+
+void KWDocument::openExistingFile( const QString& file )
+{
+ m_pageColumns.columns = 1;
+ m_pageColumns.ptColumnSpacing = m_defaultColumnSpacing;
+
+ m_pageHeaderFooter.header = HF_SAME;
+ m_pageHeaderFooter.footer = HF_SAME;
+ m_pageHeaderFooter.ptHeaderBodySpacing = 10;
+ m_pageHeaderFooter.ptFooterBodySpacing = 10;
+ m_pageHeaderFooter.ptFootNoteBodySpacing = 10;
+
+ KoDocument::openExistingFile( file );
+}
+
+void KWDocument::openTemplate( const QString& file )
+{
+ m_pageColumns.columns = 1;
+ m_pageColumns.ptColumnSpacing = m_defaultColumnSpacing;
+
+ m_pageHeaderFooter.header = HF_SAME;
+ m_pageHeaderFooter.footer = HF_SAME;
+ m_pageHeaderFooter.ptHeaderBodySpacing = 10;
+ m_pageHeaderFooter.ptFooterBodySpacing = 10;
+ m_pageHeaderFooter.ptFootNoteBodySpacing = 10;
+
+ KoDocument::openTemplate( file );
+}
+
+void KWDocument::initEmpty()
+{
+ m_pageColumns.columns = 1;
+ m_pageColumns.ptColumnSpacing = m_defaultColumnSpacing;
+
+ m_pageHeaderFooter.header = HF_SAME;
+ m_pageHeaderFooter.footer = HF_SAME;
+ m_pageHeaderFooter.ptHeaderBodySpacing = 10;
+ m_pageHeaderFooter.ptFooterBodySpacing = 10;
+ m_pageHeaderFooter.ptFootNoteBodySpacing = 10;
+
+ QString fileName( locate( "kword_template", "Normal/.source/PlainText.kwt" , KWFactory::instance() ) );
+ bool ok = loadNativeFormat( fileName );
+ if ( !ok )
+ showLoadingErrorDialog();
+ resetURL();
+ setModified( FALSE );
+ setEmpty();
+}
+
+KoPageLayout KWDocument::pageLayout(int pageNumber /* = 0 */) const
+{
+ if( pageNumber < startPage()) // impossible page..
+ pageNumber = startPage();
+ return pageManager()->pageLayout(pageNumber);
+}
+
+void KWDocument::setPageLayout( const KoPageLayout& layout, const KoColumns& cl, const KoKWHeaderFooter& hf, bool updateViews )
+{
+ m_pageLayout = layout;
+ if ( m_processingType == WP ) {
+ m_pageColumns = cl;
+ }
+ if ( m_processingType == DTP || isEmbedded() ) {
+ m_pageLayout.ptLeft = 0;
+ m_pageLayout.ptRight = 0;
+ m_pageLayout.ptTop = 0;
+ m_pageLayout.ptBottom = 0;
+ }
+ pageManager()->setDefaultPage(m_pageLayout);
+ m_pageHeaderFooter = hf;
+
+ // pages have a different size -> update framesInPage
+ // TODO: it would be better to move stuff so that text boxes remain in the same page...
+ // (page-number preservation instead of Y preservation)
+ updateAllFrames( KWFrameSet::UpdateFramesInPage );
+
+ recalcFrames();
+
+ updateAllFrames();
+
+ if ( updateViews )
+ {
+ // Invalidate document layout, for proper repaint
+ this->layout();
+ emit pageLayoutChanged( m_pageLayout );
+ updateContentsSize();
+ }
+}
+
+
+double KWDocument::ptColumnWidth() const
+{
+ KWPage *page = pageManager()->page(pageManager()->startPage());
+ return ( page->width() - page->leftMargin() - page->rightMargin() -
+ ptColumnSpacing() * ( m_pageColumns.columns - 1 ) )
+ / m_pageColumns.columns;
+}
+
+class KWFootNoteFrameSetList : public QPtrList<KWFootNoteFrameSet>
+{
+public:
+ KWFootNoteFrameSetList( bool reversed ) : m_reversed( reversed ) {}
+protected:
+ // Compare the order of the associated variables
+ virtual int compareItems(QPtrCollection::Item a, QPtrCollection::Item b)
+ {
+ KWFootNoteFrameSet* fsa = ((KWFootNoteFrameSet *)a);
+ KWFootNoteFrameSet* fsb = ((KWFootNoteFrameSet *)b);
+ Q_ASSERT( fsa->footNoteVariable() );
+ Q_ASSERT( fsb->footNoteVariable() );
+ if ( fsa->footNoteVariable() && fsb->footNoteVariable() )
+ {
+ int numa = fsa->footNoteVariable()->num();
+ int numb = fsb->footNoteVariable()->num();
+ if (numa == numb) return 0;
+ if (numa > numb) return m_reversed ? -1 : 1;
+ return m_reversed ? 1 : -1;
+ }
+ return -1; // whatever
+ }
+private:
+ bool m_reversed;
+};
+
+/* append headers and footers if needed, and create enough pages for all the existing frames */
+void KWDocument::recalcFrames( int fromPage, int toPage /*-1 for all*/, uint flags )
+{
+ fromPage = QMAX(pageManager()->startPage(), fromPage);
+ if ( m_lstFrameSet.isEmpty() )
+ return;
+ //printDebug();
+ kdDebug(32002) << "KWDocument::recalcFrames from=" << fromPage << " to=" << toPage << endl;
+
+ KWFrameSet *frameset = m_lstFrameSet.getFirst();
+
+ if ( m_processingType == WP ) { // In WP mode the pages are created automatically. In DTP not...
+
+ KWTextFrameSet *firstHeader = 0L, *evenHeader = 0L, *oddHeader = 0L;
+ KWTextFrameSet *firstFooter = 0L, *evenFooter = 0L, *oddFooter = 0L;
+ m_bHasEndNotes = false; // will be set to true if we find any endnote
+
+ // Lookup the various header / footer framesets into the variables above
+ // [Done in all cases, in order to hide unused framesets]
+
+ KWFootNoteFrameSetList footnotesList( true ); // Reversed, we want footnotes from bottom to top
+ KWFootNoteFrameSetList endnotesList( false ); // Endnotes are in top to bottom order
+ QPtrListIterator<KWFrameSet> fit = framesetsIterator();
+ for ( ; fit.current() ; ++fit )
+ {
+ KWFrameSet * fs = fit.current();
+ switch ( fs->frameSetInfo() ) {
+ case KWFrameSet::FI_FIRST_HEADER:
+ if ( isHeaderVisible() ) {
+ firstHeader = dynamic_cast<KWTextFrameSet*>( fs );
+ } else { fs->setVisible( false ); fs->deleteAllCopies(); }
+ break;
+ case KWFrameSet::FI_ODD_HEADER:
+ if ( isHeaderVisible() ) {
+ oddHeader = dynamic_cast<KWTextFrameSet*>( fs );
+ } else { fs->setVisible( false ); fs->deleteAllCopies(); }
+ break;
+ case KWFrameSet::FI_EVEN_HEADER:
+ if ( isHeaderVisible() ) {
+ evenHeader = dynamic_cast<KWTextFrameSet*>( fs );
+ } else { fs->setVisible( false ); fs->deleteAllCopies(); }
+ break;
+ case KWFrameSet::FI_FIRST_FOOTER:
+ if ( isFooterVisible() ) {
+ firstFooter = dynamic_cast<KWTextFrameSet*>( fs );
+ } else { fs->setVisible( false ); fs->deleteAllCopies(); }
+ break;
+ case KWFrameSet::FI_ODD_FOOTER:
+ if ( isFooterVisible() ) {
+ oddFooter = dynamic_cast<KWTextFrameSet*>( fs );
+ } else { fs->setVisible( false ); fs->deleteAllCopies(); }
+ break;
+ case KWFrameSet::FI_EVEN_FOOTER:
+ if ( isFooterVisible() ) {
+ evenFooter = dynamic_cast<KWTextFrameSet*>( fs );
+ } else { fs->setVisible( false ); fs->deleteAllCopies(); }
+ break;
+ case KWFrameSet::FI_FOOTNOTE: {
+ KWFootNoteFrameSet* fnfs = dynamic_cast<KWFootNoteFrameSet *>(fs);
+ if ( fnfs && fnfs->isVisible() ) // not visible is when the footnote has been deleted
+ {
+ if ( fnfs->isFootNote() )
+ footnotesList.append( fnfs );
+ else if ( fnfs->isEndNote() ) {
+ endnotesList.append( fnfs );
+ m_bHasEndNotes = true;
+ }
+ }
+ }
+ break;
+ default: break;
+ }
+ }
+
+ // This allocation each time might slow things down a bit.
+ // TODO KWHeaderFooterFrameSet : public KWTextFrameSet, and store the HeaderFooterFrameset data into there.
+ // ... hmm, and then KWFootNoteFrameSet needs to inherit KWHeaderFooterFrameSet
+ QPtrList<KWFrameLayout::HeaderFooterFrameset> headerFooterList;
+ headerFooterList.setAutoDelete( true );
+ const int firstPageNum = startPage();
+
+ // Now hide & forget the unused header/footer framesets (e.g. 'odd pages' if we are in 'all the same' mode etc.)
+ if ( isHeaderVisible() ) {
+ Q_ASSERT( firstHeader );
+ Q_ASSERT( oddHeader );
+ Q_ASSERT( evenHeader );
+ switch ( headerType() ) {
+ case HF_SAME:
+ oddHeader->setVisible( true );
+ evenHeader->setVisible( false );
+ evenHeader->deleteAllCopies();
+ firstHeader->setVisible( false );
+ firstHeader->deleteAllCopies();
+
+ headerFooterList.append( new KWFrameLayout::HeaderFooterFrameset(
+ oddHeader, firstPageNum, -1, m_pageHeaderFooter.ptHeaderBodySpacing ) );
+ break;
+ case HF_FIRST_EO_DIFF: // added for koffice-1.2-beta2
+ firstHeader->setVisible( true );
+ oddHeader->setVisible( true );
+ evenHeader->setVisible( true );
+
+ headerFooterList.append( new KWFrameLayout::HeaderFooterFrameset(
+ firstHeader, firstPageNum, firstPageNum, m_pageHeaderFooter.ptHeaderBodySpacing ) );
+ headerFooterList.append( new KWFrameLayout::HeaderFooterFrameset(
+ oddHeader, firstPageNum + 2, -1, m_pageHeaderFooter.ptHeaderBodySpacing,
+ KWFrameLayout::HeaderFooterFrameset::Odd ) );
+ headerFooterList.append( new KWFrameLayout::HeaderFooterFrameset(
+ evenHeader, firstPageNum + 1, -1, m_pageHeaderFooter.ptHeaderBodySpacing,
+ KWFrameLayout::HeaderFooterFrameset::Even ) );
+ break;
+ case HF_FIRST_DIFF:
+ oddHeader->setVisible( true );
+ evenHeader->setVisible( false );
+ evenHeader->deleteAllCopies();
+ firstHeader->setVisible( true );
+
+ headerFooterList.append( new KWFrameLayout::HeaderFooterFrameset(
+ firstHeader, firstPageNum, firstPageNum, m_pageHeaderFooter.ptHeaderBodySpacing ) );
+ headerFooterList.append( new KWFrameLayout::HeaderFooterFrameset(
+ oddHeader, firstPageNum + 1, -1, m_pageHeaderFooter.ptHeaderBodySpacing ) );
+ break;
+ case HF_EO_DIFF:
+ oddHeader->setVisible( true );
+ evenHeader->setVisible( true );
+ firstHeader->setVisible( false );
+ firstHeader->deleteAllCopies();
+
+ headerFooterList.append( new KWFrameLayout::HeaderFooterFrameset(
+ oddHeader, firstPageNum, -1, m_pageHeaderFooter.ptHeaderBodySpacing,
+ KWFrameLayout::HeaderFooterFrameset::Odd ) );
+ headerFooterList.append( new KWFrameLayout::HeaderFooterFrameset(
+ evenHeader, firstPageNum + 1, -1, m_pageHeaderFooter.ptHeaderBodySpacing,
+ KWFrameLayout::HeaderFooterFrameset::Even ) );
+ break;
+ }
+ }
+ if ( isFooterVisible() ) {
+ Q_ASSERT( firstFooter );
+ Q_ASSERT( oddFooter );
+ Q_ASSERT( evenFooter );
+ switch ( footerType() ) {
+ case HF_SAME:
+ oddFooter->setVisible( true );
+ evenFooter->setVisible( false );
+ evenFooter->deleteAllCopies();
+ firstFooter->setVisible( false );
+ firstFooter->deleteAllCopies();
+
+ headerFooterList.append( new KWFrameLayout::HeaderFooterFrameset(
+ oddFooter, firstPageNum, -1, m_pageHeaderFooter.ptFooterBodySpacing ) );
+ break;
+ case HF_FIRST_EO_DIFF: // added for koffice-1.2-beta2
+ firstFooter->setVisible( true );
+ oddFooter->setVisible( true );
+ evenFooter->setVisible( true );
+
+ headerFooterList.append( new KWFrameLayout::HeaderFooterFrameset(
+ firstFooter, firstPageNum, firstPageNum, m_pageHeaderFooter.ptFooterBodySpacing ) );
+ headerFooterList.append( new KWFrameLayout::HeaderFooterFrameset(
+ oddFooter, firstPageNum + 2, -1, m_pageHeaderFooter.ptFooterBodySpacing,
+ KWFrameLayout::HeaderFooterFrameset::Odd ) );
+ headerFooterList.append( new KWFrameLayout::HeaderFooterFrameset(
+ evenFooter, firstPageNum + 1, -1, m_pageHeaderFooter.ptFooterBodySpacing,
+ KWFrameLayout::HeaderFooterFrameset::Even ) );
+ break;
+ case HF_FIRST_DIFF:
+ oddFooter->setVisible( true );
+ evenFooter->setVisible( false );
+ evenFooter->deleteAllCopies();
+ firstFooter->setVisible( true );
+
+ headerFooterList.append( new KWFrameLayout::HeaderFooterFrameset(
+ firstFooter, firstPageNum, firstPageNum, m_pageHeaderFooter.ptFooterBodySpacing ) );
+ headerFooterList.append( new KWFrameLayout::HeaderFooterFrameset(
+ oddFooter, firstPageNum + 1, -1, m_pageHeaderFooter.ptFooterBodySpacing ) );
+ break;
+ case HF_EO_DIFF:
+ oddFooter->setVisible( true );
+ evenFooter->setVisible( true );
+ firstFooter->setVisible( false );
+ firstFooter->deleteAllCopies();
+
+ headerFooterList.append( new KWFrameLayout::HeaderFooterFrameset(
+ oddFooter, firstPageNum, -1, m_pageHeaderFooter.ptFooterBodySpacing,
+ KWFrameLayout::HeaderFooterFrameset::Odd ) );
+ headerFooterList.append( new KWFrameLayout::HeaderFooterFrameset(
+ evenFooter, firstPageNum + 1, -1, m_pageHeaderFooter.ptFooterBodySpacing,
+ KWFrameLayout::HeaderFooterFrameset::Even ) );
+ break;
+ }
+ }
+
+ // The frameset order _on screen_ is:
+ // Header
+ // Main text frame (if WP)
+ // Footnote_s_
+ // Footer
+ // In the list it will have to be from top and from bottom:
+ // Header, Footer, Footnote from bottom to top
+ QPtrList<KWFrameLayout::HeaderFooterFrameset> footnotesHFList;
+ footnotesHFList.setAutoDelete( true );
+
+ footnotesList.sort();
+ QPtrListIterator<KWFootNoteFrameSet> fnfsIt( footnotesList ); // fnfs == "footnote frameset"
+ for ( ; fnfsIt.current() ; ++fnfsIt )
+ {
+ KWFootNoteFrameSet* fnfs = fnfsIt.current();
+ int pageNum = -42; //fnfs->footNoteVariable()->pageNumber(); // determined by KWFrameLayout
+ KWFrameLayout::HeaderFooterFrameset* hff = new KWFrameLayout::HeaderFooterFrameset(
+ fnfs, pageNum, pageNum,
+ m_pageHeaderFooter.ptFootNoteBodySpacing,
+ KWFrameLayout::HeaderFooterFrameset::All );
+
+ // With other kind of framesets, the height is simply frame->height.
+ // But for footnotes, the height to pass to KWFrameLayout is the sum of the frame heights.
+ hff->m_height = 0;
+ for (QPtrListIterator<KWFrame> f = fnfs->frameIterator(); f.current() ; ++f )
+ hff->m_height += f.current()->height();
+
+ footnotesHFList.append( hff );
+ }
+
+ // Endnotes, however are laid out from top to bottom.
+ QPtrList<KWFrameLayout::HeaderFooterFrameset> endnotesHFList;
+ endnotesHFList.setAutoDelete( true );
+
+ endnotesList.sort();
+ QPtrListIterator<KWFootNoteFrameSet> enfsIt( endnotesList ); // enfs == "endnote frameset"
+ for ( ; enfsIt.current() ; ++enfsIt )
+ {
+ KWFootNoteFrameSet* enfs = enfsIt.current();
+ KWFrameLayout::HeaderFooterFrameset* hff = new KWFrameLayout::HeaderFooterFrameset(
+ enfs, -42, -42, // determined by KWFrameLayout
+ m_pageHeaderFooter.ptFootNoteBodySpacing,
+ KWFrameLayout::HeaderFooterFrameset::All );
+
+ // The height to pass to KWFrameLayout is the sum of the frame heights.
+ hff->m_height = 0;
+ for (QPtrListIterator<KWFrame> f = enfs->frameIterator(); f.current() ; ++f )
+ hff->m_height += f.current()->height();
+
+ endnotesHFList.append( hff );
+ }
+
+ // append pages as needed.
+ double maxBottom = 0;
+ for (QPtrListIterator<KWFrameSet> fsit = framesetsIterator(); fsit.current() ; ++fsit ) {
+ KWFrameSet *fs = fsit.current();
+ if ( !fs->isVisible() || fs->isAHeader() || !fs->isAFooter() ||
+ !fs->isFloating() || !fs->isFootEndNote() )
+ continue;
+ for (QPtrListIterator<KWFrame> fit = fs->frameIterator(); fit.current() ; ++fit )
+ maxBottom = QMAX(maxBottom, fit.current()->bottom());
+ }
+ KWPage *last = pageManager()->page(lastPage());
+ double docHeight = last->offsetInDocument() + last->height();
+ while(docHeight <= maxBottom) {
+ last = pageManager()->appendPage();
+ docHeight += last->height();
+ }
+ int oldPages = pageCount();
+
+ if ( toPage == -1 )
+ toPage = lastPage();
+ if ( fromPage > toPage ) // this can happen with "endnotes only" pages :) // ### really?
+ fromPage = toPage; // ie. start at the last real page
+ KWFrameLayout frameLayout( this, headerFooterList, footnotesHFList, endnotesHFList );
+ frameLayout.layout( frameset, m_pageColumns.columns, fromPage, toPage, flags );
+
+ // If the number of pages changed, update views and variables etc.
+ // (now that the frame layout has been done)
+ if ( pageCount() != oldPages && !m_bGeneratingPreview )
+ {
+ // Very much like the end of appendPage, but we don't want to call recalcFrames ;)
+ emit newContentsSize();
+ emit numPagesChanged();
+ recalcVariables( VT_PGNUM );
+ }
+
+ }
+ else {
+ // DTP mode: calculate the number of pages from the frames.
+ double maxBottom=0;
+ for (QPtrListIterator<KWFrameSet> fit = framesetsIterator(); fit.current() ; ++fit ) {
+ if(fit.current()->isDeleted()) continue;
+ if(fit.current()->frameSetInfo()==KWFrameSet::FI_BODY && !fit.current()->isFloating()) {
+ KWFrameSet * fs = fit.current();
+ for (QPtrListIterator<KWFrame> f = fs->frameIterator(); f.current() ; ++f )
+ maxBottom=QMAX(maxBottom, f.current()->bottom());
+ }
+ }
+ KWPage *last = pageManager()->page(lastPage());
+ Q_ASSERT(last);
+ if(last) { // hack to work around bug #132338
+ double docHeight = last->offsetInDocument() + last->height();
+ while(docHeight <= maxBottom) {
+ last = pageManager()->appendPage();
+ docHeight += last->height();
+ }
+ }
+ if ( toPage == -1 )
+ toPage = pageCount() - 1;
+ KWFrameList::recalcFrames(this, fromPage, toPage);
+ }
+ kdDebug(32002) << " ~recalcFrames" << endl;
+}
+
+bool KWDocument::loadChildren( KoStore *store )
+{
+ //kdDebug(32001) << "KWDocument::loadChildren" << endl;
+ QPtrListIterator<KoDocumentChild> it( children() );
+ for( ; it.current(); ++it ) {
+ if ( !it.current()->loadDocument( store ) )
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+void KWDocument::loadPictureMap ( QDomElement& domElement )
+{
+ m_pictureMap.clear();
+
+ // <PICTURES>
+ QDomElement picturesElem = domElement.namedItem( "PICTURES" ).toElement();
+ if ( !picturesElem.isNull() )
+ {
+ m_pictureCollection->readXML( picturesElem, m_pictureMap );
+ }
+
+ // <PIXMAPS>
+ QDomElement pixmapsElem = domElement.namedItem( "PIXMAPS" ).toElement();
+ if ( !pixmapsElem.isNull() )
+ {
+ m_pictureCollection->readXML( pixmapsElem, m_pictureMap );
+ }
+
+ // <CLIPARTS>
+ QDomElement clipartsElem = domElement.namedItem( "CLIPARTS" ).toElement();
+ if ( !clipartsElem.isNull() )
+ {
+ m_pictureCollection->readXML( pixmapsElem, m_pictureMap );
+ }
+}
+
+
+bool KWDocument::loadOasis( const QDomDocument& doc, KoOasisStyles& oasisStyles, const QDomDocument& settings, KoStore* store )
+{
+ QTime dt;
+ dt.start();
+ emit sigProgress( 0 );
+ clear();
+ kdDebug(32001) << "KWDocument::loadOasis" << endl;
+
+ QDomElement content = doc.documentElement();
+ QDomElement realBody ( KoDom::namedItemNS( content, KoXmlNS::office, "body" ) );
+ if ( realBody.isNull() )
+ {
+ kdError(32001) << "No office:body found!" << endl;
+ setErrorMessage( i18n( "Invalid OASIS OpenDocument file. No office:body tag found." ) );
+ return false;
+ }
+ QDomElement body = KoDom::namedItemNS( realBody, KoXmlNS::office, "text" );
+ if ( body.isNull() )
+ {
+ kdError(32001) << "No office:text found!" << endl;
+ QDomElement childElem;
+ QString localName;
+ forEachElement( childElem, realBody ) {
+ localName = childElem.localName();
+ }
+ if ( localName.isEmpty() )
+ setErrorMessage( i18n( "Invalid OASIS OpenDocument file. No tag found inside office:body." ) );
+ else
+ setErrorMessage( i18n( "This is not a word processing document, but %1. Please try opening it with the appropriate application." ).arg( KoDocument::tagNameToDocumentType( localName ) ) );
+ return false;
+ }
+
+ // TODO check versions and mimetypes etc.
+
+ KoOasisContext context( this, *m_varColl, oasisStyles, store );
+
+ createLoadingInfo();
+
+ // In theory the page format is the style:master-page-name of the first paragraph...
+ // But, hmm, in a doc with only a table there was no reference to the master page at all...
+ // So we load the standard page layout to start with, and in KWTextParag
+ // we might overwrite it with another one.
+ m_loadingInfo->m_currentMasterPage = "Standard";
+ if ( !loadOasisPageLayout( m_loadingInfo->m_currentMasterPage, context ) )
+ return false;
+
+ KWOasisLoader oasisLoader( this );
+
+ // <text:page-sequence> oasis extension for DTP (2003-10-27 post by Daniel)
+ m_processingType = ( !KoDom::namedItemNS( body, KoXmlNS::text, "page-sequence" ).isNull() )
+ ? DTP : WP;
+
+ m_hasTOC = false;
+ m_tabStop = MM_TO_POINT(15);
+ const QDomElement* defaultParagStyle = oasisStyles.defaultStyle( "paragraph" );
+ if ( defaultParagStyle ) {
+ KoStyleStack stack;
+ stack.push( *defaultParagStyle );
+ stack.setTypeProperties( "paragraph" );
+ QString tabStopVal = stack.attributeNS( KoXmlNS::style, "tab-stop-distance" );
+ if ( !tabStopVal.isEmpty() )
+ m_tabStop = KoUnit::parseValue( tabStopVal );
+ }
+ m_initialEditing = 0;
+
+ // TODO MAILMERGE
+
+ // Variable settings
+ // By default display real variable value
+ if ( !isReadWrite())
+ m_varColl->variableSetting()->setDisplayFieldCode(false);
+
+ // Load all styles before the corresponding paragraphs try to use them!
+ m_styleColl->loadOasisStyles( context );
+ if ( m_frameStyleColl->loadOasisStyles( context ) == 0 ) {
+ // no styles loaded -> load default styles
+ loadDefaultFrameStyleTemplates();
+ }
+
+ if ( m_tableStyleColl->loadOasisStyles( context, *m_styleColl, *m_frameStyleColl ) == 0 ) {
+ // no styles loaded -> load default styles
+ loadDefaultTableStyleTemplates();
+ }
+
+ static_cast<KWVariableSettings *>( m_varColl->variableSetting() )
+ ->loadNoteConfiguration( oasisStyles.officeStyle() );
+
+ loadDefaultTableTemplates();
+
+ if ( m_processingType == WP ) {
+ // Create main frameset
+ KWTextFrameSet *fs = new KWTextFrameSet( this, i18n( "Main Text Frameset" ) );
+ m_lstFrameSet.append( fs ); // don't use addFrameSet here. We'll call finalize() once and for all in completeLoading
+ fs->loadOasisContent( body, context );
+ KWFrame* frame = new KWFrame( fs, 29, 42, 566-29, 798-42 );
+ frame->setFrameBehavior( KWFrame::AutoCreateNewFrame );
+ frame->setNewFrameBehavior( KWFrame::Reconnect );
+ fs->addFrame( frame );
+
+ // load padding, background and borders for the main frame
+ const QDomElement* masterPage = context.oasisStyles().masterPages()[ m_loadingInfo->m_currentMasterPage ];
+ const QDomElement *masterPageStyle = masterPage ? context.oasisStyles().findStyle(masterPage->attributeNS( KoXmlNS::style, "page-layout-name", QString::null ) ) : 0;
+ if ( masterPageStyle )
+ {
+ KoStyleStack styleStack;
+ styleStack.push( *masterPageStyle );
+ styleStack.setTypeProperties( "page-layout" );
+ frame->loadBorderProperties( styleStack );
+ }
+ fs->renumberFootNotes( false /*no repaint*/ );
+
+ } else {
+ // DTP mode: the items in the body are page-sequence and then frames
+ QDomElement tag;
+ forEachElement( tag, body )
+ {
+ context.styleStack().save();
+ const QString localName = tag.localName();
+ if ( localName == "page-sequence" && tag.namespaceURI() == KoXmlNS::text )
+ {
+ // We don't have support for changing the page layout yet, so just take the
+ // number of pages
+ int pages=1;
+ QDomElement page;
+ forEachElement( page, tag )
+ ++pages;
+ kdDebug() << "DTP mode: found " << pages << "pages" << endl;
+ //setPageCount ( pages );
+ }
+ else if ( localName == "frame" && tag.namespaceURI() == KoXmlNS::draw )
+ oasisLoader.loadFrame( tag, context, KoPoint() );
+ else
+ kdWarning(32001) << "Unsupported tag in DTP loading:" << tag.tagName() << endl;
+ }
+ }
+
+ if ( !loadMasterPageStyle( m_loadingInfo->m_currentMasterPage, context ) )
+ return false;
+
+ if ( context.cursorTextParagraph() ) {
+ // Maybe, once 1.3-support is dropped, we can get rid of InitialEditing and fetch the
+ // values from KoOasisContext? But well, it lives a bit longer.
+ // At least we could store a KWFrameSet* and a KoTextParag* instead of a name and an id.
+ m_initialEditing = new InitialEditing();
+ KWTextFrameSet* fs = static_cast<KWTextDocument *>( context.cursorTextParagraph()->textDocument() )->textFrameSet();
+ m_initialEditing->m_initialFrameSet = fs->name();
+ m_initialEditing->m_initialCursorParag = context.cursorTextParagraph()->paragId();
+ m_initialEditing->m_initialCursorIndex = context.cursorTextIndex();
+ }
+
+ if ( !settings.isNull() )
+ {
+ oasisLoader.loadOasisSettings( settings );
+ }
+
+ kdDebug(32001) << "Loading took " << (float)(dt.elapsed()) / 1000 << " seconds" << endl;
+ endOfLoading();
+
+ // This sets the columns and header/footer flags, and calls recalcFrames,
+ // so it must be done last.
+ setPageLayout( m_pageLayout, m_loadingInfo->columns, m_loadingInfo->hf, false );
+
+ //printDebug();
+ return true;
+}
+
+bool KWDocument::loadOasisPageLayout( const QString& masterPageName, KoOasisContext& context )
+{
+ KoColumns& columns = m_loadingInfo->columns;
+
+ const KoOasisStyles& oasisStyles = context.oasisStyles();
+ const QDomElement* masterPage = oasisStyles.masterPages()[ masterPageName ];
+ Q_ASSERT( masterPage );
+ const QDomElement *masterPageStyle = masterPage ? oasisStyles.findStyle( masterPage->attributeNS( KoXmlNS::style, "page-layout-name", QString::null ) ) : 0;
+ Q_ASSERT( masterPageStyle );
+ if ( masterPageStyle )
+ {
+ m_pageLayout.loadOasis( *masterPageStyle );
+ pageManager()->setDefaultPage(m_pageLayout);
+
+ const QDomElement properties( KoDom::namedItemNS( *masterPageStyle, KoXmlNS::style, "page-layout-properties" ) );
+ const QDomElement footnoteSep = KoDom::namedItemNS( properties, KoXmlNS::style, "footnote-sep" );
+ if ( !footnoteSep.isNull() ) {
+ // style:width="0.018cm" style:distance-before-sep="0.101cm"
+ // style:distance-after-sep="0.101cm" style:adjustment="left"
+ // style:rel-width="25%" style:color="#000000"
+ const QString width = footnoteSep.attributeNS( KoXmlNS::style, "width", QString::null );
+ if ( !width.isEmpty() ) {
+ m_footNoteSeparatorLineWidth = KoUnit::parseValue( width );
+ }
+
+ QString pageWidth = footnoteSep.attributeNS( KoXmlNS::style, "rel-width", QString::null );
+ if ( pageWidth.endsWith( "%" ) ) {
+ pageWidth.truncate( pageWidth.length() - 1 ); // remove '%'
+ m_iFootNoteSeparatorLineLength = qRound( pageWidth.toDouble() );
+ }
+ // Not in KWord: color, distance before and after separator
+
+ const QString style = footnoteSep.attributeNS( KoXmlNS::style, "line-style", QString::null );
+ if ( style == "solid" || style.isEmpty() )
+ m_footNoteSeparatorLineType = SLT_SOLID;
+ else if ( style == "dash" )
+ m_footNoteSeparatorLineType = SLT_DASH;
+ else if ( style == "dotted" )
+ m_footNoteSeparatorLineType = SLT_DOT;
+ else if ( style == "dot-dash" )
+ m_footNoteSeparatorLineType = SLT_DASH_DOT;
+ else if ( style == "dot-dot-dash" )
+ m_footNoteSeparatorLineType = SLT_DASH_DOT_DOT;
+ else
+ kdDebug() << "Unknown value for m_footNoteSeparatorLineType: " << style << endl;
+
+ const QString pos = footnoteSep.attributeNS( KoXmlNS::style, "adjustment", QString::null );
+ if ( pos == "centered" )
+ m_footNoteSeparatorLinePos = SLP_CENTERED;
+ else if ( pos == "right")
+ m_footNoteSeparatorLinePos = SLP_RIGHT;
+ else // if ( pos == "left" )
+ m_footNoteSeparatorLinePos = SLP_LEFT;
+ }
+
+ const QDomElement columnsElem = KoDom::namedItemNS( properties, KoXmlNS::style, "columns" );
+ if ( !columnsElem.isNull() )
+ {
+ columns.columns = columnsElem.attributeNS( KoXmlNS::fo, "column-count", QString::null ).toInt();
+ if ( columns.columns == 0 )
+ columns.columns = 1;
+ // TODO OASIS OpenDocument supports columns of different sizes, using <style:column style:rel-width="...">
+ // (with fo:start-indent/fo:end-indent for per-column spacing)
+ // But well, it also allows us to specify a single gap.
+ if ( columnsElem.hasAttributeNS( KoXmlNS::fo, "column-gap" ) )
+ columns.ptColumnSpacing = KoUnit::parseValue( columnsElem.attributeNS( KoXmlNS::fo, "column-gap", QString::null ) );
+ // It also supports drawing a vertical line as a separator...
+ }
+
+ m_headerVisible = false;
+ m_footerVisible = false;
+
+ // TODO spHeadBody (where is this in OOo?)
+ // TODO spFootBody (where is this in OOo?)
+ // Answer: margins of the <style:header-footer> element
+ }
+ else // this doesn't happen with normal documents, but it can happen if copying something,
+ // pasting into konq as foo.odt, then opening that...
+ {
+ columns.columns = 1;
+ columns.ptColumnSpacing = 2;
+ m_headerVisible = false;
+ m_footerVisible = false;
+ m_pageLayout = KoPageLayout::standardLayout();
+ pageManager()->setDefaultPage(m_pageLayout);
+ }
+ return true;
+}
+
+bool KWDocument::loadMasterPageStyle( const QString& masterPageName, KoOasisContext& context )
+{
+ const KoOasisStyles& oasisStyles = context.oasisStyles();
+ const QDomElement* masterPage = oasisStyles.masterPages()[ masterPageName ];
+ Q_ASSERT( masterPage );
+ const QDomElement *masterPageStyle = masterPage ? oasisStyles.findStyle( masterPage->attributeNS( KoXmlNS::style, "page-layout-name", QString::null ) ) : 0;
+ Q_ASSERT( masterPageStyle );
+
+ // This check is done here and not in loadOasisPageLayout in case the Standard master-page
+ // has no page information but the first paragraph points to a master-page that does (#129585)
+ if ( m_pageLayout.ptWidth <= 1e-13 || m_pageLayout.ptHeight <= 1e-13 )
+ {
+ // Loading page layout failed, try to see why.
+ QDomElement properties( KoDom::namedItemNS( *masterPageStyle, KoXmlNS::style, "page-layout-properties" ) );
+ //if ( properties.isNull() )
+ // setErrorMessage( i18n( "Invalid document. No page layout properties were found. The application which produced this document isn't OASIS-compliant." ) );
+ //else if ( properties.hasAttributeNS( KoXmlNS::fo, "page-width" ) )
+ // setErrorMessage( i18n( "Invalid document. Page layout has no page width. The application which produced this document isn't OASIS-compliant." ) );
+ //else
+ if ( properties.hasAttributeNS( "http://www.w3.org/1999/XSL/Format", "page-width" ) )
+ setErrorMessage( i18n( "Invalid document. 'fo' has the wrong namespace. The application which produced this document is not OASIS-compliant." ) );
+ else
+ setErrorMessage( i18n( "Invalid document. Paper size: %1x%2" ).arg( m_pageLayout.ptWidth ).arg( m_pageLayout.ptHeight ) );
+ return false;
+ }
+
+
+ KoKWHeaderFooter& hf = m_loadingInfo->hf;
+
+ bool hasEvenOddHeader = false;
+ bool hasEvenOddFooter = false;
+ if ( masterPageStyle )
+ {
+ KWOasisLoader oasisLoader( this );
+
+ QDomElement headerStyle = KoDom::namedItemNS( *masterPageStyle, KoXmlNS::style, "header-style" );
+ QDomElement footerStyle = KoDom::namedItemNS( *masterPageStyle, KoXmlNS::style, "footer-style" );
+ QDomElement headerLeftElem = KoDom::namedItemNS( *masterPage, KoXmlNS::style, "header-left" );
+ QDomElement headerFirstElem = KoDom::namedItemNS( *masterPage, KoXmlNS::style, "header-first" ); // hack, not oasis compliant
+ const bool hasFirstHeader = !headerFirstElem.isNull();
+ if ( !headerLeftElem.isNull() )
+ {
+ hasEvenOddHeader = true;
+ hf.header = hasFirstHeader ? HF_FIRST_EO_DIFF : HF_EO_DIFF;
+ oasisLoader.loadOasisHeaderFooter( headerLeftElem, hasEvenOddHeader, headerStyle, context );
+ }
+ else
+ {
+ hf.header = hasFirstHeader ? HF_FIRST_DIFF : HF_SAME;
+ }
+ if ( hasFirstHeader )
+ {
+ oasisLoader.loadOasisHeaderFooter( headerFirstElem, hasEvenOddHeader, headerStyle, context );
+ }
+
+ QDomElement headerElem = KoDom::namedItemNS( *masterPage, KoXmlNS::style, "header" );
+ if ( !headerElem.isNull() )
+ {
+ oasisLoader.loadOasisHeaderFooter( headerElem, hasEvenOddHeader, headerStyle, context );
+ }
+
+ // -- and now footers
+
+ QDomElement footerLeftElem = KoDom::namedItemNS( *masterPage, KoXmlNS::style, "footer-left" );
+ QDomElement footerFirstElem = KoDom::namedItemNS( *masterPage, KoXmlNS::style, "footer-first" ); // hack, not oasis compliant
+ const bool hasFirstFooter = !footerFirstElem.isNull();
+ if ( !footerLeftElem.isNull() )
+ {
+ hasEvenOddFooter = true;
+ hf.footer = hasFirstFooter ? HF_FIRST_EO_DIFF : HF_EO_DIFF;
+ oasisLoader.loadOasisHeaderFooter( footerLeftElem, hasEvenOddFooter, footerStyle, context );
+ }
+ else
+ {
+ hf.footer = hasFirstFooter ? HF_FIRST_DIFF : HF_SAME;
+ }
+ if ( hasFirstFooter )
+ {
+ oasisLoader.loadOasisHeaderFooter( footerFirstElem, hasEvenOddFooter, footerStyle, context );
+ }
+ QDomElement footerElem = KoDom::namedItemNS( *masterPage, KoXmlNS::style, "footer" );
+ if ( !footerElem.isNull() )
+ {
+ oasisLoader.loadOasisHeaderFooter( footerElem, hasEvenOddFooter, footerStyle, context );
+ }
+
+ // The bottom margin of headers is what we call headerBodySpacing
+ // (TODO support the 3 other margins)
+ if ( !headerStyle.isNull() ) {
+ context.styleStack().push( headerStyle );
+ context.styleStack().setTypeProperties( "header-footer" );
+ hf.ptHeaderBodySpacing = KoUnit::parseValue( context.styleStack().attributeNS( KoXmlNS::fo, "margin-bottom" ) );
+ context.styleStack().pop();
+ }
+ // The top margin of footers is what we call footerBodySpacing
+ // (TODO support the 3 other margins)
+ if ( !footerStyle.isNull() ) {
+ context.styleStack().push( footerStyle );
+ context.styleStack().setTypeProperties( "header-footer" );
+ hf.ptFooterBodySpacing = KoUnit::parseValue( context.styleStack().attributeNS( KoXmlNS::fo, "margin-top" ) );
+ context.styleStack().pop();
+ }
+ // TODO ptFootNoteBodySpacing
+ }
+ return true;
+}
+
+// Called before loading
+// It's important to clear out anything that might be in the document already,
+// for things like using DCOP to load multiple documents into the same KWDocument,
+// or "reload" when kword is embedded into konqueror.
+void KWDocument::clear()
+{
+ m_pictureMap.clear();
+ m_textImageRequests.clear();
+ m_pictureRequests.clear();
+ m_anchorRequests.clear();
+ m_footnoteVarRequests.clear();
+ m_spellCheckIgnoreList.clear();
+
+ m_pageHeaderFooter.header = HF_SAME;
+ m_pageHeaderFooter.footer = HF_SAME;
+ m_pageHeaderFooter.ptHeaderBodySpacing = 10;
+ m_pageHeaderFooter.ptFooterBodySpacing = 10;
+ m_pageHeaderFooter.ptFootNoteBodySpacing = 10;
+ m_pageColumns.columns = 1;
+ m_pageColumns.ptColumnSpacing = m_defaultColumnSpacing;
+ m_bHasEndNotes = false;
+
+ m_iFootNoteSeparatorLineLength = 20; // 20%, i.e. 1/5th
+ m_footNoteSeparatorLineWidth = 0.5; // like in OOo
+ m_footNoteSeparatorLineType = SLT_SOLID;
+
+ m_lstFrameSet.clear();
+
+ m_varColl->clear();
+ m_pictureCollection->clear();
+ m_varFormatCollection->clear();
+
+ m_styleColl->clear();
+ m_frameStyleColl->clear();
+ m_tableStyleColl->clear();
+ m_tableTemplateColl->clear();
+
+ // Some simple import filters don't define any style,
+ // so let's have a Standard style at least
+ KoParagStyle * standardStyle = new KoParagStyle( "Standard" ); // This gets translated later on
+ //kdDebug() << "KWDocument::KWDocument creating standardStyle " << standardStyle << endl;
+ standardStyle->format().setFont( m_defaultFont );
+ m_styleColl->addStyle( standardStyle );
+
+ // And let's do the same for framestyles
+ KWFrameStyle * standardFrameStyle = new KWFrameStyle( "Plain" );
+ standardFrameStyle->setBackgroundColor(Qt::white);
+ standardFrameStyle->setTopBorder(KoBorder(Qt::black,KoBorder::SOLID,0));
+ standardFrameStyle->setRightBorder(KoBorder(Qt::black,KoBorder::SOLID,0));
+ standardFrameStyle->setLeftBorder(KoBorder(Qt::black,KoBorder::SOLID,0));
+ standardFrameStyle->setBottomBorder(KoBorder(Qt::black,KoBorder::SOLID,0));
+ m_frameStyleColl->addStyle( standardFrameStyle );
+
+ // And let's do the same for tablestyles
+ KWTableStyle *standardTableStyle = new KWTableStyle( "Plain", standardStyle, standardFrameStyle );
+ m_tableStyleColl->addStyle( standardTableStyle );
+}
+
+bool KWDocument::loadXML( QIODevice *, const QDomDocument & doc )
+{
+ QTime dt;
+ dt.start();
+ emit sigProgress( 0 );
+ kdDebug(32001) << "KWDocument::loadXML" << endl;
+ clear();
+
+ KoPageLayout pgLayout;
+ KoColumns columns;
+ columns.columns = 1;
+ columns.ptColumnSpacing = m_defaultColumnSpacing;
+ KoKWHeaderFooter hf;
+ hf.header = HF_SAME;
+ hf.footer = HF_SAME;
+ hf.ptHeaderBodySpacing = 10.0;
+ hf.ptFooterBodySpacing = 10.0;
+ hf.ptFootNoteBodySpacing = 10.0;
+
+ QString value;
+ QDomElement word = doc.documentElement();
+
+ value = KWDocument::getAttribute( word, "mime", QString::null );
+ if ( value.isEmpty() )
+ {
+ kdError(32001) << "No mime type specified!" << endl;
+ setErrorMessage( i18n( "Invalid document. No mimetype specified." ) );
+ return false;
+ }
+ else if ( value != "application/x-kword" && value != "application/vnd.kde.kword" )
+ {
+ kdError(32001) << "Unknown mime type " << value << endl;
+ setErrorMessage( i18n( "Invalid document. Expected mimetype application/x-kword or application/vnd.kde.kword, got %1" ).arg( value ) );
+ return false;
+ }
+ m_syntaxVersion = KWDocument::getAttribute( word, "syntaxVersion", 0 );
+ if ( m_syntaxVersion > CURRENT_SYNTAX_VERSION )
+ {
+ int ret = KMessageBox::warningContinueCancel(
+ 0, i18n("This document was created with a newer version of KWord (syntax version: %1)\n"
+ "Opening it in this version of KWord will lose some information.").arg(m_syntaxVersion),
+ i18n("File Format Mismatch"), KStdGuiItem::cont() );
+ if ( ret == KMessageBox::Cancel )
+ {
+ setErrorMessage( "USER_CANCELED" );
+ return false;
+ }
+ }
+
+ createLoadingInfo();
+
+ // Looks like support for the old way of naming images internally,
+ // see completeLoading.
+ value = KWDocument::getAttribute( word, "url", QString::null );
+ if ( !value.isNull() )
+ {
+ m_urlIntern = KURL( value ).path();
+ }
+
+ emit sigProgress(5);
+
+ // <PAPER>
+ QDomElement paper = word.namedItem( "PAPER" ).toElement();
+ if ( !paper.isNull() )
+ {
+ pgLayout.format = static_cast<KoFormat>( KWDocument::getAttribute( paper, "format", 0 ) );
+ pgLayout.orientation = static_cast<KoOrientation>( KWDocument::getAttribute( paper, "orientation", 0 ) );
+ pgLayout.ptWidth = getAttribute( paper, "width", 0.0 );
+ pgLayout.ptHeight = getAttribute( paper, "height", 0.0 );
+ kdDebug() << " ptWidth=" << pgLayout.ptWidth << endl;
+ kdDebug() << " ptHeight=" << pgLayout.ptHeight << endl;
+ if ( pgLayout.ptWidth <= 0 || pgLayout.ptHeight <= 0 )
+ {
+ // Old document?
+ pgLayout.ptWidth = getAttribute( paper, "ptWidth", 0.0 );
+ pgLayout.ptHeight = getAttribute( paper, "ptHeight", 0.0 );
+ kdDebug() << " ptWidth=" << pgLayout.ptWidth << endl;
+ kdDebug() << " ptHeight=" << pgLayout.ptHeight << endl;
+
+ // Still wrong?
+ if ( pgLayout.ptWidth <= 0 || pgLayout.ptHeight <= 0 )
+ {
+ setErrorMessage( i18n( "Invalid document. Paper size: %1x%2" )
+ .arg( pgLayout.ptWidth ).arg( pgLayout.ptHeight ) );
+ return false;
+ }
+ }
+
+ hf.header = static_cast<KoHFType>( KWDocument::getAttribute( paper, "hType", 0 ) );
+ hf.footer = static_cast<KoHFType>( KWDocument::getAttribute( paper, "fType", 0 ) );
+ hf.ptHeaderBodySpacing = getAttribute( paper, "spHeadBody", 0.0 );
+ hf.ptFooterBodySpacing = getAttribute( paper, "spFootBody", 0.0 );
+ hf.ptFootNoteBodySpacing = getAttribute( paper, "spFootNoteBody", 10.0 );
+ m_iFootNoteSeparatorLineLength = getAttribute( paper, "slFootNoteLength", 20);
+ if ( paper.hasAttribute( "slFootNoteWidth" ) )
+ m_footNoteSeparatorLineWidth = paper.attribute( "slFootNoteWidth" ).toDouble();
+ m_footNoteSeparatorLineType = static_cast<SeparatorLineLineType>(getAttribute( paper, "slFootNoteType",0));
+
+ if ( paper.hasAttribute("slFootNotePosition"))
+ {
+ QString tmp =paper.attribute("slFootNotePosition");
+ if ( tmp =="centered" )
+ m_footNoteSeparatorLinePos = SLP_CENTERED;
+ else if ( tmp =="right")
+ m_footNoteSeparatorLinePos = SLP_RIGHT;
+ else if ( tmp =="left" )
+ m_footNoteSeparatorLinePos = SLP_LEFT;
+ }
+ columns.columns = KWDocument::getAttribute( paper, "columns", 1 );
+ columns.ptColumnSpacing = KWDocument::getAttribute( paper, "columnspacing", 0.0 );
+ // Now part of the app config
+ //m_zoom = KWDocument::getAttribute( paper, "zoom", 100 );
+ //if(m_zoom!=100)
+ // setZoomAndResolution( m_zoom, KoGlobal::dpiX(), KoGlobal::dpiY(), false, false );
+
+
+ // Support the undocumented syntax actually used by KDE 2.0 for some of the above (:-().
+ // Do not add anything to this block!
+ if ( pgLayout.ptWidth == 0.0 )
+ pgLayout.ptWidth = getAttribute( paper, "ptWidth", 0.0 );
+ if ( pgLayout.ptHeight == 0.0 )
+ pgLayout.ptHeight = getAttribute( paper, "ptHeight", 0.0 );
+ if ( hf.ptHeaderBodySpacing == 0.0 )
+ hf.ptHeaderBodySpacing = getAttribute( paper, "ptHeadBody", 0.0 );
+ if ( hf.ptFooterBodySpacing == 0.0 )
+ hf.ptFooterBodySpacing = getAttribute( paper, "ptFootBody", 0.0 );
+ if ( columns.ptColumnSpacing == 0.0 )
+ columns.ptColumnSpacing = getAttribute( paper, "ptColumnspc", 0.0 );
+
+ // <PAPERBORDERS>
+ QDomElement paperborders = paper.namedItem( "PAPERBORDERS" ).toElement();
+ if ( !paperborders.isNull() )
+ {
+ pgLayout.ptLeft = getAttribute( paperborders, "left", 0.0 );
+ pgLayout.ptTop = getAttribute( paperborders, "top", 0.0 );
+ pgLayout.ptRight = getAttribute( paperborders, "right", 0.0 );
+ pgLayout.ptBottom = getAttribute( paperborders, "bottom", 0.0 );
+
+ // Support the undocumented syntax actually used by KDE 2.0 for some of the above (:-().
+ if ( pgLayout.ptLeft == 0.0 )
+ pgLayout.ptLeft = getAttribute( paperborders, "ptLeft", 0.0 );
+ if ( pgLayout.ptTop == 0.0 )
+ pgLayout.ptTop = getAttribute( paperborders, "ptTop", 0.0 );
+ if ( pgLayout.ptRight == 0.0 )
+ pgLayout.ptRight = getAttribute( paperborders, "ptRight", 0.0 );
+ if ( pgLayout.ptBottom == 0.0 )
+ pgLayout.ptBottom = getAttribute( paperborders, "ptBottom", 0.0 );
+ }
+ else
+ kdWarning() << "No <PAPERBORDERS> tag!" << endl;
+ }
+ else
+ kdWarning() << "No <PAPER> tag! This is a mandatory tag! Expect weird page sizes..." << endl;
+
+ // <ATTRIBUTES>
+ QDomElement attributes = word.namedItem( "ATTRIBUTES" ).toElement();
+ if ( !attributes.isNull() )
+ {
+ m_processingType = static_cast<ProcessingType>( KWDocument::getAttribute( attributes, "processing", 0 ) );
+ //KWDocument::getAttribute( attributes, "standardpage", QString::null );
+ m_headerVisible = static_cast<bool>( KWDocument::getAttribute( attributes, "hasHeader", 0 ) );
+ m_footerVisible = static_cast<bool>( KWDocument::getAttribute( attributes, "hasFooter", 0 ) );
+ if ( attributes.hasAttribute( "unit" ) )
+ setUnit( KoUnit::unit( attributes.attribute( "unit" ) ) );
+ m_hasTOC = static_cast<bool>(KWDocument::getAttribute( attributes,"hasTOC", 0 ) );
+ m_tabStop = KWDocument::getAttribute( attributes, "tabStopValue", MM_TO_POINT(15) );
+ m_initialEditing = new InitialEditing();
+ m_initialEditing->m_initialFrameSet = attributes.attribute( "activeFrameset" );
+ m_initialEditing->m_initialCursorParag = attributes.attribute( "cursorParagraph" ).toInt();
+ m_initialEditing->m_initialCursorIndex = attributes.attribute( "cursorIndex" ).toInt();
+ } else {
+ m_processingType = WP;
+ m_headerVisible = false;
+ m_footerVisible = false;
+ m_hasTOC = false;
+ m_tabStop = MM_TO_POINT(15);
+ delete m_initialEditing;
+ m_initialEditing = 0L;
+ }
+
+ setPageLayout( pgLayout, columns, hf, false );
+
+ variableCollection()->variableSetting()->load(word );
+ //by default display real variable value
+ if ( !isReadWrite())
+ variableCollection()->variableSetting()->setDisplayFieldCode(false);
+
+ emit sigProgress(10);
+
+ QDomElement mailmerge = word.namedItem( "MAILMERGE" ).toElement();
+ if (mailmerge!=QDomElement())
+ {
+ m_slDataBase->load(mailmerge);
+ }
+
+ emit sigProgress(15);
+
+ // Load all styles before the corresponding paragraphs try to use them!
+ QDomElement stylesElem = word.namedItem( "STYLES" ).toElement();
+ if ( !stylesElem.isNull() )
+ loadStyleTemplates( stylesElem );
+
+ emit sigProgress(17);
+
+ QDomElement frameStylesElem = word.namedItem( "FRAMESTYLES" ).toElement();
+ if ( !frameStylesElem.isNull() )
+ loadFrameStyleTemplates( frameStylesElem );
+ else // load default styles
+ loadDefaultFrameStyleTemplates();
+
+ emit sigProgress(18);
+
+ QDomElement tableStylesElem = word.namedItem( "TABLESTYLES" ).toElement();
+ if ( !tableStylesElem.isNull() )
+ loadTableStyleTemplates( tableStylesElem );
+ else // load default styles
+ loadDefaultTableStyleTemplates();
+
+ emit sigProgress(19);
+
+ loadDefaultTableTemplates();
+
+ emit sigProgress(20);
+
+ QDomElement bookmark = word.namedItem( "BOOKMARKS" ).toElement();
+ if( !bookmark.isNull() )
+ {
+ QDomElement bookmarkitem = word.namedItem("BOOKMARKS").toElement();
+ bookmarkitem = bookmarkitem.firstChild().toElement();
+
+ while ( !bookmarkitem.isNull() )
+ {
+ if ( bookmarkitem.tagName() == "BOOKMARKITEM" )
+ {
+ KWLoadingInfo::BookMark bk;
+ bk.bookname=bookmarkitem.attribute("name");
+ bk.cursorStartIndex=bookmarkitem.attribute("cursorIndexStart").toInt();
+ bk.frameSetName=bookmarkitem.attribute("frameset");
+ bk.paragStartIndex = bookmarkitem.attribute("startparag").toInt();
+ bk.paragEndIndex = bookmarkitem.attribute("endparag").toInt();
+ bk.cursorEndIndex = bookmarkitem.attribute("cursorIndexEnd").toInt();
+ Q_ASSERT( m_loadingInfo );
+ m_loadingInfo->bookMarkList.append( bk );
+ }
+ bookmarkitem = bookmarkitem.nextSibling().toElement();
+ }
+ }
+
+ QStringList lst;
+ QDomElement spellCheckIgnore = word.namedItem( "SPELLCHECKIGNORELIST" ).toElement();
+ if( !spellCheckIgnore.isNull() )
+ {
+ QDomElement spellWord=word.namedItem("SPELLCHECKIGNORELIST").toElement();
+ spellWord=spellWord.firstChild().toElement();
+ while ( !spellWord.isNull() )
+ {
+ if ( spellWord.tagName()=="SPELLCHECKIGNOREWORD" )
+ lst.append(spellWord.attribute("word"));
+ spellWord=spellWord.nextSibling().toElement();
+ }
+ }
+ setSpellCheckIgnoreList( lst );
+
+ emit sigProgress(25);
+
+
+ QDomElement framesets = word.namedItem( "FRAMESETS" ).toElement();
+ if ( !framesets.isNull() )
+ loadFrameSets( framesets );
+
+ emit sigProgress(85);
+
+ loadPictureMap( word );
+
+ emit sigProgress(90);
+
+ // <EMBEDDED>
+ loadEmbeddedObjects( word );
+
+ emit sigProgress(100); // the rest is only processing, not loading
+
+ kdDebug(32001) << "Loading took " << (float)(dt.elapsed()) / 1000 << " seconds" << endl;
+
+ endOfLoading();
+ return true;
+}
+
+void KWDocument::endOfLoading() // called by both oasis and oldxml
+{
+ // insert pages
+ double maxBottom = 0;
+ for (QPtrListIterator<KWFrameSet> fsit = framesetsIterator(); fsit.current() ; ++fsit ) {
+ KWFrameSet *fs = fsit.current();
+ for (QPtrListIterator<KWFrame> fit = fs->frameIterator(); fit.current() ; ++fit ) {
+ KWFrame *frame = fit.current();
+ maxBottom = QMAX(maxBottom, frame->bottom());
+ }
+ }
+ KWPage *last = pageManager()->page(lastPage());
+ double docHeight = last->offsetInDocument() + last->height();
+ while(docHeight <= maxBottom) {
+ kdDebug(32001) << "KWDocument::loadXML appends a page\n";
+ last = pageManager()->appendPage();
+ docHeight += last->height();
+ }
+
+ bool first_footer = false, even_footer = false, odd_footer = false;
+ bool first_header = false, even_header = false, odd_header = false;
+
+ QPtrListIterator<KWFrameSet> fit = framesetsIterator();
+ for ( ; fit.current() ; ++fit )
+ {
+ switch( fit.current()->frameSetInfo() ) {
+ case KWFrameSet::FI_FIRST_HEADER: first_header = true; break;
+ case KWFrameSet::FI_ODD_HEADER: odd_header = true; break;
+ case KWFrameSet::FI_EVEN_HEADER: even_header = true; break;
+ case KWFrameSet::FI_FIRST_FOOTER: first_footer = true; break;
+ case KWFrameSet::FI_ODD_FOOTER: odd_footer = true; break;
+ case KWFrameSet::FI_EVEN_FOOTER: even_footer = true; break;
+ case KWFrameSet::FI_FOOTNOTE: break;
+ default: break;
+ }
+ }
+
+ // Create defaults if they were not in the input file.
+
+ // Where to insert the new frames: not at the end, since that breaks oasis-kword.sh
+ uint newFramesetsIndex = m_lstFrameSet.isEmpty() ? 0 : 1;
+
+ if ( !first_header ) {
+ KWTextFrameSet *fs = new KWTextFrameSet( this, i18n( "First Page Header" ) );
+ //kdDebug(32001) << "KWDocument::loadXML KWTextFrameSet created " << fs << endl;
+ fs->setFrameSetInfo( KWFrameSet::FI_FIRST_HEADER );
+ KWPage *page = pageManager()->page(startPage());
+ KWFrame *frame = new KWFrame(fs, page->leftMargin(), page->topMargin(),
+ page->width() - page->leftMargin() - page->rightMargin(), 20 );
+ //kdDebug(32001) << "KWDocument::loadXML KWFrame created " << frame << endl;
+ frame->setFrameBehavior( KWFrame::AutoExtendFrame );
+ frame->setNewFrameBehavior( KWFrame::Copy );
+ fs->addFrame( frame );
+ m_lstFrameSet.insert( newFramesetsIndex++, fs );
+ }
+
+ if ( !odd_header ) {
+ KWTextFrameSet *fs = new KWTextFrameSet( this, i18n( "Odd Pages Header" ) );
+ //kdDebug(32001) << "KWDocument::loadXML KWTextFrameSet created " << fs << endl;
+ fs->setFrameSetInfo( KWFrameSet::FI_ODD_HEADER );
+ KWPage *page = pageManager()->page(QMIN(startPage()+2, lastPage()));
+ KWFrame *frame = new KWFrame(fs, page->leftMargin(), page->topMargin(),
+ page->width() - page->leftMargin() - page->rightMargin(), 20 );
+ //kdDebug(32001) << "KWDocument::loadXML KWFrame created " << *frame << endl;
+ frame->setFrameBehavior( KWFrame::AutoExtendFrame );
+ frame->setNewFrameBehavior( KWFrame::Copy );
+ fs->addFrame( frame );
+ m_lstFrameSet.insert( newFramesetsIndex++, fs );
+ }
+
+ if ( !even_header ) {
+ KWTextFrameSet *fs = new KWTextFrameSet( this, i18n( "Even Pages Header" ) );
+ //kdDebug(32001) << "KWDocument::loadXML KWTextFrameSet created " << fs << endl;
+ fs->setFrameSetInfo( KWFrameSet::FI_EVEN_HEADER );
+ KWPage *page = pageManager()->page(QMIN(startPage()+1, lastPage()));
+ KWFrame *frame = new KWFrame(fs, page->leftMargin(), page->topMargin(), page->width() -
+ page->leftMargin() - page->rightMargin(), 20 );
+ //kdDebug(32001) << "KWDocument::loadXML KWFrame created " << *frame << endl;
+ frame->setFrameBehavior( KWFrame::AutoExtendFrame );
+ frame->setNewFrameBehavior( KWFrame::Copy );
+ fs->addFrame( frame );
+ m_lstFrameSet.insert( newFramesetsIndex++, fs );
+ }
+
+ if ( !first_footer ) {
+ KWTextFrameSet *fs = new KWTextFrameSet( this, i18n( "First Page Footer" ) );
+ //kdDebug(32001) << "KWDocument::loadXML KWTextFrameSet created " << fs << endl;
+ fs->setFrameSetInfo( KWFrameSet::FI_FIRST_FOOTER );
+ KWPage *page = pageManager()->page(pageManager()->startPage());
+ KWFrame *frame = new KWFrame(fs, page->leftMargin(), page->height() - page->topMargin()- 20,
+ page->width() - page->leftMargin() - page->rightMargin(), 20 );
+ //kdDebug(32001) << "KWDocument::loadXML KWFrame created " << *frame << endl;
+ frame->setFrameBehavior( KWFrame::AutoExtendFrame );
+ frame->setNewFrameBehavior( KWFrame::Copy );
+ fs->addFrame( frame );
+ m_lstFrameSet.insert( newFramesetsIndex++, fs );
+ }
+
+ if ( !odd_footer ) {
+ KWTextFrameSet *fs = new KWTextFrameSet( this, i18n( "Odd Pages Footer" ) );
+ //kdDebug(32001) << "KWDocument::loadXML KWTextFrameSet created " << fs << endl;
+ fs->setFrameSetInfo( KWFrameSet::FI_ODD_FOOTER );
+ KWPage *page = pageManager()->page(QMIN(startPage()+2, lastPage()));
+ KWFrame *frame = new KWFrame(fs, page->leftMargin(), page->height()- page->topMargin() - 20,
+ page->width() - page->leftMargin() - page->rightMargin(), 20 );
+ //kdDebug(32001) << "KWDocument::loadXML KWFrame created " << *frame << endl;
+ frame->setFrameBehavior( KWFrame::AutoExtendFrame );
+ frame->setNewFrameBehavior( KWFrame::Copy );
+ fs->addFrame( frame );
+ m_lstFrameSet.insert( newFramesetsIndex++, fs );
+ }
+
+ if ( !even_footer ) {
+ KWTextFrameSet *fs = new KWTextFrameSet( this, i18n( "Even Pages Footer" ) );
+ //kdDebug(32001) << "KWDocument::loadXML KWTextFrameSet created " << fs << endl;
+ fs->setFrameSetInfo( KWFrameSet::FI_EVEN_FOOTER );
+ KWPage *page = pageManager()->page(QMIN(startPage()+1, lastPage()));
+ KWFrame *frame = new KWFrame(fs, page->leftMargin(), page->height() - page->topMargin()- 20,
+ page->width() - page->leftMargin() - page->rightMargin(), 20 );
+ //kdDebug(32001) << "KWDocument::loadXML KWFrame created " << *frame << endl;
+ frame->setFrameBehavior( KWFrame::AutoExtendFrame );
+ frame->setNewFrameBehavior( KWFrame::Copy );
+ fs->addFrame( frame );
+ m_lstFrameSet.insert( newFramesetsIndex++, fs );
+ }
+
+ // do some sanity checking on document.
+ for (int i = frameSetCount()-1; i>-1; i--) {
+ KWFrameSet *fs = frameSet(i);
+ if(!fs) {
+ kdWarning() << "frameset " << i << " is NULL!!" << endl;
+ m_lstFrameSet.remove(i);
+ continue;
+ }
+ if( fs->type()==FT_TABLE) {
+ static_cast<KWTableFrameSet *>( fs )->validate();
+ } else if (fs->type() == FT_TEXT) {
+ for (int f=fs->frameCount()-1; f>=0; f--) {
+ KWFrame *frame = fs->frame(f);
+ if(frame->left() < 0) {
+ kdWarning() << fs->name() << " frame " << f << " pos.x is < 0, moving frame" << endl;
+ frame->moveBy( 0- frame->left(), 0);
+ }
+ if(frame->right() > m_pageLayout.ptWidth) {
+ kdWarning() << fs->name() << " frame " << f << " rightborder outside page ("
+ << frame->right() << ">" << m_pageLayout.ptWidth << "), shrinking" << endl;
+ frame->setRight(m_pageLayout.ptWidth);
+ }
+ if(fs->isProtectSize())
+ continue; // don't make frames bigger of a protected frameset.
+ if(frame->height() < s_minFrameHeight) {
+ kdWarning() << fs->name() << " frame " << f << " height is so small no text will fit, adjusting (was: "
+ << frame->height() << " is: " << s_minFrameHeight << ")" << endl;
+ frame->setHeight(s_minFrameHeight);
+ }
+ if(frame->width() < s_minFrameWidth) {
+ kdWarning() << fs->name() << " frame " << f << " width is so small no text will fit, adjusting (was: "
+ << frame->width() << " is: " << s_minFrameWidth << ")" << endl;
+ frame->setWidth(s_minFrameWidth);
+ }
+ }
+ if(fs->frameCount() == 0) {
+ KWPage *page = pageManager()->page(startPage());
+ KWFrame *frame = new KWFrame(fs, page->leftMargin(), page->topMargin(),
+ page->width() - page->leftMargin() - page->rightMargin(),
+ page->height() - page->topMargin() - page->bottomMargin());
+ //kdDebug(32001) << "KWDocument::loadXML main-KWFrame created " << *frame << endl;
+ fs->addFrame( frame );
+ }
+ } else if(fs->frameCount() == 0) {
+ kdWarning () << "frameset " << i << " " << fs->name() << " has no frames" << endl;
+ removeFrameSet(fs);
+ if ( fs->type() == FT_PART )
+ delete static_cast<KWPartFrameSet *>(fs)->getChild();
+ delete fs;
+ continue;
+ }
+ if(fs->frameCount() > 0) {
+ KWFrame *frame = fs->frame(0);
+ if(frame->isCopy()) {
+ kdWarning() << "First frame in a frameset[" << fs->name() << "] was set to be a copy; resetting\n";
+ frame->setCopy(false);
+ }
+ }
+ }
+
+ // Renumber footnotes
+ KWTextFrameSet *frameset = dynamic_cast<KWTextFrameSet *>( m_lstFrameSet.getFirst() );
+ if ( frameset )
+ frameset->renumberFootNotes( false /*no repaint*/ );
+
+ emit sigProgress(-1);
+
+ //kdDebug(32001) << "KWDocument::loadXML done" << endl;
+
+ // Connect to notifications from main text-frameset
+ if ( frameset ) {
+ connect( frameset->textObject(), SIGNAL( chapterParagraphFormatted( KoTextParag * ) ),
+ SLOT( slotChapterParagraphFormatted( KoTextParag * ) ) );
+ connect( frameset, SIGNAL( mainTextHeightChanged() ),
+ SIGNAL( mainTextHeightChanged() ) );
+ }
+
+ // Note that more stuff will happen in completeLoading
+}
+
+void KWDocument::startBackgroundSpellCheck()
+{
+ if ( backgroundSpellCheckEnabled() && isReadWrite() )
+ {
+ m_bgSpellCheck->start();
+ }
+}
+
+void KWDocument::loadEmbeddedObjects( QDomElement& word )
+{
+ QDomNodeList listEmbedded = word.elementsByTagName ( "EMBEDDED" );
+ for (unsigned int item = 0; item < listEmbedded.count(); item++)
+ {
+ QDomElement embedded = listEmbedded.item( item ).toElement();
+ loadEmbedded( embedded );
+ }
+}
+
+void KWDocument::loadEmbedded( const QDomElement &embedded )
+{
+ QDomElement object = embedded.namedItem( "OBJECT" ).toElement();
+ if ( !object.isNull() )
+ {
+ KWDocumentChild *ch = new KWDocumentChild( this );
+ ch->load( object, true );
+ insertChild( ch );
+ QDomElement settings = embedded.namedItem( "SETTINGS" ).toElement();
+ QString name;
+ if ( !settings.isNull() )
+ name = settings.attribute( "name" );
+ KWPartFrameSet *fs = new KWPartFrameSet( this, ch, name );
+ m_lstFrameSet.append( fs );
+ if ( !settings.isNull() )
+ {
+ kdDebug(32001) << "KWDocument::loadXML loading embedded object" << endl;
+ fs->load( settings );
+ }
+ else
+ kdError(32001) << "No <SETTINGS> tag in EMBEDDED" << endl;
+
+ } else
+ kdError(32001) << "No <OBJECT> tag in EMBEDDED" << endl;
+}
+
+
+void KWDocument::loadStyleTemplates( const QDomElement &stylesElem )
+{
+ QValueList<QString> followingStyles;
+ QDomNodeList listStyles = stylesElem.elementsByTagName( "STYLE" );
+ if( listStyles.count() > 0) { // we are going to import at least one style.
+ KoParagStyle *s = m_styleColl->findStyle("Standard");
+ //kdDebug(32001) << "KWDocument::loadStyleTemplates looking for Standard, to delete it. Found " << s << endl;
+ if(s) // delete the standard style.
+ m_styleColl->removeStyle(s);
+ }
+ for (unsigned int item = 0; item < listStyles.count(); item++) {
+ QDomElement styleElem = listStyles.item( item ).toElement();
+
+ KoParagStyle *sty = new KoParagStyle( QString::null );
+ // Load the style from the <STYLE> element
+ sty->loadStyle( styleElem, m_syntaxVersion );
+
+ //kdDebug(32001) << "KoParagStyle created name=" << sty->name() << endl;
+
+ if ( m_syntaxVersion < 3 )
+ {
+ // Convert old style (up to 1.2.x included)
+ // "include in TOC if chapter numbering" to the new attribute
+ if ( sty->paragLayout().counter && sty->paragLayout().counter->numbering() == KoParagCounter::NUM_CHAPTER )
+ sty->setOutline( true );
+ }
+
+ // the real value of followingStyle is set below after loading all styles
+ sty->setFollowingStyle( sty );
+
+ QDomElement formatElem = styleElem.namedItem( "FORMAT" ).toElement();
+ if ( !formatElem.isNull() )
+ sty->format() = KWTextParag::loadFormat( formatElem, 0L, defaultFont(), globalLanguage(), globalHyphenation() );
+ else
+ kdWarning(32001) << "No FORMAT tag in <STYLE>" << endl; // This leads to problems in applyStyle().
+
+ // Style created, now let's try to add it
+ sty = m_styleColl->addStyle( sty );
+
+ if(m_styleColl->styleList().count() > followingStyles.count() )
+ {
+ QString following = styleElem.namedItem("FOLLOWING").toElement().attribute("name");
+ followingStyles.append( following );
+ }
+ else
+ kdWarning () << "Found duplicate style declaration, overwriting former " << sty->name() << endl;
+ }
+
+ Q_ASSERT( followingStyles.count() == m_styleColl->styleList().count() );
+
+ unsigned int i=0;
+ for( QValueList<QString>::Iterator it = followingStyles.begin(); it != followingStyles.end(); ++it ) {
+ KoParagStyle * style = m_styleColl->findStyle(*it);
+ m_styleColl->styleAt(i++)->setFollowingStyle( style );
+ }
+
+}
+
+void KWDocument::loadFrameStyleTemplates( const QDomElement &stylesElem )
+{
+ QDomNodeList listStyles = stylesElem.elementsByTagName( "FRAMESTYLE" );
+ if( listStyles.count() > 0) { // we are going to import at least one style.
+ KWFrameStyle *s = m_frameStyleColl->findStyle("Plain");
+ if(s) // delete the standard style.
+ m_frameStyleColl->removeStyle(s);
+ }
+ for (unsigned int item = 0; item < listStyles.count(); item++) {
+ QDomElement styleElem = listStyles.item( item ).toElement();
+
+ KWFrameStyle *sty = new KWFrameStyle( styleElem );
+ m_frameStyleColl->addStyle( sty );
+ }
+}
+
+void KWDocument::loadDefaultFrameStyleTemplates()
+{
+ const QString fsfileName( locate("data", "kword/framestyles.xml") );
+
+ kdDebug(30003) << "Data directory: " << KGlobal::dirs()->resourceDirs( "data" ) << endl;
+ kdDebug(30003) << "Directory searched: " << KGlobal::dirs()->resourceDirs( "data" ) << endl;
+ kdDebug(30003) << "File framestyles.xml searched at: " << fsfileName << endl;
+
+ m_frameStyleColl->setDefault( true );
+
+ if ( ! QFile::exists( fsfileName ) )
+ {
+ kdWarning(30003) << "Cannot find any framestyles.xml" << endl;
+ if (!m_frameStyleColl->findStyle("Plain")) {
+ KWFrameStyle * standardFrameStyle = new KWFrameStyle( "Plain" );
+ standardFrameStyle->setBackgroundColor(QColor("white"));
+ standardFrameStyle->setTopBorder(KoBorder(QColor("black"),KoBorder::SOLID,0));
+ standardFrameStyle->setRightBorder(KoBorder(QColor("black"),KoBorder::SOLID,0));
+ standardFrameStyle->setLeftBorder(KoBorder(QColor("black"),KoBorder::SOLID,0));
+ standardFrameStyle->setBottomBorder(KoBorder(QColor("black"),KoBorder::SOLID,0));
+ m_frameStyleColl->addStyle( standardFrameStyle );
+ }
+ return;
+ }
+
+ kdDebug(30003) << "File framestyles.xml found!" << endl;
+
+ // Open file and parse it
+ QFile in( fsfileName );
+ if ( !in.open( IO_ReadOnly ) )
+ {
+ //i18n( "Couldn't open the file for reading (check read permissions)" );
+ kdWarning(30003) << "Couldn't open the file for reading (check read permissions)" << endl;
+ return;
+ }
+ QString errorMsg;
+ int errorLine;
+ int errorColumn;
+ QDomDocument doc;
+ if ( ! doc.setContent( &in , &errorMsg, &errorLine, &errorColumn ) )
+ {
+ kdError (30003) << "Parsing Error! Aborting! (in KWDocument::loadDefaultFrameStyleTemplates())" << endl
+ << " Line: " << errorLine << " Column: " << errorColumn << endl
+ << " Message: " << errorMsg << endl;
+ }
+ in.close();
+
+ // Start adding framestyles
+ QDomElement stylesElem = doc.documentElement();
+
+ QDomNodeList listStyles = stylesElem.elementsByTagName( "FRAMESTYLE" );
+ if( listStyles.count() > 0) { // we are going to import at least one style.
+ KWFrameStyle *s = m_frameStyleColl->findStyle("Plain");
+ if(s) // delete the standard style.
+ m_frameStyleColl->removeStyle(s);
+ }
+ for (unsigned int item = 0; item < listStyles.count(); item++) {
+ QDomElement styleElem = listStyles.item( item ).toElement();
+
+ KWFrameStyle *sty = new KWFrameStyle( styleElem );
+ m_frameStyleColl->addStyle( sty );
+ }
+}
+
+void KWDocument::loadTableStyleTemplates( const QDomElement& stylesElem )
+{
+ QDomNodeList listStyles = stylesElem.elementsByTagName( "TABLESTYLE" );
+ if( listStyles.count() > 0) { // we are going to import at least one style.
+ KWTableStyle *s = m_tableStyleColl->findStyle("Plain");
+ if(s) // delete the standard style.
+ m_tableStyleColl->removeStyle(s);
+ }
+ for (unsigned int item = 0; item < listStyles.count(); item++) {
+ QDomElement styleElem = listStyles.item( item ).toElement();
+
+ KWTableStyle *sty = new KWTableStyle( styleElem, this );
+ m_tableStyleColl->addStyle( sty );
+ }
+}
+
+void KWDocument::loadDefaultTableStyleTemplates()
+{
+ KURL fsfile;
+
+ m_tableStyleColl->setDefault( true );
+
+ if ( ! QFile::exists(locate("data", "kword/tablestyles.xml")) )
+ {
+ if (!m_tableStyleColl->findStyle("Plain")) {
+ m_tableStyleColl->addStyle( new KWTableStyle( "Plain", m_styleColl->styleAt(0), m_frameStyleColl->frameStyleAt(0) ) );
+ }
+ return;
+ }
+
+ fsfile.setPath( locate("data", "kword/tablestyles.xml") );
+
+ // Open file and parse it
+ QFile in( fsfile.path() );
+ if ( !in.open( IO_ReadOnly ) )
+ {
+ //i18n( "Couldn't open the file for reading (check read permissions)" );
+ return;
+ }
+ in.at(0);
+ QString errorMsg;
+ int errorLine;
+ int errorColumn;
+ QDomDocument doc;
+ if ( doc.setContent( &in , &errorMsg, &errorLine, &errorColumn ) ) {
+ }
+ else
+ {
+ kdError (30003) << "Parsing Error! Aborting! (in KWDocument::loadDefaultTableStyleTemplates())" << endl
+ << " Line: " << errorLine << " Column: " << errorColumn << endl
+ << " Message: " << errorMsg << endl;
+ }
+ in.close();
+
+ // Start adding tablestyles
+ QDomElement stylesElem = doc.documentElement();
+
+ QDomNodeList listStyles = stylesElem.elementsByTagName( "TABLESTYLE" );
+ if( listStyles.count() > 0) { // we are going to import at least one style.
+ KWTableStyle *s = m_tableStyleColl->findStyle("Plain");
+ if(s) // delete the standard style.
+ m_tableStyleColl->removeStyle(s);
+ }
+ for (unsigned int item = 0; item < listStyles.count(); item++) {
+ QDomElement styleElem = listStyles.item( item ).toElement();
+
+ KWTableStyle *sty = new KWTableStyle( styleElem, this );
+ m_tableStyleColl->addStyle( sty );
+ }
+}
+
+void KWDocument::loadDefaultTableTemplates()
+{
+ KURL fsfile;
+
+ if ( ! QFile::exists(locate("data", "kword/tabletemplates.xml")) )
+ {
+ if (!m_tableTemplateColl->findTableTemplate("Plain")) {
+ KWTableTemplate * standardTableTemplate = new KWTableTemplate( "Plain" );
+ KWTableStyle* defaultTableStyle = tableStyleCollection()->findStyle("Plain");
+ standardTableTemplate->setFirstRow( defaultTableStyle );
+ standardTableTemplate->setLastRow( defaultTableStyle );
+ standardTableTemplate->setFirstCol( defaultTableStyle );
+ standardTableTemplate->setLastCol( defaultTableStyle );
+ standardTableTemplate->setBodyCell( defaultTableStyle );
+ standardTableTemplate->setTopLeftCorner( defaultTableStyle );
+ standardTableTemplate->setTopRightCorner( defaultTableStyle );
+ standardTableTemplate->setBottomLeftCorner( defaultTableStyle );
+ standardTableTemplate->setBottomRightCorner( defaultTableStyle );
+ m_tableTemplateColl->addTableTemplate( standardTableTemplate );
+ }
+ return;
+ }
+
+ fsfile.setPath( locate("data", "kword/tabletemplates.xml") );
+
+ // Open file and parse it
+ QFile in( fsfile.path() );
+ if ( !in.open( IO_ReadOnly ) )
+ {
+ //i18n( "Couldn't open the file for reading (check read permissions)" );
+ return;
+ }
+ in.at(0);
+ QString errorMsg;
+ int errorLine;
+ int errorColumn;
+ QDomDocument doc;
+ if ( doc.setContent( &in , &errorMsg, &errorLine, &errorColumn ) ) {
+ }
+ else
+ {
+ kdError (30003) << "Parsing Error! Aborting! (in KWDocument::readTableTemplates())" << endl
+ << " Line: " << errorLine << " Column: " << errorColumn << endl
+ << " Message: " << errorMsg << endl;
+ }
+ in.close();
+
+ // Start adding framestyles
+ QDomElement templatesElem = doc.documentElement();
+
+ QDomNodeList listTemplates = templatesElem.elementsByTagName( "TABLETEMPLATE" );
+ if( listTemplates.count() > 0) {
+ KWTableTemplate *s = m_tableTemplateColl->findTableTemplate("Plain");
+ if(s)
+ m_tableTemplateColl->removeTableTemplate(s);
+ }
+ for (unsigned int item = 0; item < listTemplates.count(); item++) {
+ QDomElement templateElem = listTemplates.item( item ).toElement();
+
+ KWTableTemplate *temp = new KWTableTemplate( templateElem, this );
+ m_tableTemplateColl->addTableTemplate( temp );
+ }
+}
+
+void KWDocument::progressItemLoaded()
+{
+ if ( !m_nrItemsToLoad ) // happens when pasting
+ return;
+ m_itemsLoaded++;
+ // We progress from 20 to 85 -> 65-wide range, 20 offset.
+ unsigned int perc = 65 * m_itemsLoaded / m_nrItemsToLoad;
+ if ( perc != 65 * (m_itemsLoaded-1) / m_nrItemsToLoad ) // only emit if different from previous call
+ {
+ //kdDebug(32001) << m_itemsLoaded << " items loaded. %=" << perc + 20 << endl;
+ emit sigProgress( perc + 20 );
+ }
+}
+
+void KWDocument::loadFrameSets( const QDomElement &framesetsElem )
+{
+ // <FRAMESET>
+ // First prepare progress info
+ m_nrItemsToLoad = 0; // total count of items (mostly paragraph and frames)
+ QDomElement framesetElem = framesetsElem.firstChild().toElement();
+ // Workaround the slowness of QDom's elementsByTagName
+ QValueList<QDomElement> framesets;
+ for ( ; !framesetElem.isNull() ; framesetElem = framesetElem.nextSibling().toElement() )
+ {
+ if ( framesetElem.tagName() == "FRAMESET" )
+ {
+ framesets.append( framesetElem );
+ m_nrItemsToLoad += framesetElem.childNodes().count();
+ }
+ }
+
+ m_itemsLoaded = 0;
+
+ QValueList<QDomElement>::Iterator it = framesets.begin();
+ QValueList<QDomElement>::Iterator end = framesets.end();
+ for ( ; it != end ; ++it )
+ {
+ (void) loadFrameSet( *it );
+ }
+}
+
+KWFrameSet * KWDocument::loadFrameSet( QDomElement framesetElem, bool loadFrames, bool loadFootnote )
+{
+ FrameSetType frameSetType = static_cast<FrameSetType>( KWDocument::getAttribute( framesetElem, "frameType", FT_BASE ) );
+ QString fsname = KWDocument::getAttribute( framesetElem, "name", "" );
+
+ switch ( frameSetType ) {
+ case FT_TEXT: {
+ QString tableName = KWDocument::getAttribute( framesetElem, "grpMgr", "" );
+ if ( !tableName.isEmpty() ) {
+ // Text frameset belongs to a table -> find table by name
+ KWTableFrameSet *table = 0L;
+ QPtrListIterator<KWFrameSet> fit = framesetsIterator();
+ for ( ; fit.current() ; ++fit ) {
+ KWFrameSet *f = fit.current();
+ if( f->type() == FT_TABLE &&
+ f->isVisible() &&
+ f->name() == tableName ) {
+ table = static_cast<KWTableFrameSet *> (f);
+ break;
+ }
+ }
+ // No such table yet -> create
+ if ( !table ) {
+ table = new KWTableFrameSet( this, tableName );
+ addFrameSet(table, false);
+ }
+ // Load the cell
+ return table->loadCell( framesetElem );
+ }
+ else
+ {
+ KWFrameSet::Info info = static_cast<KWFrameSet::Info>( framesetElem.attribute("frameInfo").toInt() );
+ if ( info == KWFrameSet::FI_FOOTNOTE )
+ {
+ if ( !loadFootnote )
+ return 0L;
+ // Footnote -> create a KWFootNoteFrameSet
+ KWFootNoteFrameSet *fs = new KWFootNoteFrameSet( this, fsname );
+ fs->load( framesetElem, loadFrames );
+ addFrameSet(fs, false);
+ return fs;
+ }
+ else // Normal text frame
+ {
+ KWTextFrameSet *fs = new KWTextFrameSet( this, fsname );
+ fs->load( framesetElem, loadFrames );
+ addFrameSet(fs, false);
+
+ // Old file format had autoCreateNewFrame as a frameset attribute
+ if ( framesetElem.hasAttribute( "autoCreateNewFrame" ) )
+ {
+ KWFrame::FrameBehavior behav = static_cast<KWFrame::FrameBehavior>( framesetElem.attribute( "autoCreateNewFrame" ).toInt() );
+ QPtrListIterator<KWFrame> frameIt( fs->frameIterator() );
+ for ( ; frameIt.current() ; ++frameIt ) // Apply it to all frames
+ frameIt.current()->setFrameBehavior( behav );
+ }
+ return fs;
+ }
+ }
+ } break;
+ case FT_CLIPART:
+ {
+ kdError(32001) << "FT_CLIPART used! (in KWDocument::loadFrameSet)" << endl;
+ // Do not break!
+ }
+ case FT_PICTURE:
+ {
+ KWPictureFrameSet *fs = new KWPictureFrameSet( this, fsname );
+ fs->load( framesetElem, loadFrames );
+ addFrameSet(fs, false);
+ return fs;
+ } break;
+ case FT_FORMULA: {
+ KWFormulaFrameSet *fs = new KWFormulaFrameSet( this, fsname );
+ fs->load( framesetElem, loadFrames );
+ addFrameSet(fs, false);
+ return fs;
+ } break;
+ // Note that FT_PART cannot happen when loading from a file (part frames are saved into the SETTINGS tag)
+ // and FT_TABLE can't happen either.
+ case FT_PART:
+ kdWarning(32001) << "loadFrameSet: FT_PART: impossible case" << endl;
+ break;
+ case FT_TABLE:
+ kdWarning(32001) << "loadFrameSet: FT_TABLE: impossible case" << endl;
+ break;
+ case FT_BASE:
+ kdWarning(32001) << "loadFrameSet: FT_BASE !?!?" << endl;
+ break;
+ }
+ return 0L;
+}
+
+void KWDocument::loadImagesFromStore( KoStore *store )
+{
+ if ( store && !m_pictureMap.isEmpty() ) {
+ m_pictureCollection->readFromStore( store, m_pictureMap );
+ m_pictureMap.clear(); // Release memory
+ }
+}
+
+bool KWDocument::completeLoading( KoStore *store )
+{
+ kdDebug() << k_funcinfo << endl;
+ // Old-XML stuff. No-op when loading OASIS.
+ loadImagesFromStore( store );
+ processPictureRequests();
+ processAnchorRequests();
+ processFootNoteRequests();
+
+ // Save memory
+ m_urlIntern = QString::null;
+
+ // The fields and dates just got loaded -> update vars
+ recalcVariables( VT_FIELD );
+ recalcVariables( VT_DATE );
+ recalcVariables( VT_STATISTIC ); // e.g. number of words etc.
+
+ // Finalize all the existing [non-inline] framesets
+ QPtrListIterator<KWFrameSet> fit = framesetsIterator();
+ for ( ; fit.current() ; ++fit )
+ fit.current()->finalize();
+
+ // This computes the number of pages (from the frames)
+ // for the first time (and adds footers/headers/footnotes etc.)
+ // ## Note: with OASIS the frame loading appends pages as necessary,
+ // so maybe we don't need to calculate the pages from the frames anymore.
+ recalcFrames();
+
+ // Fix z orders on older documents
+ fixZOrders();
+
+ emit newContentsSize();
+ repaintAllViews( true ); // in case any view exists already
+ reactivateBgSpellChecking();
+ connect( documentInfo(), SIGNAL( sigDocumentInfoModifed()),this,SLOT(slotDocumentInfoModifed() ) );
+
+ //desactivate bgspellchecking
+ //attributes isReadWrite is not placed at the beginning !
+ if ( !isReadWrite())
+ enableBackgroundSpellCheck( false );
+
+ // Load bookmarks
+ initBookmarkList();
+
+ deleteLoadingInfo();
+
+ setModified( false );
+
+ return true;
+}
+
+KWLoadingInfo* KWDocument::createLoadingInfo()
+{
+ Q_ASSERT( !m_loadingInfo );
+ m_loadingInfo = new KWLoadingInfo();
+ m_loadingInfo->columns.ptColumnSpacing = m_defaultColumnSpacing;
+ return m_loadingInfo;
+}
+
+void KWDocument::deleteLoadingInfo()
+{
+ Q_ASSERT( m_loadingInfo );
+ delete m_loadingInfo;
+ m_loadingInfo = 0;
+}
+
+void KWDocument::processPictureRequests()
+{
+ QPtrListIterator<KWTextImage> it2 ( m_textImageRequests );
+ for ( ; it2.current() ; ++it2 )
+ {
+ it2.current()->setImage( *m_pictureCollection );
+ }
+ m_textImageRequests.clear();
+
+ //kdDebug(32001) << m_pictureRequests.count() << " picture requests." << endl;
+ QPtrListIterator<KWPictureFrameSet> it3( m_pictureRequests );
+ for ( ; it3.current() ; ++it3 )
+ it3.current()->setPicture( m_pictureCollection->findPicture( it3.current()->key() ) );
+ m_pictureRequests.clear();
+}
+
+void KWDocument::processAnchorRequests()
+{
+ QMapIterator<QString, KWAnchorPosition> itanch = m_anchorRequests.begin();
+ for ( ; itanch != m_anchorRequests.end(); ++itanch )
+ {
+ QString fsname = itanch.key();
+ if ( m_pasteFramesetsMap && m_pasteFramesetsMap->contains( fsname ) )
+ fsname = (*m_pasteFramesetsMap)[ fsname ];
+ kdDebug(32001) << "KWDocument::processAnchorRequests anchoring frameset " << fsname << endl;
+ KWFrameSet * fs = frameSetByName( fsname );
+ Q_ASSERT( fs );
+ if ( fs )
+ fs->setAnchored( itanch.data().textfs, itanch.data().paragId, itanch.data().index, true, false /*don't repaint yet*/ );
+ }
+ m_anchorRequests.clear();
+}
+
+bool KWDocument::processFootNoteRequests()
+{
+ bool ret = false;
+ QMapIterator<QString, KWFootNoteVariable *> itvar = m_footnoteVarRequests.begin();
+ for ( ; itvar != m_footnoteVarRequests.end(); ++itvar )
+ {
+ QString fsname = itvar.key();
+ if ( m_pasteFramesetsMap && m_pasteFramesetsMap->contains( fsname ) )
+ fsname = (*m_pasteFramesetsMap)[ fsname ];
+ //kdDebug(32001) << "KWDocument::processFootNoteRequests binding footnote var " << itvar.data() << " and frameset " << fsname << endl;
+ KWFrameSet * fs = frameSetByName( fsname );
+ Q_ASSERT( fs );
+ if ( !fs ) // #104431
+ continue;
+ Q_ASSERT( fs->type() == FT_TEXT );
+ Q_ASSERT( fs->frameSetInfo() == KWFrameSet::FI_FOOTNOTE );
+ KWFootNoteFrameSet* fnfs = dynamic_cast<KWFootNoteFrameSet *>(fs);
+ if ( fnfs )
+ {
+ fnfs->setFootNoteVariable( itvar.data() );
+ itvar.data()->setFrameSet( fnfs );
+ ret = true;
+ }
+ }
+ m_footnoteVarRequests.clear();
+ // Renumber footnotes
+ if ( ret ) {
+ KWFrameSet *frameset = m_lstFrameSet.getFirst();
+ if ( frameset && frameset->type() == FT_TEXT )
+ static_cast<KWTextFrameSet *>(frameset)->renumberFootNotes( false /*no repaint*/ );
+ }
+ return ret;
+}
+
+QString KWDocument::uniqueFramesetName( const QString& oldName )
+{
+ QString newName = oldName;
+ if (frameSetByName( oldName ))//rename it if name frameset exists
+ {
+ // make up a new name for the frameset, use Copy[digits]-[oldname] as template.
+ // Fully translatable naturally :)
+ QString searchString( "^(" + i18n("Copy%1-%2").arg("\\d*").arg("){0,1}") );
+ searchString = searchString.replace(QRegExp("\\-"), "\\-"); // escape the '-'
+ QRegExp searcher(searchString);
+ int count=0;
+ do {
+ newName=oldName;
+ newName.replace(searcher,i18n("Copy%1-%2").arg(count > 0? QString("%1").arg(count):"").arg(""));
+ count++;
+ } while ( frameSetByName( newName ) );
+ }
+ return newName;
+}
+
+void KWDocument::pasteFrames( QDomElement topElem, KMacroCommand * macroCmd, bool copyFootNote, bool loadFootNote, bool selectFrames )
+{
+ m_pasteFramesetsMap = new QMap<QString, QString>();
+ //QPtrList<KWFrameSet> frameSetsToFinalize;
+ int ref=0;
+ int nb = 0;
+ QDomElement elem = topElem.firstChild().toElement();
+ for ( ; !elem.isNull() ; elem = elem.nextSibling().toElement() )
+ {
+ //kdDebug() << "pasteFrames: elem=" << elem.tagName() << endl;
+ QDomElement frameElem;
+ KWFrameSet * fs = 0L;
+ if ( elem.tagName() == "FRAME" )
+ {
+ QString frameSetName = frameElem.attribute( "parentFrameset" );
+ fs = frameSetByName( frameSetName );
+ if ( !fs )
+ {
+ kdWarning(32001) << "pasteFrames: Frameset '" << frameSetName << "' not found" << endl;
+ continue;
+ }
+ frameElem = elem;
+ }
+ else if ( elem.tagName() == "FRAMESET" )
+ {
+ // Prepare a new name for the frameset
+ QString oldName = elem.attribute( "name" );
+ QString newName = uniqueFramesetName( oldName ); // make up a new name for the frameset
+
+ m_pasteFramesetsMap->insert( oldName, newName ); // remember the name transformation
+ if(oldName != newName)
+ kdDebug(32001) << "KWDocument::pasteFrames new frameset: " << oldName << "->" << newName << endl;
+ FrameSetType frameSetType = static_cast<FrameSetType>( KWDocument::getAttribute( elem, "frameType", FT_BASE ) );
+ switch ( frameSetType ) {
+ case FT_TABLE: {
+ KWTableFrameSet *table = new KWTableFrameSet( this, newName );
+ table->fromXML( elem, true, false /*don't apply names*/ );
+ table->moveBy( 20.0, 20.0 );
+ m_lstFrameSet.append( table );
+ table->setZOrder();
+ if ( macroCmd )
+ macroCmd->addCommand( new KWCreateTableCommand( QString::null, table ) );
+ fs = table;
+ break;
+ }
+ case FT_PART:
+ {
+ ref |= Embedded;
+#if 0
+ KWPartFrameSet *part = new KWPartFrameSet( this, newName );
+ part->fromXML( elem, true, false /*don't apply names*/ );
+ part->moveBy( 20.0, 20.0 );
+ m_lstFrameSet.append( part );
+ part->setZOrder();
+ fs = part;
+#endif
+ break;
+ }
+ default:
+ fs = loadFrameSet( elem, false, loadFootNote );
+ if ( fs )
+ {
+ kdDebug() << "KWDocument::pasteFrames created frameset: '" << newName << "'\n";
+ fs->setName( newName );
+ frameElem = elem.namedItem( "FRAME" ).toElement();
+ }
+ }
+ //when we paste a header/footer we transforme it in a body frame
+ if(fs && (fs->isHeaderOrFooter() || ( !copyFootNote && fs->isFootEndNote())))
+ fs->setFrameSetInfo(KWFrameSet::FI_BODY);
+ }
+ // Test commented out since the toplevel element can contain "PARAGRAPH" now
+ //else
+ //kdWarning(32001) << "Unsupported toplevel-element in KWCanvas::pasteFrames : '" << elem.tagName() << "'" << endl;
+
+ if ( fs )
+ {
+ //if ( frameSetsToFinalize.findRef( fs ) == -1 )
+ // frameSetsToFinalize.append( fs );
+
+ // Load the frame
+ if ( !frameElem.isNull() )
+ {
+ double offs = 20.0;
+ KoRect rect;
+ rect.setLeft( KWDocument::getAttribute( frameElem, "left", 0.0 ) + offs );
+ rect.setTop( KWDocument::getAttribute( frameElem, "top", 0.0 ) + offs );
+ rect.setRight( KWDocument::getAttribute( frameElem, "right", 0.0 ) + offs );
+ rect.setBottom( KWDocument::getAttribute( frameElem, "bottom", 0.0 ) + offs );
+ KWFrame * frame = new KWFrame( fs, rect.x(), rect.y(), rect.width(), rect.height() );
+ frame->load( frameElem, fs, KWDocument::CURRENT_SYNTAX_VERSION );
+ frame->setZOrder( maxZOrder( frame->pageNumber(this) ) + 1 +nb ); // make sure it's on top
+ nb++;
+ fs->addFrame( frame, false );
+ if ( selectFrames ) {
+ for( QValueList<KWView *>::Iterator it = m_lstViews.begin();
+ it != m_lstViews.end(); ++it ) {
+ KWFrameView *fv = (*it)->frameViewManager()->view(frame);
+ if(fv)
+ fv->setSelected(true);
+ }
+ }
+ if ( macroCmd )
+ {
+ KWCreateFrameCommand *cmd = new KWCreateFrameCommand( QString::null, frame );
+ macroCmd->addCommand(cmd);
+ }
+ }
+ int type=0;
+ // Please move this to some common method somewhere (e.g. in KWDocument) (David)
+ switch(fs->type())
+ {
+ case FT_TEXT:
+ type=(int)TextFrames;
+ break;
+ case FT_CLIPART:
+ {
+ kdError(32001) << "FT_CLIPART used! (in KWDocument::loadFrameSet)" << endl;
+ // Do not break!
+ }
+ case FT_PICTURE:
+ type=(int)Pictures;
+ break;
+ case FT_PART:
+ type=(int)Embedded;
+ break;
+ case FT_FORMULA:
+ type=(int)FormulaFrames;
+ break;
+ case FT_TABLE:
+ type=(int)Tables;
+ break;
+ default:
+ type=(int)TextFrames;
+ }
+ ref|=type;
+ }
+ }
+ refreshDocStructure(ref);
+}
+
+void KWDocument::completePasting()
+{
+ processPictureRequests();
+ processAnchorRequests();
+ if ( processFootNoteRequests() )
+ {
+ // We pasted footnotes. Relayout frames.
+ recalcFrames();
+ }
+
+ // Finalize afterwards - especially in case of inline frames, made them inline in processAnchorRequests
+ //for ( QPtrListIterator<KWFrameSet> fit( frameSetsToFinalize ); fit.current(); ++fit )
+
+ // Do it on all of them (we'd need to store frameSetsToFinalize as member var if this is really slow)
+ QPtrListIterator<KWFrameSet> fit = framesetsIterator();
+ for ( ; fit.current() ; ++fit )
+ fit.current()->finalize();
+ repaintAllViews();
+ delete m_pasteFramesetsMap;
+ m_pasteFramesetsMap = 0L;
+}
+
+void KWDocument::completeOasisPasting()
+{
+ QPtrListIterator<KWFrameSet> fit = framesetsIterator();
+ for ( ; fit.current() ; ++fit )
+ fit.current()->finalize();
+ repaintAllViews();
+}
+
+void KWDocument::insertEmbedded( KoStore *store, QDomElement topElem, KMacroCommand * macroCmd, double offset )
+{
+ if ( !m_pasteFramesetsMap ) // may have been created by pasteFrames
+ m_pasteFramesetsMap = new QMap<QString, QString>();
+
+ QDomElement elem = topElem.firstChild().toElement();
+ for ( ; !elem.isNull() ; elem = elem.nextSibling().toElement() )
+ {
+ if ( elem.tagName() == "EMBEDDED" )
+ {
+ kdDebug()<<"KWDocument::insertEmbedded() Embedded object"<<endl;
+ QDomElement object = elem.namedItem( "OBJECT" ).toElement();
+ QDomElement settings = elem.namedItem( "SETTINGS" ).toElement();
+ if ( object.isNull() || settings.isNull() )
+ {
+ kdError() << "No <OBJECT> or <SETTINGS> tag" << endl;
+ }
+ else
+ {
+ KWDocumentChild *ch = new KWDocumentChild( this );
+ kdDebug()<<"KWDocument::insertEmbedded() loading document"<<endl;
+ if ( ch->load( object, true ) )
+ {
+ ch->loadDocument( store );
+ insertChild( ch );
+ QString oldName = settings.attribute( "name" );
+ QString newName = uniqueFramesetName( oldName );
+ m_pasteFramesetsMap->insert( oldName, newName ); // remember the name transformation
+ KWPartFrameSet *part = new KWPartFrameSet( this, ch, newName );
+ m_lstFrameSet.append( part );
+ kdDebug() << "KWDocument::insertEmbedded loading embedded object" << endl;
+ part->load( settings );
+ if ( offset != 0 ) {
+ QRect r = ch->geometry();
+ r.moveBy( (int)offset, (int)offset );
+ ch->setGeometry( r );
+ }
+ part->setZOrder();
+ if ( macroCmd )
+ {
+ QPtrListIterator<KWFrame> frameIt( part->frameIterator() );
+ for ( ; frameIt.current(); ++frameIt )
+ {
+ macroCmd->addCommand( new KWCreateFrameCommand( QString::null, frameIt.current() ) );
+ }
+ }
+ }
+ }
+ }
+ }
+ refreshDocStructure( (int)Embedded );
+}
+
+bool KWDocument::saveOasis( KoStore* store, KoXmlWriter* manifestWriter )
+{
+ QValueList<KWFrameView*> noFrames;
+ return saveOasisHelper( store, manifestWriter, SaveAll, noFrames);
+}
+
+// can't be const due to recalcVariables()
+bool KWDocument::saveOasisHelper( KoStore* store, KoXmlWriter* manifestWriter, SaveFlag saveFlag, const QValueList<KWFrameView*> &selectedFrames, QString* plainText, KoPicture* picture, KWTextFrameSet* fs) {
+ m_pictureCollection->assignUniqueIds();
+ fixZOrders();
+
+ manifestWriter->addManifestEntry( "content.xml", "text/xml" );
+ KoOasisStore oasisStore( store );
+
+ KoXmlWriter* contentWriter = oasisStore.contentWriter();
+ if ( !contentWriter )
+ return false;
+
+ QValueList<KoPictureKey> pictureList;
+ if ( saveFlag == SaveAll )
+ pictureList = savePictureList();
+
+ m_varColl->variableSetting()->setModificationDate(QDateTime::currentDateTime());
+ recalcVariables( VT_DATE );
+ recalcVariables( VT_TIME ); // for "current time"
+ recalcVariables( VT_STATISTIC );
+ m_syntaxVersion = CURRENT_SYNTAX_VERSION; // ### clean this up once we remove the old format
+
+ KoGenStyles mainStyles;
+ KoSavingContext savingContext( mainStyles, m_varColl->variableSetting(), m_pageColumns.columns > 1, KoSavingContext::Store );
+
+ // Save user styles as KoGenStyle objects
+ m_styleColl->saveOasis( mainStyles, KoGenStyle::STYLE_USER, savingContext );
+
+ QByteArray headerFooterContent;
+ if ( saveFlag == SaveAll )
+ {
+ // Save visual info for the first view, such as the active frameset and cursor position
+ // It looks like a hack, but reopening a document creates only one view anyway (David)
+ KWView * view = static_cast<KWView*>(views().getFirst());
+ if ( view ) // no view if embedded document
+ {
+ KWFrameSetEdit* edit = view->getGUI()->canvasWidget()->currentFrameSetEdit();
+ if ( edit )
+ {
+ KWTextFrameSetEdit* textedit = dynamic_cast<KWTextFrameSetEdit *>(edit);
+ if ( textedit && textedit->cursor() ) {
+ KoTextCursor* cursor = textedit->cursor();
+ savingContext.setCursorPosition( cursor->parag(),
+ cursor->index() );
+ }
+ }
+ }
+
+ // Header and footers save their content into master-styles/master-page, and their
+ // styles into the page-layout automatic-style.
+ // However the paragraph styles used by header/footers need to be known before
+ // hand, to promote them to styles.xml. So we collect them first, which means
+ // storing the content into a buffer.
+ QBuffer buffer( headerFooterContent );
+ buffer.open( IO_WriteOnly );
+ KoXmlWriter headerFooterTmpWriter( &buffer ); // TODO pass indentation level
+ QPtrListIterator<KWFrameSet> fit = framesetsIterator();
+ // ## This loop is duplicated in saveOasisDocumentStyles
+ for ( ; fit.current() ; ++fit ) {
+ const KWFrameSet* fs = fit.current();
+ if ( fs->isVisible() && // HACK to avoid saving [hidden] headers/footers framesets for now
+ !fs->isFloating() &&
+ !fs->isDeleted() &&
+ fs->type() == FT_TEXT &&
+ fs->isHeaderOrFooter() )
+ {
+ // Save content
+ headerFooterTmpWriter.startElement( fs->headerFooterTag() ); // e.g. style:header
+ static_cast<const KWTextFrameSet *>(fs)->saveOasisContent( headerFooterTmpWriter, savingContext );
+ headerFooterTmpWriter.endElement();
+ }
+ }
+ // Add trailing '0' (Qt4: remove)
+ headerFooterContent.resize( headerFooterContent.size() + 1 );
+ headerFooterContent[headerFooterContent.size()-1] = '\0';
+
+ // Now mark all autostyles as "for styles.xml" since headers/footers need them
+ QValueList<KoGenStyles::NamedStyle> autoStyles = mainStyles.styles( KoGenStyle::STYLE_AUTO );
+ for ( QValueList<KoGenStyles::NamedStyle>::const_iterator it = autoStyles.begin();
+ it != autoStyles.end(); ++it ) {
+ mainStyles.markStyleForStylesXml( (*it).name );
+ }
+ }
+
+ KoXmlWriter* bodyWriter = oasisStore.bodyWriter();
+ bodyWriter->startElement( "office:body" );
+ bodyWriter->startElement( "office:text" );
+
+ if ( saveFlag == SaveAll )
+ {
+ // save the body into bodyWriter
+ saveOasisBody( *bodyWriter, savingContext );
+ }
+ else // SaveSelected
+ {
+ // In theory we should pass a view to this method, in order to
+ // copy what is currently selected in that view only. But selection
+ // is currently part of the KoTextParag data, so it's shared between views.
+ if ( fs ) {
+ *plainText = fs->textDocument()->copySelection( *bodyWriter, savingContext, KoTextDocument::Standard );
+ // Collect inline framesets for e.g. pictures
+ KWCollectFramesetsVisitor visitor;
+ fs->textDocument()->visitSelection( KoTextDocument::Standard, &visitor );
+ const QValueList<KWFrameSet *>& frameset = visitor.frameSets();
+ kdDebug(32001) << frameset.count() << " inline framesets" << endl;
+ for ( QValueList<KWFrameSet *>::ConstIterator it = frameset.begin(); it != frameset.end(); ++it )
+ {
+ switch ( (*it)->type() ) {
+ case FT_PICTURE:
+ {
+ const KoPictureKey key = static_cast<KWPictureFrameSet *>( *it )->key();
+ if ( !pictureList.contains( key ) )
+ pictureList.append( key );
+ }
+ break;
+ case FT_PART:
+ // TODO
+ default:
+ break;
+ }
+ }
+ }
+
+ // write selected (non-inline) frames
+ QString newText;
+ saveSelectedFrames( *bodyWriter, savingContext, pictureList,
+ selectedFrames, &newText ); // output vars
+ *plainText += newText;
+ // Single image -> return it
+ if ( picture && pictureList.count() == 1 )
+ {
+ *picture = m_pictureCollection->findPicture( pictureList.first() );
+ }
+ }
+
+ bodyWriter->endElement(); // office:text
+ bodyWriter->endElement(); // office:body
+
+ savingContext.writeFontFaces( *contentWriter );
+ contentWriter->startElement( "office:automatic-styles" );
+ KWOasisSaver::writeAutomaticStyles( *contentWriter, mainStyles, false );
+ contentWriter->endElement(); // office:automatic-styles
+
+ oasisStore.closeContentWriter();
+
+ // Done with content.xml
+
+ if ( !store->open( "styles.xml" ) )
+ return false;
+ manifestWriter->addManifestEntry( "styles.xml", "text/xml" );
+ saveOasisDocumentStyles( store, mainStyles, savingContext, saveFlag, headerFooterContent );
+ if ( !store->close() ) // done with styles.xml
+ return false;
+
+ //kdDebug(32001) << "saveOasis: " << pictureList.count() << " pictures" << endl;
+ m_pictureCollection->saveOasisToStore( store, pictureList, manifestWriter );
+
+ if ( saveFlag == SaveSelected ) {
+ // Save embedded objects - code inspired from KoDocument::saveChildrenOasis,
+ // for the case where we're saving only some embedded objects, like with Ctrl+C.
+
+ // IMPORTANT: This must be done *after* we're done with writing content.xml,
+ // not while writing it (like in saveSelectedFrames).
+ // We can't be writing to two files at the same time.
+
+ QValueList<KoDocumentChild*> embeddedObjects;
+ QValueListConstIterator<KWFrameView*> framesIterator = selectedFrames.begin();
+ for(; framesIterator != selectedFrames.end(); ++framesIterator) {
+ KWFrame *frame = (*framesIterator)->frame();
+ KWFrameSet *fs = frame->frameSet();
+ if ( fs->isVisible() && fs->type() == FT_PART) {
+ embeddedObjects.append( static_cast<KWPartFrameSet *>(fs)->getChild() );
+ }
+ }
+
+ QValueList<KoDocumentChild *>::const_iterator chl = embeddedObjects.begin();
+ for( ; chl != embeddedObjects.end(); ++chl ) {
+ if ( !(*chl)->saveOasis( store, manifestWriter ) )
+ return false;
+ }
+ }
+
+ if ( saveFlag == SaveAll )
+ {
+
+ if(!store->open("settings.xml"))
+ return false;
+
+ KoStoreDevice contentDev( store );
+ KoXmlWriter* settingsWriter = createOasisXmlWriter(&contentDev, "office:document-settings");
+ saveOasisSettings( *settingsWriter );
+ delete settingsWriter;
+
+ if(!store->close())
+ return false;
+
+ manifestWriter->addManifestEntry("settings.xml", "text/xml");
+ }
+ return true;
+}
+
+// can't be const due to recalcVariables()
+QDragObject* KWDocument::dragSelected( const QValueList<KWFrameView*> &selectedFrames) {
+ return dragSelectedPrivate(0, selectedFrames, 0);
+}
+// can't be const due to recalcVariables()
+QDragObject* KWDocument::dragSelected( QWidget *parent, KWTextFrameSet* fs) {
+ QValueList<KWFrameView*> noFrames;
+ return dragSelectedPrivate(parent, noFrames, fs);
+}
+// can't be const due to recalcVariables()
+QDragObject* KWDocument::dragSelectedPrivate( QWidget *parent, const QValueList<KWFrameView*> &selectedFrames, KWTextFrameSet* fs)
+{
+ // We'll create a store (ZIP format) in memory
+ QBuffer buffer;
+ QCString mimeType = KWOasisSaver::selectionMimeType();
+ KoStore* store = KoStore::createStore( &buffer, KoStore::Write, mimeType );
+ Q_ASSERT( store );
+ Q_ASSERT( !store->bad() );
+ KoOasisStore oasisStore( store );
+
+ KoXmlWriter* manifestWriter = oasisStore.manifestWriter( mimeType );
+
+ QString plainText;
+ KoPicture picture;
+ if ( !saveOasisHelper( store, manifestWriter, KWDocument::SaveSelected, selectedFrames, &plainText, &picture, fs )
+ || !oasisStore.closeManifestWriter() )
+ {
+ delete store;
+ return 0;
+ }
+
+ delete store;
+
+ KMultipleDrag* multiDrag = new KMultipleDrag( parent );
+ if ( !plainText.isEmpty() )
+ multiDrag->addDragObject( new QTextDrag( plainText, 0 ) );
+ if ( !picture.isNull() )
+ multiDrag->addDragObject( picture.dragObject( 0 ) );
+ KoStoreDrag* storeDrag = new KoStoreDrag( KWOasisSaver::selectionMimeType(), 0 );
+ kdDebug() << k_funcinfo << "setting zip data: " << buffer.buffer().size() << " bytes." << endl;
+ storeDrag->setEncodedData( buffer.buffer() );
+ multiDrag->addDragObject( storeDrag );
+ return multiDrag;
+}
+
+void KWDocument::saveSelectedFrames( KoXmlWriter& bodyWriter, KoSavingContext& savingContext, QValueList<KoPictureKey>& pictureList, const QValueList<KWFrameView*> &selectedFrames, QString* plainText ) const {
+ QPtrList<KoDocumentChild> embeddedObjects;
+ QValueListConstIterator<KWFrameView*> framesIterator = selectedFrames.begin();
+ for(; framesIterator != selectedFrames.end(); ++framesIterator) {
+ KWFrame *frame = (*framesIterator)->frame();
+ KWFrameSet *fs = frame->frameSet();
+ if ( fs->isVisible() && fs->type() == FT_PART) {
+ embeddedObjects.append( static_cast<KWPartFrameSet *>(fs)->getChild() );
+ }
+ bool isTable = fs->type() == FT_TABLE;
+
+ // Two cases to be distinguished here
+ // If it's the first frame of a frameset, then copy the frameset contents and the frame itself
+ // Otherwise copy only the frame information
+ if ( frame == fs->frame(0) || isTable ) {
+ fs->saveOasis( bodyWriter, savingContext, false );
+ if ( plainText )
+ *plainText += fs->toPlainText();
+ }
+ else if ( !isTable ) {
+#if 0
+ // Save the frame information
+ QDomElement frameElem = parentElem.ownerDocument().createElement( "FRAME" );
+ parentElem.appendChild( frameElem );
+ frame->save( frameElem );
+ if ( frame != firstFrame )
+ {
+ // Frame saved alone -> remember which frameset it's part of
+ frameElem.setAttribute( "parentFrameset", fs->name() );
+ }
+#endif
+ }
+ if ( fs->type() == FT_PICTURE ) {
+ kdDebug(32001) << "found non-inline picture framesets" << endl;
+
+ const KoPictureKey key = static_cast<KWPictureFrameSet *>( fs )->key();
+ if ( !pictureList.contains( key ) )
+ pictureList.append( key );
+ }
+ if ( isTable ) // Copy tables only once, even if they have many cells selected
+ break;
+ }
+}
+
+void KWDocument::saveOasisSettings( KoXmlWriter& settingsWriter ) const
+{
+ settingsWriter.startElement("office:settings");
+ settingsWriter.startElement("config:config-item-set");
+
+ settingsWriter.addAttribute("config:name", "view-settings");
+
+ KoUnit::saveOasis(&settingsWriter, unit());
+
+ settingsWriter.endElement(); // config:config-item-set
+
+ settingsWriter.startElement("config:config-item-set");
+ settingsWriter.addAttribute("config:name", "configuration-settings");
+ settingsWriter.addConfigItem("SpellCheckerIgnoreList", m_spellCheckIgnoreList.join( "," ) );
+ settingsWriter.endElement(); // config:config-item-set
+
+ m_varColl->variableSetting()->saveOasis( settingsWriter );
+
+ settingsWriter.endElement(); // office:settings
+ settingsWriter.endElement(); // Root element
+ settingsWriter.endDocument();
+}
+
+void KWDocument::saveOasisDocumentStyles( KoStore* store, KoGenStyles& mainStyles, KoSavingContext& savingContext, SaveFlag saveFlag, const QByteArray& headerFooterContent ) const
+{
+ if ( saveFlag == SaveAll )
+ {
+ m_frameStyleColl->saveOasis( mainStyles, savingContext );
+ m_tableStyleColl->saveOasis( mainStyles, savingContext );
+ }
+
+ KoStoreDevice stylesDev( store );
+ KoXmlWriter* stylesWriter = createOasisXmlWriter( &stylesDev, "office:document-styles" );
+
+ // Yeah we need to save the same font faces in both content.xml and styles.xml...
+ savingContext.writeFontFaces( *stylesWriter );
+
+ stylesWriter->startElement( "office:styles" );
+
+ if ( saveFlag == SaveAll )
+ {
+ stylesWriter->startElement( "style:default-style" );
+ stylesWriter->addAttribute( "style:family", "paragraph" );
+ stylesWriter->startElement( "style:paragraph-properties" );
+ stylesWriter->addAttributePt( "style:tab-stop-distance", m_tabStop );
+ stylesWriter->endElement(); // paragraph-properties
+ stylesWriter->endElement(); // default-style
+ }
+
+ QValueList<KoGenStyles::NamedStyle> styles = mainStyles.styles( KoGenStyle::STYLE_USER );
+ QValueList<KoGenStyles::NamedStyle>::const_iterator it = styles.begin();
+ for ( ; it != styles.end() ; ++it ) {
+ (*it).style->writeStyle( stylesWriter, mainStyles, "style:style", (*it).name, "style:paragraph-properties" );
+ }
+ styles = mainStyles.styles( KWDocument::STYLE_FRAME_USER );
+ it = styles.begin();
+ for ( ; it != styles.end() ; ++it ) {
+ (*it).style->writeStyle( stylesWriter, mainStyles, "style:style", (*it).name , "style:graphic-properties" );
+ }
+ styles = mainStyles.styles( KWDocument::STYLE_TABLE_CELL_USER );
+ it = styles.begin();
+ for ( ; it != styles.end() ; ++it ) {
+ (*it).style->writeStyle( stylesWriter, mainStyles, "style:style", (*it).name , "style:table-cell-properties" );
+ }
+ styles = mainStyles.styles( KoGenStyle::STYLE_LIST );
+ it = styles.begin();
+ for ( ; it != styles.end() ; ++it ) {
+ (*it).style->writeStyle( stylesWriter, mainStyles, "text:list-style", (*it).name, 0 );
+ }
+ m_styleColl->saveOasisOutlineStyles( *stylesWriter );
+ if ( saveFlag == SaveAll )
+ static_cast<KWVariableSettings *>( m_varColl->variableSetting() )->saveNoteConfiguration( *stylesWriter );
+ stylesWriter->endElement(); // office:styles
+
+ QString pageLayoutName;
+ if ( saveFlag == SaveAll )
+ {
+ stylesWriter->startElement( "office:automatic-styles" );
+
+ KoGenStyle pageLayout = m_pageLayout.saveOasis();
+ pageLayout.addAttribute( "style:page-usage", "all" ); // needed?
+ // This is for e.g. spreadsheets, not for word-processors.
+ //pageLayout.addProperty( "style:first-page-number", m_varColl->variableSetting()->startingPage() );
+
+ if ( m_processingType == WP )
+ {
+ KWTextFrameSet *frameset = dynamic_cast<KWTextFrameSet *>( m_lstFrameSet.getFirst() );
+ if ( frameset ) {
+ frameset->frame(0)->saveBorderProperties( pageLayout );
+ }
+ }
+
+ QBuffer buffer;
+ buffer.open( IO_WriteOnly );
+ KoXmlWriter footnoteSepTmpWriter( &buffer ); // TODO pass indentation level
+ footnoteSepTmpWriter.startElement( "style:footnote-sep" );
+ QString tmp;
+ switch( m_footNoteSeparatorLinePos )
+ {
+ case SLP_CENTERED:
+ tmp = "centered";
+ break;
+ case SLP_RIGHT:
+ tmp = "right";
+ break;
+ case SLP_LEFT:
+ tmp = "left";
+ break;
+ }
+
+ footnoteSepTmpWriter.addAttribute( "style:adjustment", tmp );
+ footnoteSepTmpWriter.addAttributePt( "style:width", m_footNoteSeparatorLineWidth );
+ footnoteSepTmpWriter.addAttribute( "style:rel-width", QString::number( footNoteSeparatorLineLength() ) + "%" );
+ switch( m_footNoteSeparatorLineType )
+ {
+ case SLT_SOLID:
+ tmp = "solid";
+ break;
+ case SLT_DASH:
+ tmp = "dash";
+ break;
+ case SLT_DOT:
+ tmp = "dotted";
+ break;
+ case SLT_DASH_DOT:
+ tmp = "dot-dash";
+ break;
+ case SLT_DASH_DOT_DOT:
+ tmp = "dot-dot-dash";
+ break;
+ }
+
+ footnoteSepTmpWriter.addAttribute( "style:line-style", tmp );
+
+ footnoteSepTmpWriter.endElement();
+ const QString elementContents = QString::fromUtf8( buffer.buffer(), buffer.buffer().size() );
+ pageLayout.addChildElement( "separator", elementContents );
+ buffer.close();
+
+ if ( m_pageColumns.columns > 1 ) {
+ buffer.setBuffer( QByteArray() ); // clear data
+ buffer.open( IO_WriteOnly );
+ KoXmlWriter columnsTmpWriter( &buffer ); // TODO pass indentation level
+ columnsTmpWriter.startElement( "style:columns" );
+ columnsTmpWriter.addAttribute( "fo:column-count", m_pageColumns.columns );
+ columnsTmpWriter.addAttributePt( "fo:column-gap", m_pageColumns.ptColumnSpacing );
+ columnsTmpWriter.endElement(); // style:columns
+ buffer.close();
+ const QString elementContents = QString::fromUtf8( buffer.buffer(), buffer.buffer().size() );
+ pageLayout.addChildElement( "columns", elementContents );
+ }
+
+ // This is a bit of a hack, which only works as long as we have only one page master
+ // if there's more than one pagemaster we need to rethink all this
+
+ pageLayoutName = mainStyles.lookup( pageLayout, "pm" );
+ pageLayout.writeStyle( stylesWriter, mainStyles, "style:page-layout", pageLayoutName,
+ "style:page-layout-properties", false /*don't close*/ );
+
+ // Ouch another problem: there is only one header style in oasis
+ // ##### can't have different borders for even/odd headers...
+ bool headerStyleSaved = false;
+ bool footerStyleSaved = false;
+ // ## This loop is duplicated in saveOasis
+ QPtrListIterator<KWFrameSet> fit = framesetsIterator();
+ for ( ; fit.current() ; ++fit ) {
+ const KWFrameSet* fs = fit.current();
+ if ( fs->isVisible() && // HACK to avoid saving [hidden] headers/footers framesets for now
+ !fs->isFloating() &&
+ !fs->isDeleted() &&
+ fs->type() == FT_TEXT &&
+ fs->isHeaderOrFooter() )
+ {
+ // Save header/footer style
+ KWFrame* frame = fs->frame(0);
+ if ( fs->isAHeader() ) {
+ if ( headerStyleSaved )
+ continue;
+ headerStyleSaved = true;
+ stylesWriter->startElement( "style:header-style" );
+ } else {
+ if ( footerStyleSaved )
+ continue;
+ footerStyleSaved = true;
+ stylesWriter->startElement( "style:footer-style" );
+ }
+#if 0 // more code reuse, but harder to integrate
+ KoGenStyle hfStyle;
+ hfStyle.addPropertyPt( "fo:min-height", frame->minimumFrameHeight() );
+ frame->saveBorderProperties( hfStyle );
+ frame->saveMarginProperties( hfStyle );
+ ...
+#endif
+ stylesWriter->startElement( "style:header-footer-properties" );
+ stylesWriter->addAttributePt( "fo:min-height", frame->minimumFrameHeight() );
+ if ( fs->isAHeader() )
+ stylesWriter->addAttributePt( "fo:margin-bottom", m_pageHeaderFooter.ptHeaderBodySpacing );
+ else
+ stylesWriter->addAttributePt( "fo:margin-top", m_pageHeaderFooter.ptFooterBodySpacing );
+ // TODO frame->saveBorderAttributes( *stylesWriter );
+ // Interesting idea, but we can't set margins (runaround) on
+ //frame->saveMarginAttributes( *stylesWriter );
+ stylesWriter->endElement(); // header-footer-properties
+ stylesWriter->endElement(); // header-style
+ }
+ }
+ stylesWriter->endElement(); // style:page-layout
+
+ // Headers and footers might have created new automatic parag/text styles -> save those
+ KWOasisSaver::writeAutomaticStyles( *stylesWriter, mainStyles, true );
+
+ stylesWriter->endElement(); // office:automatic-styles
+ }
+
+
+ stylesWriter->startElement( "office:master-styles" );
+ stylesWriter->startElement( "style:master-page" );
+ stylesWriter->addAttribute( "style:name", "Standard" );
+ stylesWriter->addAttribute( "style:page-layout-name", pageLayoutName );
+
+ if ( isHeaderVisible() || isFooterVisible() ) { // ### TODO save them even when hidden (and not empty)?
+ stylesWriter->addCompleteElement( headerFooterContent.data() );
+ }
+
+ stylesWriter->endElement();
+ stylesWriter->endElement(); // office:master-styles
+
+ stylesWriter->endElement(); // root element (office:document-styles)
+ stylesWriter->endDocument();
+ delete stylesWriter;
+}
+
+void KWDocument::saveOasisCustomFied( KoXmlWriter &writer )const
+{
+ bool customVariableFound = false;
+ QPtrListIterator<KoVariable> it( m_varColl->getVariables() );
+ for ( ; it.current() ; ++it )
+ {
+ if ( it.current()->type() == VT_CUSTOM )
+ {
+ if ( !customVariableFound )
+ {
+ writer.startElement( "text:user-field-decls" );
+ customVariableFound = true;
+ }
+ //<text:user-field-decl office:value-type="string" office:string-value="dfddd" text:name="cvbcbcbx"/>
+ writer.startElement( "text:user-field-decl" );
+ writer.addAttribute( "office:value-type", "string" );
+ writer.addAttribute( "office:string-value", static_cast<KoCustomVariable *>( it.current() )->value() );
+ writer.addAttribute( "text:name", static_cast<KoCustomVariable*>( it.current() )->name() );
+ writer.endElement();
+ }
+ }
+ if ( customVariableFound )
+ writer.endElement();
+}
+
+void KWDocument::saveOasisBody( KoXmlWriter& writer, KoSavingContext& context ) const
+{
+ saveOasisCustomFied( writer );
+ if ( m_processingType == WP ) {
+
+ // Write out the non-inline framesets first; OOo wants it that way...
+ QPtrListIterator<KWFrameSet> fit = framesetsIterator();
+ ++fit; // skip main text frameset
+ for ( ; fit.current() ; ++fit ) {
+ KWFrameSet* fs = fit.current();
+ if ( !fs->isFloating() &&
+ !fs->isDeleted() &&
+ // footnotes already saved inline, header/footers elsewhere
+ fs->frameSetInfo() == KWFrameSet::FI_BODY )
+ {
+ fs->saveOasis( writer, context, true );
+ }
+ }
+
+ // Write out the main text frameset's contents
+ KWTextFrameSet *frameset = dynamic_cast<KWTextFrameSet *>( m_lstFrameSet.getFirst() );
+ if ( frameset ) {
+ frameset->saveOasisContent( writer, context );
+ }
+
+ } else { // DTP mode: all framesets are equal
+ // write text:page-sequence, one item per page.
+ writer.startElement( "text:page-sequence" );
+ for ( int page = 0; page < pageCount(); ++page )
+ {
+ writer.startElement( "text:page" );
+ // "pm" is a hack, see mainStyles.lookup( pageLayout, "pm" ) in saveOasis
+ // [which currently happens afterwards...]
+ writer.addAttribute( "text:master-page-name", "pm" );
+ writer.endElement(); // text:page
+ }
+ writer.endElement() ; // "text:page-sequence";
+ // Now write the framesets
+ QPtrListIterator<KWFrameSet> fit = framesetsIterator();
+ for ( ; fit.current() ; ++fit ) {
+ KWFrameSet* fs = fit.current();
+ if ( !fs->isFloating() &&
+ !fs->isDeleted() &&
+ fs->frameSetInfo() == KWFrameSet::FI_BODY )
+ {
+ fs->saveOasis( writer, context, true );
+ }
+ }
+ }
+}
+
+QDomDocument KWDocument::saveXML()
+{
+ m_varColl->variableSetting()->setModificationDate(QDateTime::currentDateTime());
+ recalcVariables( VT_DATE );
+ recalcVariables( VT_TIME ); // for "current time"
+ recalcVariables( VT_STATISTIC );
+ QDomDocument doc = createDomDocument( "DOC", CURRENT_DTD_VERSION );
+ QDomElement kwdoc = doc.documentElement();
+ kwdoc.setAttribute( "editor", "KWord" );
+ kwdoc.setAttribute( "mime", "application/x-kword" );
+ m_syntaxVersion = CURRENT_SYNTAX_VERSION;
+ kwdoc.setAttribute( "syntaxVersion", m_syntaxVersion );
+
+ QDomElement paper = doc.createElement( "PAPER" );
+ kwdoc.appendChild( paper );
+ paper.setAttribute( "format", static_cast<int>( m_pageLayout.format ) );
+ paper.setAttribute( "pages", pageCount() );
+ paper.setAttribute( "width", m_pageLayout.ptWidth );
+ paper.setAttribute( "height", m_pageLayout.ptHeight );
+ paper.setAttribute( "orientation", static_cast<int>( m_pageLayout.orientation ) );
+ paper.setAttribute( "columns", m_pageColumns.columns );
+ paper.setAttribute( "columnspacing", m_pageColumns.ptColumnSpacing );
+ paper.setAttribute( "hType", static_cast<int>( m_pageHeaderFooter.header ) );
+ paper.setAttribute( "fType", static_cast<int>( m_pageHeaderFooter.footer ) );
+ paper.setAttribute( "spHeadBody", m_pageHeaderFooter.ptHeaderBodySpacing );
+ paper.setAttribute( "spFootBody", m_pageHeaderFooter.ptFooterBodySpacing );
+ paper.setAttribute( "spFootNoteBody", m_pageHeaderFooter.ptFootNoteBodySpacing );
+ if ( m_footNoteSeparatorLinePos!=SLP_LEFT )
+ {
+ if (m_footNoteSeparatorLinePos==SLP_CENTERED )
+ paper.setAttribute( "slFootNotePosition", "centered" );
+ else if ( m_footNoteSeparatorLinePos==SLP_RIGHT )
+ paper.setAttribute( "slFootNotePosition", "right" );
+ else if ( m_footNoteSeparatorLinePos==SLP_LEFT ) //never !
+ paper.setAttribute( "slFootNotePosition", "left" );
+ }
+ if ( m_footNoteSeparatorLineType != SLT_SOLID )
+ paper.setAttribute( "slFootNoteType", static_cast<int>(m_footNoteSeparatorLineType) );
+
+
+ paper.setAttribute("slFootNoteLength", m_iFootNoteSeparatorLineLength);
+ paper.setAttribute("slFootNoteWidth", m_footNoteSeparatorLineWidth);
+
+ // Now part of the app config
+ //paper.setAttribute( "zoom",m_zoom );
+
+ QDomElement borders = doc.createElement( "PAPERBORDERS" );
+ paper.appendChild( borders );
+ borders.setAttribute( "left", m_pageLayout.ptLeft );
+ borders.setAttribute( "top", m_pageLayout.ptTop );
+ borders.setAttribute( "right", m_pageLayout.ptRight );
+ borders.setAttribute( "bottom", m_pageLayout.ptBottom );
+
+ QDomElement docattrs = doc.createElement( "ATTRIBUTES" );
+ kwdoc.appendChild( docattrs );
+ docattrs.setAttribute( "processing", static_cast<int>( m_processingType ) );
+ docattrs.setAttribute( "standardpage", 1 );
+ docattrs.setAttribute( "hasHeader", static_cast<int>(isHeaderVisible()) );
+ docattrs.setAttribute( "hasFooter", static_cast<int>(isFooterVisible()) );
+ docattrs.setAttribute( "unit", KoUnit::unitName(unit()) );
+ docattrs.setAttribute( "hasTOC", static_cast<int>(m_hasTOC));
+ docattrs.setAttribute( "tabStopValue", m_tabStop );
+
+ // Save visual info for the first view, such as the active frameset and cursor position
+ // It looks like a hack, but reopening a document creates only one view anyway (David)
+ KWView * view = static_cast<KWView*>(views().getFirst());
+ if ( view ) // no view if embedded document
+ {
+ KWFrameSetEdit* edit = view->getGUI()->canvasWidget()->currentFrameSetEdit();
+ if ( edit )
+ {
+ docattrs.setAttribute( "activeFrameset", edit->frameSet()->name() );
+ KWTextFrameSetEdit* textedit = dynamic_cast<KWTextFrameSetEdit *>(edit);
+ if ( textedit && textedit->cursor() ) {
+ KoTextCursor* cursor = textedit->cursor();
+ docattrs.setAttribute( "cursorParagraph", cursor->parag()->paragId() );
+ docattrs.setAttribute( "cursorIndex", cursor->index() );
+ }
+ }
+ }
+
+ if( !m_bookmarkList->isEmpty() )
+ {
+ QDomElement bookmark = doc.createElement( "BOOKMARKS" );
+ kwdoc.appendChild( bookmark );
+
+ for ( KoTextBookmarkList::const_iterator it = m_bookmarkList->begin();
+ it != m_bookmarkList->end() ; ++it )
+ {
+ const KoTextBookmark& book = *it;
+ KWTextFrameSet* fs = static_cast<KWTextDocument*>(book.textDocument())->textFrameSet();
+ if ( book.startParag() &&
+ book.endParag() &&
+ fs && !fs->isDeleted() )
+ {
+ QDomElement bookElem = doc.createElement( "BOOKMARKITEM" );
+ bookmark.appendChild( bookElem );
+ bookElem.setAttribute( "name", book.bookmarkName() );
+ bookElem.setAttribute( "frameset", fs->name() );
+ bookElem.setAttribute( "startparag", book.startParag()->paragId() );
+ bookElem.setAttribute( "endparag", book.endParag()->paragId() );
+
+ bookElem.setAttribute( "cursorIndexStart", book.bookmarkStartIndex() );
+ bookElem.setAttribute( "cursorIndexEnd", book.bookmarkEndIndex() );
+ }
+ }
+ }
+ variableCollection()->variableSetting()->save(kwdoc );
+
+ QDomElement framesets = doc.createElement( "FRAMESETS" );
+ kwdoc.appendChild( framesets );
+
+ m_textImageRequests.clear(); // for KWTextImage
+ QValueList<KoPictureKey> savePictures;
+
+ QPtrListIterator<KWFrameSet> fit = framesetsIterator();
+ for ( ; fit.current() ; ++fit )
+ {
+ KWFrameSet *frameSet = fit.current();
+ // Save non-part framesets ( part are saved further down )
+ if ( frameSet->type() != FT_PART )
+ frameSet->save( framesets );
+
+ // If picture frameset, make a note of the image it needs.
+ if ( !frameSet->isDeleted() && ( frameSet->type() == FT_PICTURE ) )
+ {
+ KoPictureKey key = static_cast<KWPictureFrameSet *>( frameSet )->key();
+ if ( !savePictures.contains( key ) )
+ savePictures.append( key );
+ }
+ }
+
+ // Process the data of the KWTextImage classes.
+ QPtrListIterator<KWTextImage> textIt ( m_textImageRequests );
+ for ( ; textIt.current() ; ++textIt )
+ {
+ KoPictureKey key = textIt.current()->getKey();
+ kdDebug(32001) << "KWDocument::saveXML registering text image " << key.toString() << endl;
+ if ( !savePictures.contains( key ) )
+ savePictures.append( key );
+ }
+
+ QDomElement styles = doc.createElement( "STYLES" );
+ kwdoc.appendChild( styles );
+ QValueList<KoUserStyle *> styleList(m_styleColl->styleList());
+ for ( QValueList<KoUserStyle *>::const_iterator it = styleList.begin(), end = styleList.end();
+ it != end ; ++it )
+ saveStyle( static_cast<KoParagStyle *>( *it ), styles );
+
+ QDomElement frameStyles = doc.createElement( "FRAMESTYLES" );
+ kwdoc.appendChild( frameStyles );
+ QValueList<KoUserStyle *> frameStyleList(m_frameStyleColl->styleList());
+ for ( QValueList<KoUserStyle *>::const_iterator it = frameStyleList.begin(), end = frameStyleList.end();
+ it != end ; ++it )
+ saveFrameStyle( static_cast<KWFrameStyle *>(*it), frameStyles );
+
+ QDomElement tableStyles = doc.createElement( "TABLESTYLES" );
+ kwdoc.appendChild( tableStyles );
+ QValueList<KoUserStyle *> tableStyleList(m_tableStyleColl->styleList());
+ for ( QValueList<KoUserStyle *>::const_iterator it = tableStyleList.begin(), end = tableStyleList.end();
+ it != end ; ++it )
+ saveTableStyle( static_cast<KWTableStyle *>(*it), tableStyles );
+
+ QDomElement pictures = m_pictureCollection->saveXML( KoPictureCollection::CollectionPicture, doc, savePictures );
+ kwdoc.appendChild( pictures );
+
+ // Not needed anymore
+#if 0
+ // Write out the list of parags (id) that form the table of contents, see KWContents::createContents
+ if ( contents->hasContents() ) {
+ QDomElement cParags = doc.createElement( "CPARAGS" );
+ kwdoc.appendChild( cParags );
+ QValueList<int>::Iterator it = contents->begin();
+ for ( ; it != contents->end(); ++it )
+ {
+ QDomElement paragElem = doc.createElement( "PARAG" );
+ cParags.appendChild( paragElem );
+ paragElem.setAttribute( "name", QString::number( *it ) ); // write parag id
+ }
+ }
+#endif
+
+ QDomElement mailMerge=m_slDataBase->save(doc);
+ kwdoc.appendChild(mailMerge);
+
+ if( !m_spellCheckIgnoreList.isEmpty() )
+ {
+ QDomElement spellCheckIgnore = doc.createElement( "SPELLCHECKIGNORELIST" );
+ kwdoc.appendChild( spellCheckIgnore );
+ for ( QStringList::ConstIterator it = m_spellCheckIgnoreList.begin(); it != m_spellCheckIgnoreList.end(); ++it )
+ {
+ QDomElement spellElem = doc.createElement( "SPELLCHECKIGNOREWORD" );
+ spellCheckIgnore.appendChild( spellElem );
+ spellElem.setAttribute( "word", *it );
+ }
+ }
+
+ // Save embedded objects
+ saveEmbeddedObjects( kwdoc, children() );
+ return doc;
+}
+
+// KWord-1.3 format
+void KWDocument::saveEmbeddedObjects( QDomElement& parentElem, const QPtrList<KoDocumentChild>& childList )
+{
+ // Write "OBJECT" tag for every child, appending "EMBEDDING" tags to the main XML
+ QPtrListIterator<KoDocumentChild> chl( childList );
+ QDomDocument doc = parentElem.ownerDocument();
+ for( ; chl.current(); ++chl ) {
+ KWDocumentChild* curr = static_cast<KWDocumentChild*>(chl.current());
+ if ( !curr->isDeleted() )
+ {
+ QDomElement embeddedElem = doc.createElement( "EMBEDDED" );
+ parentElem.appendChild( embeddedElem );
+
+ QDomElement objectElem = curr->save( doc, true );
+ embeddedElem.appendChild( objectElem );
+
+ QDomElement settingsElem = doc.createElement( "SETTINGS" );
+ embeddedElem.appendChild( settingsElem );
+
+ curr->partFrameSet()->save( settingsElem );
+ }
+ }
+}
+
+// KWord-1.3 format
+void KWDocument::saveStyle( KoParagStyle *sty, QDomElement parentElem )
+{
+ QDomDocument doc = parentElem.ownerDocument();
+ QDomElement styleElem = doc.createElement( "STYLE" );
+ parentElem.appendChild( styleElem );
+
+ sty->saveStyle( styleElem );
+
+ QDomElement formatElem = KWTextParag::saveFormat( doc, &sty->format(), 0L, 0, 0 );
+ styleElem.appendChild( formatElem );
+}
+
+// KWord-1.3 format
+void KWDocument::saveFrameStyle( KWFrameStyle *sty, QDomElement parentElem )
+{
+ QDomDocument doc = parentElem.ownerDocument();
+ QDomElement frameStyleElem = doc.createElement( "FRAMESTYLE" );
+ parentElem.appendChild( frameStyleElem );
+
+ sty->saveFrameStyle( frameStyleElem );
+}
+
+// KWord-1.3 format
+void KWDocument::saveTableStyle( KWTableStyle *sty, QDomElement parentElem )
+{
+ QDomDocument doc = parentElem.ownerDocument();
+ QDomElement tableStyleElem = doc.createElement( "TABLESTYLE" );
+ parentElem.appendChild( tableStyleElem );
+
+ sty->saveTableStyle( tableStyleElem );
+}
+
+
+QValueList<KoPictureKey> KWDocument::savePictureList()
+{
+ QValueList<KoPictureKey> savePictures;
+
+ // At first, we must process the data of the KWTextImage classes.
+ // Process the data of the KWTextImage classes.
+ QPtrListIterator<KWTextImage> textIt ( m_textImageRequests );
+ for ( ; textIt.current() ; ++textIt )
+ {
+ KoPictureKey key = textIt.current()->getKey();
+ kdDebug(32001) << "KWDocument::saveXML registering text image " << key.toString() << endl;
+ if ( !savePictures.contains( key ) )
+ savePictures.append( key );
+ }
+ m_textImageRequests.clear(); // Save some memory!
+
+ // Now do the images/cliparts in frames.
+ QPtrListIterator<KWFrameSet> fit = framesetsIterator();
+ for ( ; fit.current() ; ++fit )
+ {
+ KWFrameSet *frameSet = fit.current();
+ // If picture frameset, make a note of the image it needs.
+ if ( !frameSet->isDeleted() && ( frameSet->type() == FT_PICTURE ) )
+ {
+ KoPictureKey key = static_cast<KWPictureFrameSet *>( frameSet )->key();
+ if ( !savePictures.contains( key ) )
+ savePictures.append( key );
+ }
+ }
+ return savePictures;
+}
+
+// KWord-1.3 format
+bool KWDocument::completeSaving( KoStore *store )
+{
+ if ( !store )
+ return TRUE;
+
+ QString u = KURL( url() ).path();
+
+ QValueList<KoPictureKey> savePictures( savePictureList() );
+
+ return m_pictureCollection->saveToStore( KoPictureCollection::CollectionPicture, store, savePictures );
+}
+
+int KWDocument::supportedSpecialFormats() const
+{
+ return KoDocument::supportedSpecialFormats();
+}
+
+void KWDocument::addView( KoView *view )
+{
+ m_lstViews.append( (KWView*)view );
+ KoDocument::addView( view );
+ for( QValueList<KWView *>::Iterator it = m_lstViews.begin(); it != m_lstViews.end(); ++it ) {
+ (*it)->deselectAllFrames();
+ }
+}
+
+void KWDocument::removeView( KoView *view )
+{
+ m_lstViews.remove( static_cast<KWView*>(view) );
+ KoDocument::removeView( view );
+}
+
+void KWDocument::addShell( KoMainWindow *shell )
+{
+ connect( shell, SIGNAL( documentSaved() ), m_commandHistory, SLOT( documentSaved() ) );
+ connect( shell, SIGNAL( saveDialogShown() ), this, SLOT( saveDialogShown() ) );
+ KoDocument::addShell( shell );
+}
+
+KoView* KWDocument::createViewInstance( QWidget* parent, const char* name )
+{
+ if ( isEmbedded() )
+ return new KWView( "ModeEmbedded", parent, name, this );
+ else
+ return new KWView( m_viewModeType, parent, name, this );
+}
+
+// Paint this document when it's embedded
+// This is also used to paint the preview.png that goes into the ZIP file
+void KWDocument::paintContent( QPainter& painter, const QRect& rectangle, bool transparent, double zoomX, double zoomY )
+{
+ //kdDebug(32001) << "KWDocument::paintContent m_zoom=" << m_zoom << " zoomX=" << zoomX << " zoomY=" << zoomY << " transparent=" << transparent << " rectangle=" << rectangle << endl;
+ Q_ASSERT( zoomX != 0 );
+ Q_ASSERT( zoomY != 0 );
+
+ setZoom( 100 );
+ m_zoomMode = KoZoomMode::ZOOM_CONSTANT;
+
+ // The caller doesn't care about DPI, that's our own internal zooming done on top of it:
+ zoomX *= POINT_TO_INCH( static_cast<double>( KoGlobal::dpiX() ) );
+ zoomY *= POINT_TO_INCH( static_cast<double>( KoGlobal::dpiY() ) );
+
+ if ( m_zoomedResolutionX != zoomX || m_zoomedResolutionY != zoomY )
+ {
+ //kdDebug(32001) << "m_zoomedResolutionX=" << m_zoomedResolutionX << " != " << zoomX << " -> calling setResolution(" << zoomX << ")" << endl;
+ int zoomLevel = qRound( 100 * zoomY / m_zoomedResolutionY ); // ## ignores the case where the x and y scaling differs
+ setZoom( zoomLevel );
+ bool forPrint = painter.device() && painter.device()->devType() == QInternal::Printer;
+ newZoomAndResolution( false, forPrint );
+ if ( KFormula::Document* formulaDocument = m_formulaDocumentWrapper->document() )
+ formulaDocument->setZoomAndResolution( zoomLevel, zoomX, zoomY, false, forPrint );
+ // Note that this zoom and resolution are then used when activating the embedded object!
+ }
+
+ QRect rect( rectangle );
+ painter.save();
+ painter.translate( rect.x(), rect.y() );
+ QRect clipRect( 0, 0, rect.width(), rect.height() );
+
+ KWViewModeEmbedded * viewMode = new KWViewModeEmbedded( this, 0 /*no canvas*/ );
+ viewMode->setDrawFrameBackground( !transparent );
+ viewMode->setDrawSelections( false );
+
+ QColorGroup cg = QApplication::palette().active();
+
+ if (!transparent)
+ {
+ QRegion emptyRegion( rect );
+ createEmptyRegion( rect, emptyRegion, viewMode );
+ eraseEmptySpace( &painter, emptyRegion, cg.brush( QColorGroup::Base ) );
+ }
+
+ QPtrListIterator<KWFrameSet> fit = framesetsIterator();
+ for ( ; fit.current() ; ++fit )
+ {
+ KWFrameSet * frameset = fit.current();
+ if ( frameset->isVisible( viewMode ) && !frameset->isFloating() )
+ frameset->drawContents( &painter, clipRect, cg,
+ false /*onlyChanged*/, true /*resetChanged*/,
+ 0L, viewMode, 0 );
+ }
+ delete viewMode;
+
+ painter.restore();
+}
+
+QPixmap KWDocument::generatePreview( const QSize& size )
+{
+ int oldZoom = m_zoom;
+ double oldResolutionX = resolutionX();
+ double oldResolutionY = resolutionY();
+ double oldZoomX = zoomedResolutionX();
+ double oldZoomY = zoomedResolutionY();
+
+ // Sometimes (due to the different resolution?) the layout creates a new page
+ // while saving the preview. If this happens, we don't want to repaint the real views
+ // (due to KWCanvas::slotNewContentsSize)
+ // ##### One day when we have real doc/view separation in kotextparag, we shouldn't mess with
+ // the real view's resolution, we should instead create a fake view for the preview itself.
+ for( QValueList<KWView *>::Iterator it = m_lstViews.begin(); it != m_lstViews.end(); ++it ) {
+ (*it)->getGUI()->canvasWidget()->setUpdatesEnabled( false );
+ }
+ Q_ASSERT( !m_bGeneratingPreview );
+ m_bGeneratingPreview = true;
+ QPixmap pix = KoDocument::generatePreview(size);
+
+ // Restore everything as it was before
+ setResolution( oldResolutionX, oldResolutionY );
+ setZoom( oldZoom );
+
+ for( QValueList<KWView *>::Iterator it = m_lstViews.begin(); it != m_lstViews.end(); ++it ) {
+ (*it)->getGUI()->canvasWidget()->setUpdatesEnabled( true );
+ }
+ newZoomAndResolution( true /*set contents size again*/, false );
+ m_bGeneratingPreview = false;
+ if ( KFormula::Document* formulaDocument = m_formulaDocumentWrapper->document() ) {
+ formulaDocument->setZoomAndResolution( oldZoom, oldZoomX, oldZoomY );
+ }
+ return pix;
+}
+
+void KWDocument::createEmptyRegion( const QRect & crect, QRegion & emptyRegion, KWViewMode * viewMode )
+{
+ QPtrListIterator<KWFrameSet> fit = framesetsIterator();
+ for ( ; fit.current() ; ++fit )
+ {
+ KWFrameSet *frameset = fit.current();
+ if ( frameset->isVisible( viewMode ) )
+ frameset->createEmptyRegion( crect, emptyRegion, viewMode );
+ }
+}
+
+void KWDocument::eraseEmptySpace( QPainter * painter, const QRegion & emptySpaceRegion, const QBrush & brush )
+{
+ painter->save();
+ painter->setClipRegion( emptySpaceRegion, QPainter::CoordPainter );
+ painter->setPen( Qt::NoPen );
+
+ //kdDebug(32001) << "KWDocument::eraseEmptySpace emptySpaceRegion: " << emptySpaceRegion << endl;
+ //kdDebug(32001) << " boundingRect: " << DEBUGRECT( emptySpaceRegion.boundingRect() ) << endl;
+ painter->fillRect( emptySpaceRegion.boundingRect(), brush );
+ painter->restore();
+}
+
+KWDocumentChild* KWDocument::createChildDoc( const KoRect& rect, KoDocument* childDoc )
+{
+ KWDocumentChild* ch = new KWDocumentChild( this, rect.toQRect(), childDoc );
+ insertChild( ch );
+ return ch;
+}
+
+KWPartFrameSet* KWDocument::insertObject( const KoRect& rect, KoDocumentEntry& e, QWidget* parentWidget )
+{
+ KoDocument* doc = e.createDoc( this );
+ if ( !doc )
+ return 0;
+ if ( !doc->showEmbedInitDialog( parentWidget ) )
+ return 0;
+
+ KWDocumentChild* ch = createChildDoc( rect, doc );
+ setModified( TRUE );
+
+ KWPartFrameSet *frameset = new KWPartFrameSet( this, ch, QString::null );
+ KWFrame *frame = new KWFrame(frameset, rect.x(), rect.y(), rect.width(), rect.height() );
+ frame->setZOrder( maxZOrder( frame->pageNumber(this) ) + 1 ); // make sure it's on top
+ frameset->addFrame( frame );
+ addFrameSet( frameset );
+
+ KWCreateFrameCommand *cmd = new KWCreateFrameCommand( i18n("Create Part Frame"), frame);
+ addCommand(cmd);
+
+ frameChanged( frame ); // repaint etc.
+
+ return frameset;
+}
+
+
+void KWDocument::delayedRepaintAllViews() {
+ if (!m_repaintAllViewsPending) {
+ QTimer::singleShot( 0, this, SLOT( slotRepaintAllViews() ) );
+ m_repaintAllViewsPending=true;
+ }
+}
+
+void KWDocument::slotRepaintAllViews() {
+ m_repaintAllViewsPending=false;
+ repaintAllViews( false );
+}
+
+void KWDocument::delayedRecalcFrames( int fromPage ) {
+ //kdDebug() << k_funcinfo << fromPage << endl;
+ if ( m_recalcFramesPending == -1 || fromPage < m_recalcFramesPending )
+ {
+ m_recalcFramesPending = fromPage;
+ QTimer::singleShot( 0, this, SLOT( slotRecalcFrames() ) );
+ }
+}
+
+void KWDocument::slotRecalcFrames() {
+ int from = m_recalcFramesPending;
+ kdDebug() << k_funcinfo << "from=" << from << endl;
+ m_recalcFramesPending = -1;
+ if ( from != -1 )
+ recalcFrames( from );
+}
+
+void KWDocument::repaintAllViewsExcept( KWView *view, bool erase )
+{
+ //kdDebug(32001) << "KWDocument::repaintAllViewsExcept" << endl;
+ for( QValueList<KWView *>::Iterator it = m_lstViews.begin(); it != m_lstViews.end(); ++it ) {
+ KWView* viewPtr = *it;
+ if ( viewPtr != view /*&& viewPtr->getGUI() && viewPtr->getGUI()->canvasWidget()*/ ) {
+ viewPtr->getGUI()->canvasWidget()->repaintAll( erase );
+ }
+ }
+}
+
+void KWDocument::updateAllStyleLists()
+{
+ for( QValueList<KWView *>::Iterator it = m_lstViews.begin(); it != m_lstViews.end(); ++it )
+ (*it)->updateStyleList();
+}
+
+void KWDocument::updateStyleListOrder( const QStringList &list )
+{
+ styleCollection()->updateStyleListOrder( list );
+}
+
+void KWDocument::applyStyleChange( KoStyleChangeDefMap changed )
+{
+ QPtrList<KWTextFrameSet> textFramesets = allTextFramesets( true );
+
+ KWTextFrameSet *frm;
+ for ( frm=textFramesets.first(); frm != 0; frm=textFramesets.next() ){
+ frm->applyStyleChange( changed );
+ }
+}
+
+void KWDocument::updateAllFrameStyleLists()
+{
+ for( QValueList<KWView *>::Iterator it = m_lstViews.begin(); it != m_lstViews.end(); ++it )
+ (*it)->updateFrameStyleList();
+}
+
+void KWDocument::updateAllTableStyleLists()
+{
+ for( QValueList<KWView *>::Iterator it = m_lstViews.begin(); it != m_lstViews.end(); ++it )
+ (*it)->updateTableStyleList();
+}
+
+void KWDocument::repaintAllViews( bool erase )
+{
+ //kdDebug(32001) << "KWDocument::repaintAllViews" << endl;
+ for( QValueList<KWView *>::Iterator it = m_lstViews.begin(); it != m_lstViews.end(); ++it )
+ (*it)->getGUI()->canvasWidget()->repaintAll( erase );
+}
+
+QPtrList<KWFrame> KWDocument::framesToCopyOnNewPage( int afterPageNum ) const {
+ // afterPageNum can be -1 for 'before page 1'
+
+ // Look at frames on pages afterPageNum and afterPageNum-1 (for sheetside stuff)
+ QPtrList<KWFrame> framesToLookAt;
+ if ( afterPageNum >= startPage() )
+ framesToLookAt = framesInPage( afterPageNum, false );
+
+ if ( afterPageNum >= startPage() + 1 )
+ {
+ QPtrList<KWFrame> framesToAlsoLookAt = framesInPage( afterPageNum-1, false ); // order doesn't matter
+
+ // Merge into single list. Other alternative, two loops, code inside moved to another method.
+ QPtrListIterator<KWFrame> frameAlsoIt( framesToAlsoLookAt );
+ for ( ; frameAlsoIt.current(); ++frameAlsoIt )
+ framesToLookAt.append( frameAlsoIt.current() );
+ }
+
+ QPtrList<KWFrame> framesToCopy; // the result
+
+ QPtrListIterator<KWFrame> frameIt( framesToLookAt );
+ for ( ; frameIt.current(); ++frameIt )
+ {
+ KWFrame * frame = frameIt.current();
+ KWFrameSet* frameSet = frame->frameSet();
+
+ // don't add tables! A table cell ( frameset ) _must_ not have cells auto-added to them!
+ if ( frameSet->type() == FT_TABLE ) continue;
+
+ // NewFrameBehavior == Copy is handled here except for headers/footers, which
+ // are created in recalcFrames()
+ if(frameSet->isAHeader() || frameSet->isAFooter()) continue;
+
+#ifdef DEBUG_PAGES
+ kdDebug(32002) << "KWDocument::framesToCopyOnNewPage looking at frame " << frame << ", pageNum=" << frame->pageNumber() << " from " << frameSet->name() << endl;
+ static const char * newFrameBh[] = { "Reconnect", "NoFollowup", "Copy" };
+ kdDebug(32002) << " frame->newFrameBehavior()==" << newFrameBh[frame->newFrameBehavior()] << endl;
+#endif
+ const int frameIsOnPage = frame->pageNumber();
+ if (frame->newFrameBehavior() == KWFrame::Copy &&
+ (frameIsOnPage == afterPageNum && frame->sheetSide() == KWFrame::AnySide ||
+ frameIsOnPage == afterPageNum -1 && frame->sheetSide() != KWFrame::AnySide))
+ framesToCopy.append( frame );
+ }
+ return framesToCopy;
+}
+
+KWPage* KWDocument::insertPage( int afterPageNum ) // can be -1 for 'before page 0'
+{
+#ifdef DEBUG_PAGES
+ kdDebug(32002) << "insertPage: afterPageNum=" << afterPageNum << endl;
+#endif
+ if ( processingType() == WP )
+ Q_ASSERT( afterPageNum == lastPage() ); // WP mode: can only append.
+
+ double pageHeight = pageManager()->page( afterPageNum )->height();
+ // If not appending, move down everything after 'afterPageNum', to make room.
+ for ( int pg = pageCount () -1 ; pg > afterPageNum ; --pg )
+ {
+ // pg is the 'src' page. Its contents must be moved to the page pg+1
+ QPtrList<KWFrame> frames = framesInPage( pg, false );
+#ifdef DEBUG_PAGES
+ kdDebug(32002) << "insertPage: moving " << frames.count() << " frames down, from page " << pg << endl;
+#endif
+ QPtrListIterator<KWFrame> frameIt( frames );
+ for ( ; frameIt.current(); ++frameIt )
+ frameIt.current()->moveBy( 0, pageHeight );
+ }
+
+ KWPage *page = pageManager()->insertPage(afterPageNum+1);
+
+ // Fill in the new page
+ QPtrList<KWFrame> framesToCopy = framesToCopyOnNewPage( afterPageNum );
+ QPtrListIterator<KWFrame> frameIt( framesToCopy );
+ for ( ; frameIt.current(); ++frameIt )
+ {
+ KWFrame * frame = frameIt.current();
+
+ KWFrame *newFrame = frame->getCopy();
+ newFrame->moveBy( 0, pageHeight );
+ frame->frameSet()->addFrame( newFrame );
+
+ if ( frame->newFrameBehavior()==KWFrame::Copy )
+ newFrame->setCopy( true );
+ //kdDebug(32002) << " => created frame " << newFrame << " " << *newFrame << endl;
+ }
+ return page;
+}
+
+KWPage* KWDocument::appendPage()
+{
+#ifdef DEBUG_PAGES
+ kdDebug(32002) << "KWDocument::appendPage pageCount()=" << pageCount() << " -> insertPage(" << lastPage() << ")" << endl;
+#endif
+ return insertPage( lastPage() );
+}
+
+void KWDocument::afterInsertPage( int pageNum )
+{
+#ifdef DEBUG_PAGES
+ kdDebug(32002) << "KWDocument::afterInsertPage " << pageNum << endl;
+#endif
+ if ( !m_bGeneratingPreview )
+ emit newContentsSize();
+
+ // Get headers and footers on the new page
+ // This shouldn't delete the newly created page because it's still empty though
+ recalcFrames( pageNum, -1, KWFrameLayout::DontRemovePages );
+ // Take into account the frames on the new page, and run updateFramesOnTopOrBelow (#73819)
+ updateAllFrames();
+
+ recalcVariables( VT_PGNUM );
+ emit numPagesChanged();
+ if ( m_viewModeType == "ModePreview" )
+ repaintAllViews();
+}
+
+bool KWDocument::canRemovePage( int num )
+{
+kdDebug() << "KWDocument::canRemovePage " << num<< endl;
+ QPtrListIterator<KWFrameSet> fit = framesetsIterator();
+ for ( ; fit.current() ; ++fit )
+ {
+ KWFrameSet * frameSet = fit.current();
+ if ( frameSet->isHeaderOrFooter() ) // don't look at headers/footers, but look at footnotes/endnotes
+ continue;
+ if ( frameSet->isVisible() && !frameSet->canRemovePage( num ) )
+ return false;
+ }
+#ifdef DEBUG_PAGES
+ kdDebug(32002) << "KWDocument::canRemovePage " << num << "-> TRUE" << endl;
+#endif
+ return true;
+}
+
+void KWDocument::removePage( int pageNum )
+{
+ if ( processingType() == WP )
+ Q_ASSERT( pageNum == lastPage() ); // WP mode: can only remove last page.
+ Q_ASSERT( pageCount() > 1 );
+ if ( pageCount() == 1 )
+ return;
+
+ // ## This assumes that framesInPage is up-to-date.
+ QPtrList<KWFrame> framesToDelete = framesInPage( pageNum, false );
+#ifdef DEBUG_PAGES
+ kdDebug(32002) << "KWDocument::removePage " << pageNum << ", " << framesToDelete.count() << " frames to delete" << endl;
+#endif
+ QPtrListIterator<KWFrame> frameIt( framesToDelete );
+ for ( ; frameIt.current(); ++frameIt )
+ {
+ KWFrame * frame = frameIt.current();
+ KWFrameSet * frameSet = frame->frameSet();
+ if ( frameSet->frameSetInfo() != KWFrameSet::FI_BODY )
+ continue;
+ frameSet->deleteFrame( frame, true );
+ }
+
+ // If not removing the last one, move up everything after the one we removed.
+ for ( int pg = pageNum+1 ; pg < pageCount() ; ++pg )
+ {
+ // pg is the 'src' page. Its contents must be moved to the page pg-1
+ QPtrList<KWFrame> frames = framesInPage( pg, false );
+#ifdef DEBUG_PAGES
+ kdDebug(32002) << "removePage: moving " << frames.count() << " frames up, from page " << pg << endl;
+#endif
+ QPtrListIterator<KWFrame> frameIt( frames );
+ for ( ; frameIt.current(); ++frameIt )
+ frameIt.current()->moveBy( 0, pageManager()->page(0)->height() );
+ }
+
+ pageManager()->removePage(pageNum);
+#ifdef DEBUG_PAGES
+ kdDebug(32002) << "KWDocument::removePage -- -> " << pageCount() << endl;
+#endif
+ // Emitting this one for each page being removed helps giving the user some feedback
+ emit numPagesChanged();
+}
+
+void KWDocument::afterRemovePages()
+{
+ //### IMHO recalcFrames should take care of updateAllFrames (it already does it partially).
+ recalcFrames();
+ // Do this before recalcVariables (which repaints). The removed frames must be removed from the frame caches.
+ // We don't call updateAllFrames() directly, because it still calls
+ // updateFramesOnTopOrBelow, which is useless (and slow) here.
+ QPtrListIterator<KWFrameSet> fit = framesetsIterator();
+ for ( ; fit.current() ; ++fit )
+ fit.current()->updateFrames();
+
+ recalcVariables( VT_PGNUM );
+ if ( !m_bGeneratingPreview )
+ emit newContentsSize();
+ if ( m_viewModeType == "ModePreview" )
+ repaintAllViews();
+}
+
+bool KWDocument::tryRemovingPages()
+{
+ int last = lastPage();
+ bool removed = false;
+ // Last frame is empty -> try removing last page, and more if necessary
+ while ( last > startPage() && canRemovePage( last ) )
+ {
+ removePage( last ); // this modifies pageCount
+ if ( last <= lastPage() )
+ {
+ kdWarning() << "Didn't manage to remove page " << last << " (still having " << pageCount() << " pages ). Aborting" << endl;
+ break;
+ }
+ removed = true;
+ last = lastPage();
+ }
+ // Don't call afterRemovePages or recalcFrames from here, since this method is
+ // itself called from KWFrameLayout (#95047)
+ return removed;
+}
+
+
+KWFrameSet * KWDocument::frameSetByName( const QString & name )
+{
+ // Note: this isn't recursive, so it won't find table cells.
+ QPtrListIterator<KWFrameSet> fit = framesetsIterator();
+ for ( ; fit.current() ; ++fit )
+ if ( fit.current()->name() == name )
+ return fit.current();
+ return 0L;
+}
+
+//#define DEBUG_FRAMESELECT
+
+QString KWDocument::generateFramesetName( const QString & templateName )
+{
+ QString name;
+ int num = 1;
+ bool exists;
+ do {
+ name = templateName.arg( num );
+ exists = frameSetByName( name );
+ ++num;
+ } while ( exists );
+ return name;
+}
+
+void KWDocument::fixZOrders() {
+ //KWFrame *frameFixed = 0;
+ for (int pgnum = startPage() ; pgnum <= lastPage() ; pgnum++) {
+ QPtrList<KWFrame> frames = framesInPage(pgnum);
+ // scan this page to see if we need to fixup:
+ // fix up if two frames have the same zOrder,
+ // or if a zOrder is negative (not allowed by OASIS)
+ bool need_fixup = false;
+ KWFrame *f = frames.last();
+ if ( !f )
+ continue;
+ int lastZOrder = f->zOrder();
+ f = frames.prev();
+ for ( ; f ; f=frames.prev() ) {
+ if ( !f->frameSet()->isFloating() &&
+ ( f->zOrder() == lastZOrder || f->zOrder() < 0 ) ) {
+ need_fixup = true;
+ break;
+ }
+ lastZOrder = f->zOrder();
+ }
+ if ( need_fixup ) {
+ int current_zorder=0;
+ kdDebug() << "fixing page " << pgnum << " z-orders " << endl;
+ for (KWFrame *fr = frames.first();fr;fr=frames.next()) {
+ // only consider non-inline framesets.
+ if (fr->frameSet()->isFloating())
+ continue;
+ current_zorder++;
+ fr->setZOrder(current_zorder);
+ //frameFixed = f;
+ }
+ }
+
+ if ( m_processingType == KWDocument::WP )
+ {
+ // In all cases, ensure the main frames are below the rest.
+ // (This could not be the case after e.g. an import filter does it wrong)
+ lowerMainFrames( pgnum );
+ }
+ }
+ //if ( frameFixed )
+ // frameFixed->frameStack()->recalcAllFrames();
+ KWFrameList::recalcAllFrames(this);
+}
+
+void KWDocument::lowerMainFrames( int pageNum )
+{
+ QPtrList<KWFrame> framesInPage = this->framesInPage(pageNum);
+ int lowestZOrder=10000;
+ for ( QPtrListIterator<KWFrame> frameIt( framesInPage ); frameIt.current(); ++frameIt )
+ lowestZOrder=QMIN(lowestZOrder, frameIt.current()->zOrder());
+ lowerMainFrames( pageNum, lowestZOrder );
+}
+
+// separated from the above one for KWView (which knows lowestZOrder already)
+void KWDocument::lowerMainFrames( int pageNum, int lowestZOrder )
+{
+ // Get the main frameset and see if we have to lower its frame(s).
+ QPtrList<KWFrame> framesInPage = this->framesInPage(pageNum);
+ for ( QPtrListIterator<KWFrame> frameIt( framesInPage ); frameIt.current(); ++frameIt ) {
+ if(frameIt.current()->frameSet()->isMainFrameset()) {
+ if(lowestZOrder <= frameIt.current()->zOrder())
+ frameIt.current()->setZOrder(lowestZOrder-1);
+ // keep going, in case of multiple columns
+ }
+ }
+}
+
+QPtrList<KWFrame> KWDocument::framesInPage( int pageNum, bool sorted ) const {
+
+ ZOrderedFrameList frames;
+ QPtrListIterator<KWFrameSet> fit = framesetsIterator();
+ for ( ; fit.current() ; ++fit )
+ {
+ KWFrameSet *frameSet = fit.current();
+ if ( !frameSet->isVisible() )
+ continue;
+ // Append all frames from frameSet in page pageNum
+ QPtrListIterator<KWFrame> it( frameSet->framesInPage( pageNum ) );
+ for ( ; it.current() ; ++it )
+ frames.append( it.current() );
+ }
+ if (sorted) frames.sort();
+ return frames;
+}
+
+void KWDocument::updateAllFrames( int flags )
+{
+#ifdef DEBUG_SPEED
+ QTime dt;
+ dt.start();
+#endif
+ QPtrListIterator<KWFrameSet> fit = framesetsIterator();
+ for ( ; fit.current() ; ++fit )
+ fit.current()->updateFrames( flags );
+
+#ifdef DEBUG_SPEED
+ kdDebug(32001) << "updateAllFrames(" << flags << ") took " << (float)(dt.elapsed()) / 1000 << " seconds" << endl;
+#endif
+
+ // TODO: check all calls to updateAllFrames, and fix them.
+ // E.g., if one frame moved, updateAllFrames isn't necessary,
+ // only fs->updateFrames() and doc->updateFramesOnTopOrBelow() are necessary.
+
+ // Update frames ontop and below _afterwards_,
+ // it needs the 'frames in page' array (in other framesets)
+ KWFrameList::recalcAllFrames(this);
+}
+
+// Tell this method when a frame is moved / resized / created / deleted
+// and everything will be update / repainted accordingly
+void KWDocument::frameChanged( KWFrame * frame )
+{
+ if(! m_framesChangedHandler) {
+ m_framesChangedHandler = new FramesChangedHandler(this);
+ QTimer::singleShot( 0, this, SLOT( updateFramesChanged() ) );
+ }
+ m_framesChangedHandler->addFrame(frame);
+}
+
+void KWDocument::framesChanged( const QPtrList<KWFrame> & frames, KWView * view )
+{
+ Q_UNUSED( view ); // DF: seems my idea of excluding one view got thrown away
+ QPtrListIterator<KWFrame> it( frames );
+ for ( ; it.current() ; ++it )
+ frameChanged(it.current());
+}
+
+void KWDocument::updateFramesChanged() { // slot called from frameChanged()
+ if(!m_framesChangedHandler) return;
+ m_framesChangedHandler->execute();
+ delete m_framesChangedHandler;
+ m_framesChangedHandler = 0;
+}
+
+void KWDocument::framesChanged( const QValueList<KWFrame*> &frames) {
+ QValueListConstIterator<KWFrame*> framesIterator = frames.begin();
+ for(;framesIterator != frames.end(); ++framesIterator)
+ frameChanged(*framesIterator);
+}
+
+void KWDocument::setHeaderVisible( bool h )
+{
+ m_headerVisible = h;
+ recalcFrames();
+ updateAllFrames();
+ layout();
+ setModified(true);
+ repaintAllViews( true );
+}
+
+void KWDocument::setFooterVisible( bool f )
+{
+ m_footerVisible = f;
+ recalcFrames();
+ updateAllFrames();
+ layout();
+ setModified(true);
+ repaintAllViews( true );
+}
+
+bool KWDocument::hasEndNotes() const
+{
+ return m_bHasEndNotes;
+}
+
+void KWDocument::updateHeaderButton()
+{
+ for( QValueList<KWView *>::Iterator it = m_lstViews.begin(); it != m_lstViews.end(); ++it )
+ {
+ (*it)->updateHeaderFooterButton();
+ (*it)->updateHeader();
+ }
+}
+
+void KWDocument::updateFooterButton()
+{
+ for( QValueList<KWView *>::Iterator it = m_lstViews.begin(); it != m_lstViews.end(); ++it )
+ {
+ (*it)->updateHeaderFooterButton();
+ (*it)->updateFooter();
+ }
+}
+
+void KWDocument::addTextImageRequest( KWTextImage *img )
+{
+ m_textImageRequests.append( img );
+}
+
+void KWDocument::addPictureRequest( KWPictureFrameSet *fs )
+{
+ m_pictureRequests.append( fs );
+}
+
+void KWDocument::addAnchorRequest( const QString &framesetName, const KWAnchorPosition &anchorPos )
+{
+ m_anchorRequests.insert( framesetName, anchorPos );
+}
+
+void KWDocument::addFootNoteRequest( const QString &framesetName, KWFootNoteVariable* var )
+{
+ if ( var->noteType() == EndNote )
+ m_bHasEndNotes = true;
+ m_footnoteVarRequests.insert( framesetName, var );
+}
+
+void KWDocument::refreshMenuCustomVariable()
+{
+ emit sig_refreshMenuCustomVariable();
+}
+
+void KWDocument::recalcVariables( int type )
+{
+ const QValueList<KoVariable *> modifiedVariables = m_varColl->recalcVariables(type);
+ if ( m_bGeneratingPreview )
+ return;
+
+ QMap<KoTextDocument *, bool> modifiedTextDocuments; // Qt4: QSet
+ for ( QValueList<KoVariable *>::const_iterator it = modifiedVariables.begin(), end = modifiedVariables.end() ; it != end ; ++it ) {
+ KoTextDocument* textdoc = (*it)->textDocument();
+ if ( modifiedTextDocuments.find( textdoc ) != modifiedTextDocuments.end() ) // Qt4: !contains
+ {
+ modifiedTextDocuments.insert( textdoc, true );
+ KWTextFrameSet * textfs = static_cast<KWTextDocument *>(textdoc)->textFrameSet();
+ slotRepaintChanged( textfs );
+ }
+ }
+}
+
+int KWDocument::mailMergeRecord() const
+{
+ return slRecordNum;
+}
+
+void KWDocument::setMailMergeRecord( int r )
+{
+ slRecordNum = r;
+}
+
+void KWDocument::getPageLayout( KoPageLayout& layout, KoColumns& cl, KoKWHeaderFooter& hf )
+{
+ layout = m_pageLayout;
+ cl = m_pageColumns;
+ hf = m_pageHeaderFooter;
+}
+
+void KWDocument::addFrameSet( KWFrameSet *f, bool finalize /*= true*/ )
+{
+ if(m_lstFrameSet.contains(f) > 0) {
+ kdWarning(32001) << "Frameset " << f << " " << f->name() << " already in list!" << endl;
+ return;
+ }
+ m_lstFrameSet.append(f);
+
+ KWFrameList::createFrameList(f, this);
+
+ if ( finalize )
+ f->finalize();
+ setModified( true );
+ emit sigFrameSetAdded(f);
+}
+
+void KWDocument::removeFrameSet( KWFrameSet *f )
+{
+ emit sig_terminateEditing( f );
+ m_lstFrameSet.take( m_lstFrameSet.find(f) );
+ setModified( true );
+ emit sigFrameSetRemoved(f);
+}
+
+void KWDocument::addCommand( KCommand * cmd )
+{
+ Q_ASSERT( cmd );
+ //kdDebug(32001) << "KWDocument::addCommand " << cmd->name() << endl;
+ m_commandHistory->addCommand( cmd, false );
+ setModified( true );
+}
+
+void KWDocument::slotDocumentRestored()
+{
+ setModified( false );
+}
+
+void KWDocument::slotCommandExecuted()
+{
+ setModified( true );
+}
+
+#ifndef NDEBUG
+void KWDocument::printStyleDebug()
+{
+ kdDebug() << "----------------------------------------"<<endl;
+ m_styleColl->printDebug();
+ kdDebug() << m_frameStyleColl->count() << " frame styles" << endl;
+ kdDebug() << m_tableStyleColl->count() << " table-cell styles" << endl;
+}
+
+void KWDocument::printDebug()
+{
+ kdDebug() << "----------------------------------------"<<endl;
+ kdDebug() << " Debug info"<<endl;
+ kdDebug() << "Document:" << this <<endl;
+ kdDebug() << "Type of document: (0=WP, 1=DTP) " << processingType() <<endl;
+ kdDebug() << "Header visible: " << isHeaderVisible() << endl;
+ kdDebug() << "Footer visible: " << isFooterVisible() << endl;
+ kdDebug() << "Units: " << unit() <<endl;
+ kdDebug() << "# Framesets: " << frameSetCount() <<endl;
+ QPtrListIterator<KWFrameSet> fit = framesetsIterator();
+ for ( unsigned int iFrameset = 0; fit.current() ; ++fit, iFrameset++ )
+ {
+ KWFrameSet * frameset = fit.current();
+ kdDebug() << "Frameset " << iFrameset << ": '" <<
+ frameset->name() << "' (" << frameset << ")" << (frameset->isDeleted()?" Deleted":"")<<endl;
+ if ( frameset->isVisible())
+ frameset->printDebug();
+ else
+ kdDebug() << " [hidden] #" << frameset->frameCount() << " frames" << endl;
+ }
+
+ for ( uint pgNum = 0 ; pgNum < m_sectionTitles.size() ; ++pgNum ) {
+ kdDebug() << "Page " << pgNum << " Section: '" << m_sectionTitles[ pgNum ] << "'"<< endl;
+ }
+ /*
+ kdDebug() << "# Images: " << getImageCollection()->iterator().count() <<endl;
+ QDictIterator<KWImage> it( getImageCollection()->iterator() );
+ while ( it.current() ) {
+ kdDebug() << " + " << it.current()->getFilename() << ": "<<it.current()->refCount() <<endl;
+ ++it;
+ }
+ */
+
+ kdDebug() << "PageManager holds "<< pageCount() << " pages in the range: " << startPage() <<
+ "-" << lastPage() << endl;
+ for (int pgnum = startPage() ; pgnum <= lastPage() ; pgnum++) {
+ KWPage *page = pageManager()->page(pgnum);
+ kdDebug() << "Page " << pgnum << " width=" << page->width() << " height=" << page->height() << endl;
+ }
+ kdDebug() << " The height of the doc (in pt) is: " << pageManager()->
+ bottomOfPage(lastPage()) << endl;
+}
+#endif
+
+void KWDocument::layout()
+{
+ QPtrListIterator<KWFrameSet> it = framesetsIterator();
+ for (; it.current(); ++it )
+ if ( it.current()->isVisible() )
+ it.current()->layout();
+}
+
+void KWDocument::invalidate(const KWFrameSet *skipThisFrameSet)
+{
+ QPtrListIterator<KWFrameSet> it = framesetsIterator();
+ for (; it.current(); ++it )
+ if(it.current()!=skipThisFrameSet)
+ it.current()->invalidate();
+}
+
+KFormula::Document* KWDocument::formulaDocument( bool init )
+{
+ KFormula::Document* formulaDocument = m_formulaDocumentWrapper->document();
+ if (!formulaDocument) {
+ kdDebug() << k_funcinfo << endl;
+ formulaDocument = new KFormula::Document;
+ m_formulaDocumentWrapper->document( formulaDocument, init );
+ if ( formulaDocument != 0 ) {
+ // re-calculate dpiX and dpiY
+ formulaDocument->setZoomAndResolution( m_zoom,
+ qRound(INCH_TO_POINT( m_resolutionX )),
+ qRound(INCH_TO_POINT( m_resolutionY )) );
+ formulaDocument->newZoomAndResolution(false,false);
+ }
+ }
+ return formulaDocument;
+}
+
+
+void KWDocument::slotRepaintChanged( KWFrameSet * frameset )
+{
+ // This has to be a loop instead of a signal, so that we can
+ // send "true" for the last view (see KWFrameSet::drawContents)
+ for( QValueList<KWView *>::Iterator it = m_lstViews.begin(); it != m_lstViews.end(); ++it ) {
+ (*it)->getGUI()->canvasWidget()->repaintChanged( frameset, it == m_lstViews.fromLast() );
+ }
+}
+
+void KWDocument::deleteTable( KWTableFrameSet *table )
+{
+ if ( !table )
+ return;
+ if ( table->isFloating() )
+ {
+ emit sig_terminateEditing( table ); // to unselect its cells, especially
+ KWAnchor * anchor = table->findAnchor( 0 );
+ addCommand( table->anchorFrameset()->deleteAnchoredFrame( anchor ) );
+ }
+ else
+ {
+ KWDeleteTableCommand *cmd = new KWDeleteTableCommand( i18n("Delete Table"), table );
+ addCommand( cmd );
+ cmd->execute();
+ }
+}
+
+void KWDocument::deleteFrame( KWFrame * frame )
+{
+ KWFrameSet * fs = frame->frameSet();
+ kdDebug(32002) << "KWDocument::deleteFrame frame=" << frame << " fs=" << fs << endl;
+ QString cmdName;
+ TypeStructDocItem docItem = (TypeStructDocItem) 0;
+ switch (fs->type() ) {
+ case FT_TEXT:
+ cmdName=i18n("Delete Text Frame");
+ docItem=TextFrames;
+ break;
+ case FT_FORMULA:
+ cmdName=i18n("Delete Formula Frame");
+ docItem=FormulaFrames;
+ break;
+ case FT_CLIPART:
+ kdError(32001) << "FT_CLIPART used! (in KWDocument::deleteFrame)" << endl;
+ break;
+ case FT_PICTURE:
+ cmdName=i18n("Delete Picture Frame");
+ docItem=Pictures;
+ break;
+ case FT_PART:
+ cmdName=i18n("Delete Object Frame");
+ docItem=Embedded;
+ break;
+ case FT_TABLE:
+ case FT_BASE:
+ Q_ASSERT( 0 );
+ break;
+ }
+ if ( fs->isFloating() )
+ {
+ KWAnchor * anchor = fs->findAnchor( 0 );
+ addCommand( fs->anchorFrameset()->deleteAnchoredFrame( anchor ) );
+ }
+ else
+ {
+ KWDeleteFrameCommand *cmd = new KWDeleteFrameCommand( cmdName, frame );
+ addCommand( cmd );
+ cmd->execute();
+ }
+ emit docStructureChanged(docItem);
+}
+
+void KWDocument::reorganizeGUI()
+{
+ for( QValueList<KWView *>::Iterator it = m_lstViews.begin(); it != m_lstViews.end(); ++it )
+ (*it)->getGUI()->reorganize();
+}
+
+void KWDocument::slotDocumentInfoModifed()
+{
+ if (!variableCollection()->variableSetting()->displayFieldCode())
+ recalcVariables( VT_FIELD );
+}
+
+void KWDocument::refreshDocStructure(int type)
+{
+ emit docStructureChanged(type);
+}
+
+int KWDocument::typeItemDocStructure(FrameSetType type)
+{
+ int typeItem;
+ switch(type)
+ {
+ case FT_TEXT:
+ typeItem=(int)TextFrames;
+ break;
+ case FT_PICTURE:
+ typeItem=(int)Pictures;
+ break;
+ case FT_PART:
+ typeItem=(int)Embedded;
+ break;
+ case FT_FORMULA:
+ typeItem=(int)FormulaFrames;
+ break;
+ case FT_TABLE:
+ typeItem=(int)Tables;
+ break;
+ default:
+ typeItem=(int)TextFrames;
+ }
+ return typeItem;
+}
+
+void KWDocument::refreshDocStructure(FrameSetType type)
+{
+ emit docStructureChanged(typeItemDocStructure(type));
+}
+
+QBrush KWDocument::resolveBgBrush( const QBrush & brush, QPainter * painter )
+{
+ if ( brush.color().isValid() )
+ return brush;
+ QBrush ret( brush );
+ ret.setColor( defaultBgColor( painter ) );
+ return ret;
+}
+
+QColor KWDocument::resolveBgColor( const QColor & col, QPainter * painter )
+{
+ if (col.isValid())
+ return col;
+
+ return defaultBgColor( painter );
+}
+
+QColor KWDocument::defaultBgColor( QPainter * painter )
+{
+ if ( painter && painter->device()->devType() == QInternal::Printer )
+ return Qt::white;
+ return QApplication::palette().color( QPalette::Active, QColorGroup::Base );
+}
+
+
+void KWDocument::setTocPresent(bool hasToc)
+{
+ m_hasTOC=hasToc;
+ for( QValueList<KWView *>::Iterator it = m_lstViews.begin(); it != m_lstViews.end(); ++it )
+ (*it)->updateTocActionText(hasToc);
+}
+
+void KWDocument::refreshMenuExpression()
+{
+ for( QValueList<KWView *>::Iterator it = m_lstViews.begin(); it != m_lstViews.end(); ++it )
+ (*it)->refreshMenuExpression();
+}
+
+void KWDocument::updateZoomRuler()
+{
+ for( QValueList<KWView *>::Iterator it = m_lstViews.begin(); it != m_lstViews.end(); ++it ) {
+ (*it)->getGUI()->getHorzRuler()->setZoom( zoomedResolutionX() );
+ (*it)->getGUI()->getVertRuler()->setZoom( zoomedResolutionY() );
+ (*it)->slotUpdateRuler();
+ }
+}
+
+void KWDocument::updateRulerFrameStartEnd()
+{
+ for( QValueList<KWView *>::Iterator it = m_lstViews.begin(); it != m_lstViews.end(); ++it )
+ (*it)->slotUpdateRuler();
+}
+
+int KWDocument::undoRedoLimit() const
+{
+ return m_commandHistory->undoLimit();
+}
+
+void KWDocument::setUndoRedoLimit(int val)
+{
+ m_commandHistory->setUndoLimit(val);
+ m_commandHistory->setRedoLimit(val);
+}
+
+void KWDocument::setGridX(double gridx) {
+ m_gridX = gridx;
+ for( QValueList<KWView *>::Iterator it = m_lstViews.begin(); it != m_lstViews.end(); ++it )
+ (*it)->getGUI()->getHorzRuler()->setGridSize(gridx);
+}
+
+QValueList<KoTextObject *> KWDocument::visibleTextObjects(KWViewMode *viewmode) const
+{
+ QValueList<KoTextObject *> lst;
+ QPtrList<KWTextFrameSet> textFramesets = allTextFramesets( true );
+
+ KWTextFrameSet *frm;
+ for ( frm=textFramesets.first(); frm != 0; frm=textFramesets.next() ) {
+ if ( frm && frm->isVisible(viewmode) && !frm->textObject()->protectContent() )
+ {
+ lst.append( frm->textObject() );
+ }
+ }
+
+ return lst;
+}
+
+void KWDocument::refreshGUIButton()
+{
+ for( QValueList<KWView *>::Iterator it = m_lstViews.begin(); it != m_lstViews.end(); ++it )
+ (*it)->initGUIButton();
+}
+
+void KWDocument::enableBackgroundSpellCheck( bool b )
+{
+ m_bgSpellCheck->setEnabled(b);
+ for( QValueList<KWView *>::Iterator it = m_lstViews.begin(); it != m_lstViews.end(); ++it )
+ (*it)->updateBgSpellCheckingState();
+}
+
+bool KWDocument::backgroundSpellCheckEnabled() const
+{
+ return m_bgSpellCheck->enabled();
+}
+
+void KWDocument::reactivateBgSpellChecking()
+{
+ QPtrList<KWTextFrameSet> textFramesets = allTextFramesets( true );
+
+ KWTextFrameSet *frm;
+ for ( frm=textFramesets.first(); frm != 0; frm=textFramesets.next() ){
+ frm->textObject()->setNeedSpellCheck(true);
+ }
+ repaintAllViews();
+ startBackgroundSpellCheck();
+}
+
+void KWDocument::slotChapterParagraphFormatted( KoTextParag* /*parag*/ )
+{
+ // Attempt at invalidating from the parag's page only
+ // But that's not good enough - if a header gets moved down,
+ // we also need to invalidate the previous page, from where the paragraph disappeared.
+ /*
+ KoPoint p;
+ KWFrame* frame = internalToDocument( parag->rect().topLeft(), p );
+ Q_ASSERT( frame );
+ if ( frame )
+ // Remove any information from this page and further pages.
+ m_sectionTitles.resize( frame->pageNumber() );
+ */
+
+ m_sectionTitles.resize( 0 ); // clear up the entire cache
+
+ // Don't store info from parag into m_sectionTitles here.
+ // It breaks when having two headings in the same page
+ // (or if it keeps existing info then it can't update properly)
+}
+
+QString KWDocument::checkSectionTitleInParag( KoTextParag* parag, KWTextFrameSet* frameset, int pageNum ) const
+{
+ if ( parag->counter() && parag->counter()->numbering() == KoParagCounter::NUM_CHAPTER
+ && parag->counter()->depth() == 0 )
+ {
+ QString txt = parag->string()->toString();
+ txt = txt.left( txt.length() - 1 ); // remove trailing space
+#ifndef NDEBUG // not needed, just checking
+ KoPoint p;
+ KWFrame* frame = frameset->internalToDocument( parag->rect().topLeft(), p );
+ Q_ASSERT( frame );
+ if ( frame ) {
+ int pgNum = frame->pageNumber();
+ if( pgNum != pageNum )
+ kdWarning() << "sectionTitle: was looking for pageNum " << pageNum << ", got frame " << frame << " page " << pgNum << endl;
+ }
+ kdDebug(32001) << "KWDocument::sectionTitle for " << pageNum << ":" << txt << endl;
+#endif
+ // Ensure array is big enough
+ if ( pageNum > (int)m_sectionTitles.size()-1 )
+ const_cast<KWDocument*>(this)->m_sectionTitles.resize( pageNum + 1 );
+ const_cast<KWDocument*>(this)->m_sectionTitles[ pageNum ] = txt;
+ return txt;
+ }
+ return QString::null;
+}
+
+QString KWDocument::sectionTitle( int pageNum ) const
+{
+ //kdDebug(32001) << "KWDocument::sectionTitle(pageNum=" << pageNum << ") m_sectionTitles.size()=" << m_sectionTitles.size() << endl;
+ // First look in the cache. If info is present, it's uptodate (see slotChapterParagraphFormatted)
+ if ( (int)m_sectionTitles.size() > pageNum )
+ {
+ // Look whether this page has a section title, and if not, go back pages, one by one
+ for ( int i = pageNum; i >= 0 ; --i )
+ {
+ const QString& s = m_sectionTitles[i];
+ if ( !s.isEmpty() )
+ {
+ // Update cache, to make this faster next time
+ if ( pageNum > (int)m_sectionTitles.size()-1 )
+ const_cast<KWDocument*>(this)->m_sectionTitles.resize( pageNum + 1 );
+ const_cast<KWDocument*>(this)->m_sectionTitles[ pageNum ] = s;
+ return s;
+ }
+ }
+ }
+
+ // If not in the cache, determine from the paragraphs in the page.
+
+ if ( m_lstFrameSet.isEmpty() )
+ return QString::null;
+ // We use the "main" frameset to determine section titles.
+ KWTextFrameSet *frameset = dynamic_cast<KWTextFrameSet *>( m_lstFrameSet.getFirst() );
+ if ( !frameset )
+ return QString::null;
+
+ int topLUpix, bottomLUpix;
+ if ( !frameset->minMaxInternalOnPage( pageNum, topLUpix, bottomLUpix ) )
+ return QString::null;
+
+ KoTextParag* parag = frameset->textDocument()->firstParag();
+ //kdDebug(32001) << "KWDocument::sectionTitle " << pageNum
+ // << " topLUpix=" << topLUpix << " bottomLUpix=" << bottomLUpix << endl;
+
+ KoTextParag* lastParagOfPageAbove = parag;
+ for ( ; parag ; parag = parag->next() )
+ {
+ if ( parag->rect().bottom() < topLUpix ) // too early
+ {
+ lastParagOfPageAbove = parag;
+ continue;
+ }
+ if ( parag->rect().top() > bottomLUpix ) // done
+ break;
+ QString txt = checkSectionTitleInParag( parag, frameset, pageNum );
+ if ( !txt.isEmpty() )
+ return txt;
+ }
+
+ // No heading found in page.
+ // Go back up until the first section parag
+ parag = lastParagOfPageAbove;
+ for ( ; parag ; parag = parag->prev() )
+ {
+ QString txt = checkSectionTitleInParag( parag, frameset, pageNum );
+ if ( !txt.isEmpty() )
+ return txt;
+ }
+
+ // First page, no heading found
+ return QString::null;
+}
+
+
+void KWDocument::setSpellCheckIgnoreList( const QStringList& lst )
+{
+ m_spellCheckIgnoreList = lst;
+ m_bgSpellCheck->settings()->setCurrentIgnoreList( m_spellCheckIgnoreList + m_spellCheckPersonalDict );
+ setModified( true );
+}
+
+void KWDocument::addSpellCheckIgnoreWord( const QString & word )
+{
+ // ### missing: undo/redo support
+ if( m_spellCheckIgnoreList.findIndex( word ) == -1 )
+ m_spellCheckIgnoreList.append( word );
+ setSpellCheckIgnoreList( m_spellCheckIgnoreList );
+ if ( backgroundSpellCheckEnabled() )
+ // Re-check everything to make this word normal again
+ reactivateBgSpellChecking();
+}
+
+int KWDocument::maxZOrder( int pageNum) const
+{
+ bool first = true;
+ int maxZOrder = 0; //this value is only used if there's no frame on the page
+ QPtrList<KWFrame> frames = framesInPage( pageNum );
+ QPtrListIterator<KWFrame> frameIt( frames );
+ for ( ; frameIt.current(); ++frameIt ) {
+ if ( first || frameIt.current()->zOrder() > maxZOrder ) {
+ maxZOrder = frameIt.current()->zOrder();
+ first = false;
+ }
+ }
+ return maxZOrder;
+}
+
+QPtrList<KWTextFrameSet> KWDocument::allTextFramesets(bool onlyReadWrite) const
+{
+ QPtrList<KWTextFrameSet> textFramesets;
+ QPtrListIterator<KWFrameSet> fit = framesetsIterator();
+ for ( ; fit.current() ; ++fit ) {
+ if(fit.current()->isDeleted()) continue;
+ fit.current()->addTextFrameSets(textFramesets, onlyReadWrite);
+ }
+ return textFramesets;
+}
+
+QValueList<KoTextDocument *> KWDocument::allTextDocuments() const
+{
+ QValueList<KoTextDocument *> lst;
+ const QPtrList<KWTextFrameSet> textFramesets = allTextFramesets(false);
+ QPtrListIterator<KWTextFrameSet> fit( textFramesets );
+ for ( ; fit.current() ; ++fit ) {
+ lst.append( fit.current()->textObject()->textDocument() );
+ }
+ return lst;
+}
+
+int KWDocument::numberOfTextFrameSet( KWFrameSet* fs, bool onlyReadWrite )
+{
+ QPtrList<KWTextFrameSet> textFramesets = allTextFramesets( onlyReadWrite );
+ return textFramesets.findRef( static_cast<KWTextFrameSet*>(fs) );
+}
+
+KWFrameSet * KWDocument::textFrameSetFromIndex( unsigned int num, bool onlyReadWrite )
+{
+ return allTextFramesets( onlyReadWrite ).at( num );
+}
+
+void KWDocument::updateTextFrameSetEdit()
+{
+ for( QValueList<KWView *>::Iterator it = m_lstViews.begin(); it != m_lstViews.end(); ++it )
+ (*it)->slotFrameSetEditChanged();
+
+}
+
+void KWDocument::displayFootNoteFieldCode()
+{
+ QPtrListIterator<KoVariable> it( m_varColl->getVariables() );
+ for ( ; it.current() ; ++it )
+ {
+ if ( it.current()->type() == VT_FOOTNOTE )
+ {
+ static_cast<KWFootNoteVariable *>(it.current())->resize();
+ static_cast<KWFootNoteVariable *>(it.current())->frameSet()->setCounterText( static_cast<KWFootNoteVariable *>(it.current())->text() );
+
+ KoTextParag * parag = it.current()->paragraph();
+ if ( parag )
+ {
+ parag->invalidate( 0 );
+ parag->setChanged( true );
+ }
+ }
+ }
+}
+
+void KWDocument::changeFootNoteConfig()
+{
+ QMap<KoTextDocument *, bool> modifiedTextDocuments; // Qt4: QSet
+ QPtrListIterator<KoVariable> it( m_varColl->getVariables() );
+ for ( ; it.current() ; ++it )
+ {
+ if ( it.current()->type() == VT_FOOTNOTE )
+ {
+ KWFootNoteVariable* footNoteVar = static_cast<KWFootNoteVariable *>(it.current());
+ footNoteVar->formatedNote();
+ if(footNoteVar->frameSet()->isDeleted())
+ continue;
+ footNoteVar->resize();
+ footNoteVar->frameSet()->setCounterText( footNoteVar->text() );
+
+ KoTextParag * parag = footNoteVar->paragraph();
+ if ( parag )
+ {
+ parag->invalidate( 0 );
+ parag->setChanged( true );
+ }
+ KoTextDocument* textdoc = parag->textDocument();
+ if ( modifiedTextDocuments.find( textdoc ) != modifiedTextDocuments.end() ) // Qt4: !contains
+ modifiedTextDocuments.insert( textdoc, true );
+ }
+ }
+ for( QMap<KoTextDocument *,bool>::const_iterator it = modifiedTextDocuments.begin();
+ it != modifiedTextDocuments.end(); ++it ) {
+ KoTextDocument* textdoc = it.key();
+ KWTextFrameSet * textfs = static_cast<KWTextDocument *>(textdoc)->textFrameSet();
+ slotRepaintChanged( textfs );
+ }
+}
+
+
+void KWDocument::setTabStopValue ( double tabStop )
+{
+ m_tabStop = tabStop;
+ QPtrList<KWTextFrameSet> textFramesets = allTextFramesets( true );
+
+ KWTextFrameSet *frm;
+ for ( frm=textFramesets.first(); frm != 0; frm=textFramesets.next() ){
+ frm->textDocument()->setTabStops( ptToLayoutUnitPixX( tabStop ));
+ frm->layout();
+ }
+ repaintAllViews();
+}
+
+void KWDocument::setGlobalHyphenation( bool hyphen )
+{
+ m_bGlobalHyphenation = hyphen;
+ // This is only used as a default setting for the default format in new documents;
+ // In existing documents the hyphenation comes from the existing formats.
+}
+
+void KWDocument::setViewFrameBorders( bool b )
+{
+ m_viewFrameBorders = b;
+ m_layoutViewMode->setDrawFrameBorders( b );
+ for( QValueList<KWView *>::Iterator it = m_lstViews.begin(); it != m_lstViews.end(); ++it )
+ (*it)->getGUI()->canvasWidget()->viewMode()->setDrawFrameBorders( b );
+}
+
+void KWDocument::switchViewMode( const QString& newViewModeType )
+{
+ // Don't compare m_viewModeType and newViewMode here, it would break
+ // changing the number of pages per row for the preview mode, in kwconfig.
+ m_viewModeType = newViewModeType;
+ delete m_layoutViewMode;
+ m_layoutViewMode = KWViewMode::create( m_viewModeType, this, 0 /*no canvas */ );
+
+ //necessary to switchmode view in all canvas in first.
+ //otherwise with more than one view kword crashes !
+ for( QValueList<KWView *>::Iterator it = m_lstViews.begin(); it != m_lstViews.end(); ++it )
+ (*it)->getGUI()->canvasWidget()->switchViewMode( m_viewModeType );
+
+ for( QValueList<KWView *>::Iterator it = m_lstViews.begin(); it != m_lstViews.end(); ++it )
+ (*it)->switchModeView();
+ emit newContentsSize();
+
+ // Since the text layout depends on the view mode, we need to redo it
+ // But after telling the canvas about the new viewmode, otherwise stuff like
+ // slotNewContentsSize will crash.
+ updateAllFrames();
+ layout();
+
+ repaintAllViews( true );
+ for( QValueList<KWView *>::Iterator it = m_lstViews.begin(); it != m_lstViews.end(); ++it )
+ (*it)->getGUI()->canvasWidget()->ensureCursorVisible();
+}
+
+void KWDocument::changeBgSpellCheckingState( bool b )
+{
+ enableBackgroundSpellCheck( b );
+ reactivateBgSpellChecking();
+ KConfig *config = KWFactory::instance()->config();
+ config->setGroup("KSpell kword" );
+ config->writeEntry( "SpellCheck", (int)b );
+}
+
+QString KWDocument::initialFrameSet() const
+{
+ return m_initialEditing ? m_initialEditing->m_initialFrameSet : QString::null;
+}
+
+int KWDocument::initialCursorParag() const
+{
+ return m_initialEditing ? m_initialEditing->m_initialCursorParag : 0;
+}
+
+int KWDocument::initialCursorIndex() const
+{
+ return m_initialEditing ? m_initialEditing->m_initialCursorIndex : 0;
+}
+
+void KWDocument::deleteInitialEditingInfo()
+{
+ delete m_initialEditing;
+ m_initialEditing = 0L;
+}
+
+bool KWDocument::cursorInProtectedArea()const
+{
+ return m_cursorInProtectectedArea;
+}
+
+void KWDocument::setCursorInProtectedArea( bool b )
+{
+ m_cursorInProtectectedArea=b;
+ testAndCloseAllFrameSetProtectedContent();
+}
+
+
+void KWDocument::testAndCloseAllFrameSetProtectedContent()
+{
+ if ( !m_cursorInProtectectedArea )
+ {
+ for( QValueList<KWView *>::Iterator it = m_lstViews.begin(); it != m_lstViews.end(); ++it )
+ (*it)->testAndCloseAllFrameSetProtectedContent();
+ }
+}
+
+void KWDocument::updateRulerInProtectContentMode()
+{
+ for( QValueList<KWView *>::const_iterator it = m_lstViews.begin(); it != m_lstViews.end(); ++it )
+ (*it)->updateRulerInProtectContentMode();
+}
+
+
+void KWDocument::insertBookmark( const QString &name, KoTextParag *startparag, KoTextParag *endparag, int start, int end )
+{
+ m_bookmarkList->append( KoTextBookmark( name, startparag, endparag, start, end ) );
+}
+
+void KWDocument::deleteBookmark( const QString &name )
+{
+ if ( m_bookmarkList->removeByName( name ) )
+ setModified(true);
+}
+
+void KWDocument::renameBookmark( const QString &oldName, const QString &newName )
+{
+ if ( oldName == newName )
+ return;
+
+ KoTextBookmarkList::iterator it = m_bookmarkList->findByName( oldName );
+ if ( it != m_bookmarkList->end() )
+ {
+ (*it).setBookmarkName( newName );
+ setModified(true);
+ }
+}
+
+const KoTextBookmark * KWDocument::bookmarkByName( const QString & name ) const
+{
+ KoTextBookmarkList::const_iterator it = m_bookmarkList->findByName( name );
+ if ( it != m_bookmarkList->end() )
+ return &(*it);
+ return 0;
+}
+
+QStringList KWDocument::listOfBookmarkName( KWViewMode * viewMode ) const
+{
+ QStringList list;
+ KoTextBookmarkList::const_iterator it = m_bookmarkList->begin();
+ const KoTextBookmarkList::const_iterator end = m_bookmarkList->end();
+ for ( ; it != end ; ++it )
+ {
+ const KoTextBookmark& book = *it;
+ KWFrameSet* fs = static_cast<KWTextDocument *>(book.textDocument())->textFrameSet();
+ if ( fs->isVisible( viewMode ) && !fs->isDeleted() )
+ list.append( book.bookmarkName() );
+ }
+ return list;
+}
+
+void KWDocument::paragraphModified(KoTextParag* /*parag*/, int /*KoTextParag::ParagModifyType*/ /*type*/, int /*start*/, int /*length*/)
+{
+ //kdDebug()<<" parag :"<<parag<<" start :"<<start<<" length :"<<length<<endl;
+ emit docStructureChanged( Tables | TextFrames );
+}
+
+
+void KWDocument::paragraphDeleted( KoTextParag *parag, KWFrameSet *frm )
+{
+ KWTextFrameSet* textfs = dynamic_cast<KWTextFrameSet *>( frm );
+ if ( textfs )
+ {
+ // For speed KoTextBookmarkList should probably be a per-paragraph map.
+ // The problem is that a bookmark is associated with TWO paragraphs...
+
+ KoTextBookmarkList::iterator it = m_bookmarkList->begin();
+ const KoTextBookmarkList::iterator end = m_bookmarkList->end();
+ for ( ; it != end ; ++it )
+ {
+ KoTextBookmark& book = *it;
+
+ // Adjust bookmark to point to a valid paragraph, below or above the deleted one.
+ // The old implementation turned the bookmark into a useless one. OOo simply deletes the bookmark...
+ if ( book.startParag() == parag )
+ book.setStartParag( parag->next() ? parag->next() : parag->prev() );
+ if ( book.endParag() == parag )
+ book.setEndParag( parag->next() ? parag->next() : parag->prev() );
+ }
+ }
+}
+
+void KWDocument::initBookmarkList()
+{
+ Q_ASSERT( m_loadingInfo );
+ if ( !m_loadingInfo )
+ return;
+ KWLoadingInfo::BookMarkList::Iterator it = m_loadingInfo->bookMarkList.begin();
+ KWLoadingInfo::BookMarkList::Iterator end = m_loadingInfo->bookMarkList.end();
+ for( ; it != end; ++it )
+ {
+ KWFrameSet * fs = 0L;
+ QString fsName = (*it).frameSetName;
+ if ( !fsName.isEmpty() )
+ fs = frameSetByName( fsName );
+ if ( fs )
+ {
+ KWTextFrameSet *frm = dynamic_cast<KWTextFrameSet *>(fs);
+ if ( frm )
+ {
+ KoTextDocument* textdoc = frm->textDocument();
+ KoTextParag* startparag = textdoc->paragAt( (*it).paragStartIndex );
+ KoTextParag* endparag = textdoc->paragAt( (*it).paragEndIndex );
+ if ( startparag && endparag )
+ {
+ m_bookmarkList->append( KoTextBookmark( (*it).bookname,
+ startparag, endparag,
+ (*it).cursorStartIndex, (*it).cursorEndIndex ) );
+ }
+ }
+ }
+ }
+}
+
+QPixmap* KWDocument::doubleBufferPixmap( const QSize& s )
+{
+ if ( !m_bufPixmap ) {
+ int w = QABS( s.width() );
+ int h = QABS( s.height() );
+ m_bufPixmap = new QPixmap( w, h );
+ } else {
+ if ( m_bufPixmap->width() < s.width() ||
+ m_bufPixmap->height() < s.height() ) {
+ m_bufPixmap->resize( QMAX( s.width(), m_bufPixmap->width() ),
+ QMAX( s.height(), m_bufPixmap->height() ) );
+ }
+ }
+
+ return m_bufPixmap;
+}
+
+void KWDocument::maybeDeleteDoubleBufferPixmap()
+{
+ if ( m_bufPixmap && m_bufPixmap->height() * m_bufPixmap->width() > 400*400 )
+ {
+ delete m_bufPixmap;
+ m_bufPixmap = 0L;
+ }
+}
+
+void KWDocument::setPersonalExpressionPath( const QStringList & lst)
+{
+ m_personalExpressionPath = lst;
+ refreshMenuExpression();
+}
+
+void KWDocument::updateDirectCursorButton()
+{
+ for( QValueList<KWView *>::Iterator it = m_lstViews.begin(); it != m_lstViews.end(); ++it )
+ (*it)->updateDirectCursorButton();
+}
+
+void KWDocument::setInsertDirectCursor(bool b)
+{
+ m_bInsertDirectCursor=b;
+ KConfig *config = KWFactory::instance()->config();
+ config->setGroup( "Interface" );
+ config->writeEntry( "InsertDirectCursor", b );
+ updateDirectCursorButton();
+}
+
+void KWDocument::saveDialogShown()
+{
+ if ( !textFrameSet(0) )
+ return;
+ // Grab first 50 chars from the main frameset's document
+ // ### This is a somewhat slow method, if the document is huge - better iterate
+ // over the first few parags until 50 chars have been collected.
+ QString first_row = textFrameSet(0)->textDocument()->plainText().left(50);
+ bool truncate = false;
+ QChar ch;
+ for (int i=0; i < (int)first_row.length(); i++)
+ {
+ ch = first_row.at(i);
+ if (!truncate)
+ if (ch.isPunct() || ch.isSpace() || ch == '.' )
+ {
+ first_row.remove(i,1);
+ --i;
+ }
+ else
+ truncate = true;
+ else if ( truncate && (ch.isPunct() || ch == '.' || ch == '\n' ) )
+ {
+ first_row.truncate(i);
+ break;
+ }
+ }
+ first_row = first_row.stripWhiteSpace();
+ kdDebug() << "Suggested filename:" << first_row << endl;
+ setURL(first_row);
+}
+
+void KWDocument::addWordToDictionary( const QString& word )
+{
+ if ( m_bgSpellCheck )
+ {
+ if( m_spellCheckPersonalDict.findIndex( word ) == -1 )
+ m_spellCheckPersonalDict.append( word );
+ m_bgSpellCheck->settings()->setCurrentIgnoreList( m_spellCheckIgnoreList + m_spellCheckPersonalDict );
+ if ( backgroundSpellCheckEnabled() )
+ // Re-check everything to make this word normal again
+ reactivateBgSpellChecking();
+ }
+}
+
+void KWDocument::setEmpty()
+{
+ KoDocument::setEmpty();
+ // Whether loaded from template or from empty doc: this is a new one -> set creation date
+ m_varColl->variableSetting()->setCreationDate(QDateTime::currentDateTime());
+ recalcVariables( VT_DATE ); // , VST_CREATION_DATE ...
+ // If we then load a document, it will override that date.
+}
+
+void KWDocument::updateGridButton()
+{
+ QPtrListIterator<KoView> it( views() );
+ for (; it.current(); ++it )
+ ((KWView*)it.current())->updateGridButton();
+
+}
+
+unsigned int KWDocument::paperHeight(int pageNum) const {
+ return static_cast<unsigned int>(zoomItY( pageManager()->pageLayout(pageNum).ptHeight ));
+}
+
+unsigned int KWDocument::paperWidth(int pageNum) const {
+ return static_cast<unsigned int>(zoomItX( pageManager()->pageLayout(pageNum).ptWidth ));
+}
+
+unsigned int KWDocument::pageTop( int pgNum ) const {
+ return zoomItY( pageManager()->topOfPage( pgNum ) );
+}
+
+int KWDocument::pageCount() const {
+ return pageManager()->pageCount();
+}
+
+int KWDocument::startPage() const {
+ return pageManager()->startPage();
+}
+int KWDocument::lastPage() const {
+ return pageManager()->lastPageNumber();
+}
+
+QWidget* KWDocument::createCustomDocumentWidget(QWidget *parent) {
+ KoColumns columns;
+ columns.columns = 1;
+ columns.ptColumnSpacing = m_defaultColumnSpacing;
+ return new KWStartupWidget(parent, this, columns);
+}
+
+KWDocument::FramesChangedHandler::FramesChangedHandler(KWDocument *parent) {
+ m_parent = parent;
+ m_needLayout = false;
+}
+
+void KWDocument::FramesChangedHandler::addFrame(KWFrame *frame) {
+ if(frame == 0) return;
+ if(m_frameSets.contains(frame->frameSet())) return;
+ m_frameSets.append(frame->frameSet());
+ if( frame->runAround() != KWFrame::RA_NO )
+ m_needLayout = true;
+}
+
+void KWDocument::FramesChangedHandler::addFrameSet(KWFrameSet *fs) {
+ if(m_frameSets.contains(fs)) return;
+ m_frameSets.append(fs);
+ m_needLayout = true;
+}
+
+void KWDocument::FramesChangedHandler::execute() {
+ if(m_frameSets.count() == 0)
+ m_parent->updateAllFrames();
+ else {
+ QValueListIterator<KWFrameSet*> iter = m_frameSets.begin();
+ for(;iter != m_frameSets.end(); ++iter) {
+ KWFrameSet *fs = *iter;
+ fs->updateFrames();
+ if(!m_needLayout)
+ fs->layout();
+ }
+
+ KWFrameList::recalcAllFrames(m_parent);
+ }
+
+ // If frame with text flowing around it -> re-layout all frames
+ if ( m_needLayout)
+ m_parent->layout();
+ //m_parent->repaintAllViewsExcept( 0 );
+ m_parent->repaintAllViews();
+ m_parent->updateRulerFrameStartEnd();
+}
+
+#include "KWDocument.moc"
diff --git a/kword/KWDocument.h b/kword/KWDocument.h
new file mode 100644
index 00000000..1b8ebac9
--- /dev/null
+++ b/kword/KWDocument.h
@@ -0,0 +1,1020 @@
+/* This file is part of the KDE project
+ Copyright (C) 1998, 1999 Reginald Stadlbauer <reggie@kde.org>
+ Copyright (C) 2002-2006 David Faure <faure@kde.org>
+ Copyright (C) 2005 Thomas Zander <zander@kde.org>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+*/
+
+#ifndef kwdoc_h
+#define kwdoc_h
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+class QDragObject;
+class KoSavingContext;
+class KoGenStyles;
+class KWDocument;
+class KPrinter;
+class KWTextImage;
+class KWTextFrameSet;
+class KWPictureFrameSet;
+class KWMailMergeDataBase;
+class KWFrameSet;
+class KWTableFrameSet;
+class KWPartFrameSet;
+class KoStyleCollection;
+class KoParagStyle;
+class KWFrameStyle;
+class KWTableStyle;
+class KWTableTemplate;
+#define KoParagStyle KoParagStyle
+class KWFrame;
+class KWViewMode;
+class KMacroCommand;
+class KoDocumentEntry;
+class QPainter;
+class KoAutoFormat;
+class KCommand;
+class KoCommandHistory;
+class KoVariable;
+class KoVariableFormatCollection;
+class KWVariableCollection;
+class KoTextObject;
+class KWBgSpellCheck;
+class KoStyleCollection;
+class KWFrameStyleCollection;
+class KWTableStyleCollection;
+class KWTableTemplateCollection;
+class KWFootNoteVariable;
+class DCOPObject;
+class KWLoadingInfo;
+class KoPicture;
+class KoTextBookmark;
+class KoTextBookmarkList;
+class KoPictureCollection;
+class KWDocumentChild;
+class KWPageManager;
+class KWPage;
+
+class QFont;
+class QStringList;
+class QRect;
+
+namespace KFormula {
+ class Document;
+ class DocumentWrapper;
+}
+
+class KoTextParag;
+class KoOasisSettings;
+
+#include "KWAnchorPos.h" // legacy loading stuff
+#include "KWView.h"
+
+#include <KoDocument.h>
+#include <KoTextZoomHandler.h>
+#include <KoPictureKey.h>
+#include <KoStyleCollection.h> // for KoStyleChangeDefMap
+
+#include <qmap.h>
+#include <qptrlist.h>
+#include <qfont.h>
+#include <qvaluevector.h>
+
+/******************************************************************/
+/* Class: KWDocument */
+/******************************************************************/
+
+class KWDocument : public KoDocument, public KoTextZoomHandler
+{
+ Q_OBJECT
+ Q_PROPERTY( double ptColumnWidth READ ptColumnWidth )
+ Q_PROPERTY( double ptColumnSpacing READ ptColumnSpacing )
+ Q_PROPERTY( double gridX READ gridX WRITE setGridX )
+ Q_PROPERTY( double gridY READ gridY WRITE setGridY )
+ Q_PROPERTY( bool snapToGrid READ snapToGrid WRITE setSnapToGrid )
+ Q_PROPERTY( double indentValue READ indentValue WRITE setIndentValue )
+ Q_PROPERTY( int nbPagePerRow READ nbPagePerRow WRITE setNbPagePerRow )
+ Q_PROPERTY( double defaultColumnSpacing READ defaultColumnSpacing WRITE setDefaultColumnSpacing )
+ Q_PROPERTY( int maxRecentFiles READ maxRecentFiles )
+ Q_PROPERTY( QString globalLanguage READ globalLanguage WRITE setGlobalLanguage )
+ Q_PROPERTY( bool globalHyphenation READ globalHyphenation WRITE setGlobalHyphenation )
+ Q_PROPERTY( bool insertDirectCursor READ insertDirectCursor WRITE setInsertDirectCursor )
+ Q_PROPERTY( QStringList personalExpressionPath READ personalExpressionPath WRITE setPersonalExpressionPath )
+ Q_PROPERTY( bool viewFormattingBreak READ viewFormattingBreak WRITE setViewFormattingBreak )
+ Q_PROPERTY( bool viewFormattingTabs READ viewFormattingTabs WRITE setViewFormattingTabs )
+ Q_PROPERTY( bool viewFormattingSpace READ viewFormattingSpace WRITE setViewFormattingSpace )
+ Q_PROPERTY( bool viewFormattingEndParag READ viewFormattingEndParag WRITE setViewFormattingEndParag )
+ Q_PROPERTY( bool cursorInProtectedArea READ cursorInProtectedArea WRITE setCursorInProtectedArea )
+ Q_PROPERTY( bool pgUpDownMovesCaret READ pgUpDownMovesCaret WRITE setPgUpDownMovesCaret )
+ Q_PROPERTY( bool allowAutoFormat READ allowAutoFormat WRITE setAllowAutoFormat )
+ Q_PROPERTY( int undoRedoLimit READ undoRedoLimit WRITE setUndoRedoLimit )
+
+public:
+ friend class KWOasisLoader;
+ friend class KWStartupWidget;
+
+ KWDocument( QWidget *parentWidget = 0, const char *widname = 0, QObject* parent = 0, const char* name = 0, bool singleViewMode = false );
+ ~KWDocument();
+
+ enum ProcessingType {WP = 0, DTP = 1};
+
+ static const int CURRENT_SYNTAX_VERSION;
+
+public:
+ virtual bool initDoc(InitDocFlags flags, QWidget* parentWidget=0);
+
+ virtual bool loadOasis( const QDomDocument& doc, KoOasisStyles& oasisStyles, const QDomDocument& settings, KoStore* store );
+
+ /**
+ * Those values are used as KoGenStyle types.
+ *
+ * STYLE_FRAME_AUTO: for frame styles (family="graphic") used by actual frames, saved into content.xml
+ * STYLE_FRAME_USER: for frame styles (family="graphic") defined by the user, saved into styles.xml
+ * STYLE_TABLE_CELL_AUTO: for table-cell styles (family="table-cell") used by actual tables, saved into content.xml
+ * STYLE_TABLE_CELL_USER: for table-cell styles (family="table-cell") defined by the user, saved into styles.xml
+ * ...
+ */
+ enum { STYLE_FRAME_AUTO = 20, STYLE_FRAME_USER,
+ STYLE_TABLE_CELL_AUTO, STYLE_TABLE_CELL_USER,
+ STYLE_TABLE, STYLE_TABLE_COLUMN, STYLE_TABLE_ROW };
+
+ virtual bool saveOasis( KoStore* store, KoXmlWriter* manifestWriter );
+
+ virtual int supportedSpecialFormats() const;
+
+ enum SaveFlag { SaveAll, SaveSelected }; // kpresenter will also have SavePage
+
+ /**
+ * Return a drag object with the selected frames
+ */
+ QDragObject* dragSelected( const QValueList<KWFrameView*> &selectedFrames);
+ /**
+ * Return a drag object with the selected text
+ */
+ QDragObject* dragSelected( QWidget *parent, KWTextFrameSet* fs );
+
+ virtual bool loadXML( QIODevice *, const QDomDocument & dom );
+ virtual bool loadChildren( KoStore *store );
+ virtual QDomDocument saveXML();
+ void processPictureRequests();
+ void processAnchorRequests();
+ bool processFootNoteRequests();
+
+ int syntaxVersion( ) const { return m_syntaxVersion; }
+
+ /// Called by KWFrame*'s loading code to emit correct progress info
+ void progressItemLoaded();
+
+ /**
+ * Draw as embedded.
+ */
+ virtual void paintContent( QPainter& painter, const QRect& rect, bool transparent = false, double zoomX = 1.0, double zoomY = 1.0 );
+
+ virtual QPixmap generatePreview( const QSize &size );
+
+ /**
+ * @param emptyRegion The region is modified to subtract the areas painted, thus
+ * allowing the caller to determine which areas remain to be painted.
+ */
+ void createEmptyRegion( const QRect & crect, QRegion & emptyRegion, KWViewMode * viewMode );
+ /**
+ * Erase the empty space defined by @p emptySpaceRegion.
+ * Usually used to clear the space where there is no frame (e.g. page margins).
+ */
+ void eraseEmptySpace( QPainter * painter, const QRegion & emptySpaceRegion, const QBrush & brush );
+
+ virtual void setEmpty();
+
+ virtual void addView( KoView *view );
+ virtual void removeView( KoView *view );
+
+ virtual void addShell( KoMainWindow *shell );
+
+ KWPartFrameSet* insertObject( const KoRect& rect, KoDocumentEntry& e, QWidget* parentWidget );
+
+ /// Create an embedded document; used by KWPartFrameSet but is defined here
+ /// because KoDocument:insertChild is protected.
+ KWDocumentChild* createChildDoc( const KoRect& rect, KoDocument* childDoc );
+
+ void setPageLayout( const KoPageLayout& layout, const KoColumns& cl, const KoKWHeaderFooter& hf, bool updateViews = true );
+
+ void getPageLayout( KoPageLayout& layout, KoColumns& cl, KoKWHeaderFooter& hf );
+
+ KWTextFrameSet * textFrameSet ( unsigned int num ) const;
+ /// Return the frameset number @p num
+ KWFrameSet *frameSet( unsigned int num )
+ { return m_lstFrameSet.at( num ); }
+
+ /// Return the frameset with a given name
+ KWFrameSet * frameSetByName( const QString & name );
+
+ /// Return the total number of framesets
+ unsigned int frameSetCount() const
+ { return m_lstFrameSet.count(); }
+
+ /// Generate a new name for a frameset. @p templateName must contain a %1 [for a number].
+ QString generateFramesetName( const QString & templateName );
+
+ /// Prefer this over frameSet(i), if iterating over all of them
+ QPtrListIterator<KWFrameSet> framesetsIterator() const { return QPtrListIterator<KWFrameSet>(m_lstFrameSet); }
+
+ QValueList<KoTextObject *> visibleTextObjects(KWViewMode *viewmode) const;
+
+ /// Register new frameset
+ void addFrameSet( KWFrameSet *f, bool finalize = true );
+ /// Remove frameset from list (don't delete)
+ void removeFrameSet( KWFrameSet *f );
+
+ /// Frame/table deletion - with undo/redo support
+ /// Moved to KWDocument so that dialogs can call them if necessary
+ void deleteTable( KWTableFrameSet *groupManager );
+ void deleteFrame( KWFrame * frame );
+
+ /// return the height of one page in pixels in the current zoom level (normal coord system)
+ unsigned int paperHeight(int pageNum) const;
+ /// return the width of one page in pixels in the current zoom level (normal coord system)
+ unsigned int paperWidth(int pageNum) const;
+ /// Top of the page number pgNum, in pixels (in the normal coord system)
+ unsigned int pageTop( int pgNum ) const;
+ double ptColumnWidth() const;
+ double ptColumnSpacing() const { return m_pageColumns.ptColumnSpacing; }
+ double ptFootnoteBodySpacing() const { return m_pageHeaderFooter.ptFootNoteBodySpacing; }
+
+ unsigned int numColumns() const { return m_pageColumns.columns; }
+
+ void repaintAllViews( bool erase = false );
+ /** Update all views of this document, area can be cleared before redrawing with the
+ * erase flag. (false implied). All views EXCEPT the argument view are updated ( give 0L for all )
+ */
+ void repaintAllViewsExcept( KWView *view, bool erase = false );
+
+
+ /**
+ * schedule a repaint of all views but don't execute immediately
+ */
+ void delayedRepaintAllViews();
+
+ /**
+ * schedule a frame layout (e.g. for footnotes) but don't execute immediately
+ */
+ void delayedRecalcFrames( int fromPage );
+
+ /**
+ * Return a double-buffer pixmap of (at least) the given size.
+ */
+ QPixmap* doubleBufferPixmap( const QSize& );
+ /**
+ * Call this when you're done with the double-buffer pixmap (at the
+ * end of the current painting, for all objects that need to be painted).
+ * If it's too big, KWDocument will delete it to save memory.
+ */
+ void maybeDeleteDoubleBufferPixmap();
+
+ /**
+ * Tell this method when a frame is moved / resized / created / deleted
+ * and everything will be update / repainted accordingly.
+ */
+ void frameChanged( KWFrame * frame );
+ void framesChanged( const QPtrList<KWFrame> & frames, KWView * view = 0L );
+
+ QString uniqueFramesetName( const QString& oldName );
+ /**
+ * @param copyFootNote ...
+ * @param dontCreateFootNote true when we copy footnote into an other frameset than mainFrameSet => footnote is removed !
+ * @param selectFrames if true, pasted frames are auto-selected. Set to false when loading from a file etc.
+ */
+ void pasteFrames( QDomElement topElem, KMacroCommand * macroCmd, bool copyFootNote = false, bool dontCreateFootNote = false, bool selectFrames = true );
+
+ void insertEmbedded( KoStore *store, QDomElement topElem, KMacroCommand * macroCmd, double offset );
+ void completePasting();
+ void completeOasisPasting();
+ void saveOasisDocumentStyles( KoStore* store, KoGenStyles& mainStyles, KoSavingContext& savingContext, SaveFlag saveFlag, const QByteArray& headerFooterContent ) const;
+
+ KoStyleCollection * styleCollection()const { return m_styleColl;}
+ KWFrameStyleCollection * frameStyleCollection()const { return m_frameStyleColl;}
+ KWTableStyleCollection * tableStyleCollection()const { return m_tableStyleColl;}
+ KWTableTemplateCollection * tableTemplateCollection()const { return m_tableTemplateColl;}
+
+ QFont defaultFont() const { return m_defaultFont; }
+ void setDefaultFont( const QFont & newFont ) {
+ m_defaultFont = newFont;
+ }
+
+ /**
+ * returns the amount of pages in the document.
+ * @see startPage() @see lastPage()
+ */
+ int pageCount() const;
+ /**
+ * returns the page number of the first page in this document, this is the page number
+ * that will be shown on prints and used in the TOC and user-variables.
+ * @see pageCount() @see lastPage()
+ */
+ int startPage() const;
+ /**
+ * Returns the last page number in this document.
+ * With a higher startPage and a constante pagecount this number will also get higher.
+ */
+ int lastPage() const;
+
+ KoPictureCollection *pictureCollection() { return m_pictureCollection; }
+ KoVariableFormatCollection *variableFormatCollection()const { return m_varFormatCollection; }
+
+ QValueList<KWView *> getAllViews() const { return m_lstViews; }
+
+ /**
+ * Insert a new page after another,
+ * creating followup frames (but not headers/footers),
+ * @param afterPageNum the page is inserted after the one specified here
+ * If afterPageNum is -1, a page is inserted before page 0.
+ * In all cases, the new page will have the number afterPageNum+1.
+ * Use appendPage in WP mode, insertPage in DTP mode.
+ */
+ KWPage* insertPage( int afterPageNum );
+ /**
+ * Append a new page, creating followup frames (but not headers/footers),
+ * and return the page number.
+ */
+ KWPage* appendPage();
+ /**
+ * Call this after appendPage, to get headers/footers on the new page,
+ * and all the caches properly updated. This is separate from appendPage
+ * so that KWFrameLayout can call appendPage() only.
+ */
+ void afterInsertPage( int num );
+ /**
+ * @return list of frames that will be copied onto the new page
+ * Used by insertPage but also by KWTextFrameSet to check if it's worth
+ * auto-inserting a new page (to avoid infinite loops if not)
+ */
+ QPtrList<KWFrame> framesToCopyOnNewPage( int afterPageNum ) const;
+
+ /**
+ * Remove a page. Call afterRemovePages() after removing one or more pages.
+ */
+ void removePage( int num );
+
+ /**
+ * Update things after removing one or more pages.
+ */
+ void afterRemovePages();
+
+ /**
+ * Check if we can remove empty page(s) from the end
+ * If so, do it and return true.
+ * Note that this doesn't call afterRemovePages, this is up to the caller.
+ */
+ bool tryRemovingPages();
+
+ ProcessingType processingType()const { return m_processingType; }
+ int frameSetNum( KWFrameSet* fs ) { return m_lstFrameSet.findRef( fs ); }
+
+ void lowerMainFrames( int pageNum );
+ void lowerMainFrames( int pageNum, int lowestZOrder );
+
+ /// \note This method considers _all_ text framesets, even table cells
+ QPtrList<KWTextFrameSet> allTextFramesets( bool onlyReadWrite ) const;
+ /// \note This method considers _all_ text framesets, even table cells
+ int numberOfTextFrameSet( KWFrameSet* fs, bool onlyReadWrite );
+ /// \note This method considers _all_ text framesets, even table cells
+ KWFrameSet * textFrameSetFromIndex( unsigned int num, bool onlyReadWrite );
+
+ /// Reimplementation from KoDocument.
+ /// \note This method considers _all_ text framesets, even table cells
+ virtual QValueList<KoTextDocument *> allTextDocuments() const;
+
+
+ /** Gather all the frames which are on a certain page and return them.
+ * The list is ordered. @see KWFrameSet::framesInPage
+ * @param pageNum the number of the page
+ * @param sorted if true the list is ordered per z-order. should be true always.
+ */
+ QPtrList<KWFrame> framesInPage( int pageNum , bool sorted=true) const;
+
+
+ /**
+ * Max z-order among all frames on the given page
+ * \note There is no minZOrder() method, because of the main frameset, see kwview::lowerFrame
+ */
+ int maxZOrder( int pageNum ) const;
+
+ void updateAllFrames( int flags = 0xff /* see KWFrameSet::UpdateFramesFlags */ );
+
+ // The grid is in _pt_ now
+ double gridX()const { return m_gridX; }
+ double gridY()const { return m_gridY; }
+ void setGridX(double gridx);
+ void setGridY(double gridy) { m_gridY = gridy; }
+
+ void updateGridButton();
+
+ bool showGrid() const { return m_bShowGrid; }
+ void setShowGrid ( bool grid ) { m_bShowGrid = grid; }
+
+ bool snapToGrid() const { return m_bSnapToGrid; }
+ void setSnapToGrid( bool b ) { m_bSnapToGrid = b; }
+
+ // Currently unused. Not sure we want to go that way, now that we have
+ // paragLayoutChanged and formatChanged in applyStyleChange.
+ //int applyStyleChangeMask() { return styleMask; }
+ //void setApplyStyleChangeMask( int f ) { styleMask = f; }
+
+ // paragLayoutChanged is a set of flags for the parag layout - see the enum in KWParagLayout
+ // formatChanged is a set of flags from KoTextFormat
+ // If both are -1, it means the style has been deleted.
+ void applyStyleChange( KoStyleChangeDefMap changed );
+ void updateAllStyleLists();
+ void updateStyleListOrder( const QStringList &list );
+
+ void updateAllFrameStyleLists();
+ void updateAllTableStyleLists();
+
+ bool isHeaderVisible() const { return m_headerVisible; }
+ bool isFooterVisible() const { return m_footerVisible; }
+ void setHeaderVisible( bool h );
+ void setFooterVisible( bool f );
+ bool hasEndNotes() const;
+
+ /// @param flags see KWFrameLayout
+ void recalcFrames( int fromPage = 0, int toPage = -1, uint flags = 0 );
+
+ KoHFType headerType() const { return m_pageHeaderFooter.header; }
+ KoHFType footerType() const { return m_pageHeaderFooter.footer; }
+ const KoKWHeaderFooter& headerFooterInfo() const { return m_pageHeaderFooter; }
+
+ void setFrameCoords( double x, double y, double w, double h );
+
+ void addCommand( KCommand * cmd );
+
+ KoCommandHistory * commandHistory() const { return m_commandHistory; }
+ KoAutoFormat * autoFormat() const { return m_autoFormat; }
+
+ /**
+ * This is used upon loading, to delay certain things until completeLoading,
+ * for KWTextImage
+ */
+ void addTextImageRequest( KWTextImage *img );
+ /**
+ * This is used upon loading, to delay certain things until completeLoading,
+ * for KWPictureFrameSet
+ */
+ void addPictureRequest( KWPictureFrameSet *fs );
+ /**
+ * This is used upon loading, to delay certain things until completeLoading,
+ * for KWTextParag
+ */
+ void addAnchorRequest( const QString &framesetName, const KWAnchorPosition &anchorPos );
+ /**
+ * This is used upon loading, to delay certain things until completeLoading,
+ * for KWFootNoteVariable
+ */
+ void addFootNoteRequest( const QString &framesetName, KWFootNoteVariable* var );
+
+ /// This is used by loadFrameSets() and by KWCanvas to paste framesets
+ KWFrameSet *loadFrameSet( QDomElement framesetElem, bool loadFrames = true , bool loadFootnote = true);
+ void loadEmbeddedObjects( QDomElement& word );
+ void saveEmbeddedObjects( QDomElement& parentElem, const QPtrList<KoDocumentChild>& childList );
+ void loadEmbedded( const QDomElement &embedded );
+
+ void recalcVariables( int type );
+
+ KWVariableCollection *variableCollection() const { return m_varColl; }
+
+ KWMailMergeDataBase *mailMergeDataBase() const { return m_slDataBase; }
+ int mailMergeRecord() const;
+ void setMailMergeRecord( int r );
+
+ bool backgroundSpellCheckEnabled() const;
+ void enableBackgroundSpellCheck( bool b );
+
+ bool canRemovePage( int num );
+
+ /**
+ * Change the zoom factor to @p z (e.g. 150 for 150%)
+ * and/or change the resolution, given in DPI.
+ * This is done on startup and when printing.
+ * The same call combines both so that all the updating done behind
+ * the scenes is done only once, even if both zoom and DPI must be changed.
+ */
+ virtual void setZoomAndResolution( int zoom, int dpiX, int dpiY );
+
+ void newZoomAndResolution( bool updateViews, bool forPrint );
+
+ /**
+ * Due to the way the text formatter works (it caches layout information in
+ * the paragraphs and characters), we currently can't have one viewmode per view.
+ * It has to be the same for all views.
+ */
+ QString viewModeType() const { return m_viewModeType; }
+
+ /**
+ * The view mode used for text layouting.
+ */
+ KWViewMode* layoutViewMode() const { return m_layoutViewMode; }
+
+ /**
+ * Changes m_viewMode, and updates all views to this viewmode
+ */
+ void switchViewMode( const QString& newViewMode );
+
+
+ /// \todo useless method
+ static QString getAttribute(QDomElement &element, const char *attributeName, const QString &defaultValue)
+ {
+ return element.attribute( attributeName, defaultValue );
+ }
+
+ static int getAttribute(QDomElement &element, const char *attributeName, int defaultValue)
+ {
+ QString value;
+ if ( ( value = element.attribute( attributeName ) ) != QString::null )
+ return value.toInt();
+ else
+ return defaultValue;
+ }
+
+ static double getAttribute(QDomElement &element, const char *attributeName, double defaultValue)
+ {
+ QString value;
+ if ( ( value = element.attribute( attributeName ) ) != QString::null )
+ return value.toDouble();
+ else
+ return defaultValue;
+ }
+
+#ifndef NDEBUG
+ void printStyleDebug();
+ void printDebug();
+#endif
+
+ /** calls layout() on all framesets */
+ void layout();
+
+ // This settings has to be here [instead of KWView] because we need to
+ // format paragraphs slightly differently (to add room for the CR char)
+ bool viewFormattingChars() const { return m_viewFormattingChars; }
+ void setViewFormattingChars(bool b) { m_viewFormattingChars=b; }
+
+ bool viewFormattingEndParag() const { return m_viewFormattingEndParag; }
+ void setViewFormattingEndParag(bool b) { m_viewFormattingEndParag=b; }
+
+ bool viewFormattingSpace() const { return m_viewFormattingSpace; }
+ void setViewFormattingSpace(bool b) { m_viewFormattingSpace=b; }
+
+ bool viewFormattingTabs() const { return m_viewFormattingTabs; }
+ void setViewFormattingTabs(bool b) { m_viewFormattingTabs=b; }
+
+ bool viewFormattingBreak() const { return m_viewFormattingBreak; }
+ void setViewFormattingBreak(bool b) { m_viewFormattingBreak=b; }
+
+ // Also view properties, but stored, loaded and saved here (lacking a more global object).
+ bool viewFrameBorders() const { return m_viewFrameBorders; }
+ void setViewFrameBorders( bool b );
+ void setShowRuler(bool ruler){ m_bShowRuler=ruler; }
+ bool showRuler() const { return m_bShowRuler; }
+
+ bool showStatusBar() const { return m_bShowStatusBar;}
+ void setShowStatusBar( bool status ) { m_bShowStatusBar = status;}
+
+ bool showScrollBar() const { return m_bShowScrollBar; }
+ void setShowScrollBar( bool status ) { m_bShowScrollBar = status;}
+
+ bool pgUpDownMovesCaret() const { return m_pgUpDownMovesCaret; }
+ void setPgUpDownMovesCaret( bool b ) { m_pgUpDownMovesCaret = b; }
+
+ bool showdocStruct() const {return m_bShowDocStruct;}
+ void setShowDocStruct(bool b){m_bShowDocStruct=b;}
+
+ bool allowAutoFormat() const { return m_bAllowAutoFormat; }
+ void setAllowAutoFormat(bool b){ m_bAllowAutoFormat=b; }
+
+ bool insertDirectCursor() const { return m_bInsertDirectCursor; }
+ void setInsertDirectCursor(bool b);
+
+
+ // in pt
+ double indentValue()const { return m_indent; }
+ void setIndentValue(double ind) { m_indent=ind; }
+
+ int nbPagePerRow() const{ return m_iNbPagePerRow; }
+ void setNbPagePerRow(int nb) { m_iNbPagePerRow=nb; }
+
+ int maxRecentFiles() const { return m_maxRecentFiles; }
+
+
+ // in pt
+ double defaultColumnSpacing()const{ return m_defaultColumnSpacing ;}
+ void setDefaultColumnSpacing(double val){ m_defaultColumnSpacing=val; }
+ /**
+ * @returns the document for the formulas
+ * @param init if true mathematical fonts may be installed if needed.
+ * Should be true unless no real document is being used (i. e. in
+ * configuration dialog>
+ */
+ KFormula::Document* formulaDocument( bool init = true );
+
+ void reorganizeGUI();
+ /// Tell all views to stop editing this frameset, if they were doing so
+ void terminateEditing( KWFrameSet * frameSet )
+ { emit sig_terminateEditing( frameSet ); }
+
+ void clearUndoRedoInfos();
+
+ void refreshDocStructure(FrameSetType);
+ void refreshDocStructure(int);
+
+ int typeItemDocStructure(FrameSetType type);
+
+ void refreshMenuExpression();
+
+ void refreshMenuCustomVariable();
+
+ void updateZoomRuler();
+
+ /// Mark the document to have a table of contents and update the view-menu-item text
+ void setTocPresent(bool hasToc);
+ /// Returns if the document has a table of contents
+ bool tocPresent(){return m_hasTOC;}
+
+ QString sectionTitle( int pageNum ) const;
+
+ void updateRulerFrameStartEnd();
+
+ /** Convert a color into a color to be displayed for it
+ * (when using color schemes, we still want to print black on white).
+ * See also KoTextFormat::defaultTextColor. */
+ static QColor resolveTextColor( const QColor & col, QPainter * painter );
+ static QColor defaultTextColor( QPainter * painter );
+ static QColor resolveBgColor( const QColor & col, QPainter * painter = 0 );
+ static QBrush resolveBgBrush( const QBrush & brush, QPainter * painter = 0 );
+ static QColor defaultBgColor( QPainter * painter );
+
+
+ virtual DCOPObject* dcopObject();
+
+ int undoRedoLimit() const;
+ void setUndoRedoLimit(int val);
+
+ void updateContentsSize(){emit newContentsSize();}
+
+ void refreshGUIButton();
+
+ void initConfig();
+ void saveConfig();
+ void startBackgroundSpellCheck();
+ void reactivateBgSpellChecking();
+
+ void updateHeaderButton();
+ void updateFooterButton();
+
+ QStringList spellCheckIgnoreList() const { return m_spellCheckIgnoreList; }
+ void setSpellCheckIgnoreList( const QStringList& lst );
+ void addSpellCheckIgnoreWord( const QString & );
+
+ void updateTextFrameSetEdit();
+ void changeFootNoteConfig();
+ void displayFootNoteFieldCode();
+
+
+ double tabStopValue() const { return m_tabStop; }
+ void setTabStopValue ( double tabStop );
+
+ void changeBgSpellCheckingState( bool b );
+
+ // To position the cursor when opening a document
+ QString initialFrameSet() const; ///< \note can be empty for "unset"
+ int initialCursorParag() const;
+ int initialCursorIndex() const;
+ /// Once we're done with this info, get rid of it
+ void deleteInitialEditingInfo();
+
+ bool cursorInProtectedArea()const;
+ void setCursorInProtectedArea( bool b );
+
+ SeparatorLinePos footNoteSeparatorLinePosition()const { return m_footNoteSeparatorLinePos;}
+ void setFootNoteSeparatorLinePosition(SeparatorLinePos pos) {m_footNoteSeparatorLinePos = pos;}
+
+ int footNoteSeparatorLineLength() const { return m_iFootNoteSeparatorLineLength;}
+ void setFootNoteSeparatorLineLength( int length){ m_iFootNoteSeparatorLineLength = length;}
+
+ double footNoteSeparatorLineWidth() const { return m_footNoteSeparatorLineWidth;}
+ void setFootNoteSeparatorLineWidth( double width){ m_footNoteSeparatorLineWidth=width;}
+
+ SeparatorLineLineType footNoteSeparatorLineType()const { return m_footNoteSeparatorLineType;}
+ void setFootNoteSeparatorLineType( SeparatorLineLineType type) {m_footNoteSeparatorLineType = type;}
+
+ const KoTextBookmarkList* bookmarkList() const { return m_bookmarkList; }
+ void insertBookmark( const QString &name, KoTextParag *startparag, KoTextParag *endparag, int start, int end );
+ void deleteBookmark( const QString &name );
+ void renameBookmark( const QString &oldname, const QString &newName );
+
+ const KoTextBookmark * bookmarkByName( const QString & name ) const;
+ QStringList listOfBookmarkName(KWViewMode * viewMode) const;
+
+ void paragraphDeleted( KoTextParag *parag, KWFrameSet *frm);
+ void paragraphModified(KoTextParag* parag, int /*KoTextParag::ParagModifyType*/ type, int start, int lenght);
+
+ void initBookmarkList();
+ void loadImagesFromStore( KoStore *store );
+ void loadPictureMap ( QDomElement& domElement );
+
+ void testAndCloseAllFrameSetProtectedContent();
+ void updateRulerInProtectContentMode();
+
+ KoPageLayout pageLayout(int pageNumber = 0) const;
+
+ QStringList personalExpressionPath() const { return m_personalExpressionPath;}
+ void setPersonalExpressionPath( const QStringList & );
+
+
+ void updateDirectCursorButton();
+
+ QString globalLanguage()const { return m_globalLanguage; }
+ void setGlobalLanguage( const QString & lang ){m_globalLanguage = lang;}
+ void addWordToDictionary( const QString & );
+
+ bool globalHyphenation() const { return m_bGlobalHyphenation; }
+ void setGlobalHyphenation ( bool hyphen );
+
+ KWLoadingInfo* createLoadingInfo();
+ KWLoadingInfo* loadingInfo() const { return m_loadingInfo; }
+ void deleteLoadingInfo();
+
+ KFormula::DocumentWrapper* formulaDocumentWrapper() { return m_formulaDocumentWrapper; }
+
+ KWPageManager *pageManager() const { return m_pageManager; }
+
+ KWBgSpellCheck* backSpeller() const { return m_bgSpellCheck; }
+
+ /// Load the given page layout; public for KWTextParag
+ bool loadOasisPageLayout( const QString& masterPageName, KoOasisContext& context );
+
+ // end of public methods
+signals:
+
+ /// This is emitted by setPageLayout if updateViews=true
+ void pageLayoutChanged( const KoPageLayout& );
+
+ /// Emitted when the scrollview contents must be resized (e.g. new page, new layout...)
+ void newContentsSize();
+
+ /** This is emitted when the height of the text in the main frameset changes
+ * \note Mostly useful for the text viewmode.
+ */
+ void mainTextHeightChanged();
+
+ /// This is emitted when the number of pages changes.
+ void numPagesChanged();
+
+ void docStructureChanged(int);
+ void sig_terminateEditing( KWFrameSet * fs );
+
+ void sig_refreshMenuCustomVariable();
+
+ void sigFrameSetAdded(KWFrameSet*);
+ void sigFrameSetRemoved(KWFrameSet*);
+
+public slots:
+ void slotRepaintChanged( KWFrameSet * frameset );
+ void framesChanged( const QValueList<KWFrame*> &frames);
+
+ /** calls invalidate() on all framesets */
+ void invalidate(const KWFrameSet *skipThisFrameSet=0);
+
+ virtual void initEmpty();
+
+protected slots:
+ void slotRecalcFrames();
+ void slotRepaintAllViews();
+ void slotDocumentRestored();
+ void slotCommandExecuted();
+ void slotDocumentInfoModifed();
+ void slotChapterParagraphFormatted( KoTextParag* parag );
+ void saveDialogShown(); ///< called just before the save-dialog is shown
+
+ virtual void openExistingFile( const QString& file );
+ virtual void openTemplate( const QString& file );
+
+private slots:
+ /// is called from a singleShot timer due to frameChanged()
+ void updateFramesChanged();
+
+protected:
+ void nextParagraphNeedingCheck();
+ /// fix up Z-order for import from older kword versions.
+ void fixZOrders();
+ QString checkSectionTitleInParag( KoTextParag* parag, KWTextFrameSet*, int pageNum ) const;
+ KoView* createViewInstance( QWidget* parent, const char* name );
+
+ virtual bool completeLoading( KoStore* store );
+ virtual bool completeSaving( KoStore *store );
+
+ void loadFrameSets( const QDomElement &framesets );
+ void loadStyleTemplates( const QDomElement &styles );
+ void saveStyle( KoParagStyle *sty, QDomElement parentElem );
+ void saveFrameStyle( KWFrameStyle *sty, QDomElement parentElem );
+ void saveTableStyle( KWTableStyle *sty, QDomElement parentElem );
+
+ void loadFrameStyleTemplates( const QDomElement &styles );
+ void loadDefaultFrameStyleTemplates();
+ void loadTableStyleTemplates( const QDomElement &styles );
+ void loadDefaultTableStyleTemplates();
+ void loadDefaultTableTemplates();
+ bool loadMasterPageStyle( const QString& masterPageName, KoOasisContext& context );
+
+ void saveOasisBody( KoXmlWriter& writer, KoSavingContext& context ) const;
+ void saveOasisCustomFied( KoXmlWriter &writer )const;
+
+ QValueList<KoPictureKey> savePictureList();
+
+ /// helper method for the 2 different dragSelected() versions
+ QDragObject* dragSelectedPrivate( QWidget *parent, const QValueList<KWFrameView*> &selectedFrames, KWTextFrameSet* fs);
+ /**
+ * Save the whole document, or just the selection, into OASIS format
+ * When saving the selection, also return the data as plain text and/or plain picture,
+ * which are used to insert into the KMultipleDrag drag object.
+ *
+ * @param store the KoStore to save into
+ * @param manifestWriter pointer to a koxmlwriter to add entries to the manifest
+ * @param saveFlag either the whole document, or only the selected text/objects.
+ * @param plainText must be set when saveFlag==SaveSelected.
+ * It returns the plain text format of the saved data, when available.
+ * @param picture must be set when saveFlag==SaveSelected.
+ * It returns the selected picture, when exactly one picture was selected.
+ * @param fs the text frameset, which must be set when saveFlag==SaveSelected.
+ */
+ bool saveOasisHelper( KoStore* store, KoXmlWriter* manifestWriter, SaveFlag saveFlag,
+ const QValueList<KWFrameView*> &selectedFrames,
+ QString* plainText = 0, KoPicture* picture = 0, KWTextFrameSet* fs = 0 );
+
+ void saveOasisSettings( KoXmlWriter &settingsWriter ) const;
+ void saveSelectedFrames( KoXmlWriter& bodyWriter,
+ KoSavingContext& savingContext, QValueList<KoPictureKey>& pictureList,
+ const QValueList<KWFrameView*> &selectedFrames, QString* plainText ) const;
+
+ // inherited from KoDocument
+ QWidget* createCustomDocumentWidget(QWidget *parent);
+
+private:
+ void clear();
+ void endOfLoading();
+
+ class FramesChangedHandler {
+ public:
+ FramesChangedHandler(KWDocument *parent);
+ void addFrame(KWFrame*);
+ void addFrameSet(KWFrameSet*);
+ void execute();
+ private:
+ KWDocument *m_parent;
+ QValueList<KWFrameSet*> m_frameSets;
+ bool m_needLayout;
+ };
+
+ // Variables:
+ QValueList<KWView *> m_lstViews;
+
+ KoColumns m_pageColumns;
+ KoKWHeaderFooter m_pageHeaderFooter;
+
+ KoPictureCollection* m_pictureCollection;
+
+ QPtrList<KWFrameSet> m_lstFrameSet;
+
+ unsigned int m_itemsLoaded;
+ unsigned int m_nrItemsToLoad;
+
+ ProcessingType m_processingType;
+ double m_gridX, m_gridY;
+
+ DCOPObject *dcop;
+
+ KoCommandHistory * m_commandHistory;
+ KoAutoFormat * m_autoFormat;
+
+ // ===== Legacy loading stuff, remove when switching to OASIS =====
+ /// \note Shared between loadXML and loadComplete
+ QString m_urlIntern;
+
+ QMap<KoPictureKey, QString> m_pictureMap;
+
+ /// List used to help loading and saving images of the old type ("text image" of class KWTextImage)
+ QPtrList<KWTextImage> m_textImageRequests;
+ QPtrList<KWPictureFrameSet> m_pictureRequests;
+ QMap<QString, KWAnchorPosition> m_anchorRequests;
+ QMap<QString, KWFootNoteVariable *> m_footnoteVarRequests; ///< \todo still needed? (move to KWLoadingInfo if so)
+ // ===== End of legacy loading stuff =====
+
+ QMap<QString,QString> * m_pasteFramesetsMap;
+
+ KoVariableFormatCollection *m_varFormatCollection;
+ KWMailMergeDataBase *m_slDataBase;
+ int slRecordNum;
+
+ /**
+ * When a document is written out, the syntax version in use will be recorded. When read back
+ * in, this variable reflects that value.
+ * \note KWord legacy format only
+ */
+ int m_syntaxVersion;
+
+ QFont m_defaultFont;
+ bool m_headerVisible, m_footerVisible;
+ bool m_viewFrameBorders;
+ bool m_bShowRuler;
+ bool m_bShowDocStruct;
+ bool m_hasTOC;
+ bool m_bShowStatusBar;
+ bool m_pgUpDownMovesCaret;
+ bool m_repaintAllViewsPending;
+ bool m_bAllowAutoFormat;
+ bool m_bShowScrollBar;
+ bool m_cursorInProtectectedArea;
+ bool m_bInsertDirectCursor;
+ bool m_bHasEndNotes;
+
+ bool m_viewFormattingChars;
+ bool m_viewFormattingEndParag;
+ bool m_viewFormattingSpace;
+ bool m_viewFormattingTabs;
+ bool m_viewFormattingBreak;
+
+ /** The wrapper that contains the formula's document and its
+ * actions. It owns the real document.
+ */
+ KFormula::DocumentWrapper* m_formulaDocumentWrapper;
+
+ double m_indent; ///< \note in pt
+ double m_defaultColumnSpacing;
+
+ int m_iNbPagePerRow;
+ int m_maxRecentFiles;
+ int m_recalcFramesPending;
+
+ /// The name of the viewmode used by all views.
+ QString m_viewModeType;
+ /// The viewmode used for text layouting
+ KWViewMode* m_layoutViewMode;
+ KWVariableCollection *m_varColl;
+ KWBgSpellCheck *m_bgSpellCheck;
+ KoStyleCollection *m_styleColl;
+ KWFrameStyleCollection *m_frameStyleColl;
+ KWTableStyleCollection *m_tableStyleColl;
+ KWTableTemplateCollection *m_tableTemplateColl;
+
+
+ SeparatorLinePos m_footNoteSeparatorLinePos;
+ /// It's a percentage of page.
+ int m_iFootNoteSeparatorLineLength;
+
+ double m_footNoteSeparatorLineWidth;
+
+ SeparatorLineLineType m_footNoteSeparatorLineType;
+
+ /** Page number -> section title array, for the Section variable.
+ * Note that pages without a section title don't appear in the array. */
+ QValueVector< QString > m_sectionTitles;
+
+ double m_tabStop;
+ QStringList m_spellCheckIgnoreList; // per-document
+ QStringList m_spellCheckPersonalDict; // per-user
+ QPixmap* m_bufPixmap;
+
+ KWLoadingInfo* m_loadingInfo;
+
+ class InitialEditing;
+ /// \note Remains alive a little bit longer than the loading info (until KWCanvas ctor)
+ InitialEditing *m_initialEditing;
+
+ KoTextBookmarkList* m_bookmarkList;
+
+ QStringList m_personalExpressionPath;
+ QString m_globalLanguage;
+ bool m_bGlobalHyphenation;
+ bool m_bGeneratingPreview;
+
+ bool m_bShowGrid;
+ bool m_bSnapToGrid;
+
+ KWPageManager *m_pageManager;
+ FramesChangedHandler *m_framesChangedHandler;
+};
+
+#endif
diff --git a/kword/KWEditPersonnalExpression.cpp b/kword/KWEditPersonnalExpression.cpp
new file mode 100644
index 00000000..d11449af
--- /dev/null
+++ b/kword/KWEditPersonnalExpression.cpp
@@ -0,0 +1,370 @@
+/* This file is part of the KDE project
+ Copyright (C) 2001,2002 Montel Laurent <lmontel@mandrakesoft.com>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+*/
+
+#include "KWEditPersonnalExpression.h"
+#include "KWView.h"
+
+#include <klocale.h>
+#include <klineeditdlg.h>
+#include <kdebug.h>
+#include <kstandarddirs.h>
+
+#include <qfile.h>
+#include <qpushbutton.h>
+#include <qcombobox.h>
+#include <qlineedit.h>
+#include <qlabel.h>
+#include <qlayout.h>
+
+KWEditPersonnalExpression::KWEditPersonnalExpression( QWidget *parent, const char *name )
+ : KDialogBase( parent, name , true, i18n("Edit Personal Expression"), Ok|Cancel, Ok, true )
+{
+ resize( 412, 339 );
+ QWidget *page = new QWidget( this );
+ setMainWidget(page);
+ QGridLayout* form1Layout = new QGridLayout( page, 1, 1, 0, KDialog::spacingHint(), "form1Layout");
+
+ QHBoxLayout *horlayout1 = new QHBoxLayout( 0, 0, KDialog::spacingHint(), "horlayout1");
+
+ QLabel *groupnameLabel = new QLabel(i18n("Group name:"), page, "groupnameLabel" );
+ horlayout1->addWidget( groupnameLabel );
+
+ m_groupLineEdit = new QLineEdit( page, "groupLineEdit" );
+ horlayout1->addWidget( m_groupLineEdit );
+
+ form1Layout->addLayout( horlayout1, 0, 1 );
+
+ QGroupBox *expressionGroupBox = new QGroupBox( page, "expressionGroupBox" );
+ expressionGroupBox->setSizePolicy( QSizePolicy( (QSizePolicy::SizeType)5, (QSizePolicy::SizeType)5, 1, 0, expressionGroupBox->sizePolicy().hasHeightForWidth() ) );
+ expressionGroupBox->setTitle( i18n( "Expressions" ) );
+ expressionGroupBox->setColumnLayout(0, Qt::Vertical );
+ expressionGroupBox->layout()->setSpacing( KDialog::spacingHint() );
+ expressionGroupBox->layout()->setMargin( KDialog::marginHint() );
+ QVBoxLayout *expressionGroupBoxLayout = new QVBoxLayout( expressionGroupBox->layout() );
+ expressionGroupBoxLayout->setAlignment( Qt::AlignTop );
+
+ m_ExpressionsList = new QListBox( expressionGroupBox, "listOfExpressions" );
+ m_ExpressionsList->setSizePolicy( QSizePolicy( (QSizePolicy::SizeType)7, (QSizePolicy::SizeType)7, 1, 0, m_ExpressionsList->sizePolicy().hasHeightForWidth() ) );
+ expressionGroupBoxLayout->addWidget( m_ExpressionsList );
+
+ m_expressionLineEdit = new QLineEdit( expressionGroupBox, "expressionLineEdit" );
+ expressionGroupBoxLayout->addWidget( m_expressionLineEdit );
+
+ QHBoxLayout *horlayout2 = new QHBoxLayout( 0, 0, KDialog::spacingHint(), "horlayout2");
+ QSpacerItem* spacer = new QSpacerItem( 0, 0, QSizePolicy::Expanding, QSizePolicy::Minimum );
+ horlayout2->addItem( spacer );
+
+ m_addExpression = new QPushButton( i18n("&New"), expressionGroupBox, "m_addExpression" );
+ horlayout2->addWidget( m_addExpression );
+
+ m_delExpression = new QPushButton( i18n("&Delete"), expressionGroupBox, "m_delExpression" );
+ horlayout2->addWidget( m_delExpression );
+ expressionGroupBoxLayout->addLayout( horlayout2 );
+
+ form1Layout->addWidget( expressionGroupBox, 1, 1 );
+
+ QVBoxLayout *vertlayout = new QVBoxLayout( 0, 0, KDialog::spacingHint(), "vertlayout");
+
+ m_groupList = new QListBox( page, "groupList" );
+ m_groupList->insertItem( "group1" );
+ m_groupList->setMaximumSize( QSize( 200, 32767 ) );
+ vertlayout->addWidget( m_groupList );
+
+ QHBoxLayout *horlayout3 = new QHBoxLayout( 0, 0, KDialog::spacingHint(), "horlayout3");
+
+ m_addGroup = new QPushButton( i18n("New"), page, "m_addGroup" );
+ horlayout3->addWidget( m_addGroup );
+
+ m_delGroup = new QPushButton(i18n("Delete"), page, "m_delGroup" );
+ horlayout3->addWidget( m_delGroup );
+ vertlayout->addLayout( horlayout3 );
+
+ form1Layout->addMultiCellLayout( vertlayout, 0, 1, 0, 0 );
+
+ loadFile();
+ if(listExpression.count() == 0)
+ slotAddGroup();
+ else
+ initGroupList();
+
+ connect(m_groupList,SIGNAL(selectionChanged()), this,SLOT(slotGroupSelected()));
+ connect(m_ExpressionsList,SIGNAL(selectionChanged()), this,SLOT(slotExpressionSelected()));
+ if(m_groupList->count() > 0) m_groupList->setSelected(0, true);
+
+ connect(m_groupLineEdit,SIGNAL(textChanged(const QString&)), this,SLOT(slotUpdateGroupName(const QString&)));
+ connect(m_expressionLineEdit,SIGNAL(textChanged(const QString&)), this,SLOT(slotUpdateExpression(const QString&)));
+ connect(m_addExpression, SIGNAL( clicked() ), this,SLOT( slotAddExpression() ));
+ connect(m_delExpression, SIGNAL( clicked() ), this,SLOT( slotRemoveExpression() ));
+ connect(m_addGroup, SIGNAL( clicked() ), this,SLOT( slotAddGroup()));
+ connect(m_delGroup, SIGNAL( clicked() ), this,SLOT( slotRemoveGroup() ));
+ updateWidget();
+
+ setFocus();
+}
+
+void KWEditPersonnalExpression::slotExpressionSelected()
+{
+ m_delExpression->setEnabled(m_ExpressionsList->currentItem()!=-1);
+ m_expressionLineEdit->setText(m_ExpressionsList->currentText());
+}
+
+void KWEditPersonnalExpression::slotGroupSelected()
+{
+ m_groupLineEdit->blockSignals(true);
+ m_delExpression->setEnabled(m_groupList->currentItem()!=-1);
+ m_groupLineEdit->setText(m_groupList->currentText());
+ list::Iterator it= listExpression.find(m_groupList->currentText());
+ QStringList lst(it.data());
+ m_ExpressionsList->blockSignals(true);
+ m_ExpressionsList->clear();
+ m_ExpressionsList->insertStringList(lst);
+ m_ExpressionsList->blockSignals(false);
+ m_delExpression->setEnabled(lst.count()>0);
+ if(m_ExpressionsList->count() > 0)
+ m_ExpressionsList->setSelected(0, true);
+ m_groupLineEdit->blockSignals(false);
+}
+
+void KWEditPersonnalExpression::slotUpdateGroupName(const QString &newGroupName)
+{
+ if ( m_groupList->currentItem()==-1 )
+ return;
+
+ m_addGroup->setEnabled( true );
+ list::Iterator it= listExpression.find(m_groupList->currentText());
+ QStringList lst(it.data());
+ listExpression.insert(newGroupName,lst);
+ listExpression.remove(m_groupList->currentText());
+ m_groupList->blockSignals(true);
+ m_groupList->changeItem(newGroupName, m_groupList->currentItem());
+ m_groupList->blockSignals(false);
+ m_bChanged=true;
+}
+
+void KWEditPersonnalExpression::slotUpdateExpression(const QString &newExpression)
+{
+ if(newExpression.isEmpty() || m_groupList->currentItem()==-1 || m_ExpressionsList->currentText().isEmpty())
+ return;
+
+ list::Iterator it= listExpression.find(m_groupList->currentText());
+ QStringList lst = it.data();
+ QStringList::Iterator it2=lst.find(m_ExpressionsList->currentText());
+ lst.insert(it2,QString(newExpression));
+ lst.remove(it2);
+ listExpression.replace(m_groupList->currentText(),lst);
+
+ lst.remove(m_ExpressionsList->currentText());
+ m_ExpressionsList->blockSignals(true);
+ m_ExpressionsList->changeItem(newExpression, m_ExpressionsList->currentItem());
+ m_ExpressionsList->blockSignals(false);
+ m_bChanged=true;
+}
+
+void KWEditPersonnalExpression::loadFile()
+{
+ QString file=locateLocal("data","kword/expression/perso.xml");
+ init( file );
+}
+
+void KWEditPersonnalExpression::initGroupList()
+{
+ QStringList lst;
+ m_groupList->clear();
+ list::Iterator it;
+ for( it = listExpression.begin(); it != listExpression.end(); ++it )
+ lst<<it.key();
+ m_groupList->insertStringList(lst);
+}
+
+void KWEditPersonnalExpression::init(const QString& filename )
+{
+ QFile file( filename );
+ if ( !file.open( IO_ReadOnly ) )
+ return;
+
+ kdDebug() << "KWEditPersonnalExpression::init parsing " << filename << endl;
+ QDomDocument doc;
+ doc.setContent( &file );
+ file.close();
+
+ QString group = "";
+ QStringList list;
+ QDomNode n = doc.documentElement().firstChild();
+ for( ; !n.isNull(); n = n.nextSibling() )
+ {
+ if ( n.isElement() )
+ {
+ QDomElement e = n.toElement();
+ if ( e.tagName() == "Type" )
+ {
+ list.clear();
+ group = i18n( e.namedItem( "TypeName" ).toElement().text().utf8() );
+
+ QDomNode n2 = e.firstChild();
+ for( ; !n2.isNull(); n2 = n2.nextSibling() )
+ {
+
+ if ( n2.isElement() )
+ {
+ QDomElement e2 = n2.toElement();
+ if ( e2.tagName() == "Expression" )
+ {
+ QString text = i18n( e2.namedItem( "Text" ).toElement().text().utf8() );
+ list<<text;
+ }
+ }
+ }
+ listExpression.insert(group,list);
+
+ group = "";
+ }
+ }
+ }
+}
+
+void KWEditPersonnalExpression::slotOk()
+{
+ if( m_bChanged)
+ saveFile();
+ KDialogBase::slotOk();
+}
+
+void KWEditPersonnalExpression::slotAddExpression() {
+ list::Iterator it= listExpression.find(m_groupList->currentText());
+ QStringList lst(it.data());
+ QString newWord = i18n("empty");
+ if ( lst.contains( newWord ))
+ return;
+ lst<< newWord;
+ listExpression.replace(m_groupList->currentText(),lst);
+
+ m_ExpressionsList->blockSignals(true);
+ m_ExpressionsList->insertItem(newWord);
+ m_ExpressionsList->clearSelection();
+ m_ExpressionsList->setBottomItem (m_ExpressionsList->count() -1);
+ m_ExpressionsList->blockSignals(false);
+ m_ExpressionsList->setSelected(m_ExpressionsList->count() -1, true);
+ m_expressionLineEdit->selectAll();
+ m_expressionLineEdit->setFocus();
+
+ updateExpression();
+
+ m_bChanged=true;
+}
+
+void KWEditPersonnalExpression::slotRemoveExpression() {
+ QString text=m_ExpressionsList->currentText ();
+ if(!text.isEmpty())
+ {
+ list::Iterator it= listExpression.find(m_groupList->currentText());
+ QStringList lst(it.data());
+ lst.remove(text);
+ listExpression.replace(m_groupList->currentText(),lst);
+
+ m_ExpressionsList->blockSignals(true);
+ m_ExpressionsList->clear();
+ m_ExpressionsList->insertStringList(lst);
+ m_delExpression->setEnabled(lst.count()>0);
+ m_ExpressionsList->blockSignals(false);
+ m_expressionLineEdit->blockSignals(true);
+ m_expressionLineEdit->clear();
+ m_expressionLineEdit->blockSignals(false);
+ m_bChanged=true;
+ }
+}
+
+void KWEditPersonnalExpression::slotAddGroup() {
+ listExpression.insert(i18n("new group"),QStringList());
+ initGroupList();
+ m_groupList->setCurrentItem(m_groupList->count() -1);
+ updateWidget();
+ m_bChanged=true;
+}
+
+void KWEditPersonnalExpression::slotRemoveGroup() {
+ QString group=m_groupList->currentText();
+ if(group.isEmpty())
+ return;
+ listExpression.remove( group );
+ m_groupList->removeItem(m_groupList->currentItem());
+ updateWidget();
+ m_bChanged=true;
+}
+
+void KWEditPersonnalExpression::updateWidget()
+{
+ bool state = listExpression.count()> 0;
+ m_delGroup->setEnabled( state );
+ m_addExpression->setEnabled( state );
+ m_groupLineEdit->setEnabled( state );
+
+ state =state && m_ExpressionsList->count()>0;
+ m_expressionLineEdit->setEnabled( state );
+ m_delExpression->setEnabled( state);
+
+}
+
+void KWEditPersonnalExpression::updateExpression()
+{
+ bool state = m_ExpressionsList->count()>0;
+ m_expressionLineEdit->setEnabled( state );
+ m_delExpression->setEnabled( state);
+}
+
+void KWEditPersonnalExpression::saveFile()
+{
+ QDomDocument doc( "KWordExpression" );
+ QDomElement begin = doc.createElement( "KWordExpression" );
+ doc.appendChild( begin );
+ QStringList lst;
+ list::Iterator it;
+ for( it = listExpression.begin(); it != listExpression.end(); ++it )
+ {
+ lst=it.data();
+ if ( !lst.isEmpty() )
+ {
+ QDomElement type = doc.createElement( "Type" );
+ begin.appendChild( type );
+ QDomElement typeName = doc.createElement( "TypeName" );
+ type.appendChild( typeName );
+ typeName.appendChild( doc.createTextNode(it.key() ) );
+
+ for( uint i=0;i<lst.count();i++ )
+ {
+ QDomElement expr = doc.createElement( "Expression" );
+ type.appendChild( expr );
+ QDomElement text = doc.createElement( "Text" );
+ expr.appendChild( text );
+ text.appendChild( doc.createTextNode(lst[i] ) );
+ }
+ }
+ }
+ QCString s = doc.toCString();
+
+ QFile file( locateLocal("data","kword/expression/perso.xml") );
+ if ( !file.open( IO_WriteOnly ) )
+ {
+ kdDebug()<<"Error \n";
+ return;
+ }
+ file.writeBlock(s,s.length());
+ file.close();
+}
+
+#include "KWEditPersonnalExpression.moc"
diff --git a/kword/KWEditPersonnalExpression.h b/kword/KWEditPersonnalExpression.h
new file mode 100644
index 00000000..d33e7dfc
--- /dev/null
+++ b/kword/KWEditPersonnalExpression.h
@@ -0,0 +1,70 @@
+/* This file is part of the KDE project
+ Copyright (C) 2001 Montel Laurent <lmontel@mandrakesoft.com>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+*/
+
+#ifndef __KWEditPersonnalExpression__
+#define __KWEditPersonnalExpression__
+
+#include <kdialogbase.h>
+#include <qmap.h>
+
+class QPushButton;
+class QComboBox;
+class QListBox;
+class QLineEdit;
+
+class KWEditPersonnalExpression : public KDialogBase
+{
+ Q_OBJECT
+public:
+ KWEditPersonnalExpression( QWidget *parent, const char *name = 0 );
+
+protected:
+ void init(const QString& filename );
+ void loadFile();
+ void initGroupList();
+ void saveFile();
+ void updateWidget();
+ void updateExpression();
+
+protected slots:
+ void slotGroupSelected();
+ void slotExpressionSelected();
+ void slotUpdateGroupName(const QString &newGroupName);
+ void slotUpdateExpression(const QString &newExpression);
+ void slotRemoveExpression();
+ void slotAddExpression();
+ void slotRemoveGroup();
+ void slotAddGroup();
+ virtual void slotOk();
+
+ private:
+ typedef QMap<QString,QStringList> list;
+ list listExpression;
+ QListBox *m_groupList;
+ QListBox *m_ExpressionsList;
+ QPushButton *m_addGroup;
+ QPushButton *m_delGroup;
+ QPushButton *m_addExpression;
+ QPushButton *m_delExpression;
+ QLineEdit *m_groupLineEdit;
+ QLineEdit *m_expressionLineEdit;
+ bool m_bChanged;
+};
+
+#endif
diff --git a/kword/KWFactory.cpp b/kword/KWFactory.cpp
new file mode 100644
index 00000000..f19bdc8a
--- /dev/null
+++ b/kword/KWFactory.cpp
@@ -0,0 +1,87 @@
+/* This file is part of the KDE project
+ Copyright (C) 1998, 1999 Reginald Stadlbauer <reggie@kde.org>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+*/
+
+#include "KWFactory.h"
+#include "KWAboutData.h"
+#include "KWDocument.h"
+
+#include <kstandarddirs.h>
+
+#include <kiconloader.h>
+
+KInstance* KWFactory::s_instance = 0;
+KAboutData* KWFactory::s_aboutData = 0;
+
+KWFactory::KWFactory( QObject* parent, const char* name )
+ : KoFactory( parent, name )
+{
+ // Create our instance, so that it becomes KGlobal::instance if the
+ // main app is KWord.
+ (void) instance();
+}
+
+KWFactory::~KWFactory()
+{
+ delete s_aboutData;
+ s_aboutData=0;
+ delete s_instance;
+ s_instance=0L;
+}
+
+KParts::Part* KWFactory::createPartObject( QWidget *parentWidget, const char *widname, QObject* parent, const char* name, const char* classname, const QStringList & )
+{
+ bool bWantKoDocument = ( strcmp( classname, "KoDocument" ) == 0 );
+
+ KWDocument *doc = new KWDocument( parentWidget, widname, parent, name, !bWantKoDocument );
+
+ if ( !bWantKoDocument )
+ doc->setReadWrite( false );
+
+ return doc;
+}
+
+KAboutData* KWFactory::aboutData()
+{
+ if(!s_aboutData) {
+ s_aboutData = newKWordAboutData();
+ }
+ return s_aboutData;
+}
+
+KInstance* KWFactory::instance()
+{
+ if ( !s_instance )
+ {
+ s_instance = new KInstance( aboutData() );
+
+ s_instance->dirs()->addResourceType( "kword_template",
+ KStandardDirs::kde_default("data") + "kword/templates/");
+ s_instance->dirs()->addResourceType( "expression", KStandardDirs::kde_default("data") + "kword/expression/");
+ s_instance->dirs()->addResourceType( "horizontalLine", KStandardDirs::kde_default("data") + "kword/horizontalline/");
+
+ s_instance->dirs()->addResourceType( "toolbar",
+ KStandardDirs::kde_default("data") + "koffice/toolbar/");
+ s_instance->dirs()->addResourceType( "toolbar",
+ KStandardDirs::kde_default("data") + "kformula/pics/");
+ s_instance->iconLoader()->addAppDir("koffice");
+ }
+ return s_instance;
+}
+
+#include "KWFactory.moc"
diff --git a/kword/KWFactory.h b/kword/KWFactory.h
new file mode 100644
index 00000000..9330331b
--- /dev/null
+++ b/kword/KWFactory.h
@@ -0,0 +1,46 @@
+/* This file is part of the KDE project
+ Copyright (C) 1998, 1999 Reginald Stadlbauer <reggie@kde.org>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+*/
+
+#ifndef KWORD_FACTORY_H
+#define KWORD_FACTORY_H
+
+#include <KoFactory.h>
+
+class KAboutData;
+
+class KWFactory : public KoFactory
+{
+ Q_OBJECT
+public:
+ KWFactory( QObject* parent = 0, const char* name = 0 );
+ ~KWFactory();
+
+ virtual KParts::Part* createPartObject( QWidget * = 0, const char * = 0, QObject* parent = 0, const char* name = 0, const char* classname = "KoDocument", const QStringList &args = QStringList() );
+
+ static KInstance* instance();
+
+ // _Creates_ a KAboutData but doesn't keep ownership
+ static KAboutData* aboutData();
+
+private:
+ static KInstance* s_instance;
+ static KAboutData* s_aboutData;
+};
+
+#endif
diff --git a/kword/KWFactoryInit.cpp b/kword/KWFactoryInit.cpp
new file mode 100644
index 00000000..2dd682c8
--- /dev/null
+++ b/kword/KWFactoryInit.cpp
@@ -0,0 +1,23 @@
+/* This file is part of the KDE project
+ Copyright (C) 2005 David Faure <faure@kde.org>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+
+#include "KWFactory.h"
+
+K_EXPORT_COMPONENT_FACTORY( libkwordpart, KWFactory )
+
diff --git a/kword/KWFindReplace.cpp b/kword/KWFindReplace.cpp
new file mode 100644
index 00000000..765b82e3
--- /dev/null
+++ b/kword/KWFindReplace.cpp
@@ -0,0 +1,62 @@
+/* This file is part of the KDE project
+ Copyright (C) 1998, 1999 Reginald Stadlbauer <reggie@kde.org>
+ Copyright (C) 2001, S.R.Haque <srhaque@iee.org>
+ Copyright (C) 2001, David Faure <faure@kde.org>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+*/
+
+#include <kdebug.h>
+#include "KWFindReplace.h"
+#include "KWCanvas.h"
+#include "KWDocument.h"
+#include "KWTextFrameSet.h"
+#include <KoTextObject.h>
+#include <kcommand.h>
+#include <KoSearchDia.h>
+#include "KWTextDocument.h"
+//#include <KoTextDocument.h>
+
+KWFindReplace::KWFindReplace( KWCanvas * canvas, KoSearchDia * dialog, const QValueList<KoTextObject *> & lstObjects, KWTextFrameSetEdit *textView)
+ : KoFindReplace( canvas, dialog, lstObjects, textView )
+{
+ m_canvas = canvas;
+}
+
+KWFindReplace::KWFindReplace( KWCanvas * canvas, KoReplaceDia * dialog, const QValueList<KoTextObject *> & lstObjects, KWTextFrameSetEdit *textView )
+ : KoFindReplace( canvas, dialog, lstObjects, textView )
+{
+ m_canvas = canvas;
+}
+
+KWFindReplace::~KWFindReplace()
+{
+ //kdDebug() << "KWFindReplace::~KWFindReplace m_destroying=" << m_destroying << endl;
+}
+
+void KWFindReplace::emitNewCommand(KCommand *cmd)
+{
+ m_canvas->kWordDocument()->addCommand(cmd);
+}
+
+void KWFindReplace::highlightPortion(KoTextParag * parag, int index, int length, KoTextDocument *textdocument, KDialogBase* dialog)
+{
+ KWTextDocument *textdoc=static_cast<KWTextDocument *>(textdocument);
+ bool repaint = isReplace() ? options() & KReplaceDialog::PromptOnReplace : true;
+ textdoc->textFrameSet()->highlightPortion( parag, index, length, m_canvas, repaint, dialog );
+}
+
+#include "KWFindReplace.moc"
diff --git a/kword/KWFindReplace.h b/kword/KWFindReplace.h
new file mode 100644
index 00000000..86d127dc
--- /dev/null
+++ b/kword/KWFindReplace.h
@@ -0,0 +1,56 @@
+/* This file is part of the KDE project
+ Copyright (C) 1998, 1999 Reginald Stadlbauer <reggie@kde.org>
+ Copyright (C) 2001, S.R.Haque <srhaque@iee.org>
+ Copyright (C) 2001, David Faure <faure@kde.org>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+*/
+
+#ifndef searchdia_h
+#define searchdia_h
+
+#include <qstring.h>
+#include <qstringlist.h>
+#include <KoRichText.h>
+#include <KoTextObject.h>
+#include <KoTextView.h>
+#include <KoSearchDia.h>
+
+class KWCanvas;
+class KWTextFrameSet;
+class KMacroCommand;
+class KWTextFrameSetEdit;
+/**
+ * This class implements the 'find' functionality ( the "search next, prompt" loop )
+ * and the 'replace' functionality. Same class, to allow centralizing the code that
+ * finds the framesets and paragraphs to look into.
+ */
+class KWFindReplace : public KoFindReplace
+{
+ Q_OBJECT
+public:
+ KWFindReplace( KWCanvas * canvas, KoSearchDia * dialog, const QValueList<KoTextObject *> & lstObjects, KWTextFrameSetEdit* textView );
+ KWFindReplace( KWCanvas * parent, KoReplaceDia * dialog, const QValueList<KoTextObject *> & lstObjects, KWTextFrameSetEdit* textView );
+ ~KWFindReplace();
+
+ virtual void emitNewCommand(KCommand *);
+ virtual void highlightPortion(KoTextParag * parag, int index, int length, KoTextDocument *textdocument, KDialogBase* dialog);
+
+private:
+ KWCanvas *m_canvas;
+};
+
+#endif
diff --git a/kword/KWFootNoteDia.cpp b/kword/KWFootNoteDia.cpp
new file mode 100644
index 00000000..52aa50c5
--- /dev/null
+++ b/kword/KWFootNoteDia.cpp
@@ -0,0 +1,138 @@
+/* This file is part of the KDE project
+ Copyright (C) 1998, 1999 Reginald Stadlbauer <reggie@kde.org>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+*/
+
+#include "KWFootNoteDia.h"
+#include "KWFootNoteDia.moc"
+
+#include <qbuttongroup.h>
+#include <qvbox.h>
+#include <qradiobutton.h>
+
+#include <klocale.h>
+#include <qlayout.h>
+#include <qlineedit.h>
+#include "KWConfigFootNoteDia.h"
+
+
+/******************************************************************/
+/* Class: KWFootNoteDia */
+/******************************************************************/
+
+KWFootNoteDia::KWFootNoteDia( NoteType _noteType, KWFootNoteVariable::Numbering _numberingType, const QString & _manualString, QWidget *parent, KWDocument *_doc, const char *name )
+ : KDialogBase( parent, name, true, QString::null, Ok|Cancel|User1, Ok, true )
+{
+ m_doc =_doc;
+ //setButtonOKText(i18n("&Insert"));
+
+ setCaption( i18n("Insert Footnote/Endnote") );
+
+ QVBox *page = makeVBoxMainWidget();
+
+ QButtonGroup *grp = new QButtonGroup( i18n("Numbering"), page );
+ QGridLayout *grid = new QGridLayout( grp, 9, 4, KDialog::marginHint(), KDialog::spacingHint());
+ m_rbAuto = new QRadioButton( i18n("&Automatic"), grp );
+ m_rbManual= new QRadioButton( i18n("&Manual"), grp );
+
+ grp->setExclusive( true );
+ int fHeight = grp->fontMetrics().height();
+ grid->addRowSpacing( 0, fHeight/2 ); // groupbox title
+ grid->addWidget( m_rbAuto, 1, 0);
+ grid->addWidget( m_rbManual, 2, 0);
+ if ( _numberingType == KWFootNoteVariable::Auto )
+ m_rbAuto->setChecked( true );
+ else
+ m_rbManual->setChecked( true );
+ m_footLine = new QLineEdit( grp);
+ m_footLine->setText( _manualString );
+ connect( m_footLine, SIGNAL( textChanged ( const QString & )), this, SLOT(footLineChanged( const QString & )));
+ connect( grp, SIGNAL( clicked ( int ) ), this, SLOT(footNoteTypeChanged()));
+ grid->addWidget( m_footLine, 2, 1);
+
+
+ grp = new QButtonGroup( 4, Qt::Vertical, page );
+ m_rbFootNote = new QRadioButton( i18n("&Footnote"), grp );
+ m_rbEndNote = new QRadioButton( i18n("&Endnote"), grp );
+
+ grp->setExclusive( true );
+ grp->insert( m_rbFootNote );
+ grp->insert( m_rbEndNote );
+ if (_noteType == FootNote )
+ m_rbFootNote->setChecked( true );
+ else
+ m_rbEndNote->setChecked( true );
+
+ footNoteTypeChanged();
+ setButtonText( KDialogBase::User1, i18n("C&onfigure...") );
+ connect( this, SIGNAL( user1Clicked() ), this, SLOT(slotConfigurate()));
+}
+
+void KWFootNoteDia::footNoteTypeChanged()
+{
+ if ( m_rbManual->isChecked())
+ {
+ enableButtonOK( !m_footLine->text().isEmpty() );
+ m_footLine->setFocus();
+ }
+ else
+ {
+ enableButtonOK(true);
+ setFocus();
+ }
+}
+
+void KWFootNoteDia::footLineChanged( const QString &text )
+{
+ m_rbManual->setChecked( true );
+ if ( text.isEmpty() || footNoteAlreadyExists(text) )
+ enableButtonOK( false );
+ else
+ enableButtonOK( true );
+}
+
+NoteType KWFootNoteDia::noteType() const
+{
+ return m_rbFootNote->isChecked() ? FootNote : EndNote;
+}
+
+KWFootNoteVariable::Numbering KWFootNoteDia::numberingType()const
+{
+ return m_rbAuto->isChecked() ? KWFootNoteVariable::Auto : KWFootNoteVariable::Manual;
+}
+
+QString KWFootNoteDia::manualString()const
+{
+ return m_rbAuto->isChecked() ? QString::null : m_footLine->text();
+}
+
+void KWFootNoteDia::slotConfigurate()
+{
+ KWConfigFootNoteDia *dia = new KWConfigFootNoteDia( this, "configfootnote", m_doc );
+ dia->exec();
+ delete dia;
+}
+
+bool KWFootNoteDia::footNoteAlreadyExists( const QString & text )
+{
+ return manualFootNotes.contains( text );
+}
+
+void KWFootNoteDia::appendManualFootNote( const QString & text )
+{
+ manualFootNotes.append( text );
+}
diff --git a/kword/KWFootNoteDia.h b/kword/KWFootNoteDia.h
new file mode 100644
index 00000000..a04584b3
--- /dev/null
+++ b/kword/KWFootNoteDia.h
@@ -0,0 +1,65 @@
+/* This file is part of the KDE project
+ Copyright (C) 1998, 1999 Reginald Stadlbauer <reggie@kde.org>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+*/
+
+#ifndef footnotedia_h
+#define footnotedia_h
+
+#include <kdialogbase.h>
+#include "defs.h" // for NoteType
+#include "KWVariable.h"
+class QRadioButton;
+class QLineEdit;
+class KWDocument;
+/******************************************************************/
+/* Class: KWFootNoteDia */
+/******************************************************************/
+
+class KWFootNoteDia : public KDialogBase
+{
+ Q_OBJECT
+
+public:
+ KWFootNoteDia( NoteType _noteType, KWFootNoteVariable::Numbering _numberingType, const QString & _manualString, QWidget *parent, KWDocument *_doc, const char *name = 0 );
+
+ NoteType noteType() const;
+ KWFootNoteVariable::Numbering numberingType()const;
+ QString manualString()const;
+ void appendManualFootNote( const QString & );
+protected:
+ bool insertFootNote();
+ bool footNoteAlreadyExists( const QString & );
+protected slots:
+ void footLineChanged( const QString & );
+ void footNoteTypeChanged();
+ void slotConfigurate();
+private:
+
+ QRadioButton *m_rbAuto;
+ QRadioButton *m_rbManual;
+
+ QRadioButton *m_rbFootNote;
+ QRadioButton *m_rbEndNote;
+ QLineEdit *m_footLine;
+ KWDocument *m_doc;
+ QValueList<QString> manualFootNotes;
+};
+
+#endif
+
+
diff --git a/kword/KWFormulaFrameSet.cpp b/kword/KWFormulaFrameSet.cpp
new file mode 100644
index 00000000..7f167a23
--- /dev/null
+++ b/kword/KWFormulaFrameSet.cpp
@@ -0,0 +1,540 @@
+/* This file is part of the KDE project
+ Copyright (C) 2003 Ulrich Kuettler <ulrich.kuettler@gmx.de>
+
+ This program is free software; you can redistribute it and/or
+ modify it under the terms of the GNU General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; see the file COPYING. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+*/
+
+#include <qfile.h>
+
+#include "KWFormulaFrameSet.h"
+
+#include "KWDocument.h"
+#include "KWView.h"
+#include "KWViewMode.h"
+#include "KWCanvas.h"
+#include "KWFrame.h"
+#include "defs.h"
+
+#include <kformulacontainer.h>
+#include <kformuladocument.h>
+#include <kformulaview.h>
+#include <KoOasisContext.h>
+#include <KoXmlNS.h>
+#include <KoXmlWriter.h>
+
+#include <klocale.h>
+#include <kmessagebox.h>
+#include <kdebug.h>
+#include <ktempfile.h>
+#include <dcopobject.h>
+#include "KWordFormulaFrameSetIface.h"
+#include "KWordFormulaFrameSetEditIface.h"
+
+#include <assert.h>
+
+// #ifdef __GNUC__
+// #undef k_funcinfo
+// #define k_funcinfo "[\033[36m" << __PRETTY_FUNCTION__ << "\033[m] "
+// #endif
+
+/******************************************************************/
+/* Class: KWFormulaFrameSet */
+/******************************************************************/
+KWFormulaFrameSet::KWFormulaFrameSet( KWDocument *doc, const QString & name )
+ : KWFrameSet( doc ), m_changed( false ), m_edit( 0 )
+{
+ if ( name.isEmpty() )
+ m_name = doc->generateFramesetName( i18n( "Formula %1" ) );
+ else
+ m_name = name;
+
+ init();
+}
+
+KWFormulaFrameSet::KWFormulaFrameSet( KWDocument* doc, const QDomElement& frameTag,
+ const QDomElement& mathTag, KoOasisContext& context )
+ : KWFrameSet( doc ), m_changed( false ), m_edit( 0 )
+{
+ m_name = frameTag.attributeNS( KoXmlNS::draw, "name", QString::null );
+ if ( doc->frameSetByName( m_name ) ) // already exists!
+ m_name = doc->generateFramesetName( m_name + " %1" );
+
+ init();
+
+ context.styleStack().save();
+ context.fillStyleStack( frameTag, KoXmlNS::draw, "style-name", "graphic" ); // get the style for the graphics element
+ /*KWFrame* frame =*/ loadOasisFrame( frameTag, context );
+ context.styleStack().restore();
+
+ formula->loadMathML( mathTag );
+}
+
+void KWFormulaFrameSet::init()
+{
+ // The newly created formula is not yet part of the formula
+ // document. It will be added when a frame is created.
+ formula = m_doc->formulaDocument()->createFormula( -1, false );
+
+ // With the new drawing scheme (drawFrame being called with translated painter)
+ // there is no need to move the KFormulaContainer anymore, it remains at (0,0).
+ formula->moveTo( 0, 0 );
+
+ connect( formula, SIGNAL( formulaChanged( double, double ) ),
+ this, SLOT( slotFormulaChanged( double, double ) ) );
+ connect( formula, SIGNAL( errorMsg( const QString& ) ),
+ this, SLOT( slotErrorMessage( const QString& ) ) );
+
+ /*
+ if ( isFloating() ) {
+ // we need to look for the anchor every time, don't cache this value.
+ // undo/redo creates/deletes anchors
+ KWAnchor * anchor = findAnchor( 0 );
+ if ( anchor ) {
+ KoTextFormat * format = anchor->format();
+ formula->setFontSize( format->pointSize() );
+ }
+ }
+ */
+ QRect rect = formula->boundingRect();
+ slotFormulaChanged(rect.width(), rect.height());
+}
+
+KWordFrameSetIface* KWFormulaFrameSet::dcopObject()
+{
+ if ( !m_dcop )
+ m_dcop = new KWordFormulaFrameSetIface( this );
+
+ return m_dcop;
+}
+
+KWFormulaFrameSet::~KWFormulaFrameSet()
+{
+ kdDebug() << k_funcinfo << endl;
+ delete formula;
+}
+
+void KWFormulaFrameSet::addFrame( KWFrame *frame, bool recalc )
+{
+ kdDebug() << k_funcinfo << endl;
+ if ( formula ) {
+ frame->setWidth( formula->width() );
+ frame->setHeight( formula->height() );
+ }
+ KWFrameSet::addFrame( frame, recalc );
+ if ( formula ) {
+ formula->registerFormula();
+ }
+}
+
+void KWFormulaFrameSet::deleteFrame( unsigned int num, bool remove, bool recalc )
+{
+ kdDebug() << k_funcinfo << endl;
+ assert( num == 0 );
+ KWFrameSet::deleteFrame( num, remove, recalc );
+ formula->unregisterFormula();
+}
+
+
+KWFrameSetEdit* KWFormulaFrameSet::createFrameSetEdit(KWCanvas* canvas)
+{
+ return new KWFormulaFrameSetEdit(this, canvas);
+}
+
+void KWFormulaFrameSet::drawFrameContents( KWFrame* /*frame*/,
+ QPainter* painter, const QRect& crect,
+ const QColorGroup& cg, bool onlyChanged,
+ bool resetChanged,
+ KWFrameSetEdit* /*edit*/, KWViewMode * )
+{
+ if ( m_changed || !onlyChanged )
+ {
+ if ( resetChanged )
+ m_changed = false;
+
+ bool printing = painter->device()->devType() == QInternal::Printer;
+ bool clipping = true;
+ QPainter *p;
+ QPixmap* pix = 0L;
+ if ( printing ) {
+ p = painter;
+ clipping = painter->hasClipping();
+
+ // That's unfortunate for formulas wider than the page.
+ // However it helps a lot with ordinary formulas.
+ painter->setClipping( false );
+ }
+ else {
+ pix = doubleBufferPixmap( crect.size() );
+ p = new QPainter( pix );
+ p->translate( -crect.x(), -crect.y() );
+ }
+
+ if ( m_edit ) {
+ //KWFormulaFrameSetEdit * formulaEdit = static_cast<KWFormulaFrameSetEdit *>(edit);
+ if ( m_edit->getFormulaView() ) {
+ m_edit->getFormulaView()->draw( *p, crect, cg );
+ }
+ else {
+ formula->draw( *p, crect, cg );
+ }
+ }
+ else {
+ formula->draw( *p, crect, cg );
+ }
+
+ if ( !printing ) {
+ p->end();
+ delete p;
+ painter->drawPixmap( crect.topLeft(), *pix );
+ }
+ else {
+ painter->setClipping( clipping );
+ }
+ }
+}
+
+
+void KWFormulaFrameSet::slotFormulaChanged( double width, double height )
+{
+ if ( m_frames.isEmpty() )
+ return;
+
+ double oldWidth = m_frames.first()->width();
+ double oldHeight = m_frames.first()->height();
+
+ m_frames.first()->setWidth( width );
+ m_frames.first()->setHeight( height );
+
+ updateFrames();
+ kWordDocument()->layout();
+ if ( ( oldWidth != width ) || ( oldHeight != height ) ) {
+ kWordDocument()->repaintAllViews( false );
+ kWordDocument()->updateRulerFrameStartEnd();
+ }
+
+ m_changed = true;
+
+ if ( !m_edit ) {
+ // A change without a FrameSetEdit! This must be the result of
+ // an undo. We need to evaluate.
+ formula->startEvaluation();
+ }
+}
+
+void KWFormulaFrameSet::slotErrorMessage( const QString& msg )
+{
+ KMessageBox::error( /*m_widget*/ 0, msg );
+}
+
+MouseMeaning KWFormulaFrameSet::getMouseMeaningInsideFrame( const KoPoint& )
+{
+ return MEANING_MOUSE_INSIDE_TEXT;
+}
+
+QDomElement KWFormulaFrameSet::save(QDomElement& parentElem, bool saveFrames)
+{
+ if ( m_frames.isEmpty() ) // Deleted frameset -> don't save
+ return QDomElement();
+ QDomElement framesetElem = parentElem.ownerDocument().createElement("FRAMESET");
+ parentElem.appendChild(framesetElem);
+
+ KWFrameSet::saveCommon(framesetElem, saveFrames);
+
+ QDomElement formulaElem = parentElem.ownerDocument().createElement("FORMULA");
+ framesetElem.appendChild(formulaElem);
+ formula->save(formulaElem);
+ return framesetElem;
+}
+
+void KWFormulaFrameSet::saveOasis(KoXmlWriter& writer, KoSavingContext& context, bool) const
+{
+ KWFrame *frame = m_frames.getFirst();
+ frame->startOasisFrame( writer, context.mainStyles(), name() );
+
+ KTempFile contentTmpFile;
+ contentTmpFile.setAutoDelete( true );
+ QFile* tmpFile = contentTmpFile.file();
+
+ QTextStream stream(tmpFile);
+ stream.setEncoding( QTextStream::UnicodeUTF8 );
+ formula->saveMathML( stream, true );
+ tmpFile->close();
+
+ writer.startElement( "draw:object" );
+ writer.startElement( "math:math" );
+ writer.addCompleteElement( tmpFile );
+ writer.endElement(); // math:math
+ writer.endElement(); // draw:object
+ writer.endElement(); // draw:frame
+}
+
+void KWFormulaFrameSet::load(QDomElement& attributes, bool loadFrames)
+{
+ KWFrameSet::load(attributes, loadFrames);
+ QDomElement formulaElem = attributes.namedItem("FORMULA").toElement();
+ paste( formulaElem );
+}
+
+void KWFormulaFrameSet::paste( QDomNode& formulaElem )
+{
+ if (!formulaElem.isNull()) {
+ if (formula == 0) {
+ formula = m_doc->formulaDocument()->createFormula( -1, false );
+ connect(formula, SIGNAL(formulaChanged(double, double)),
+ this, SLOT(slotFormulaChanged(double, double)));
+ connect( formula, SIGNAL( errorMsg( const QString& ) ),
+ this, SLOT( slotErrorMessage( const QString& ) ) );
+ }
+ m_doc->formulaDocument()->setCreationStrategy( "Oasis" );
+ if ( !formula->loadMathML( formulaElem.firstChild().toElement() ) ) {
+ kdError(32001) << "Error loading formula" << endl;
+ }
+ }
+ else {
+ kdError(32001) << "Missing math tag in FRAMESET" << endl;
+ }
+}
+
+void KWFormulaFrameSet::moveFloatingFrame( int frameNum, const KoPoint &position )
+{
+ kdDebug() << k_funcinfo << endl;
+ KWFrameSet::moveFloatingFrame( frameNum, position );
+ if ( !m_frames.isEmpty() ) {
+ formula->setDocumentPosition( position.x(), position.y()+formula->baseline() );
+ }
+}
+
+int KWFormulaFrameSet::floatingFrameBaseline( int /*frameNum*/ )
+{
+ if ( !m_frames.isEmpty() )
+ {
+ return m_doc->ptToLayoutUnitPixY( formula->baseline() );
+ }
+ return -1;
+}
+
+void KWFormulaFrameSet::setAnchorFormat( KoTextFormat* format, int /*frameNum*/ )
+{
+ if ( !m_frames.isEmpty() ) {
+ formula->setFontSizeDirect( format->pointSize() );
+ }
+}
+
+
+QPixmap* KWFormulaFrameSet::m_bufPixmap = 0;
+
+// stolen from KWDocument
+// However, I don't see if a formula frame can be an underlying
+// frame. That is why I use my own buffer.
+QPixmap* KWFormulaFrameSet::doubleBufferPixmap( const QSize& s )
+{
+ if ( !m_bufPixmap ) {
+ int w = QABS( s.width() );
+ int h = QABS( s.height() );
+ m_bufPixmap = new QPixmap( w, h );
+ } else {
+ if ( m_bufPixmap->width() < s.width() ||
+ m_bufPixmap->height() < s.height() ) {
+ m_bufPixmap->resize( QMAX( s.width(), m_bufPixmap->width() ),
+ QMAX( s.height(), m_bufPixmap->height() ) );
+ }
+ }
+
+ return m_bufPixmap;
+}
+
+
+KWFormulaFrameSetEdit::KWFormulaFrameSetEdit(KWFormulaFrameSet* fs, KWCanvas* canvas)
+ : KWFrameSetEdit(fs, canvas)
+{
+ formulaView = new KFormula::View( fs->getFormula() );
+
+ connect( formulaView, SIGNAL( cursorChanged( bool, bool ) ),
+ this, SLOT( cursorChanged( bool, bool ) ) );
+ connect( fs->getFormula(), SIGNAL( leaveFormula( Container*, FormulaCursor*, int ) ),
+ this, SLOT( slotLeaveFormula( Container*, FormulaCursor*, int ) ) );
+
+ fs->m_edit = this;
+
+ m_canvas->gui()->getView()->showFormulaToolbar(true);
+ focusInEvent();
+ dcop=0;
+}
+
+DCOPObject* KWFormulaFrameSetEdit::dcopObject()
+{
+ if ( !dcop )
+ dcop = new KWordFormulaFrameSetEditIface( this );
+ return dcop;
+}
+
+KWFormulaFrameSetEdit::~KWFormulaFrameSetEdit()
+{
+ formulaFrameSet()->m_edit = 0;
+ focusOutEvent();
+ // this causes a core dump on quit
+ m_canvas->gui()->getView()->showFormulaToolbar(false);
+ delete formulaView;
+ formulaView = 0;
+ formulaFrameSet()->getFormula()->startEvaluation();
+ formulaFrameSet()->setChanged();
+ m_canvas->repaintChanged( formulaFrameSet(), true );
+ delete dcop;
+}
+
+const KFormula::View* KWFormulaFrameSetEdit::getFormulaView() const { return formulaView; }
+KFormula::View* KWFormulaFrameSetEdit::getFormulaView() { return formulaView; }
+
+void KWFormulaFrameSetEdit::keyPressEvent( QKeyEvent* event )
+{
+ //kdDebug(32001) << "KWFormulaFrameSetEdit::keyPressEvent" << endl;
+ formulaView->keyPressEvent( event );
+}
+
+void KWFormulaFrameSetEdit::mousePressEvent( QMouseEvent* event,
+ const QPoint&,
+ const KoPoint& pos )
+{
+ // [Note that this method is called upon RMB and MMB as well, now]
+ KoPoint tl = m_currentFrame->topLeft();
+ formulaView->mousePressEvent( event, pos-tl );
+}
+
+void KWFormulaFrameSetEdit::mouseMoveEvent( QMouseEvent* event,
+ const QPoint&,
+ const KoPoint& pos )
+{
+ KoPoint tl = m_currentFrame->topLeft();
+ formulaView->mouseMoveEvent( event, pos-tl );
+}
+
+void KWFormulaFrameSetEdit::mouseReleaseEvent( QMouseEvent* event,
+ const QPoint&,
+ const KoPoint& pos )
+{
+ KoPoint tl = m_currentFrame->topLeft();
+ formulaView->mouseReleaseEvent( event, pos-tl );
+}
+
+void KWFormulaFrameSetEdit::focusInEvent()
+{
+ //kdDebug(32001) << "KWFormulaFrameSetEdit::focusInEvent" << endl;
+ if ( formulaView != 0 ) {
+ formulaView->focusInEvent(0);
+ }
+}
+
+void KWFormulaFrameSetEdit::focusOutEvent()
+{
+ //kdDebug(32001) << "KWFormulaFrameSetEdit::focusOutEvent" <<
+ //endl;
+ if ( formulaView != 0 ) {
+ formulaView->focusOutEvent(0);
+ }
+}
+
+void KWFormulaFrameSetEdit::copy()
+{
+ formulaView->getDocument()->copy();
+}
+
+void KWFormulaFrameSetEdit::cut()
+{
+ formulaView->getDocument()->cut();
+}
+
+void KWFormulaFrameSetEdit::paste()
+{
+ formulaView->getDocument()->paste();
+}
+
+void KWFormulaFrameSetEdit::pasteData( QMimeSource* /*data*/, int /*provides*/, bool )
+{
+ paste(); // TODO use data, for DnD
+}
+
+void KWFormulaFrameSetEdit::selectAll()
+{
+ formulaView->slotSelectAll();
+}
+
+void KWFormulaFrameSetEdit::moveHome()
+{
+ formulaView->moveHome( KFormula::WordMovement );
+}
+void KWFormulaFrameSetEdit::moveEnd()
+{
+ formulaView->moveEnd( KFormula::WordMovement );
+}
+
+void KWFormulaFrameSetEdit::removeFormula()
+{
+ if ( formulaFrameSet()->isFloating() ) {
+ KWCanvas* canvas = m_canvas;
+
+ // This call will destroy us! We cannot use 'this' afterwards!
+ exitRight();
+
+ QKeyEvent keyEvent( QEvent::KeyPress, Key_Backspace, 0, 0 );
+ canvas->currentFrameSetEdit()->keyPressEvent( &keyEvent );
+ }
+}
+
+void KWFormulaFrameSetEdit::cursorChanged( bool visible, bool /*selecting*/ )
+{
+ if ( visible ) {
+ if ( m_currentFrame )
+ {
+ // Add the cursor position to the (zoomed) frame position
+ QPoint nPoint = frameSet()->kWordDocument()->zoomPoint( m_currentFrame->topLeft() );
+ nPoint += formulaView->getCursorPoint();
+ // Apply viewmode conversion
+ QPoint p = m_canvas->viewMode()->normalToView( nPoint );
+ m_canvas->ensureVisible( p.x(), p.y() );
+ }
+ }
+ formulaFrameSet()->setChanged();
+ m_canvas->repaintChanged( formulaFrameSet(), true );
+}
+
+void KWFormulaFrameSetEdit::slotLeaveFormula( KFormula::Container*,
+ KFormula::FormulaCursor* cursor,
+ int cmd )
+{
+ kdDebug() << k_funcinfo << endl;
+
+ if ( cursor == formulaView->getCursor() ) {
+ switch ( cmd ) {
+ case KFormula::Container::EXIT_LEFT:
+ exitLeft();
+ break;
+ case KFormula::Container::EXIT_RIGHT:
+ exitRight();
+ break;
+ case KFormula::Container::EXIT_ABOVE:
+ exitLeft();
+ break;
+ case KFormula::Container::EXIT_BELOW:
+ exitRight();
+ break;
+ case KFormula::Container::REMOVE_FORMULA:
+ removeFormula();
+ break;
+ }
+ }
+}
+
+#include "KWFormulaFrameSet.moc"
diff --git a/kword/KWFormulaFrameSet.h b/kword/KWFormulaFrameSet.h
new file mode 100644
index 00000000..e7d64987
--- /dev/null
+++ b/kword/KWFormulaFrameSet.h
@@ -0,0 +1,177 @@
+/* This file is part of the KDE project
+ Copyright (C) 2003 Ulrich Kuettler <ulrich.kuettler@gmx.de>
+
+ This program is free software; you can redistribute it and/or
+ modify it under the terms of the GNU General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; see the file COPYING. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+*/
+
+#ifndef KWFORMULAFRAME_H
+#define KWFORMULAFRAME_H
+
+#include "KWFrameSet.h"
+#include "KWFrameSetEdit.h"
+
+class DCOPObject;
+namespace KFormula {
+ class FormulaCursor;
+ class Container;
+ class View;
+}
+
+/******************************************************************/
+/* Class: KWFormulaFrameSet */
+/******************************************************************/
+
+// needed for signals & slots ;(
+using KFormula::Container;
+using KFormula::FormulaCursor;
+using KFormula::View;
+
+class KWFormulaFrameSetEdit;
+
+class KWFormulaFrameSet : public KWFrameSet
+{
+ Q_OBJECT
+public:
+ KWFormulaFrameSet( KWDocument *doc, const QString & name );
+ /// Used for OASIS loading
+ KWFormulaFrameSet( KWDocument* doc, const QDomElement& frame,
+ const QDomElement& objectTag, KoOasisContext& context );
+ virtual ~KWFormulaFrameSet();
+
+ virtual KWordFrameSetIface* dcopObject();
+
+ /** The type of frameset. Use this to differentiate between different instantiations of
+ * the framesets. Each implementation will return a different frameType.
+ */
+ virtual FrameSetType type() const { return FT_FORMULA; }
+
+ virtual void addFrame( KWFrame *frame, bool recalc = true );
+
+ /**
+ * Delete a frame from the set of frames this frameSet has.
+ * @param num The frameNumber to be removed.
+ * @param remove passing true means that there can not be an undo of the action.
+ * @param recalc do an updateFrames()
+ */
+ virtual void deleteFrame( unsigned int num, bool remove = true, bool recalc = true );
+
+ virtual KWFrameSetEdit* createFrameSetEdit(KWCanvas*);
+
+ virtual MouseMeaning getMouseMeaningInsideFrame( const KoPoint& );
+
+ /**
+ * Paint this frameset
+ */
+ virtual void drawFrameContents(KWFrame *, QPainter*, const QRect&,
+ const QColorGroup&, bool onlyChanged, bool resetChanged,
+ KWFrameSetEdit *edit, KWViewMode *viewMode);
+
+ virtual QDomElement save( QDomElement &parentElem, bool saveFrames = true );
+ virtual void load( QDomElement &attributes, bool loadFrames = true );
+ virtual void saveOasis(KoXmlWriter&, KoSavingContext&, bool saveFrames ) const;
+ void paste( QDomNode& formulaElem );
+
+ KFormula::Container* getFormula() const { return formula; }
+
+ void setChanged() { m_changed = true; }
+
+ virtual void moveFloatingFrame( int frameNum, const KoPoint &position );
+ virtual int floatingFrameBaseline( int /*frameNum*/ );
+
+ virtual void setAnchorFormat( KoTextFormat* format, int /*frameNum*/ );
+
+
+ // TODO support for protecting the formula's contents
+ virtual void setProtectContent ( bool ) {}
+ virtual bool protectContent() const { return false; }
+
+protected slots:
+
+ void slotFormulaChanged( double width, double height );
+ void slotErrorMessage( const QString& msg );
+
+private:
+ void init();
+
+ static QPixmap* doubleBufferPixmap( const QSize& s );
+ static QPixmap* m_bufPixmap;
+
+ friend class KWFormulaFrameSetEdit;
+
+ KFormula::Container* formula;
+ bool m_changed;
+
+ KWFormulaFrameSetEdit* m_edit;
+};
+
+
+class KWFormulaFrameSetEdit : public QObject, public KWFrameSetEdit
+{
+ Q_OBJECT
+public:
+ KWFormulaFrameSetEdit(KWFormulaFrameSet* fs, KWCanvas* canvas);
+ virtual ~KWFormulaFrameSetEdit();
+
+ KWFormulaFrameSet* formulaFrameSet() const
+ {
+ return static_cast<KWFormulaFrameSet*>(frameSet());
+ }
+
+ const KFormula::View* getFormulaView() const;
+ KFormula::View* getFormulaView();
+
+ virtual DCOPObject* dcopObject();
+
+ // Events forwarded by the canvas (when being in "edit" mode)
+ virtual void keyPressEvent(QKeyEvent*);
+ virtual void mousePressEvent(QMouseEvent*, const QPoint & n, const KoPoint & d );
+ virtual void mouseMoveEvent(QMouseEvent*, const QPoint & n, const KoPoint & d); // only called if button is pressed
+ virtual void mouseReleaseEvent(QMouseEvent*, const QPoint & n, const KoPoint & d);
+ //virtual void mouseDoubleClickEvent( QMouseEvent *, const QPoint & n, const KoPoint & d ) {}
+ //virtual void dragEnterEvent( QDragEnterEvent * ) {}
+ //virtual void dragMoveEvent( QDragMoveEvent *, const QPoint &, const KoPoint & ) {}
+ //virtual void dragLeaveEvent( QDragLeaveEvent * ) {}
+ //virtual void dropEvent( QDropEvent *, const QPoint &, const KoPoint &, KWView* ) {}
+ virtual void focusInEvent();
+ virtual void focusOutEvent();
+ virtual void copy();
+ virtual void cut();
+ virtual void paste();
+ virtual void pasteData( QMimeSource* data, int provides, bool drop );
+ virtual void selectAll();
+
+ /** Moves the cursor to the first position */
+ void moveHome();
+ /** Moves the cursor to the last position */
+ void moveEnd();
+
+ void removeFormula();
+
+protected slots:
+
+ /**
+ * Make sure the cursor can be seen at its new position.
+ */
+ void cursorChanged( bool visible, bool selecting );
+
+ void slotLeaveFormula( Container*, FormulaCursor*, int );
+
+private:
+ KFormula::View* formulaView;
+ DCOPObject *dcop;
+};
+
+#endif
diff --git a/kword/KWFrame.cpp b/kword/KWFrame.cpp
new file mode 100644
index 00000000..cc31aa97
--- /dev/null
+++ b/kword/KWFrame.cpp
@@ -0,0 +1,753 @@
+/* This file is part of the KDE project
+ Copyright (C) 1998, 1999, 2000 Reginald Stadlbauer <reggie@kde.org>
+ Copyright (C) 2000-2006 David Faure <faure@kde.org>
+ Copyright (C) 2005 Thomas Zander <zander@kde.org>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+*/
+
+#include "KWFrame.h"
+#include "KWFrameSet.h"
+#include "KWFrameList.h"
+#include "KWDocument.h"
+#include "KWPageManager.h"
+#include "KWTextFrameSet.h"
+#include "KWViewMode.h"
+#include "KWCanvas.h"
+
+#include <KoOasisContext.h>
+#include <KoXmlNS.h>
+#include <KoXmlWriter.h>
+#include <KoStyleStack.h>
+
+#include <kcommand.h>
+#include <kdebug.h>
+
+#include <float.h> // for DBL_DIG
+
+//#define DEBUG_DRAW
+
+/******************************************************************/
+/* Class: ZOrderedFrameList */
+/******************************************************************/
+
+int ZOrderedFrameList::compareItems(QPtrCollection::Item a, QPtrCollection::Item b)
+{
+ int za = ((KWFrame *)a)->zOrder();
+ int zb = ((KWFrame *)b)->zOrder();
+ if (za == zb) return 0;
+ if (za < zb) return -1;
+ return 1;
+}
+
+
+/******************************************************************/
+/* Class: KWFrame */
+/******************************************************************/
+
+KWFrame::KWFrame(KWFrame * frame)
+{
+ m_runAround = RA_NO;
+ //kdDebug(32001) << "KWFrame::KWFrame this=" << this << " frame=" << frame << endl;
+ copySettings( frame );
+ m_minFrameHeight=0;
+ m_frameStack = 0; // lazy initialisation.
+}
+
+KWFrame::KWFrame(KWFrameSet *fs, double left, double top, double width, double height, RunAround ra )
+ : KoRect( left, top, width, height ),
+ // Initialize member vars here. This ensures they are all initialized, since it's
+ // easier to compare this list with the member vars list (compiler ensures order).
+ m_sheetSide( AnySide ),
+ m_runAround( ra ),
+ m_runAroundSide( RA_BIGGEST ),
+ m_frameBehavior( AutoExtendFrame ),
+ m_newFrameBehavior( ( fs && fs->type() == FT_TEXT ) ? Reconnect : NoFollowup ),
+ m_bCopy( false ),
+ m_drawFootNoteLine( false ),
+ m_runAroundLeft( 1.0 ),
+ m_runAroundRight( 1.0 ),
+ m_runAroundTop( 1.0 ),
+ m_runAroundBottom( 1.0 ),
+ m_paddingLeft( 0 ),
+ m_paddingRight( 0 ),
+ m_paddingTop( 0 ),
+ m_paddingBottom( 0 ),
+ m_minFrameHeight( 0.01 ), // not 0, since AutoExtendFrame means min-height in odt
+ m_internalY( 0 ),
+ m_zOrder( 0 ),
+ m_backgroundColor( (fs && (fs->type() == FT_PICTURE || fs->type() == FT_PART)) ? QBrush( QColor(), Qt::NoBrush) : QBrush( QColor() ) ), // valid brush with invalid color ( default )
+ m_borderLeft( QColor(), KoBorder::SOLID, 0 ),
+ m_borderRight( QColor(), KoBorder::SOLID, 0 ),
+ m_borderTop( QColor(), KoBorder::SOLID, 0 ),
+ m_borderBottom( QColor(), KoBorder::SOLID, 0 ),
+ m_frameSet( fs )
+{
+ //kdDebug(32001) << "KWFrame::KWFrame " << this << " left=" << left << " top=" << top << endl;
+ m_frameStack = 0; // lazy initialisation.
+}
+
+KWFrame::~KWFrame()
+{
+ //kdDebug(32001) << "KWFrame::~KWFrame " << this << endl;
+ delete m_frameStack;
+ m_frameStack = 0;
+}
+
+void KWFrame::setBackgroundColor( const QBrush &color )
+{
+ m_backgroundColor = color;
+}
+
+
+int KWFrame::pageNumber() const
+{
+ Q_ASSERT( m_frameSet );
+ if( !m_frameSet ) {
+ kdDebug() << k_funcinfo << this << " has no frameset!" << endl;
+ return 0;
+ }
+ if( !m_frameSet->pageManager() ) {
+ kdWarning() << k_funcinfo << this << " is not a frame that is in use; misses a pageManager!" << endl;
+ return -1;
+ }
+ return frameSet()->pageManager()->pageNumber(this);
+}
+
+int KWFrame::pageNumber( KWDocument* doc ) const
+{
+ return doc->pageManager()->pageNumber(this);
+}
+
+KWFrame *KWFrame::getCopy() {
+ /* returns a deep copy of self */
+ return new KWFrame(this);
+}
+
+void KWFrame::copySettings(KWFrame *frm)
+{
+ setFrameSet( frm->frameSet() ); // do this first in case of debug output in the methods below
+ setRect(frm->x(), frm->y(), frm->width(), frm->height());
+ // Keep order identical as member var order (and init in ctor)
+ setSheetSide(frm->sheetSide());
+ setRunAround(frm->runAround());
+ setRunAroundSide(frm->runAroundSide());
+ setFrameBehavior(frm->frameBehavior());
+ setNewFrameBehavior(frm->newFrameBehavior());
+ setRunAroundGap(frm->runAroundLeft(), frm->runAroundRight(), frm->runAroundTop(), frm->runAroundBottom());
+ setPaddingLeft(frm->paddingLeft());
+ setPaddingRight(frm->paddingRight());
+ setPaddingTop(frm->paddingTop());
+ setPaddingBottom(frm->paddingBottom());
+ setMinimumFrameHeight(frm->minimumFrameHeight());
+ m_internalY = 0; // internal Y is recalculated
+ setZOrder(frm->zOrder());
+ setCopy(frm->isCopy());
+ m_drawFootNoteLine = false; // recalculated
+ setBackgroundColor( frm->backgroundColor() );
+ setLeftBorder(frm->leftBorder());
+ setRightBorder(frm->rightBorder());
+ setTopBorder(frm->topBorder());
+ setBottomBorder(frm->bottomBorder());
+}
+
+void KWFrame::frameBordersChanged() {
+ if (frameSet()->isFloating())
+ frameSet()->anchorFrameset()->invalidate();
+}
+
+
+void KWFrame::updateRulerHandles(){
+// TODO
+#if 0
+ if(! isSelected())
+ {
+ KWDocument *doc = frameSet()->kWordDocument();
+ if(doc)
+ doc->updateRulerFrameStartEnd();
+ }
+#endif
+}
+
+QRect KWFrame::outerRect( KWViewMode* viewMode ) const
+{
+ KWDocument *doc = m_frameSet->kWordDocument();
+ QRect outerRect( doc->zoomRect( *this ) );
+ if ( viewMode && !m_frameSet->groupmanager() ) {
+ int minBorder = viewMode->drawFrameBorders() ? 1 : 0;
+ KWFrame* settingsFrame = m_frameSet->settingsFrame( this );
+ outerRect.rLeft() -= KoBorder::zoomWidthX( settingsFrame->leftBorder().width(), doc, minBorder );
+ outerRect.rTop() -= KoBorder::zoomWidthY( settingsFrame->topBorder().width(), doc, minBorder );
+ outerRect.rRight() += KoBorder::zoomWidthX( settingsFrame->rightBorder().width(), doc, minBorder );
+ outerRect.rBottom() += KoBorder::zoomWidthY( settingsFrame->bottomBorder().width(), doc, minBorder );
+ }
+ return outerRect;
+}
+
+KoRect KWFrame::outerKoRect() const
+{
+ KoRect outerRect = *this;
+ KWDocument *doc = m_frameSet->kWordDocument();
+ KWFrame* settingsFrame = m_frameSet->settingsFrame( this );
+ outerRect.rLeft() -= KoBorder::zoomWidthX( settingsFrame->leftBorder().width(), doc, 1 ) / doc->zoomedResolutionX();
+ outerRect.rTop() -= KoBorder::zoomWidthY( settingsFrame->topBorder().width(), doc, 1 ) / doc->zoomedResolutionY();
+ outerRect.rRight() += KoBorder::zoomWidthX( settingsFrame->rightBorder().width(), doc, 1 ) / doc->zoomedResolutionX();
+ outerRect.rBottom() += KoBorder::zoomWidthY( settingsFrame->bottomBorder().width(), doc, 1 ) / doc->zoomedResolutionY();
+ return outerRect;
+}
+
+KoRect KWFrame::runAroundRect() const
+{
+ KoRect raRect = outerKoRect();
+ raRect.rLeft() -= m_runAroundLeft;
+ raRect.rRight() += m_runAroundRight;
+ raRect.rTop() -= m_runAroundTop;
+ raRect.rBottom() += m_runAroundBottom;
+ return raRect;
+}
+
+void KWFrame::save( QDomElement &frameElem )
+{
+ // setAttribute( double ) uses a default precision of 6, and this seems
+ // to be 6 digits, even like '123.123' !
+ frameElem.setAttribute( "left", QString::number( left(), 'g', DBL_DIG ) );
+ frameElem.setAttribute( "top", QString::number( top(), 'g', DBL_DIG ) );
+ frameElem.setAttribute( "right", QString::number( right(), 'g', DBL_DIG ) );
+ frameElem.setAttribute( "bottom", QString::number( bottom(), 'g', DBL_DIG ) );
+ if ( minimumFrameHeight() > 0 )
+ frameElem.setAttribute( "min-height", QString::number( minimumFrameHeight(), 'g', DBL_DIG ) );
+
+ if ( !m_frameSet->isHeaderOrFooter() && !m_frameSet->isMainFrameset() )
+ {
+ if(runAround()!=RA_NO)
+ {
+ frameElem.setAttribute( "runaround", static_cast<int>( runAround() ) );
+ if (runAround() == RA_BOUNDINGRECT)
+ {
+ if (runAroundSide()==RA_LEFT)
+ frameElem.setAttribute( "runaroundSide", "left" );
+ else if (runAroundSide()==RA_RIGHT)
+ frameElem.setAttribute( "runaroundSide", "right" );
+ else
+ frameElem.setAttribute( "runaroundSide", "biggest" );
+ }
+ }
+ if(runAroundLeft()!=0 || runAroundRight()!=0 || runAroundTop()!=0 || runAroundBottom()!=0) {
+ frameElem.setAttribute( "runaroundLeft", m_runAroundLeft );
+ frameElem.setAttribute( "runaroundRight", m_runAroundRight );
+ frameElem.setAttribute( "runaroundTop", m_runAroundTop );
+ frameElem.setAttribute( "runaroundBottom", m_runAroundBottom );
+ // The old file format had only one value, keep compat
+ double runAroundGap = QMAX( QMAX( m_runAroundLeft, m_runAroundRight ), QMAX( m_runAroundTop, m_runAroundBottom ) );
+ frameElem.setAttribute( "runaroundGap", runAroundGap );
+ }
+ }
+
+ if(leftBorder().penWidth()!=0)
+ frameElem.setAttribute( "lWidth", leftBorder().penWidth() );
+
+ if(leftBorder().color.isValid())
+ {
+ frameElem.setAttribute( "lRed", leftBorder().color.red() );
+ frameElem.setAttribute( "lGreen", leftBorder().color.green() );
+ frameElem.setAttribute( "lBlue", leftBorder().color.blue() );
+ }
+ if(leftBorder().getStyle() != KoBorder::SOLID)
+ frameElem.setAttribute( "lStyle", static_cast<int>( leftBorder().getStyle()) );
+
+ if(rightBorder().penWidth()!=0)
+ frameElem.setAttribute( "rWidth", rightBorder().penWidth() );
+
+ if(rightBorder().color.isValid())
+ {
+ frameElem.setAttribute( "rRed", rightBorder().color.red() );
+ frameElem.setAttribute( "rGreen", rightBorder().color.green() );
+ frameElem.setAttribute( "rBlue", rightBorder().color.blue() );
+ }
+ if(rightBorder().getStyle() != KoBorder::SOLID)
+ frameElem.setAttribute( "rStyle", static_cast<int>( rightBorder().getStyle() ) );
+
+ if(topBorder().penWidth()!=0)
+ frameElem.setAttribute( "tWidth", topBorder().penWidth() );
+
+ if(topBorder().color.isValid())
+ {
+ frameElem.setAttribute( "tRed", topBorder().color.red() );
+ frameElem.setAttribute( "tGreen", topBorder().color.green() );
+ frameElem.setAttribute( "tBlue", topBorder().color.blue() );
+ }
+ if(topBorder().getStyle() != KoBorder::SOLID)
+ frameElem.setAttribute( "tStyle", static_cast<int>( topBorder().getStyle() ) );
+
+ if(bottomBorder().penWidth()!=0) {
+ frameElem.setAttribute( "bWidth", bottomBorder().penWidth() );
+ }
+ if(bottomBorder().color.isValid()) {
+ frameElem.setAttribute( "bRed", bottomBorder().color.red() );
+ frameElem.setAttribute( "bGreen", bottomBorder().color.green() );
+ frameElem.setAttribute( "bBlue", bottomBorder().color.blue() );
+ }
+ if(bottomBorder().getStyle() != KoBorder::SOLID)
+ frameElem.setAttribute( "bStyle", static_cast<int>( bottomBorder().getStyle() ) );
+
+ if(backgroundColor().color().isValid())
+ {
+ frameElem.setAttribute( "bkRed", backgroundColor().color().red() );
+ frameElem.setAttribute( "bkGreen", backgroundColor().color().green() );
+ frameElem.setAttribute( "bkBlue", backgroundColor().color().blue() );
+ frameElem.setAttribute( "bkStyle", (int)backgroundColor().style ());
+ }
+ if(paddingLeft() != 0)
+ frameElem.setAttribute( "bleftpt", paddingLeft() );
+
+ if(paddingRight()!=0)
+ frameElem.setAttribute( "brightpt", paddingRight() );
+
+ if(paddingTop()!=0)
+ frameElem.setAttribute( "btoppt", paddingTop() );
+
+ if(paddingBottom()!=0)
+ frameElem.setAttribute( "bbottompt", paddingBottom() );
+
+ if(frameBehavior()!=AutoCreateNewFrame)
+ frameElem.setAttribute( "autoCreateNewFrame", static_cast<int>( frameBehavior()) );
+
+ //if(newFrameBehavior()!=Reconnect) // always save this one, since the default value depends on the type of frame, etc.
+ frameElem.setAttribute( "newFrameBehavior", static_cast<int>( newFrameBehavior()) );
+
+ //same reason
+ frameElem.setAttribute( "copy", static_cast<int>( m_bCopy ) );
+
+ if(sheetSide()!= AnySide)
+ frameElem.setAttribute( "sheetSide", static_cast<int>( sheetSide()) );
+
+ frameElem.setAttribute( "z-index", zOrder() );
+}
+
+void KWFrame::load( QDomElement &frameElem, KWFrameSet* frameSet, int syntaxVersion )
+{
+ m_minFrameHeight = KWDocument::getAttribute( frameElem, "min-height", 0.0 );
+ m_runAround = static_cast<RunAround>( KWDocument::getAttribute( frameElem, "runaround", RA_NO ) );
+ QString str = frameElem.attribute( "runaroundSide" );
+ if ( str == "left" )
+ m_runAroundSide = RA_LEFT;
+ else if ( str == "right" )
+ m_runAroundSide = RA_RIGHT;
+ else
+ m_runAroundSide = RA_BIGGEST;
+
+ double runAroundGap = ( frameElem.hasAttribute( "runaroundGap" ) )
+ ? frameElem.attribute( "runaroundGap" ).toDouble()
+ : frameElem.attribute( "runaGapPT" ).toDouble();
+ setRunAroundGap( KWDocument::getAttribute( frameElem, "runaroundLeft", runAroundGap ),
+ KWDocument::getAttribute( frameElem, "runaroundRight", runAroundGap ),
+ KWDocument::getAttribute( frameElem, "runaroundTop", runAroundGap ),
+ KWDocument::getAttribute( frameElem, "runaroundBottom", runAroundGap ) );
+
+ m_sheetSide = static_cast<SheetSide>( KWDocument::getAttribute( frameElem, "sheetSide", AnySide ) );
+ m_frameBehavior = static_cast<FrameBehavior>( KWDocument::getAttribute( frameElem, "autoCreateNewFrame", AutoCreateNewFrame ) );
+ // Old documents had no "NewFrameBehavior" for footers/headers -> default to Copy.
+ NewFrameBehavior defaultValue = frameSet->isHeaderOrFooter() ? Copy : Reconnect;
+ // for old document we used the British spelling (newFrameBehaviour), so this is for backwards compatibility.
+ defaultValue = static_cast<NewFrameBehavior>( KWDocument::getAttribute( frameElem, "newFrameBehaviour", defaultValue ) );
+ m_newFrameBehavior = static_cast<NewFrameBehavior>( KWDocument::getAttribute( frameElem, "newFrameBehavior", defaultValue ) );
+ if ( frameSet->isFootEndNote() ) // note that isFootNote/isEndNote are not possible yet
+ m_newFrameBehavior = NoFollowup;
+
+ KoBorder l, r, t, b;
+ l.setPenWidth( KWDocument::getAttribute( frameElem, "lWidth", 0.0 ));
+ r.setPenWidth(KWDocument::getAttribute( frameElem, "rWidth", 0.0 ));
+ t.setPenWidth(KWDocument::getAttribute( frameElem, "tWidth", 0.0 ));
+ b.setPenWidth(KWDocument::getAttribute( frameElem, "bWidth", 0.0 ));
+ if ( frameElem.hasAttribute("lRed") )
+ l.color.setRgb(
+ KWDocument::getAttribute( frameElem, "lRed", 0 ),
+ KWDocument::getAttribute( frameElem, "lGreen", 0 ),
+ KWDocument::getAttribute( frameElem, "lBlue", 0 ) );
+ if ( frameElem.hasAttribute("rRed") )
+ r.color.setRgb(
+ KWDocument::getAttribute( frameElem, "rRed", 0 ),
+ KWDocument::getAttribute( frameElem, "rGreen", 0 ),
+ KWDocument::getAttribute( frameElem, "rBlue", 0 ) );
+ if ( frameElem.hasAttribute("tRed") )
+ t.color.setRgb(
+ KWDocument::getAttribute( frameElem, "tRed", 0 ),
+ KWDocument::getAttribute( frameElem, "tGreen", 0 ),
+ KWDocument::getAttribute( frameElem, "tBlue", 0 ) );
+ if ( frameElem.hasAttribute("bRed") )
+ b.color.setRgb(
+ KWDocument::getAttribute( frameElem, "bRed", 0 ),
+ KWDocument::getAttribute( frameElem, "bGreen", 0 ),
+ KWDocument::getAttribute( frameElem, "bBlue", 0 ) );
+ l.setStyle(static_cast<KoBorder::BorderStyle>( KWDocument::getAttribute( frameElem, "lStyle", KoBorder::SOLID ) ));
+ r.setStyle(static_cast<KoBorder::BorderStyle>( KWDocument::getAttribute( frameElem, "rStyle", KoBorder::SOLID ) ));
+ t.setStyle(static_cast<KoBorder::BorderStyle>( KWDocument::getAttribute( frameElem, "tStyle", KoBorder::SOLID ) ));
+ b.setStyle( static_cast<KoBorder::BorderStyle>( KWDocument::getAttribute( frameElem, "bStyle", KoBorder::SOLID ) ));
+ QColor c;
+ if ( frameElem.hasAttribute("bkRed") )
+ c.setRgb(
+ KWDocument::getAttribute( frameElem, "bkRed", 0 ),
+ KWDocument::getAttribute( frameElem, "bkGreen", 0 ),
+ KWDocument::getAttribute( frameElem, "bkBlue", 0 ) );
+
+ if ( syntaxVersion < 2 ) // Activate old "white border == no border" conversion
+ {
+ if(c==l.color && l.penWidth()==1 && l.getStyle()==0 )
+ l.setPenWidth(0);
+ if(c==r.color && r.penWidth()==1 && r.getStyle()==0)
+ r.setPenWidth(0);
+ if(c==t.color && t.penWidth()==1 && t.getStyle()==0 )
+ t.setPenWidth(0);
+ if(c==b.color && b.penWidth()==1 && b.getStyle()==0 )
+ b.setPenWidth(0);
+ }
+ m_borderLeft = l;
+ m_borderRight = r;
+ m_borderTop = t;
+ m_borderBottom = b;
+ m_backgroundColor = QBrush( c );
+
+
+ if( frameElem.hasAttribute("bkStyle"))
+ m_backgroundColor.setStyle (static_cast<Qt::BrushStyle>(KWDocument::getAttribute( frameElem, "bkStyle", Qt::SolidPattern )));
+
+ m_paddingLeft = frameElem.attribute( "bleftpt" ).toDouble();
+ m_paddingRight = frameElem.attribute( "brightpt" ).toDouble();
+ m_paddingTop = frameElem.attribute( "btoppt" ).toDouble();
+ m_paddingBottom = frameElem.attribute( "bbottompt" ).toDouble();
+ m_bCopy = KWDocument::getAttribute( frameElem, "copy", frameSet->isHeaderOrFooter() /* default to true for h/f */ );
+ m_zOrder = frameElem.attribute( "z-index" ).toInt();
+}
+
+// This is shared with table cells - so, no runaround and newframebehavior etc.
+// Only background, borders, padding.
+void KWFrame::loadBorderProperties( KoStyleStack& styleStack )
+{
+ // padding. fo:padding for 4 values or padding-left/right/top/bottom
+ m_paddingLeft = KoUnit::parseValue( styleStack.attributeNS( KoXmlNS::fo, "padding", "left" ) );
+ m_paddingRight = KoUnit::parseValue( styleStack.attributeNS( KoXmlNS::fo, "padding", "right" ) );
+ m_paddingTop = KoUnit::parseValue( styleStack.attributeNS( KoXmlNS::fo, "padding", "top" ) );
+ m_paddingBottom = KoUnit::parseValue( styleStack.attributeNS( KoXmlNS::fo, "padding", "bottom" ) );
+
+ // background color
+ if ( styleStack.hasAttributeNS( KoXmlNS::fo, "background-color" ) ) {
+ QString color = styleStack.attributeNS( KoXmlNS::fo, "background-color" );
+ if ( color == "transparent" )
+ m_backgroundColor = QBrush( QColor(), Qt::NoBrush );
+ else
+ {
+ m_backgroundColor = QBrush( QColor( color ) /*, brush style is a dead feature, ignored */ );
+ }
+ }
+ // OOo compatibility: it uses background-transparency=100% instead of background-color="transparent"
+ if ( styleStack.hasAttributeNS( KoXmlNS::fo, "background-transparency" ) ) {
+ QString transp = styleStack.attributeNS( KoXmlNS::fo, "background-transparency" );
+ if ( transp == "100%" )
+ m_backgroundColor.setStyle( Qt::NoBrush );
+ }
+
+ // borders (3.11.27)
+ // can be none/hidden, solid and double. General form is the XSL/FO "width|style|color"
+ {
+ m_borderLeft.loadFoBorder( styleStack.attributeNS( KoXmlNS::fo, "border", "left") );
+ m_borderRight.loadFoBorder( styleStack.attributeNS( KoXmlNS::fo, "border", "right") );
+ m_borderTop.loadFoBorder( styleStack.attributeNS( KoXmlNS::fo, "border", "top") );
+ m_borderBottom.loadFoBorder( styleStack.attributeNS( KoXmlNS::fo, "border", "bottom") );
+ }
+ // TODO more refined border spec for double borders (3.11.28)
+}
+
+void KWFrame::loadCommonOasisProperties( KoOasisContext& context, KWFrameSet* frameSet, const char* typeProperties )
+{
+ KoStyleStack& styleStack = context.styleStack();
+ styleStack.setTypeProperties( typeProperties );
+
+ loadBorderProperties( styleStack );
+
+ // Background color is now done with fill-color.
+ // loadBorderProperties loads fo:background-color for compatibility (and for table cells),
+ // but the correct way for text boxes is draw:fill-color
+ if ( styleStack.hasAttributeNS( KoXmlNS::draw, "fill-color" ) ) {
+ QString color = styleStack.attributeNS( KoXmlNS::draw, "fill-color" );
+ if ( color == "transparent" )
+ m_backgroundColor = QBrush( QColor(), Qt::NoBrush );
+ else
+ {
+ m_backgroundColor = QBrush( QColor( color ) /*, brush style is a dead feature, ignored */ );
+ }
+ }
+
+#if 0 // not allowed in the current OASIS spec
+ // margins, i.e. runAroundGap. fo:margin for 4 values or padding-left/right/top/bottom
+ m_runAroundLeft = KoUnit::parseValue( styleStack.attributeNS( KoXmlNS::fo, "margin", "left" ) );
+ m_runAroundRight = KoUnit::parseValue( styleStack.attributeNS( KoXmlNS::fo, "margin", "right" ) );
+ m_runAroundTop = KoUnit::parseValue( styleStack.attributeNS( KoXmlNS::fo, "margin", "top" ) );
+ m_runAroundBottom = KoUnit::parseValue( styleStack.attributeNS( KoXmlNS::fo, "margin", "bottom" ) );
+#endif
+ // margins, i.e. runAroundGap. fo:margin-left/right/top/bottom
+ m_runAroundLeft = KoUnit::parseValue( styleStack.attributeNS( KoXmlNS::fo, "margin-left" ) );
+ m_runAroundRight = KoUnit::parseValue( styleStack.attributeNS( KoXmlNS::fo, "margin-right" ) );
+ m_runAroundTop = KoUnit::parseValue( styleStack.attributeNS( KoXmlNS::fo, "margin-top" ) );
+ m_runAroundBottom = KoUnit::parseValue( styleStack.attributeNS( KoXmlNS::fo, "margin-bottom" ) );
+
+ // This attribute isn't part of the OASIS spec. Doesn't matter since it doesn't affect rendering
+ // of existing documents, only editing (and only KWord has this kind of option until now).
+ const QCString frameBehaviorOnNewPage = styleStack.attributeNS( KoXmlNS::koffice, "frame-behavior-on-new-page" ).latin1();
+ if ( frameBehaviorOnNewPage == "followup" )
+ m_newFrameBehavior = Reconnect;
+ else if ( frameBehaviorOnNewPage == "copy" )
+ m_newFrameBehavior = Copy;
+ else if ( frameBehaviorOnNewPage == "none" )
+ m_newFrameBehavior = NoFollowup;
+ else { // Defaults for OASIS documents not created by KWord
+ m_newFrameBehavior = frameSet->isHeaderOrFooter() ? Copy : NoFollowup;
+ if ( !frameBehaviorOnNewPage.isEmpty() )
+ kdWarning(32001) << "Unknown value for koffice:frame-behavior-on-new-page: " << frameBehaviorOnNewPage << endl;
+ }
+ // Footnotes and endnotes are handled in a special way.
+ if ( frameSet->isFootEndNote() ) // note that isFootNote/isEndNote are not possible yet
+ m_newFrameBehavior = NoFollowup;
+
+ KWFrame::RunAround runAround = KWFrame::RA_BOUNDINGRECT;
+ KWFrame::RunAroundSide runAroundSide = KWFrame::RA_BIGGEST;
+ const QCString oowrap = styleStack.attributeNS( KoXmlNS::style, "wrap" ).latin1();
+ if ( oowrap == "none" ) // 'no wrap' means 'avoid horizontal space'
+ runAround = KWFrame::RA_SKIP;
+ else if ( oowrap == "left" )
+ runAroundSide = KWFrame::RA_LEFT;
+ else if ( oowrap == "right" )
+ runAroundSide= KWFrame::RA_RIGHT;
+ else if ( oowrap == "run-through" )
+ runAround = KWFrame::RA_NO;
+ //if ( oowrap == "biggest" ) // OASIS extension
+ // ->( KWFrame::RA_BOUNDINGRECT, KWFrame::RA_BIGGEST ), already set above
+ //if ( oowrap == "parallel" || oowrap == "dynamic" )
+ // dynamic is called "optimal" in the OO GUI. It's different from biggest because it can lead to parallel.
+ // Those are not supported in KWord, let's use biggest instead
+ setRunAround( runAround );
+ setRunAroundSide( runAroundSide );
+}
+
+void KWFrame::startOasisFrame( KoXmlWriter &writer, KoGenStyles& mainStyles, const QString& name, const QString& lastFrameName ) const
+{
+ writer.startElement( "draw:frame" );
+ writer.addAttribute( "draw:name", name );
+ writer.addAttribute( "draw:style-name", saveOasisFrameStyle( mainStyles ) );
+
+ if ( !frameSet()->isFloating() )
+ { // non-inline frame, anchored to page
+ const int pgNum = pageNumber();
+ const double yInPage = top() - frameSet()->pageManager()->topOfPage(pgNum);
+ writer.addAttributePt( "svg:x", left() );
+ writer.addAttributePt( "svg:y", yInPage );
+ writer.addAttribute( "text:anchor-type", "page" );
+ writer.addAttribute( "text:anchor-page-number", pgNum );
+ writer.addAttribute( "draw:z-index", zOrder() );
+ }
+ writer.addAttributePt( "svg:width", width() );
+ writer.addAttributePt( "svg:height", height() );
+ if ( isCopy() )
+ writer.addAttribute( "draw:copy-of", lastFrameName );
+}
+
+// shared between startOasisFrame and table cells.
+// Only background, borders, padding.
+void KWFrame::saveBorderProperties( KoGenStyle& frameStyle ) const
+{
+ // Background: color and transparency
+ // OOo seems to use style:background-transparency="100%", but the schema allows background-color=transparent
+ if ( m_backgroundColor.style() == Qt::NoBrush )
+ frameStyle.addProperty( "fo:background-color", "transparent" );
+ else if ( m_backgroundColor.color().isValid() )
+ frameStyle.addProperty( "fo:background-color", m_backgroundColor.color().name() );
+
+ // Borders
+ if ( ( m_borderLeft == m_borderRight )
+ && ( m_borderLeft == m_borderTop )
+ && ( m_borderLeft == m_borderBottom ) )
+ {
+ frameStyle.addProperty( "fo:border", m_borderLeft.saveFoBorder() );
+ }
+ else
+ {
+ frameStyle.addProperty( "fo:border-left", m_borderLeft.saveFoBorder() );
+ frameStyle.addProperty( "fo:border-right", m_borderRight.saveFoBorder() );
+ frameStyle.addProperty( "fo:border-top", m_borderTop.saveFoBorder() );
+ frameStyle.addProperty( "fo:border-bottom", m_borderBottom.saveFoBorder() );
+ }
+
+ if ( m_paddingLeft != 0 && ( ( m_paddingLeft == m_paddingRight )
+ && ( m_paddingLeft == m_paddingTop )
+ && ( m_paddingLeft == m_paddingBottom ) ) )
+ frameStyle.addPropertyPt( "fo:padding", m_paddingLeft );
+ else
+ {
+ if ( m_paddingLeft != 0 )
+ frameStyle.addPropertyPt( "fo:padding-left", m_paddingLeft );
+ if ( m_paddingRight != 0 )
+ frameStyle.addPropertyPt( "fo:padding-right", m_paddingRight );
+ if ( m_paddingTop != 0 )
+ frameStyle.addPropertyPt( "fo:padding-top", m_paddingTop );
+ if ( m_paddingBottom != 0 )
+ frameStyle.addPropertyPt( "fo:padding-bottom", m_paddingBottom );
+ }
+}
+
+void KWFrame::saveMarginAttributes( KoXmlWriter &writer ) const
+{
+ if ( m_runAroundLeft != 0 )
+ writer.addAttributePt( "fo:margin-left", m_runAroundLeft );
+ if ( m_runAroundRight != 0 )
+ writer.addAttributePt( "fo:margin-right", m_runAroundRight );
+ if ( m_runAroundTop != 0 )
+ writer.addAttributePt( "fo:margin-top", m_runAroundTop );
+ if ( m_runAroundBottom != 0 )
+ writer.addAttributePt( "fo:margin-bottom", m_runAroundBottom );
+}
+
+void KWFrame::saveMarginProperties( KoGenStyle& frameStyle ) const
+{
+#if 0 // not allowed in the current OASIS spec
+ if ( m_runAroundLeft != 0 && ( ( m_runAroundLeft == m_runAroundRight )
+ && ( m_runAroundLeft == m_runAroundTop )
+ && ( m_runAroundLeft == m_runAroundBottom ) ) )
+ frameStyle.addPropertyPt( "fo:margin", m_runAroundLeft );
+ else
+ {
+#endif
+ if ( m_runAroundLeft != 0 )
+ frameStyle.addPropertyPt( "fo:margin-left", m_runAroundLeft );
+ if ( m_runAroundRight != 0 )
+ frameStyle.addPropertyPt( "fo:margin-right", m_runAroundRight );
+ if ( m_runAroundTop != 0 )
+ frameStyle.addPropertyPt( "fo:margin-top", m_runAroundTop );
+ if ( m_runAroundBottom != 0 )
+ frameStyle.addPropertyPt( "fo:margin-bottom", m_runAroundBottom );
+#if 0 // not allowed in the current OASIS spec
+ }
+#endif
+}
+
+QString KWFrame::saveOasisFrameStyle( KoGenStyles& mainStyles ) const
+{
+ KoGenStyle frameStyle( KWDocument::STYLE_FRAME_AUTO, "graphic" );
+ QString protect;
+ if ( frameSet()->protectContent() )
+ protect = "content";
+ if ( frameSet()->isProtectSize() ) // ## should be moved for frame
+ {
+ if ( !protect.isEmpty() )
+ protect+=" ";
+ protect+="size";
+ }
+ if ( !protect.isEmpty() )
+ frameStyle.addProperty( "style:protect", protect );
+
+ if ( !frameSet()->isFloating() )
+ { // non-inline frame, anchored to page
+ frameStyle.addProperty( "style:horizontal-rel", "page" );
+ frameStyle.addProperty( "style:vertical-rel", "page" );
+ frameStyle.addProperty( "style:horizontal-pos", "from-left" );
+ frameStyle.addProperty( "style:vertical-pos", "from-top" );
+ }
+
+ // Background (KWFrame::saveBorderProperties saves as fo:background-color, but OOo-2.0.x uses draw:fill-color)
+ // So now we use draw:fill-color too, the text background color is in fact a paragraph feature.
+ if ( m_backgroundColor.style() == Qt::NoBrush )
+ frameStyle.addProperty( "draw:fill-color", "transparent" );
+ else if ( m_backgroundColor.color().isValid() )
+ frameStyle.addProperty( "draw:fill-color", m_backgroundColor.color().name() );
+
+ saveBorderProperties( frameStyle );
+ saveMarginProperties( frameStyle );
+
+ if ( runAround() == KWFrame::RA_SKIP )
+ frameStyle.addProperty( "style:wrap", "none" );
+ else if ( runAround() == KWFrame::RA_NO )
+ frameStyle.addProperty( "style:wrap", "run-through" );
+ else // RA_BOUNDINGRECT
+ {
+ if ( runAroundSide() == KWFrame::RA_LEFT )
+ frameStyle.addProperty( "style:wrap", "left" );
+ else if ( runAroundSide() == KWFrame::RA_RIGHT )
+ frameStyle.addProperty( "style:wrap", "right" );
+ else if ( runAroundSide() == KWFrame::RA_BIGGEST )
+ frameStyle.addProperty( "style:wrap", "biggest" );
+ }
+
+ // This attribute isn't part of the OASIS spec. Doesn't matter since it doesn't affect rendering
+ // of existing documents, only editing (and only KWord has this kind of option until now).
+ NewFrameBehavior defaultNfb = frameSet()->isHeaderOrFooter() ? Copy : NoFollowup;
+ if ( m_newFrameBehavior != defaultNfb ) {
+ const char* value = "none";
+ if ( m_newFrameBehavior == Reconnect )
+ value = "followup";
+ else if ( m_newFrameBehavior == Copy )
+ value = "copy";
+ else if ( m_newFrameBehavior == NoFollowup )
+ value = "none";
+ frameStyle.addProperty( "koffice:frame-behavior-on-new-page", value );
+ }
+
+ // The loading code for this one is in kwtextframeset, maybe this should be moved there too
+ const char* frameBehav = 0;
+ if ( m_frameBehavior == KWFrame::Ignore )
+ frameBehav = "clip";
+ else if ( m_frameBehavior == KWFrame::AutoCreateNewFrame )
+ frameBehav = "auto-create-new-frame";
+ // the third case, AutoExtendFrame is handled by min-height
+ if ( frameBehav )
+ frameStyle.addProperty( "style:overflow-behavior", frameBehav );
+
+ return mainStyles.lookup( frameStyle, "fr" );
+}
+
+bool KWFrame::frameAtPos( const QPoint& point, bool borderOfFrameOnly) const {
+ // Forwarded to KWFrameSet to make it virtual
+ return frameSet()->isFrameAtPos( this, point, borderOfFrameOnly );
+}
+
+KoRect KWFrame::innerRect() const
+{
+ KoRect inner( this->normalize());
+ inner.moveBy( paddingLeft(), paddingTop() );
+ inner.setWidth( innerWidth() );
+ inner.setHeight( innerHeight() );
+ return inner;
+}
+
+double KWFrame::innerWidth() const
+{
+ return KMAX( 0.0, width() - m_paddingLeft - m_paddingRight );
+}
+
+double KWFrame::innerHeight() const
+{
+ return KMAX( 0.0, height() - m_paddingTop - m_paddingBottom );
+}
+
+void KWFrame::setFramePadding( double left, double top, double right, double bottom)
+{
+ m_paddingLeft = left;
+ m_paddingTop = top;
+ m_paddingRight = right;
+ m_paddingBottom = bottom;
+}
+
+bool KWFrame::compareFrameZOrder(KWFrame *f1, KWFrame *f2)
+{
+ return f1->zOrder() < f2->zOrder();
+}
diff --git a/kword/KWFrame.h b/kword/KWFrame.h
new file mode 100644
index 00000000..37a3ff25
--- /dev/null
+++ b/kword/KWFrame.h
@@ -0,0 +1,335 @@
+/* This file is part of the KDE project
+ Copyright (C) 1998, 1999, 2000 Reginald Stadlbauer <reggie@kde.org>
+ Copyright (C) 2000-2006 David Faure <faure@kde.org>
+ Copyright (C) 2005 Thomas Zander <zander@kde.org>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+*/
+
+#ifndef frame_h
+#define frame_h
+
+#include "defs.h"
+#include <KoRect.h>
+#include <qbrush.h>
+#include "KoBorder.h"
+#include <qptrlist.h>
+
+class KWCanvas;
+class KWDocument;
+class KWFrame;
+class KWFrameList;
+class KWFrameSet;
+class KWViewMode;
+
+class KoGenStyle;
+class KoGenStyles;
+class KoOasisContext;
+class KoStyleStack;
+class KoXmlWriter;
+
+class QDomElement;
+
+/**
+ * small utility class representing a sortable (by z-order) list of frames
+ * you can use sort() and inSort(item)
+ *
+ * Deprecated, use QValueVector<KWFrame*> from now on, and sort it with
+ * std::sort(frames.begin(),frames.end(),KWFrame::compareFrameZOrder);
+ *
+ * With Qt4 we'll be able to use qSort for lists.
+ */
+class ZOrderedFrameList : public QPtrList<KWFrame>
+{
+protected:
+ virtual int compareItems(QPtrCollection::Item a, QPtrCollection::Item b);
+};
+
+
+/**
+ * This class represents a single frame.
+ * A frame belongs to a frameset which states its contents.
+ * A frame does NOT have contents, the frameset stores that.
+ * A frame is really just a square that is used to place the content
+ * of a frameset.
+ */
+class KWFrame : public KoRect
+{
+public:
+ /** Runaround types
+ * RA_NO = No run around, all text is just printed.
+ * RA_BOUNDINGRECT = run around the square of this frame.
+ * RA_SKIP = stop running text on the whole horizontal space this frame occupies.
+ */
+ enum RunAround { RA_NO = 0, RA_BOUNDINGRECT = 1, RA_SKIP = 2 };
+
+ /** Runaround side - only meaningful when RA_BOUNDINGRECT is used
+ */
+ enum RunAroundSide { RA_BIGGEST = 0, RA_LEFT = 1, RA_RIGHT = 2 };
+
+ /**
+ * Constructor
+ * @param fs parent frameset
+ * @param left, top, width, height coordinates of the frame
+ * The page number will be automatically determined from the position of the frame.
+ * @param ra the "runaround" setting, i.e. whether text should flow below the frame,
+ * around the frame, or avoiding the frame on the whole horizontal band.
+ */
+ KWFrame(KWFrameSet *fs, double left, double top, double width, double height,
+ RunAround ra = RA_BOUNDINGRECT);
+ KWFrame(KWFrame * frame);
+ /** Destructor
+ */
+ virtual ~KWFrame();
+
+ double runAroundLeft() const { return m_runAroundLeft; }
+ double runAroundRight() const { return m_runAroundRight; }
+ double runAroundTop() const { return m_runAroundTop; }
+ double runAroundBottom() const { return m_runAroundBottom; }
+
+ void setRunAroundGap( double left, double right, double top, double bottom ) {
+ m_runAroundLeft = left;
+ m_runAroundRight = right;
+ m_runAroundTop = top;
+ m_runAroundBottom = bottom;
+ }
+
+ RunAround runAround()const { return m_runAround; }
+ void setRunAround( RunAround _ra ) { m_runAround = _ra; }
+
+ RunAroundSide runAroundSide() const { return m_runAroundSide; }
+ void setRunAroundSide( RunAroundSide rs ) { m_runAroundSide = rs; }
+
+ /** what should happen when the frame is full
+ */
+ enum FrameBehavior { AutoExtendFrame=0 , AutoCreateNewFrame=1, Ignore=2 };
+
+ FrameBehavior frameBehavior()const { return m_frameBehavior; }
+ void setFrameBehavior( FrameBehavior fb ) { m_frameBehavior = fb; }
+
+ /* Frame duplication properties */
+
+ /** This frame will only be copied to:
+ * AnySide, OddSide or EvenSide
+ */
+ enum SheetSide { AnySide=0, OddSide=1, EvenSide=2};
+ SheetSide sheetSide()const { return m_sheetSide; }
+ void setSheetSide( SheetSide ss ) { m_sheetSide = ss; }
+
+ /** What happens on new page
+ * (create a new frame and reconnect, no followup, make copy) */
+ enum NewFrameBehavior { Reconnect=0, NoFollowup=1, Copy=2 };
+ NewFrameBehavior newFrameBehavior()const { return m_newFrameBehavior; }
+ void setNewFrameBehavior( NewFrameBehavior nfb ) { m_newFrameBehavior = nfb; }
+
+ /** Drawing property: if isCopy, this frame is a copy of the previous frame in the frameset
+ */
+ bool isCopy()const { return m_bCopy; }
+ void setCopy( bool copy ) { m_bCopy = copy; }
+
+ /** Data stucture methods
+ */
+ KWFrameSet *frameSet() const { return m_frameSet; }
+ void setFrameSet( KWFrameSet *fs ) { m_frameSet = fs; }
+
+ /** The page on which this frame is
+ */
+ int pageNumber() const;
+ /** Same as pageNumber(), but works if the frame hasn't been added to a frameset yet
+ */
+ int pageNumber( KWDocument* doc ) const;
+
+ /** The z-order of the frame, relative to the other frames on the same page
+ */
+ void setZOrder( int z ) { m_zOrder = z; }
+ int zOrder() const { return m_zOrder; }
+
+ /**
+ * This is a method used to sort a list using the STL sorting methods.
+ * @param f1 the first object
+ * @param f2 the second object
+ */
+ static bool compareFrameZOrder(KWFrame *f1, KWFrame *f2);
+
+ KWFrameList* frameStack() { return m_frameStack; }
+ void setFrameStack(KWFrameList *fl) { m_frameStack = fl; }
+
+ /** All borders can be custom drawn with their own colors etc.
+ */
+ const KoBorder &leftBorder() const { return m_borderLeft; }
+ const KoBorder &rightBorder() const { return m_borderRight; }
+ const KoBorder &topBorder() const { return m_borderTop; }
+ const KoBorder &bottomBorder() const { return m_borderBottom; }
+
+
+ void setLeftBorder( KoBorder _brd ) { m_borderLeft = _brd; }
+ void setRightBorder( KoBorder _brd ) { m_borderRight = _brd; }
+ void setTopBorder( KoBorder _brd ) { m_borderTop = _brd; }
+ void setBottomBorder( KoBorder _brd ) { m_borderBottom = _brd; }
+
+ /** Return the _zoomed_ rectangle for this frame, including the border - for drawing
+ * @param viewMode needed to know if borders are visible or not
+ */
+ QRect outerRect( KWViewMode* viewMode ) const;
+
+ /** Return the unzoomed rectangle, including the border, for the frames-on-top list.
+ * The default border of size 1-pixel that is drawn on screen is _not_ included here
+ * [since it depends on the zoom]
+ */
+ KoRect outerKoRect() const;
+
+ /** Return the rectangle for this frame including the border and the runaround gap.
+ * This is the rectangle that the surrounding text must run around.
+ */
+ KoRect runAroundRect() const;
+
+ /** Return the rectangle for this frame.
+ * This method is just so that new code doesn't rely on "KWFrame inherits KoRect",
+ * which would be good to get rid of, at some point.
+ */
+ const KoRect& rect() const { return *this; }
+
+ /** Marks a frame to have changed position/borders.
+ Make sure you call this when the frame borders changed so when its inline it will be moved.
+ */
+ void frameBordersChanged();
+ void updateRulerHandles();
+
+ QBrush backgroundColor() const { return m_backgroundColor; }
+ void setBackgroundColor( const QBrush &_color );
+ bool isTransparent() const { return m_backgroundColor.style() != Qt::SolidPattern; }
+
+ KoRect innerRect() const;
+
+ double innerWidth() const;
+ double innerHeight() const;
+
+
+ /** The "internal Y" is the offset (in pt) of the real frame showed in this one
+ * ("real" means "the last that isn't a copy")
+ * This offset in pt is the sum of the height of the frames before that one.
+ * For text frames, this is equivalent to the layout units (after multiplication). */
+ void setInternalY( double y ) { m_internalY = y; }
+ double internalY() const { return m_internalY; }
+
+ /// set left padding (distance between frame contents and frame border)
+ void setPaddingLeft( double b ) { m_paddingLeft = b; }
+ /// set right padding
+ void setPaddingRight( double b ) { m_paddingRight = b; }
+ /// set top padding
+ void setPaddingTop( double b ) { m_paddingTop = b; }
+ /// set bottom padding
+ void setPaddingBottom( double b ) { m_paddingBottom = b; }
+
+ /// get left padding
+ double paddingLeft() const { return m_paddingLeft; }
+ /// get right padding
+ double paddingRight() const { return m_paddingRight; }
+ /// get top padding
+ double paddingTop() const { return m_paddingTop; }
+ /// get bottom padding
+ double paddingBottom() const { return m_paddingBottom; }
+
+ void setFramePadding( double _left, double _top, double right, double bottom);
+ /** returns a copy of self
+ */
+ KWFrame *getCopy();
+
+ void copySettings(KWFrame *frm);
+
+ /** create XML to describe yourself
+ */
+ void save( QDomElement &frameElem );
+ /** read attributes from XML. @p headerOrFooter if true some defaults are different
+ */
+ void load( QDomElement &frameElem, KWFrameSet* frameSet, int syntaxVersion );
+ void loadCommonOasisProperties( KoOasisContext& context, KWFrameSet* frameSet, const char* typeProperties );
+ void loadBorderProperties( KoStyleStack& styleStack );
+
+ QString saveOasisFrameStyle( KoGenStyles& mainStyles ) const;
+ /**
+ * Write out a draw:frame element and its style.
+ * The caller is responsible for creating the child element and closing the draw:frame element.
+ * @p lastFrameName is the name of the previous frame in the same frameset; this is only used for copy-frames
+ */
+ void startOasisFrame( KoXmlWriter &xmlWriter, KoGenStyles& mainStyles, const QString& name,
+ const QString& lastFrameName = QString::null ) const;
+ void saveBorderProperties( KoGenStyle& frameStyle ) const;
+ void saveMarginProperties( KoGenStyle& frameStyle ) const;
+ void saveMarginAttributes( KoXmlWriter &writer ) const;
+
+ /**
+ * The property minimum frame height is used to make the automatic frame shrinking code stop.
+ * Each frame has a height based on its frame dimentions, but changes in content may change
+ * the sizes automatically. If all text is removed from a text frame it will grow smaller
+ * until the minimum frame height is reached, and it will not shrink below that.
+ * @param h the new minimum height
+ */
+ void setMinimumFrameHeight(double h) { m_minFrameHeight = h; }
+ /**
+ * @return the minimum frame height.
+ * @see setMinimumFrameHeight() for details.
+ */
+ double minimumFrameHeight(void)const {return m_minFrameHeight;}
+
+ /** Return if the point is on the frame.
+ @param nPoint the point in normal coordinates.
+ @param borderOfFrameOnly when true an additional check is done if the point
+ is on the border. */
+ bool frameAtPos( const QPoint& nPoint, bool borderOfFrameOnly=false ) const;
+
+ /**
+ * Only applicable to frames of the main text frameset.
+ * Set to true by KWFrameLayout if the "footnote line" should be
+ * drawn under this frame.
+ */
+ void setDrawFootNoteLine( bool b ) { m_drawFootNoteLine = b; }
+ bool drawFootNoteLine()const { return m_drawFootNoteLine; }
+
+private:
+ SheetSide m_sheetSide : 2;
+ RunAround m_runAround : 2;
+ RunAroundSide m_runAroundSide : 2;
+ FrameBehavior m_frameBehavior : 2;
+ NewFrameBehavior m_newFrameBehavior : 2;
+ bool m_bCopy;
+ bool m_drawFootNoteLine;
+
+ double m_runAroundLeft, m_runAroundRight, m_runAroundTop, m_runAroundBottom;
+ double m_paddingLeft, m_paddingRight, m_paddingTop, m_paddingBottom;
+ double m_minFrameHeight;
+
+ double m_internalY;
+ int m_zOrder;
+
+ QBrush m_backgroundColor;
+ KoBorder m_borderLeft, m_borderRight, m_borderTop, m_borderBottom;
+
+ /** List of frames we have below and on top of us.
+ * Frames on top we should never overwrite. Frames below us needd for selection code &
+ * transparancy */
+ KWFrameList *m_frameStack;
+ KWFrameSet *m_frameSet;
+
+ /** Prevent operator=
+ */
+ KWFrame &operator=( const KWFrame &_frame );
+ /** Prevent copy constructor
+ */
+ KWFrame ( const KWFrame &_frame );
+};
+
+#endif
diff --git a/kword/KWFrameDia.cpp b/kword/KWFrameDia.cpp
new file mode 100644
index 00000000..0e4a2e98
--- /dev/null
+++ b/kword/KWFrameDia.cpp
@@ -0,0 +1,2490 @@
+/* This file is part of the KDE project
+ Copyright (C) 1998, 1999 Reginald Stadlbauer <reggie@kde.org>
+ Copyright (C) 2005 Thomas Zander <zander@kde.org>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+*/
+
+#include "KWFrameDia.h"
+#include "KWTextFrameSet.h"
+#include "KWDocument.h"
+#include "KWFrameDia.moc"
+#include "KWCommand.h"
+#include "KWTableFrameSet.h"
+#include "KWPageManager.h"
+#include "KWPage.h"
+#include "KWPictureFrameSet.h"
+
+#include <KoSetPropCommand.h>
+#include <KoParagDia_p.h> // for KoBorderPreview
+
+#include <knuminput.h>
+#include <klocale.h>
+#include <kiconloader.h>
+#include <kmessagebox.h>
+#include <knumvalidator.h>
+#include <kcolorbutton.h>
+#include <kdebug.h>
+
+#include <qwhatsthis.h>
+#include <qlineedit.h>
+#include <qcheckbox.h>
+#include <qcombobox.h>
+#include <qhbuttongroup.h>
+#include <qlabel.h>
+#include <qradiobutton.h>
+#include <qlistview.h>
+#include <qbuttongroup.h>
+#include <qhbox.h>
+#include <qheader.h>
+#include <qlayout.h>
+
+#include <stdlib.h>
+#include <limits.h>
+
+/******************************************************************/
+/* Class KWBrushStylePreview - only used by kwframestylemanager */
+/******************************************************************/
+KWBrushStylePreview::KWBrushStylePreview( QWidget* parent )
+ : QFrame(parent)
+{
+}
+
+void KWBrushStylePreview::drawContents( QPainter* painter )
+{
+ painter->save();
+ painter->translate( contentsRect().x(), contentsRect().y() );
+ painter->fillRect( contentsRect(), colorGroup().base() ); // in case of a transparent brush
+ painter->fillRect( contentsRect(), brush );
+ painter->restore();
+}
+
+
+/******************************************************************/
+/* Class: KWFrameDia *
+ *
+ * TAB Frame Options
+ * Set options dependent of frametype
+ * TAB Text Runaround
+ * Set the text behaviour of this frame
+ * TAB Frameset
+ * here the user can select from the current TEXT framesets, a new one is
+ * included in the list.
+ * Afterwards (on ok) the frame should be checked if it is already owned by a
+ * frameset, if so that connection must be disconnected (if different) and
+ * framebehaviour will be copied from the frameset
+ * then the new connection should be made.
+ *
+ * TAB Geometry
+ * position/size
+ ******************************************************************/
+
+KWFrameDia::KWFrameDia( QWidget* parent, KWFrame *frame)
+ : KDialogBase( Tabbed, QString::null, Ok | Apply| Cancel, Ok, parent, "framedialog", true)
+{
+ m_noSignal=false;
+ m_frame = frame;
+ m_mainFrame = 0;
+ if(m_frame==0) {
+ kdDebug() << "ERROR: KWFrameDia::constructor no frame.."<<endl;
+ return;
+ }
+ setCaption( i18n( "Frame Properties for %1" ).arg( m_frame->frameSet()->name() ) );
+ KWFrameSet *fs = m_frame->frameSet()->groupmanager();
+ if(fs==0L) fs=m_frame->frameSet();
+ m_frameType = fs->type();
+ m_frameSetFloating = fs->isFloating();
+ m_frameSetProtectedSize = fs->isProtectSize();
+ m_mainFrameSetIncluded = fs->isMainFrameset();
+ m_defaultFrameSetIncluded = fs->isMainFrameset() || fs->isHeaderOrFooter() || fs->isFootEndNote();
+ if ( m_mainFrameSetIncluded )
+ m_mainFrame = m_frame;
+
+ m_doc = 0;
+ init();
+}
+
+/* Contructor when the dialog is used on creation of frame */
+KWFrameDia::KWFrameDia( QWidget* parent, KWFrame *frame, KWDocument *doc, FrameSetType ft )
+ : KDialogBase( Tabbed, i18n("Frame Properties for New Frame"), Ok | Cancel, Ok, parent, "framedialog", true)
+{
+ m_noSignal=false;
+ m_frameType=ft;
+ m_doc = doc;
+ m_frame= frame;
+ m_frameSetFloating = false;
+ m_frameSetProtectedSize = false;
+ m_mainFrameSetIncluded = false;
+ m_defaultFrameSetIncluded = false;
+ if(m_frame==0) {
+ kdDebug() << "ERROR: KWFrameDia::constructor no m_frame.."<<endl;
+ return;
+ }
+ m_mainFrame = 0;
+ init();
+}
+
+KWFrameDia::KWFrameDia( QWidget *parent, QPtrList<KWFrame> listOfFrames) : KDialogBase( Tabbed, i18n("Frames Properties"), Ok | Apply | Cancel, Ok, parent, "framedialog", true) , m_allFrames() {
+ m_noSignal=false;
+
+ m_mainFrame = m_frame = 0L;
+ m_tab1 = m_tab2 = m_tab3 = m_tab4 = m_tab5 = m_tab6 = 0;
+
+ KWFrame *f=listOfFrames.first();
+ if(f==0) {
+ kdDebug() << "ERROR: KWFrameDia::constructor no frames.."<<endl;
+ return;
+ }
+ if ( listOfFrames.count() == 1 )
+ setCaption( i18n( "Frame Settings for %1" ).arg( f->frameSet()->name() ) );
+
+ KWFrameSet *fs = f->frameSet()->groupmanager();
+ if(fs==0L) fs=f->frameSet();
+ m_frameType = fs->type();
+ bool frameTypeUnset=true;
+ m_doc = fs->kWordDocument();
+
+ if( !fs->isMainFrameset() ) { // don't include the main fs.
+ m_allFrames.append(f);
+ frameTypeUnset=false;
+ }
+ else
+ m_mainFrame = f;
+
+ f=listOfFrames.next();
+ while(f) {
+ fs = f->frameSet()->groupmanager();
+ if(fs==0L) fs=f->frameSet();
+ if(m_doc->processingType() != KWDocument::WP || m_doc->frameSet(0) != fs) { // don't include the main fs.
+ if(!frameTypeUnset && m_frameType != fs->type()) m_frameType= FT_TEXT;
+ if(frameTypeUnset) {
+ m_frameType = fs->type();
+ frameTypeUnset = false;
+ } else if(m_frameType != fs->type()) m_frameType= FT_TEXT;
+ m_allFrames.append(f);
+ }
+ f=listOfFrames.next();
+ }
+ if(m_allFrames.count()==0)
+ m_allFrames.append(listOfFrames.first());
+
+ // Now that m_allFrames is set, calculate m_mainFrameSetIncluded and m_defaultFrameSetIncluded
+ m_mainFrameSetIncluded = false;
+ m_defaultFrameSetIncluded = false;
+ for ( f = m_allFrames.first(); f; f = m_allFrames.next() ) {
+ fs = f->frameSet();
+ if ( !m_mainFrameSetIncluded )
+ {
+ m_mainFrameSetIncluded = fs->isMainFrameset();
+ if ( m_mainFrameSetIncluded )
+ m_mainFrame = f;
+ }
+ if ( !m_defaultFrameSetIncluded )
+ m_defaultFrameSetIncluded = fs->isMainFrameset() || fs->isHeaderOrFooter() || fs->isFootEndNote();
+ }
+
+
+ init();
+}
+
+void KWFrameDia::init() {
+
+ m_tab1 = m_tab2 = m_tab3 = m_tab4 = m_tab5 = m_tab6 = 0;
+ m_sw = m_sh = 0L;
+ m_cbAspectRatio=0L;
+ KWFrameSet *fs=0;
+ if(m_frame) {
+ fs = m_frame->frameSet(); // 0 when creating a frame
+ KoRect r = m_frame->normalize();
+ m_frame->setRect( r.x(), r.y(), r.width(), r.height() );
+ }
+ if(!m_doc && fs)
+ {
+ m_doc = fs->kWordDocument();
+ }
+ if(!m_doc)
+ {
+ kdDebug() << "ERROR: KWFrameDia::init frame has no reference to m_doc.."<<endl;
+ return;
+ }
+ if( fs && fs->isMainFrameset() )
+ {
+ setupTab6();
+ setupTab5();
+ setupTab4();
+ }
+ else if ( fs && (fs->isHeaderOrFooter() || fs->isFootEndNote()) )
+ {
+ setupTab1();
+ if ( !fs->isMainFrameset() && !fs->isHeaderOrFooter() && !fs->isFootEndNote())
+ setupTab2();
+ setupTab4();
+ setupTab5();
+ setupTab6();
+ }
+ else if(m_frameType == FT_TEXT)
+ {
+ setupTab1();
+ if ( fs && !fs->isMainFrameset() && !fs->isHeaderOrFooter() && !fs->isFootEndNote())
+ setupTab2();
+ else if ( !fs )
+ setupTab2();
+ setupTab3();
+ setupTab4();
+ setupTab5();
+ setupTab6();
+ if(! fs) // first creation
+ showPage(2);
+ }
+ else if(m_frameType == FT_PICTURE)
+ {
+ setupTab1();
+ if ( m_frameType == FT_PICTURE )
+ setupTab2();
+ if(m_frame) // not for multiframe dia
+ setupTab4();
+ setupTab6();
+ showPage(1); // while options are not implemented..
+ }
+ else if(m_frameType == FT_PART)
+ {
+ setupTab2();
+ if(m_frame) // not for multiframe dia
+ setupTab4();
+ setupTab6();
+ }
+ else if(m_frameType == FT_FORMULA)
+ {
+ setupTab1();
+ setupTab2();
+ if(m_frame) // not for multiframe dia
+ setupTab4();
+ setupTab6();
+ showPage(1); // while options are not implemented..
+ }
+ else if(m_frameType == FT_TABLE)
+ {
+ setupTab4();
+ setupTab5();
+ setupTab6();
+ }
+ setInitialSize( QSize(550, 400) );
+}
+
+void KWFrameDia::setupTab1(){ // TAB Frame Options
+ //kdDebug() << "setup tab 1 Frame options"<<endl;
+ m_tab1 = addPage( i18n("Options") );
+ int columns = 0;
+ if(m_frameType == FT_FORMULA || m_frameType == FT_PICTURE)
+ columns = 1;
+ else if(m_frameType == FT_TEXT)
+ columns = 2;
+
+ m_grid1 = new QGridLayout( m_tab1, 0 /*auto create*/, columns, 0, KDialog::spacingHint() );
+
+ // Options for all types of frames
+ m_cbCopy = new QCheckBox( i18n("Frame is a copy of the previous frame"),m_tab1 );
+ m_grid1->addWidget(m_cbCopy,1,0);
+
+ if(m_frame) {
+ m_cbCopy->setChecked( m_frame->isCopy() );
+ m_cbCopy->setEnabled( m_frame->frameSet() && m_frame->frameSet()->frame( 0 ) != m_frame ); // First one can't be a copy
+ } else { // list of frames as input.
+ KWFrame *f=m_allFrames.first();
+ bool show=true;
+ bool enabled=f->frameSet() && f->frameSet()->frame( 0 ) != f; // First one can't be a copy
+ bool checked=f->isCopy();
+ f=m_allFrames.next();
+ while(f) {
+ enabled=enabled || (f->frameSet() && f->frameSet()->frame( 0 ) != f);
+ if(checked != f->isCopy()) show=false;
+ f=m_allFrames.next();
+ }
+ if(! show) {
+ m_cbCopy->setTristate();
+ m_cbCopy->setNoChange();
+ }
+ else m_cbCopy->setChecked(checked);
+ m_cbCopy->setEnabled( enabled );
+ }
+
+ // Well, for images, formulas etc. it doesn't make sense to activate 'is copy'. What else would it show ?
+ if(m_frameType!=FT_TEXT)
+ m_cbCopy->setEnabled( false );
+
+ int row = 2;
+ int column = 0;
+
+ // Picture m_frame
+ if(m_frameType==FT_PICTURE)
+ {
+ m_cbAspectRatio = new QCheckBox (i18n("Retain original aspect ratio"),m_tab1);
+ connect( m_cbAspectRatio, SIGNAL(toggled(bool)),
+ this, SLOT(slotKeepRatioToggled(bool)));
+ bool show=true;
+ bool on=true;
+ if(m_frame) {
+ if ( m_frame->frameSet() )
+ on= static_cast<KWPictureFrameSet *>( m_frame->frameSet() )->keepAspectRatio();
+ } else {
+ KWFrame *f=m_allFrames.first();
+ KWPictureFrameSet *fs = dynamic_cast<KWPictureFrameSet *> (f->frameSet());
+ if(fs)
+ on=fs->keepAspectRatio();
+ f=m_allFrames.next();
+ while(f) {
+ KWPictureFrameSet *fs = dynamic_cast<KWPictureFrameSet *> (f->frameSet());
+ if(fs)
+ if(on != fs->keepAspectRatio()) {
+ show=false;
+ break;
+ }
+ f=m_allFrames.next();
+ }
+ }
+ m_cbAspectRatio->setChecked( on );
+ if(! show) {
+ m_cbAspectRatio->setTristate();
+ m_cbAspectRatio->setNoChange();
+ }
+ m_grid1->addWidget(m_cbAspectRatio, row, 0);
+ ++row;
+ }
+ else
+ m_cbAspectRatio = 0L;
+
+ // Text m_frame
+ if(m_frameType==FT_TEXT)
+ {
+ // AutoCreateNewFrame policy.
+ m_endOfFrame = new QGroupBox(i18n("If Text is Too Long for Frame"), m_tab1 );
+ m_grid1->addWidget( m_endOfFrame, row, 0 );
+
+ m_eofGrid= new QGridLayout (m_endOfFrame, 4, 1, KDialog::marginHint(), KDialog::spacingHint());
+ m_rAppendFrame = new QRadioButton( i18n( "Create a new page" ), m_endOfFrame );
+ QWhatsThis::add( m_rAppendFrame, "<b>Create a new page:</b><br/> if there is too "
+ "much text for this text frame, a new page will be created and, "
+ "since \"Reconnect frame to current flow\" is the only possible "
+ "option together with this one, "
+ "the new page will have a frame for showing the additional text." );
+ m_eofGrid->addWidget( m_rAppendFrame, 1, 0 );
+
+ m_rResizeFrame = new QRadioButton( i18n( "Resize last frame" ), m_endOfFrame );
+ QWhatsThis::add( m_rResizeFrame, "<b>Resize last frame:</b><br/> "
+ "if there is too much text for this text frame, "
+ "the frame will resize itself (increasing its height) as much as it needs, "
+ "to be able to contain all the text. More precisely, when the frameset has "
+ "multiple chained frames, it's always the last one which will be resized." );
+ m_eofGrid->addWidget( m_rResizeFrame, 2, 0 );
+
+ m_rNoShow = new QRadioButton( i18n( "Don't show the extra text" ), m_endOfFrame );
+ QWhatsThis::add( m_rNoShow, "<b>Don't show the extra text:</b><br/> "
+ "if there is too much text for this text frame, nothing happens "
+ "automatically. Initially the extra text won't appear. One possibility "
+ "then is to resize the frame manually. The other possibility is, with the option "
+ "\"Reconnect frame to current flow\" selected, to create a new page "
+ "which will then have a followup frame with the extra text." );
+ m_eofGrid->addWidget( m_rNoShow, 3, 0 );
+ QButtonGroup *grp = new QButtonGroup( m_endOfFrame );
+ grp->hide();
+ grp->setExclusive( true );
+ grp->insert( m_rAppendFrame );
+ grp->insert( m_rResizeFrame );
+ grp->insert( m_rNoShow );
+
+ m_eofGrid->addRowSpacing( 0, KDialog::marginHint() + 5 );
+ KWFrame::FrameBehavior fb;
+ bool show=true;
+ if(m_frame) {
+ fb = m_frame->frameBehavior();
+ } else {
+ KWFrame *f=m_allFrames.first();
+ fb = f->frameBehavior();
+ f=m_allFrames.next();
+ while(f) {
+ if(fb != f->frameBehavior()) {
+ show=false;
+ break;
+ }
+ f=m_allFrames.next();
+ }
+ }
+ if(show) {
+ if(fb == KWFrame::AutoExtendFrame) {
+ m_rResizeFrame->setChecked(true);
+ } else if (fb == KWFrame::AutoCreateNewFrame) {
+ m_rAppendFrame->setChecked(true);
+ } else {
+ m_rNoShow->setChecked(true);
+ }
+ }
+ column++;
+ } else {
+ m_rResizeFrame = 0L;
+ m_rAppendFrame = 0L;
+ m_rNoShow = 0L;
+ }
+
+ // NewFrameBehavior - now for all type of frames
+ m_onNewPage = new QGroupBox(i18n("On New Page Creation"),m_tab1);
+ m_grid1->addWidget( m_onNewPage, row, column );
+
+ m_onpGrid = new QGridLayout( m_onNewPage, 4, 1, KDialog::marginHint(), KDialog::spacingHint() );
+ m_reconnect = new QRadioButton (i18n ("Reconnect frame to current flow"), m_onNewPage);
+ QWhatsThis::add(m_reconnect, i18n("<b>Reconnect frame to current flow:</b><br/>"
+ "When a new page is created, a new frame will be created for this "
+ "frameset, so that the text can flow from one page to the next if necessary. "
+ "This is what happens for the \"main text frameset\", but this option makes it possible "
+ "to choose the same behavior for other framesets, for instance in magazine layouts."));
+ if ( m_rResizeFrame )
+ connect( m_reconnect, SIGNAL( clicked() ), this, SLOT( setFrameBehaviorInputOn() ) );
+ m_onpGrid->addRowSpacing( 0, KDialog::marginHint() + 5 );
+ m_onpGrid->addWidget( m_reconnect, 1, 0 );
+
+ m_noFollowup = new QRadioButton (i18n ("Do not create a followup frame"), m_onNewPage);
+ QWhatsThis::add(m_noFollowup, i18n("<b>Do not create a followup frame:</b><br/>"
+ "When a new page is created, no frame will be created for this frameset."));
+ if ( m_rResizeFrame )
+ connect( m_noFollowup, SIGNAL( clicked() ), this, SLOT( setFrameBehaviorInputOn() ) );
+ m_onpGrid->addWidget( m_noFollowup, 2, 0 );
+
+ m_copyRadio= new QRadioButton (i18n ("Place a copy of this frame"), m_onNewPage);
+ QWhatsThis::add(m_copyRadio, i18n("<b>Place a copy of this frame:</b><br/>"
+ "When a new page is created, a frame will be created for this frameset, "
+ "which will always show the exact same thing as the frame on the previous "
+ "page. This is what happens for headers and footers, but this option "
+ "makes it possible to choose the same behavior for other framesets, for "
+ "instance a company logo and/or title that should appear exactly the same on every page."));
+ if ( m_rResizeFrame )
+ connect( m_copyRadio, SIGNAL( clicked() ), this, SLOT( setFrameBehaviorInputOff() ) );
+ m_onpGrid->addWidget( m_copyRadio, 3, 0);
+
+ enableOnNewPageOptions();
+
+ QButtonGroup *grp2 = new QButtonGroup( m_onNewPage );
+ grp2->hide();
+ grp2->setExclusive( true );
+ grp2->insert( m_reconnect );
+ grp2->insert( m_noFollowup );
+ grp2->insert( m_copyRadio );
+ m_grid1->addRowSpacing( row, m_onNewPage->height());
+ KWFrame::NewFrameBehavior nfb;
+ bool show=true;
+ if(m_frame) {
+ nfb = m_frame->newFrameBehavior();
+ } else {
+ KWFrame *f=m_allFrames.first();
+ nfb = f->newFrameBehavior();
+ f=m_allFrames.next();
+ while(f) {
+ if(nfb != f->newFrameBehavior()) {
+ show=false;
+ break;
+ }
+ f=m_allFrames.next();
+ }
+ }
+ if(show) {
+ if(nfb == KWFrame::Reconnect) {
+ m_reconnect->setChecked(true);
+ } else if(nfb == KWFrame::NoFollowup) {
+ m_noFollowup->setChecked(true);
+ } else {
+ m_copyRadio->setChecked(true);
+ setFrameBehaviorInputOff();
+ }
+ }
+
+
+ // SideHeads definition - for text frames only
+ if( false && m_frameType == FT_TEXT ) // disabled in the GUI for now! (TZ June 2002)
+ {
+ row++;
+ m_sideHeads = new QGroupBox(i18n("SideHead Definition"),m_tab1);
+ m_sideHeads->setEnabled(false); //###
+ m_grid1->addWidget(m_sideHeads, row, 0);
+
+ m_sideGrid = new QGridLayout( m_sideHeads, 4, 2, KDialog::marginHint(), KDialog::spacingHint() );
+ sideTitle1 = new QLabel ( i18n("Size (%1):").arg(m_doc->unitName()),m_sideHeads);
+ sideTitle1->resize(sideTitle1->sizeHint());
+ m_sideGrid->addWidget(sideTitle1,1,0);
+ m_sideWidth= new QLineEdit(m_sideHeads,"");
+ m_sideWidth->setMaxLength(6);
+ m_sideGrid->addWidget(m_sideWidth,1,1);
+ sideTitle2 = new QLabel( i18n("Gap size (%1):").arg(m_doc->unitName()),m_sideHeads);
+ sideTitle2->resize(sideTitle2->sizeHint());
+ m_sideGrid->addWidget(sideTitle2,2,0);
+ m_sideGap = new QLineEdit(m_sideHeads,"");
+ m_sideGap->setMaxLength(6);
+ m_sideGrid->addWidget(m_sideGap,2,1);
+ m_sideAlign = new QComboBox (false,m_sideHeads);
+ m_sideAlign->setAutoResize(false);
+ m_sideAlign->insertItem ( i18n("Left"));
+ m_sideAlign->insertItem ( i18n("Right"));
+ m_sideAlign->insertItem ( i18n("Closest to Binding"));
+ m_sideAlign->insertItem ( i18n("Closest to Page Edge"));
+ m_sideAlign->resize(m_sideAlign->sizeHint());
+ m_sideGrid->addMultiCellWidget(m_sideAlign,3,3,0,1);
+ m_sideGrid->addRowSpacing( 0, KDialog::marginHint() + 5 );
+
+ // init for sideheads.
+ m_sideWidth->setText("0");
+ m_sideWidth->setValidator( new KFloatValidator(0,9999,true, m_sideWidth) );
+
+ m_sideGap->setText("0");
+ m_sideGap->setValidator( new KFloatValidator(0,9999,true, m_sideGap) );
+ // add rest of sidehead init..
+ }
+
+ m_cbAllFrames = new QCheckBox (i18n("Changes will be applied to all frames in frameset"),m_tab1);
+ m_cbAllFrames->setChecked(m_frame!=0L);
+ row++;
+ m_grid1->addMultiCellWidget(m_cbAllFrames,row,row, 0, 1);
+ m_cbProtectContent = new QCheckBox( i18n("Protect content"), m_tab1);
+ QWhatsThis::add(m_cbProtectContent, i18n("<b>Protect content:</b><br/>"
+ "Disallow changes to be made to the contents of the frame(s)."));
+ connect( m_cbProtectContent, SIGNAL(toggled ( bool ) ), this, SLOT(slotProtectContentChanged( bool )));
+ row++;
+ m_grid1->addMultiCellWidget(m_cbProtectContent,row,row, 0, 1);
+ if( m_frameType != FT_TEXT || m_frame!=0 && m_frame->frameSet()==0) {
+ m_cbAllFrames->setChecked(false);
+ m_cbAllFrames->hide();
+ m_cbProtectContent->setChecked( false );
+ m_cbProtectContent->hide();
+ }
+ else if ( m_frameType == FT_TEXT /*&& m_frame!=0 && m_frame->frameSet()*/ )
+ {
+ bool show=true;
+ bool on=true;
+ if(m_frame)
+ {
+ if ( m_frame->frameSet() )
+ on= static_cast<KWTextFrameSet *>(m_frame->frameSet() )->textObject()->protectContent();
+ }
+ else
+ {
+ KWFrame *f=m_allFrames.first();
+ KWTextFrameSet *fs = dynamic_cast<KWTextFrameSet *> (f->frameSet());
+ if(fs)
+ on=fs->textObject()->protectContent();
+ f=m_allFrames.next();
+ while(f) {
+ KWTextFrameSet *fs = dynamic_cast<KWTextFrameSet *> (f->frameSet());
+ if(fs)
+ {
+ if(on != fs->textObject()->protectContent())
+ {
+ show=false;
+ break;
+ }
+ }
+ f=m_allFrames.next();
+ }
+ }
+ m_cbProtectContent->setChecked( on );
+ if(! show) {
+ m_cbProtectContent->setTristate();
+ m_cbProtectContent->setNoChange();
+ }
+ }
+
+ for(int i=0;i < row;i++)
+ m_grid1->setRowStretch( i, 0 );
+ m_grid1->setRowStretch( row + 1, 1 );
+}
+
+void KWFrameDia::setupTab2() { // TAB Text Runaround
+ m_tab2 = addPage( i18n( "Text Run Around" ) );
+
+ QVBoxLayout *tabLayout = new QVBoxLayout( m_tab2, 0, KDialog::spacingHint(), "tabLayout");
+
+ // First groupbox
+ m_runGroup = new QButtonGroup( i18n( "Layout of Text in Other Frames" ), m_tab2);
+ m_runGroup->setColumnLayout( 0, Qt::Vertical );
+ m_runGroup->layout()->setSpacing( KDialog::spacingHint() );
+ QGridLayout *groupBox1Layout = new QGridLayout( m_runGroup->layout() );
+ groupBox1Layout->setAlignment( Qt::AlignTop );
+
+ m_rRunNo = new QRadioButton( i18n( "Text will run &through this frame" ), m_runGroup );
+ groupBox1Layout->addWidget( m_rRunNo, 0, 1 );
+
+ m_rRunBounding = new QRadioButton( i18n( "Text will run &around the frame" ), m_runGroup );
+ groupBox1Layout->addWidget( m_rRunBounding, 1, 1 );
+
+ m_rRunSkip = new QRadioButton( i18n( "Text will &not run around this frame" ), m_runGroup );
+ groupBox1Layout->addWidget( m_rRunSkip, 2, 1 );
+
+ QPixmap pixmap = KWBarIcon( "run_not" );
+ QLabel *lRunNo = new QLabel( m_runGroup );
+ lRunNo->setBackgroundPixmap( pixmap );
+ lRunNo->setFixedSize( pixmap.size() );
+ groupBox1Layout->addWidget( lRunNo, 0, 0 );
+
+ pixmap = KWBarIcon( "run_bounding" );
+ QLabel *lRunBounding = new QLabel( m_runGroup );
+ lRunBounding->setBackgroundPixmap( pixmap );
+ lRunBounding->setFixedSize( pixmap.size() );
+ groupBox1Layout->addWidget( lRunBounding, 1, 0 );
+
+ pixmap = KWBarIcon( "run_skip" );
+ QLabel *lRunSkip = new QLabel( m_runGroup );
+ lRunSkip->setBackgroundPixmap( pixmap );
+ lRunSkip->setFixedSize( pixmap.size() );
+ groupBox1Layout->addWidget( lRunSkip, 2, 0 );
+
+ tabLayout->addWidget( m_runGroup );
+
+ // Second groupbox
+ m_runSideGroup = new QButtonGroup( i18n( "Run Around Side" ), m_tab2);
+ m_runSideGroup->setColumnLayout( 0, Qt::Vertical );
+ m_runSideGroup->layout()->setSpacing( KDialog::spacingHint() );
+ m_runSideGroup->layout()->setMargin( KDialog::marginHint() );
+ QGridLayout *runSideLayout = new QGridLayout( m_runSideGroup->layout() );
+ runSideLayout->setAlignment( Qt::AlignTop );
+
+ m_rRunLeft = new QRadioButton( i18n( "Run Around", "&Left" ), m_runSideGroup );
+ runSideLayout->addWidget( m_rRunLeft, 0, 0 /*1*/ );
+
+ m_rRunRight = new QRadioButton( i18n( "Run Around", "&Right" ), m_runSideGroup );
+ runSideLayout->addWidget( m_rRunRight, 1, 0 /*1*/ );
+
+ m_rRunBiggest = new QRadioButton( i18n( "Run Around", "Lon&gest side" ), m_runSideGroup );
+ runSideLayout->addWidget( m_rRunBiggest, 2, 0 /*1*/ );
+
+#if 0 // TODO icons!
+ QPixmap pixmap = KWBarIcon( "run_left" );
+ QLabel *label = new QLabel( m_runSideGroup );
+ label->setBackgroundPixmap( pixmap );
+ label->setFixedSize( pixmap.size() );
+ runSideLayout->addWidget( label, 0, 0 );
+
+ pixmap = KWBarIcon( "run_right" );
+ label = new QLabel( m_runSideGroup );
+ label->setBackgroundPixmap( pixmap );
+ label->setFixedSize( pixmap.size() );
+ runSideLayout->addWidget( label, 1, 0 );
+
+ pixmap = KWBarIcon( "run_biggest" );
+ label = new QLabel( m_runSideGroup );
+ label->setBackgroundPixmap( pixmap );
+ label->setFixedSize( pixmap.size() );
+ runSideLayout->addWidget( label, 2, 0 );
+#endif
+
+ tabLayout->addWidget( m_runSideGroup );
+
+ m_raDistConfigWidget = new KWFourSideConfigWidget( m_doc, i18n("Distance Between Frame && Text"), m_tab2 );
+ if ( m_frame )
+ m_raDistConfigWidget->setValues( QMAX(0.00, m_frame->runAroundLeft()),
+ QMAX(0.00, m_frame->runAroundRight()),
+ QMAX(0.00, m_frame->runAroundTop()),
+ QMAX(0.00, m_frame->runAroundBottom()) );
+ tabLayout->addWidget( m_raDistConfigWidget );
+
+
+
+ // Show current settings
+
+ // Runaround
+ bool show=true;
+ KWFrame::RunAround ra = KWFrame::RA_NO;
+ if ( m_frame )
+ ra = m_frame->runAround();
+ else {
+ KWFrame *f=m_allFrames.first();
+ ra = f->runAround();
+ f=m_allFrames.next();
+ while(f) {
+ if(ra != f->runAround()) show=false;
+ f=m_allFrames.next();
+ }
+ }
+
+ if(show) {
+ switch ( ra ) {
+ case KWFrame::RA_NO: m_rRunNo->setChecked( true ); break;
+ case KWFrame::RA_BOUNDINGRECT: m_rRunBounding->setChecked( true ); break;
+ case KWFrame::RA_SKIP: m_rRunSkip->setChecked( true ); break;
+ }
+ }
+
+ // Runaround side
+ show = true;
+ KWFrame::RunAroundSide rs = KWFrame::RA_BIGGEST;
+ if ( m_frame )
+ rs = m_frame->runAroundSide();
+ else {
+ KWFrame *f=m_allFrames.first();
+ rs = f->runAroundSide();
+ f = m_allFrames.next();
+ while(f) {
+ if(rs != f->runAroundSide()) show=false;
+ f=m_allFrames.next();
+ }
+ }
+
+ if(show) {
+ switch ( rs ) {
+ case KWFrame::RA_LEFT: m_rRunLeft->setChecked( true ); break;
+ case KWFrame::RA_RIGHT: m_rRunRight->setChecked( true ); break;
+ case KWFrame::RA_BIGGEST: m_rRunBiggest->setChecked( true ); break;
+ }
+ }
+
+ // Runaround gap
+ show=true;
+ double ragapLeft = 0;
+ double ragapRight = 0;
+ double ragapTop = 0;
+ double ragapBottom = 0;
+ if ( m_frame ) {
+ ragapLeft = m_frame->runAroundLeft();
+ ragapRight = m_frame->runAroundRight();
+ ragapTop = m_frame->runAroundTop();
+ ragapBottom = m_frame->runAroundBottom();
+ }
+ else {
+ KWFrame *f = m_allFrames.first();
+ ragapLeft = f->runAroundLeft();
+ ragapRight = f->runAroundRight();
+ ragapTop = f->runAroundTop();
+ ragapBottom = f->runAroundBottom();
+ for( f = m_allFrames.next() ; f ; f = m_allFrames.next() ) {
+ if( ragapLeft != f->runAroundLeft() ||
+ ragapRight != f->runAroundRight() ||
+ ragapTop != f->runAroundTop() ||
+ ragapBottom != f->runAroundBottom() )
+ show = false; // TODO special value in the spinbox
+ f = m_allFrames.next();
+ }
+ }
+
+ if(show)
+ m_raDistConfigWidget->setValues( ragapLeft, ragapRight, ragapTop, ragapBottom );
+
+ enableRunAround();
+
+ // Changing the type of runaround needs to enable/disable the runaround-side options
+ connect( m_runGroup, SIGNAL( clicked(int) ), this, SLOT( enableRunAround() ) );
+}
+
+void KWFrameDia::setupTab3(){ // TAB Frameset
+ /*
+ * here the user can select from the current TEXT framesets
+ * Afterwards (on ok) the frame should be checked if it is already owned by a
+ * frameset, if so that connection must be disconnected (if different) and
+ * framebehaviour will be copied from the frameset
+ * then the new connection should be made.
+ */
+ //kdDebug() << "setup tab 3 frameSet"<<endl;
+ m_tab3 = addPage( i18n( "Connect Text Frames" ) );
+
+ QVBoxLayout *tabLayout = new QVBoxLayout( m_tab3, 0, KDialog::spacingHint());
+
+ QButtonGroup *myGroup = new QButtonGroup(this);
+ myGroup->hide();
+
+ m_rExistingFrameset = new QRadioButton( m_tab3, "m_rExistingFrameset" );
+ m_rExistingFrameset->setText( i18n("Select existing frameset to connect frame to:") );
+ tabLayout->addWidget( m_rExistingFrameset );
+ myGroup->insert(m_rExistingFrameset,1);
+ connect (m_rExistingFrameset, SIGNAL( toggled(bool)), this, SLOT(ensureValidFramesetSelected()));
+
+ QHBoxLayout *layout2 = new QHBoxLayout( 0, 0, 6);
+ QSpacerItem* spacer = new QSpacerItem( 20, 20, QSizePolicy::Minimum, QSizePolicy::Expanding );
+ layout2->addItem( spacer );
+
+ m_lFrameSList = new QListView( m_tab3, "m_lFrameSList" );
+ m_lFrameSList->addColumn( i18n("No.") );
+ m_lFrameSList->addColumn( i18n("Frameset Name") );
+ m_lFrameSList->setAllColumnsShowFocus( true );
+ m_lFrameSList->header()->setMovingEnabled( false );
+ connect( m_lFrameSList, SIGNAL(selectionChanged ()),this,SLOT(selectExistingFrameset ()) );
+ connect (m_lFrameSList, SIGNAL( selectionChanged()), this, SLOT(ensureValidFramesetSelected()));
+
+ layout2->addWidget( m_lFrameSList );
+ tabLayout->addLayout( layout2 );
+
+ m_rNewFrameset = new QRadioButton( m_tab3);
+ m_rNewFrameset->setText( i18n( "Create a new frameset" ) );
+ tabLayout->addWidget( m_rNewFrameset );
+ myGroup->insert(m_rNewFrameset,2);
+
+ QFrame *line1 = new QFrame( m_tab3 );
+ line1->setProperty( "frameShape", (int)QFrame::HLine );
+ line1->setFrameShadow( QFrame::Plain );
+ line1->setFrameShape( QFrame::HLine );
+ tabLayout->addWidget( line1 );
+
+ QHBoxLayout *layout1 = new QHBoxLayout( 0, 0, 6 );
+ QLabel *textLabel1 = new QLabel( m_tab3 );
+ textLabel1->setText( i18n( "Name of frameset:" ) );
+ layout1->addWidget( textLabel1 );
+
+ m_eFrameSetName = new QLineEdit( m_tab3 );
+ layout1->addWidget( m_eFrameSetName );
+ tabLayout->addLayout( layout1 );
+
+ int amount=0;
+ // now fill the gui.
+ for ( unsigned int i = 0; i < m_doc->frameSetCount(); i++ ) {
+ KWFrameSet * fs = m_doc->frameSet( i );
+ if ( i == 0 && m_doc->processingType() == KWDocument::WP )
+ continue;
+ if ( fs->type() != FT_TEXT || fs->isHeaderOrFooter() )
+ continue;
+ if ( fs->frameSetInfo() == KWFrameSet::FI_FOOTNOTE )
+ continue;
+ if ( fs->groupmanager() )
+ continue;
+ if ( fs->isDeleted() )
+ continue;
+ QListViewItem *item = new QListViewItem( m_lFrameSList );
+ item->setText( 0, QString( "%1" ).arg( i + 1 ) );
+ item->setText( 1, fs->name() );
+ amount++;
+ if( m_frame && m_frame->frameSet() == fs ) {
+ m_lFrameSList->setSelected(item, TRUE );
+ m_oldFrameSetName = fs->name();
+ m_rExistingFrameset->setChecked(true);
+ }
+ }
+ if(amount==0) {
+ m_rNewFrameset->setChecked(/*true*/false);
+ m_rNewFrameset->setEnabled(false);
+ m_rExistingFrameset->setEnabled(false);
+ m_lFrameSList->setEnabled(false);
+ }
+ //we can't create a new frame when we select
+ //multi frame!!!!
+ if ( m_allFrames.count() > 1 ) {
+ m_rNewFrameset->setChecked(false);
+ m_rNewFrameset->setEnabled(false);
+ myGroup->setRadioButtonExclusive( false );
+ }
+ if(m_frame && m_frame->frameSet() == 0) {
+ m_oldFrameSetName = m_doc->generateFramesetName( i18n( "Text Frameset %1" ) );
+ m_rNewFrameset->setChecked(true);
+ }
+ m_eFrameSetName->setText( m_oldFrameSetName );
+
+ connect( m_lFrameSList, SIGNAL( currentChanged( QListViewItem * ) ),
+ this, SLOT( connectListSelected( QListViewItem * ) ) );
+ connect(m_eFrameSetName, SIGNAL(textChanged ( const QString & ) ),
+ this,SLOT(textNameFrameChanged ( const QString & ) ) );
+ connect(m_eFrameSetName, SIGNAL(textChanged ( const QString & )),
+ this,SLOT(textNameFrameChanged ( const QString & ) ));
+ connect( m_rNewFrameset, SIGNAL(toggled (bool)),
+ this,SLOT(selectNewFrameset (bool)) );
+}
+
+void KWFrameDia::selectExistingFrameset() {
+ m_rExistingFrameset->setChecked(true);
+}
+
+void KWFrameDia::selectNewFrameset(bool on) {
+ if(!on) return;
+
+ QListViewItem *frameSetItem = m_lFrameSList->selectedItem();
+ if ( !frameSetItem)
+ return;
+ QString str = frameSetItem->text( 0 );
+ KWFrameSet *fs = m_doc->frameSet(str.toInt() - 1);
+
+ frameSetItem->setText(1, fs->name() );
+}
+
+void KWFrameDia::textNameFrameChanged ( const QString &text )
+{
+ if(m_rExistingFrameset->isChecked()) {
+ QListViewItem *item = m_lFrameSList->selectedItem();
+ if ( !item )
+ return;
+ item->setText(1, text );
+ }
+ if(m_rNewFrameset->isChecked() || m_rExistingFrameset->isChecked()) //when one of both is clicked.
+ enableButtonOK( !text.isEmpty() );
+ else
+ enableButtonOK( true );
+}
+
+void KWFrameDia::setupTab4() { // TAB Geometry
+ m_noSignal = true;
+
+ m_tab4 = addPage( i18n( "Geometry" ) );
+ QGridLayout* grid4 = new QGridLayout( m_tab4, 5, 1, 0, KDialog::spacingHint() );
+
+ m_floating = new QCheckBox( i18n("Frame is inline"), m_tab4 );
+
+ connect( m_floating, SIGNAL( toggled(bool) ), this, SLOT( slotFloatingToggled(bool) ) );
+ int row = 0;
+ grid4->addMultiCellWidget( m_floating, row, row, 0, 1 );
+
+ row++;
+ m_protectSize = new QCheckBox( i18n("Protect size and position"), m_tab4);
+ grid4->addMultiCellWidget( m_protectSize, row, row, 0, 1 );
+ connect( m_protectSize, SIGNAL( toggled(bool) ), this, SLOT( slotProtectSizeToggled(bool) ) );
+
+ /* ideally the following properties could be given to any floating frame:
+ Position: (y)
+ Top of frame
+ Top of paragraph
+ Above current line
+ At insertion point
+ Below current line
+ Bottom of paragraph
+ Bottom of frame
+ Absolute
+ Alignment: (x)
+ Left
+ Right
+ Center
+ Closest to binding
+ Further from binding
+ Absolute
+ */
+
+ m_grp1 = new QGroupBox( i18n("Position"), m_tab4 );
+ QGridLayout* pGrid = new QGridLayout( m_grp1, 3, 4, KDialog::marginHint(), KDialog::spacingHint() );
+
+ m_lx = new QLabel( i18n( "Left:" ), m_grp1 );
+ m_lx->resize( m_lx->sizeHint() );
+ pGrid->addWidget( m_lx, 1, 0 );
+
+ m_sx = new KoUnitDoubleSpinBox( m_grp1, 0, 9999, 1, 0.0, m_doc->unit() );
+
+ m_sx->resize( m_sx->sizeHint() );
+ pGrid->addWidget( m_sx, 1, 1 );
+
+ m_ly = new QLabel( i18n( "Top:" ), m_grp1 );
+ m_ly->resize( m_ly->sizeHint() );
+ pGrid->addWidget( m_ly, 1, 2 );
+
+ m_sy = new KoUnitDoubleSpinBox( m_grp1, 0, 9999, 1, 0.0, m_doc->unit() );
+ m_sy->resize( m_sy->sizeHint() );
+ pGrid->addWidget( m_sy, 1, 3 );
+
+ m_lw = new QLabel( i18n( "Width:" ), m_grp1 );
+ m_lw->resize( m_lw->sizeHint() );
+ pGrid->addWidget( m_lw, 2, 0 );
+
+ m_sw = new KoUnitDoubleSpinBox( m_grp1, 0, 9999, 1, 0.0, m_doc->unit() );
+
+ m_sw->resize( m_sw->sizeHint() );
+ connect( m_sw, SIGNAL(valueChanged(double)),
+ this, SLOT(slotUpdateHeightForWidth(double)) );
+
+ pGrid->addWidget( m_sw, 2, 1 );
+
+ m_lh = new QLabel( i18n( "Height:" ), m_grp1 );
+ m_lh->resize( m_lh->sizeHint() );
+ pGrid->addWidget( m_lh, 2, 2 );
+
+ m_sh = new KoUnitDoubleSpinBox( m_grp1, 0, 9999, 1, 0.0, m_doc->unit() );
+ connect( m_sh, SIGNAL(valueChanged(double)),
+ this, SLOT(slotUpdateWidthForHeight(double)) );
+
+ m_sh->resize( m_sh->sizeHint() );
+
+ pGrid->addWidget( m_sh, 2, 3 );
+
+ pGrid->setRowSpacing( 0, KDialog::spacingHint() + 5 );
+
+ row++;
+ grid4->addMultiCellWidget( m_grp1, row, row, 0,1 );
+
+ if(m_frame) {
+ m_paddingConfigWidget = new KWFourSideConfigWidget( m_doc, i18n("Margins"), m_tab4 );
+ m_paddingConfigWidget->setValues( QMAX(0.00, m_frame->paddingLeft()),
+ QMAX(0.00, m_frame->paddingRight()),
+ QMAX(0.00, m_frame->paddingTop()),
+ QMAX(0.00, m_frame->paddingBottom()) );
+ row++;
+ grid4->addMultiCellWidget( m_paddingConfigWidget, row, row, 0, 1 );
+
+ if ( m_tab1 && m_cbProtectContent )
+ {
+ m_paddingConfigWidget->setEnabled( !m_cbProtectContent->isChecked() );
+ }
+ }
+ else
+ {
+ m_paddingConfigWidget = 0;
+ }
+
+ initGeometrySettings();
+
+ if ( !m_frame || m_defaultFrameSetIncluded ) {
+ // is multi frame, positions don't work for that..
+ // also not for default frames.
+ m_sx->setEnabled( false );
+ m_sy->setEnabled( false );
+ m_lx->setEnabled( false );
+ m_ly->setEnabled( false );
+ m_lw->setEnabled( false );
+ m_lh->setEnabled( false );
+ m_floating->setEnabled( false );
+ }
+
+ if ( m_defaultFrameSetIncluded || m_mainFrameSetIncluded)
+ {
+ m_sw->setEnabled( false );
+ m_sh->setEnabled( false );
+ m_grp1->setEnabled( false );
+ }
+
+ if ( m_mainFrameSetIncluded )
+ {
+ m_grp1->hide();
+ m_floating->hide( );
+ m_protectSize->hide();
+ }
+ m_noSignal=false;
+
+ ++row;
+ grid4->setRowStretch( row, 1 );
+}
+
+void KWFrameDia::initGeometrySettings()
+{
+ if ( m_frame ) {
+ // is single frame dia. Fill position strings and checkboxes now.
+
+ // Can't use frame->pageNum() here since frameset might be 0
+ int pageNum = m_doc->pageManager()->pageNumber(m_frame);
+
+ m_sx->setValue( KoUnit::toUserValue( m_frame->x(), m_doc->unit() ) );
+ m_sy->setValue( KoUnit::toUserValue( m_frame->y() - m_doc->pageManager()->topOfPage(pageNum), m_doc->unit() ) );
+ m_sw->setValue( KoUnit::toUserValue( m_frame->width(), m_doc->unit() ) );
+ m_sh->setValue( KoUnit::toUserValue( m_frame->height(), m_doc->unit() ) );
+
+ calcRatio();
+
+ // userValue leads to some rounding -> store old values from the ones
+ // displayed, so that the "change detection" in apply() works.
+ m_oldX = m_sx->value();
+ m_oldY = m_sy->value();
+ m_oldW = m_sw->value();
+ m_oldH = m_sh->value();
+
+#ifdef ALLOW_NON_INLINE_TABLES
+ KWFrameSet * fs = m_frame->frameSet();
+ if ( fs && fs->groupmanager() )
+ m_floating->setText( i18n( "Table is inline" ) );
+#else
+ m_floating->hide();
+#endif
+
+ m_floating->setChecked( m_frameSetFloating );
+ m_protectSize->setChecked( m_frameSetProtectedSize);
+ } else {
+ // multi frame. Fill inline and protect checkbox, leave away the position strings.
+ KWFrame *f=m_allFrames.first();
+ KWFrameSet *fs=f->frameSet();
+ bool ps=fs->isProtectSize();
+ m_protectSize->setChecked( ps );
+
+ bool table=fs->groupmanager();
+ if(table)
+ fs=fs->groupmanager();
+ bool inlineframe =fs->isFloating();
+ m_floating->setChecked( inlineframe );
+
+ double commonWidth = f->width();
+ double commonHeight = f->height();
+ m_sw->setEnabled( true );
+ m_sh->setEnabled( true );
+
+ f=m_allFrames.next();
+ while(f) {
+ KWFrameSet *fs=f->frameSet();
+ if(ps != fs->isProtectSize()) {
+ m_protectSize->setTristate();
+ m_protectSize->setNoChange();
+ }
+ if(fs->groupmanager()) //table
+ fs=fs->groupmanager();
+ else
+ table=false;
+
+ if(inlineframe != fs->isFloating()) {
+ m_floating->setTristate();
+ m_floating->setNoChange();
+ }
+
+ if ( kAbs( f->width() - commonWidth ) > 1E-6 ) {
+ kdDebug() << k_funcinfo << "width differs:" << f->width() << " " << commonWidth << endl;
+ m_sw->setEnabled( false );
+ }
+ if ( kAbs( f->height() - commonHeight ) > 1E-6 ) {
+ kdDebug() << k_funcinfo << "height differs:" << f->height() << " " << commonHeight << endl;
+ m_sh->setEnabled( false );
+ }
+
+ f=m_allFrames.next();
+ }
+ // TODO show a special value when frames have a different width/height
+ if ( m_sw->isEnabled() )
+ m_sw->setValue( KoUnit::toUserValue( commonWidth, m_doc->unit() ) );
+ if ( m_sh->isEnabled() )
+ m_sh->setValue( KoUnit::toUserValue( commonHeight, m_doc->unit() ) );
+ if(table)
+ {
+#ifdef ALLOW_NON_INLINE_TABLES
+ m_floating->setText( i18n( "Table is inline" ) );
+#else
+ m_floating->hide();
+#endif
+ }
+ }
+}
+
+void KWFrameDia::setupTab5() { // Tab Background fill/color
+ m_tab5 = addPage( i18n("Background") );
+ QGridLayout* grid5 = new QGridLayout( m_tab5, 0 /*auto*/, 2, 0, KDialog::spacingHint() );
+
+ int row = 0;
+ if (!m_frame ) {
+ m_overwriteColor = new QCheckBox (i18n("Set new color on all selected frames"), m_tab5);
+ grid5->addMultiCellWidget(m_overwriteColor,row,row,0,1);
+ row++;
+ }
+ //brushPreview=new KWBrushStylePreview(m_tab5);
+ //grid5->addMultiCellWidget(brushPreview,row,5,1,1);
+
+ m_transparentCB = new QCheckBox( i18n( "Transparent background" ), m_tab5 );
+ grid5->addWidget(m_transparentCB,row++,0);
+ m_transparentCB->setEnabled( !m_mainFrameSetIncluded );
+
+ QLabel *labelBgColor = new QLabel( i18n( "Background color:" ), m_tab5 );
+
+ grid5->addWidget(labelBgColor,row++,0);
+
+ m_brushColor = new KColorButton( Qt::white, KWDocument::defaultBgColor(0), m_tab5 );
+ grid5->addWidget(m_brushColor,row++,0);
+
+// connect( m_brushColor, SIGNAL( changed( const QColor & ) ),
+// this, SLOT( updateBrushPreview() ) );
+
+
+ // ###########################
+ // Fill styles are ugly and not WYSIWYG (due to being pixel-based)
+ // Feature not in OOo either (they have a configurable level of transparency instead, much nicer)
+#if 0
+ l = new QLabel( i18n( "Background style:" ), m_tab5 );
+ grid5->addWidget(l,row++,0);
+
+ brushStyle = new QComboBox( false,m_tab5, "BStyle" );
+ grid5->addWidget(brushStyle,row++,0);
+
+ brushStyle->insertItem( i18n( "No Background Fill" ) );
+ // xgettext:no-c-format
+ brushStyle->insertItem( i18n( "100% Fill Pattern" ) );
+ // xgettext:no-c-format
+ brushStyle->insertItem( i18n( "94% Fill Pattern" ) );
+ // xgettext:no-c-format
+ brushStyle->insertItem( i18n( "88% Fill Pattern" ) );
+ // xgettext:no-c-format
+ brushStyle->insertItem( i18n( "63% Fill Pattern" ) );
+ // xgettext:no-c-format
+ brushStyle->insertItem( i18n( "50% Fill Pattern" ) );
+ // xgettext:no-c-format
+ brushStyle->insertItem( i18n( "37% Fill Pattern" ) );
+ // xgettext:no-c-format
+ brushStyle->insertItem( i18n( "12% Fill Pattern" ) );
+ // xgettext:no-c-format
+ brushStyle->insertItem( i18n( "6% Fill Pattern" ) );
+ brushStyle->insertItem( i18n( "Horizontal Lines" ) );
+ brushStyle->insertItem( i18n( "Vertical Lines" ) );
+ brushStyle->insertItem( i18n( "Crossing Lines" ) );
+ brushStyle->insertItem( i18n( "Diagonal Lines ( / )" ) );
+ brushStyle->insertItem( i18n( "Diagonal Lines ( \\ )" ) );
+ brushStyle->insertItem( i18n( "Diagonal Crossing Lines" ) );
+ connect( brushStyle, SIGNAL( activated( int ) ),
+ this, SLOT( updateBrushPreview() ) );
+
+ updateBrushPreview();
+#endif
+
+ connect( m_transparentCB, SIGNAL( toggled( bool ) ), labelBgColor, SLOT( setDisabled( bool ) ) );
+ connect( m_transparentCB, SIGNAL( toggled( bool ) ), m_brushColor, SLOT( setDisabled( bool ) ) );
+ initBrush();
+
+ QSpacerItem* spacer = new QSpacerItem( 10, 10, QSizePolicy::Minimum, QSizePolicy::Expanding);
+ grid5->addItem( spacer,row,0 );
+}
+
+void KWFrameDia::setupTab6() // Border style
+{
+ m_tab6 = addPage( i18n("&Borders") );
+
+ QGridLayout *grid = new QGridLayout( m_tab6, 8, 2, 0, KDialog::spacingHint() );
+
+ QLabel * lStyle = new QLabel( i18n( "St&yle:" ), m_tab6 );
+ grid->addWidget( lStyle, 0, 0 );
+
+ m_cStyle = new QComboBox( false, m_tab6 );
+ m_cStyle->insertItem( KoBorder::getStyle( KoBorder::SOLID ) );
+ m_cStyle->insertItem( KoBorder::getStyle( KoBorder::DASH ) );
+ m_cStyle->insertItem( KoBorder::getStyle( KoBorder::DOT ) );
+ m_cStyle->insertItem( KoBorder::getStyle( KoBorder::DASH_DOT ) );
+ m_cStyle->insertItem( KoBorder::getStyle( KoBorder::DASH_DOT_DOT ) );
+ m_cStyle->insertItem( KoBorder::getStyle( KoBorder::DOUBLE_LINE ) );
+ lStyle->setBuddy( m_cStyle );
+ grid->addWidget( m_cStyle, 1, 0 );
+
+ QLabel * lWidth = new QLabel( i18n( "&Width:" ), m_tab6 );
+ grid->addWidget( lWidth, 2, 0 );
+
+ m_cWidth = new QComboBox( false, m_tab6 );
+ for( unsigned int i = 1; i <= 10; i++ )
+ m_cWidth->insertItem(QString::number(i));
+ lWidth->setBuddy( m_cWidth );
+ grid->addWidget( m_cWidth, 3, 0 );
+
+ QLabel * lColor = new QLabel( i18n( "Co&lor:" ), m_tab6 );
+ grid->addWidget( lColor, 4, 0 );
+
+ m_bColor = new KColorButton( black,
+ black,
+ m_tab6 );
+
+ lColor->setBuddy( m_bColor );
+ grid->addWidget( m_bColor, 5, 0 );
+
+ QButtonGroup * bb = new QHButtonGroup( m_tab6 );
+ bb->setFrameStyle(QFrame::NoFrame);
+ m_bLeft = new QPushButton(bb);
+ m_bLeft->setPixmap( BarIcon( "borderleft" ) );
+ m_bLeft->setToggleButton( true );
+ m_bRight = new QPushButton(bb);
+ m_bRight->setPixmap( BarIcon( "borderright" ) );
+ m_bRight->setToggleButton( true );
+ m_bTop = new QPushButton(bb);
+ m_bTop->setPixmap( BarIcon( "bordertop" ) );
+ m_bTop->setToggleButton( true );
+ m_bBottom = new QPushButton(bb);
+ m_bBottom->setPixmap( BarIcon( "borderbottom" ) );
+ m_bBottom->setToggleButton( true );
+ grid->addWidget( bb, 6, 0 );
+
+ connect( m_bLeft, SIGNAL( toggled( bool ) ), this, SLOT( brdLeftToggled( bool ) ) );
+ connect( m_bRight, SIGNAL( toggled( bool ) ), this, SLOT( brdRightToggled( bool ) ) );
+ connect( m_bTop, SIGNAL( toggled( bool ) ), this, SLOT( brdTopToggled( bool ) ) );
+ connect( m_bBottom, SIGNAL( toggled( bool ) ), this, SLOT( brdBottomToggled( bool ) ) );
+
+ initBorderSettings();
+
+ QGroupBox *grp=new QGroupBox( 0, Qt::Vertical, i18n( "Preview" ), m_tab6, "previewgrp" );
+ grid->addMultiCellWidget( grp , 0, 7, 1, 1 );
+ grp->layout()->setSpacing(KDialog::spacingHint());
+ grp->layout()->setMargin(KDialog::marginHint());
+ m_prev3 = new KoBorderPreview( grp );
+ QVBoxLayout *lay1 = new QVBoxLayout( grp->layout() );
+ lay1->addWidget(m_prev3);
+
+ connect( m_prev3, SIGNAL( choosearea(QMouseEvent * ) ),
+ this, SLOT( slotPressEvent(QMouseEvent *) ) );
+
+ // update the bordet preview widget
+ m_prev3->setLeftBorder( m_leftBorder );
+ m_prev3->setRightBorder( m_rightBorder );
+ m_prev3->setTopBorder( m_topBorder );
+ m_prev3->setBottomBorder( m_bottomBorder );
+
+ grid->setRowStretch( 7, 1 );
+ grid->setColStretch( 1, 1 );
+}
+
+void KWFrameDia::initBorderSettings()
+{
+ KWFrame *f = m_mainFrame ? m_mainFrame : ( m_frame ? m_frame : m_allFrames.first() );
+ m_leftBorder = f->leftBorder();
+ m_rightBorder = f->rightBorder();
+ m_topBorder = f->topBorder();
+ m_bottomBorder = f->bottomBorder();
+}
+
+#define OFFSETX 15
+#define OFFSETY 7
+#define Ko_SPACE 30
+void KWFrameDia::slotPressEvent(QMouseEvent *ev)
+{
+ QRect r = m_prev3->contentsRect();
+ QRect rect(r.x()+OFFSETX,r.y()+OFFSETY,r.width()-OFFSETX,r.y()+OFFSETY+Ko_SPACE);
+ if(rect.contains(QPoint(ev->x(),ev->y())))
+ {
+ if( ( ((int)m_topBorder.penWidth() != m_cWidth->currentText().toInt()) ||(m_topBorder.color != m_bColor->color() )
+ ||(m_topBorder.getStyle()!=KoBorder::getStyle(m_cStyle->currentText()) )) && m_bTop->isOn() )
+ {
+ m_topBorder.setPenWidth( m_cWidth->currentText().toInt() );
+ m_topBorder.color = QColor( m_bColor->color() );
+ m_topBorder.setStyle(KoBorder::getStyle(m_cStyle->currentText()));
+ m_prev3->setTopBorder( m_topBorder );
+ }
+ else
+ m_bTop->setOn(!m_bTop->isOn());
+ }
+ rect.setCoords(r.x()+OFFSETX,r.height()-OFFSETY-Ko_SPACE,r.width()-OFFSETX,r.height()-OFFSETY);
+ if(rect.contains(QPoint(ev->x(),ev->y())))
+ {
+ if( ( ((int)m_bottomBorder.penWidth() != m_cWidth->currentText().toInt()) ||(m_bottomBorder.color != m_bColor->color() )
+ ||(m_bottomBorder.getStyle()!=KoBorder::getStyle(m_cStyle->currentText()) )) && m_bBottom->isOn() )
+ {
+ m_bottomBorder.setPenWidth(m_cWidth->currentText().toInt());
+ m_bottomBorder.color = QColor( m_bColor->color() );
+ m_bottomBorder.setStyle(KoBorder::getStyle(m_cStyle->currentText()));
+ m_prev3->setBottomBorder( m_bottomBorder );
+ }
+ else
+ m_bBottom->setOn(!m_bBottom->isOn());
+ }
+
+ rect.setCoords(r.x()+OFFSETX,r.y()+OFFSETY,r.x()+Ko_SPACE+OFFSETX,r.height()-OFFSETY);
+ if(rect.contains(QPoint(ev->x(),ev->y())))
+ {
+
+ if( ( ((int)m_leftBorder.penWidth() != m_cWidth->currentText().toInt()) ||(m_leftBorder.color != m_bColor->color() )
+ ||(m_leftBorder.getStyle()!=KoBorder::getStyle(m_cStyle->currentText()) )) && m_bLeft->isOn() )
+ {
+ m_leftBorder.setPenWidth( m_cWidth->currentText().toInt());
+ m_leftBorder.color = QColor( m_bColor->color() );
+ m_leftBorder.setStyle(KoBorder::getStyle(m_cStyle->currentText()));
+ m_prev3->setLeftBorder( m_leftBorder );
+ }
+ else
+ m_bLeft->setOn(!m_bLeft->isOn());
+ }
+ rect.setCoords(r.width()-OFFSETX-Ko_SPACE,r.y()+OFFSETY,r.width()-OFFSETX,r.height()-OFFSETY);
+ if(rect.contains(QPoint(ev->x(),ev->y())))
+ {
+
+ if( ( ((int)m_rightBorder.penWidth() != m_cWidth->currentText().toInt()) ||(m_rightBorder.color != m_bColor->color() )
+ ||(m_rightBorder.getStyle()!=KoBorder::getStyle(m_cStyle->currentText()) )) && m_bRight->isOn() )
+ {
+ m_rightBorder.setPenWidth( m_cWidth->currentText().toInt());
+ m_rightBorder.color = m_bColor->color();
+ m_rightBorder.setStyle(KoBorder::getStyle(m_cStyle->currentText()));
+ m_prev3->setRightBorder( m_rightBorder );
+ }
+ else
+ m_bRight->setOn(!m_bRight->isOn());
+ }
+}
+#undef OFFSETX
+#undef OFFSETY
+#undef Ko_SPACE
+
+
+void KWFrameDia::brdLeftToggled( bool on )
+{
+ if ( !on )
+ m_leftBorder.setPenWidth(0);
+ else {
+ m_leftBorder.setPenWidth(m_cWidth->currentText().toInt());
+ m_leftBorder.color = m_bColor->color();
+ m_leftBorder.setStyle(KoBorder::getStyle( m_cStyle->currentText() ));
+ }
+ m_prev3->setLeftBorder( m_leftBorder );
+}
+
+void KWFrameDia::brdRightToggled( bool on )
+{
+ if ( !on )
+ m_rightBorder.setPenWidth(0);
+ else {
+ m_rightBorder.setPenWidth(m_cWidth->currentText().toInt());
+ m_rightBorder.color = m_bColor->color();
+ m_rightBorder.setStyle( KoBorder::getStyle( m_cStyle->currentText() ));
+ }
+ m_prev3->setRightBorder( m_rightBorder );
+}
+
+void KWFrameDia::brdTopToggled( bool on )
+{
+ if ( !on )
+ m_topBorder.setPenWidth(0);
+ else {
+ m_topBorder.setPenWidth(m_cWidth->currentText().toInt());
+ m_topBorder.color = m_bColor->color();
+ m_topBorder.setStyle(KoBorder::getStyle( m_cStyle->currentText() ));
+ }
+ m_prev3->setTopBorder( m_topBorder );
+}
+
+void KWFrameDia::brdBottomToggled( bool on )
+{
+ if ( !on )
+ m_bottomBorder.setPenWidth ( 0 );
+ else {
+ m_bottomBorder.setPenWidth( m_cWidth->currentText().toInt());
+ m_bottomBorder.color = m_bColor->color();
+ m_bottomBorder.setStyle(KoBorder::getStyle(m_cStyle->currentText()));
+ }
+ m_prev3->setBottomBorder( m_bottomBorder );
+}
+
+void KWFrameDia::slotProtectContentChanged( bool b )
+{
+ if (m_tab4 && !m_noSignal && m_paddingConfigWidget) {
+ m_paddingConfigWidget->setEnabled( !b );
+ }
+}
+
+void KWFrameDia::slotUpdateWidthForHeight(double height)
+{
+ if ( !m_cbAspectRatio || m_cbAspectRatio->state() != QButton::NoChange)
+ return;
+ if ( m_heightByWidthRatio == 0 )
+ return; // avoid DBZ
+ m_sw->setValue( height / m_heightByWidthRatio );
+
+}
+
+void KWFrameDia::slotUpdateHeightForWidth( double width )
+{
+ if ( !m_cbAspectRatio || m_cbAspectRatio->state() != QButton::NoChange)
+ return;
+ m_sh->setValue( width * m_heightByWidthRatio );
+}
+
+void KWFrameDia::slotKeepRatioToggled(bool on)
+{
+ if ( !on || !m_sw || !m_sh) return;
+ calcRatio();
+}
+void KWFrameDia::ensureValidFramesetSelected()
+{
+ enableButtonOK( m_rNewFrameset->isChecked() || m_rExistingFrameset->isChecked() && m_lFrameSList->selectedItem() != NULL);
+}
+
+void KWFrameDia::calcRatio()
+{
+ if ( m_sw->value() == 0 )
+ m_heightByWidthRatio = 1.0; // arbitrary
+ else
+ m_heightByWidthRatio = m_sh->value() / m_sw->value();
+}
+
+void KWFrameDia::initBrush()
+{
+ bool allFramesSame=true;
+ if ( m_frame )
+ m_newBrushStyle = m_frame->backgroundColor();
+ else {
+ KWFrame *f=m_allFrames.first();
+ m_newBrushStyle = f->backgroundColor();
+ f=m_allFrames.next();
+ while(f) {
+ if(m_newBrushStyle != f->backgroundColor()) {
+ allFramesSame=false;
+ break;
+ }
+ f=m_allFrames.next();
+ }
+ m_overwriteColor->setChecked(allFramesSame);
+ }
+
+ m_transparentCB->setChecked( m_newBrushStyle.style() == NoBrush );
+
+#if 0
+ switch ( m_newBrushStyle.style() )
+ {
+ case NoBrush:
+ brushStyle->setCurrentItem( 0 );
+ break;
+ case SolidPattern:
+ brushStyle->setCurrentItem( 1 );
+ break;
+ case Dense1Pattern:
+ brushStyle->setCurrentItem( 2 );
+ break;
+ case Dense2Pattern:
+ brushStyle->setCurrentItem( 3 );
+ break;
+ case Dense3Pattern:
+ brushStyle->setCurrentItem( 4 );
+ break;
+ case Dense4Pattern:
+ brushStyle->setCurrentItem( 5 );
+ break;
+ case Dense5Pattern:
+ brushStyle->setCurrentItem( 6 );
+ break;
+ case Dense6Pattern:
+ brushStyle->setCurrentItem( 7 );
+ break;
+ case Dense7Pattern:
+ brushStyle->setCurrentItem( 8 );
+ break;
+ case HorPattern:
+ brushStyle->setCurrentItem( 9 );
+ break;
+ case VerPattern:
+ brushStyle->setCurrentItem( 10 );
+ break;
+ case CrossPattern:
+ brushStyle->setCurrentItem( 11 );
+ break;
+ case BDiagPattern:
+ brushStyle->setCurrentItem( 12 );
+ break;
+ case FDiagPattern:
+ brushStyle->setCurrentItem( 13 );
+ break;
+ case DiagCrossPattern:
+ brushStyle->setCurrentItem( 14 );
+ break;
+ case CustomPattern:
+ break;
+ }
+#endif
+
+ QColor col = KWDocument::resolveBgColor( m_newBrushStyle.color(), 0 );
+ m_brushColor->setColor( col );
+}
+
+QBrush KWFrameDia::frameBrushStyle() const
+{
+ QBrush brush;
+
+ brush.setStyle( m_transparentCB->isChecked() ? NoBrush : SolidPattern );
+
+#if 0
+ switch ( brushStyle->currentItem() )
+ {
+ case 0:
+ brush.setStyle( NoBrush );
+ break;
+ case 1:
+ brush.setStyle( SolidPattern );
+ break;
+ case 2:
+ brush.setStyle( Dense1Pattern );
+ break;
+ case 3:
+ brush.setStyle( Dense2Pattern );
+ break;
+ case 4:
+ brush.setStyle( Dense3Pattern );
+ break;
+ case 5:
+ brush.setStyle( Dense4Pattern );
+ break;
+ case 6:
+ brush.setStyle( Dense5Pattern );
+ break;
+ case 7:
+ brush.setStyle( Dense6Pattern );
+ break;
+ case 8:
+ brush.setStyle( Dense7Pattern );
+ break;
+ case 9:
+ brush.setStyle( HorPattern );
+ break;
+ case 10:
+ brush.setStyle( VerPattern );
+ break;
+ case 11:
+ brush.setStyle( CrossPattern );
+ break;
+ case 12:
+ brush.setStyle( BDiagPattern );
+ break;
+ case 13:
+ brush.setStyle( FDiagPattern );
+ break;
+ case 14:
+ brush.setStyle( DiagCrossPattern );
+ break;
+ }
+#endif
+
+ brush.setColor( m_brushColor->color() );
+
+ return brush;
+}
+
+#if 0
+void KWFrameDia::updateBrushPreview()
+{
+ if(brushStyle->currentItem()==0) {
+ brushPreview->hide();
+ } else {
+ brushPreview->show();
+ brushPreview->setBrush(frameBrushStyle());
+ brushPreview->repaint(true);
+ }
+}
+#endif
+
+// Called when "m_reconnect" or "no followup" is checked
+void KWFrameDia::setFrameBehaviorInputOn() {
+ if ( m_tab4 && m_floating->isChecked() )
+ return;
+ if( m_rAppendFrame && m_rResizeFrame && m_rNoShow /*&& !m_rAppendFrame->isEnabled()*/ ) {
+ if(m_frameBehavior== KWFrame::AutoExtendFrame) {
+ m_rResizeFrame->setChecked(true);
+ } else if (m_frameBehavior== KWFrame::AutoCreateNewFrame) {
+ m_rAppendFrame->setChecked(true);
+ } else {
+ m_rNoShow->setChecked(true);
+ }
+ m_rResizeFrame->setEnabled(true);
+ // Can't have "create a new page" if "no followup", that wouldn't work
+ kdDebug() << "setFrameBehaviorInputOn: m_reconnect->isChecked()==" << m_reconnect->isChecked() << endl;
+ m_rAppendFrame->setEnabled( m_reconnect->isChecked() );
+ m_rNoShow->setEnabled(true);
+ }
+}
+
+// Called when "place a copy" is checked
+void KWFrameDia::setFrameBehaviorInputOff() {
+ if ( m_tab4 && m_floating->isChecked() )
+ return;
+ if( m_rAppendFrame && m_rResizeFrame && m_rNoShow && m_rAppendFrame->isEnabled() ) {
+ if(m_rResizeFrame->isChecked()) {
+ m_frameBehavior=KWFrame::AutoExtendFrame;
+ } else if ( m_rAppendFrame->isChecked()) {
+ m_frameBehavior=KWFrame::AutoCreateNewFrame;
+ } else {
+ m_frameBehavior=KWFrame::Ignore;
+ }
+ // In "Place a copy" mode, we can't have "create new page if text too long"
+ if ( m_rAppendFrame->isChecked() )
+ m_rNoShow->setChecked(true);
+ m_rAppendFrame->setEnabled(false);
+ m_rResizeFrame->setEnabled(true);
+ m_rNoShow->setEnabled(true);
+ }
+}
+
+void KWFrameDia::enableSizeAndPosition()
+{
+ bool canMove = ( m_floating->state() == QButton::Off ) // can move if no frame is floating
+ && ( m_protectSize->state() == QButton::Off ) // protects size too
+ && !m_defaultFrameSetIncluded // those can't be moved
+ && m_frame; // can't move if multiple frames selected
+ m_sx->setEnabled( canMove );
+ m_sy->setEnabled( canMove );
+ bool canResize = ( m_protectSize->state() == QButton::Off ) // can resize if no frame is protect-size'd
+ && !m_defaultFrameSetIncluded; // those can't be resized
+ m_sw->setEnabled( canResize );
+ m_sh->setEnabled( canResize );
+}
+
+void KWFrameDia::slotProtectSizeToggled(bool)
+{
+ enableSizeAndPosition();
+}
+
+void KWFrameDia::slotFloatingToggled(bool b)
+{
+ enableSizeAndPosition();
+ if (m_tab1 && m_rAppendFrame && m_rResizeFrame && m_rNoShow ) {
+ m_cbCopy->setEnabled( !b ); // 'copy' irrelevant for floating frames.
+ if ( m_rAppendFrame )
+ {
+ m_rAppendFrame->setEnabled( !b ); // 'create new page' irrelevant for floating frames.
+ if ( b && m_rAppendFrame->isChecked() )
+ m_rNoShow->setChecked( true );
+ }
+ enableOnNewPageOptions();
+ if ( b ) {
+ m_noFollowup->setChecked( true );
+ m_cbCopy->setChecked( false );
+ } else {
+ // Revert to non-inline frame stuff
+ m_rResizeFrame->setEnabled(true);
+ m_rAppendFrame->setEnabled(true);
+ m_rNoShow->setEnabled(true);
+ }
+ }
+
+ enableRunAround();
+}
+
+// Enable or disable the "on new page" options
+void KWFrameDia::enableOnNewPageOptions()
+{
+ if ( m_tab1 )
+ {
+ bool f = m_tab4 && m_floating->isChecked();
+ // 'what happens on new page' is irrelevant for floating frames
+ m_reconnect->setEnabled( !f );
+ m_noFollowup->setEnabled( !f );
+ m_copyRadio->setEnabled( !f );
+
+ if( m_frameType != FT_TEXT )
+ m_reconnect->setEnabled( false );
+ else if(m_frame) {
+ KWFrameSet *fs = m_frame->frameSet(); // 0 when creating a frame
+ if ( fs && (fs->isHeaderOrFooter() || fs->isFootEndNote() ))
+ {
+ m_reconnect->setEnabled( false );
+ m_noFollowup->setEnabled( false );
+ }
+ }
+ }
+}
+
+void KWFrameDia::enableRunAround()
+{
+ if ( m_tab2 )
+ {
+ if ( m_tab4 && m_floating->isChecked() ) {
+ m_runGroup->setEnabled( false ); // Runaround options don't make sense for floating frames
+ } else
+ {
+ if ( m_frame && m_frame->frameSet() )
+ m_runGroup->setEnabled( !m_frameSetFloating && !m_frame->frameSet()->isMainFrameset() && !m_frame->frameSet()->isHeaderOrFooter() && !m_frame->frameSet()->isFootEndNote() );
+ else
+ m_runGroup->setEnabled( true );
+ }
+ m_runSideGroup->setEnabled( m_runGroup->isEnabled() && m_rRunBounding->isChecked() );
+ m_raDistConfigWidget->setEnabled( m_runGroup->isEnabled() &&
+ ( m_rRunBounding->isChecked() || m_rRunSkip->isChecked() ) );
+ }
+}
+
+bool KWFrameDia::applyChanges()
+{
+ kdDebug() << "KWFrameDia::applyChanges"<<endl;
+ KWFrame *frameCopy = 0L;
+ bool isNewFrame=false;
+ if(m_frame) { // only do undo/redo when we have 1 frame to change for now..
+ frameCopy = m_frame->getCopy(); // keep a copy of the original (for undo/redo)
+ isNewFrame = m_frame->frameSet() == 0L; // true if we are creating a newframe
+ }
+ QString name=QString::null;
+
+ KMacroCommand * macroCmd=0L;
+ if ( m_tab3 ) { // TAB Frameset
+ // Frame/Frameset belonging, and frameset naming
+ // We basically have three cases:
+ // * Creating a new frame (fs==0), and creating a frameset (m_rNewFrameset selected)
+ // * Creating a frame (fs==0), and attaching to an existing frameset (other)
+ // * Editing a frame (fs!=0), possibly changing the frameset attachment (maybe creating a new one)
+
+ name = m_eFrameSetName->text();
+ if ( name.isEmpty() ) // Don't allow empty names
+ name = m_doc->generateFramesetName( i18n( "Text Frameset %1" ) );
+ KWFrameSet *fs = 0L;
+ QListViewItem *frameSetItem = m_lFrameSList->selectedItem();
+ if(frameSetItem) {
+ QString str = frameSetItem->text( 0 );
+ fs = m_doc->frameSet(str.toInt() - 1);
+ }
+ if(m_rNewFrameset->isChecked()) { // create a new FS.
+ if(m_frame && m_frame->frameSet()) {
+ // disconnect.
+ if(! mayDeleteFrameSet( static_cast<KWTextFrameSet*>(m_frame->frameSet())))
+ return false;
+ m_frame->frameSet()->deleteFrame( m_frame, false );
+ } else {
+ // first check all frames and ask the user if its ok to disconnect.
+ for(KWFrame *f=m_allFrames.first();f; f=m_allFrames.next()) {
+ if(! mayDeleteFrameSet( static_cast<KWTextFrameSet*>(f->frameSet())))
+ return false;
+ }
+ for(KWFrame *f=m_allFrames.first();f; f=m_allFrames.next())
+ f->frameSet()->deleteFrame( f, false );
+ }
+ } else if(m_rExistingFrameset->isChecked()) { // rename and/or m_reconnect a new frameset for this frame.
+ if(frameSetItem && (fs->name() != frameSetItem->text( 1 ))) { // rename FS.
+ if(!macroCmd)
+ macroCmd = new KMacroCommand( i18n("Rename Frameset") );
+ // Rename frameset
+ typedef KoSetPropCommand<QString, KWFrameSet, &KWFrameSet::setName> FramesetNameCommand;
+ FramesetNameCommand* cmd = new FramesetNameCommand( fs, i18n( "Rename Frameset" ), fs->name(), frameSetItem->text( 1 ) );
+ macroCmd->addCommand(cmd);
+ cmd->execute();
+ }
+ if(m_frame && fs ) {
+ if(m_frame->frameSet() != fs) {
+ if(m_frame->frameSet()!=0) {
+ // m_reconnect.
+ if(! mayDeleteFrameSet( dynamic_cast<KWTextFrameSet*>(m_frame->frameSet())))
+ return false;
+ m_frame->frameSet()->deleteFrame( m_frame, false );
+ }
+ fs->addFrame(m_frame);
+ }
+ } else if ( fs ){
+ // first check all frames and ask the user if its ok to m_reconnect.
+ for(KWFrame *f=m_allFrames.first();f; f=m_allFrames.next()) {
+ if(f->frameSet() != fs) { // m_reconnect.
+ if(! mayDeleteFrameSet( dynamic_cast<KWTextFrameSet*>(f->frameSet())))
+ return false;
+ }
+ }
+ if ( fs )
+ {
+ // then do the reconnects.
+ for(KWFrame *f=m_allFrames.first();f; f=m_allFrames.next()) {
+ KWFrameSet *fs2=f->frameSet();
+ if(! (fs2->isHeaderOrFooter() || fs2->isMainFrameset()) ) {
+ if(fs2 != fs) { // m_reconnect.
+ f->frameSet()->deleteFrame( f, false );
+ fs->addFrame(f);
+ }
+ }
+ }
+ }
+ }
+ }
+ if(m_rNewFrameset->isChecked() || m_rExistingFrameset->isChecked()) {
+ // check if new name is unique
+ for (QPtrListIterator<KWFrameSet> fit = m_doc->framesetsIterator(); fit.current() ; ++fit ) {
+ if ( !fit.current()->isDeleted() && // Allow to reuse a deleted frameset's name
+ fs != fit.current() && fit.current()->name() == name) {
+ if ( m_rNewFrameset->isChecked() )
+ KMessageBox::sorry( this,
+ i18n( "A new frameset with the name '%1' "
+ "can not be made because a frameset with that name "
+ "already exists. Please enter another name or select "
+ "an existing frameset from the list.").arg(name));
+ else
+ KMessageBox::sorry( this,
+ i18n( "A frameset with the name '%1' "
+ "already exists. Please enter another name." ).arg(name) );
+ m_eFrameSetName->setText(m_oldFrameSetName);
+ return false;
+ }
+ }
+ }
+ }
+ if ( m_tab1 ) { // TAB Frame Options
+ // Copy
+ if(m_frame)
+ m_frame->setCopy( m_cbCopy->isChecked() );
+ else if(m_cbCopy->state() != QButton::NoChange) {
+ for(KWFrame *f=m_allFrames.first();f; f=m_allFrames.next()) {
+ if(f == f->frameSet()->frame(0)) continue; // skip first frame of any frameset.
+ f->setCopy( m_cbCopy->isChecked() );
+ }
+ }
+
+ // FrameBehavior
+ if ( m_frameType == FT_TEXT )
+ {
+ bool update=true;
+ KWFrame::FrameBehavior fb=KWFrame::AutoCreateNewFrame;
+ if(m_rResizeFrame->isChecked())
+ fb = KWFrame::AutoExtendFrame;
+ else if ( m_rAppendFrame->isChecked())
+ fb = KWFrame::AutoCreateNewFrame;
+ else if ( m_rNoShow->isChecked())
+ fb = KWFrame::Ignore;
+ else
+ update=false;
+
+ if(m_frame)
+ if(m_cbAllFrames->isChecked() && m_frame->frameSet())
+ m_frame->frameSet()->setFrameBehavior(fb);
+ else
+ m_frame->setFrameBehavior(fb);
+ else if(update) {
+ for(KWFrame *f=m_allFrames.first();f; f=m_allFrames.next())
+ if(m_cbAllFrames->isChecked())
+ f->frameSet()->setFrameBehavior(fb);
+ else
+ f->setFrameBehavior(fb);
+ }
+ if ( m_frame && m_frame->frameSet())
+ {
+ KWTextFrameSet * frm=static_cast<KWTextFrameSet *>( m_frame->frameSet() );
+ if(frm->textObject()->protectContent()!=m_cbProtectContent->isChecked())
+ {
+ if(!macroCmd)
+ macroCmd = new KMacroCommand( i18n("Protect Content") );
+ KWProtectContentCommand * cmd = new KWProtectContentCommand( i18n("Protect Content"), frm,m_cbProtectContent->isChecked() );
+ cmd->execute();
+ macroCmd->addCommand(cmd);
+ }
+ }
+ else
+ {
+ if ( m_cbProtectContent->state() != QButton::NoChange)
+ {
+ for(KWFrame *f=m_allFrames.first();f; f=m_allFrames.next())
+ {
+ KWTextFrameSet * frm=dynamic_cast<KWTextFrameSet *>( f->frameSet() );
+ if ( frm )
+ {
+ if(frm->textObject()->protectContent()!=m_cbProtectContent->isChecked())
+ {
+ if(!macroCmd)
+ macroCmd = new KMacroCommand( i18n("Protect Content") );
+ KWProtectContentCommand * cmd = new KWProtectContentCommand( i18n("Protect Content"), frm,m_cbProtectContent->isChecked() );
+ cmd->execute();
+ macroCmd->addCommand(cmd);
+ }
+ }
+
+ }
+ }
+ }
+
+ }
+ // NewFrameBehavior
+ bool update=true;
+ KWFrame::NewFrameBehavior nfb=KWFrame::Reconnect;
+ if( m_reconnect && m_reconnect->isChecked() )
+ nfb = KWFrame::Reconnect;
+ else if ( m_noFollowup->isChecked() )
+ nfb = KWFrame::NoFollowup;
+ else if ( m_copyRadio->isChecked() )
+ nfb = KWFrame::Copy;
+ else
+ update=false;
+
+ if(m_frame)
+ if(m_cbAllFrames->isChecked() && m_frame->frameSet())
+ m_frame->frameSet()->setNewFrameBehavior(nfb);
+ else
+ m_frame->setNewFrameBehavior(nfb);
+ else if(update)
+ for(KWFrame *f=m_allFrames.first();f; f=m_allFrames.next())
+ if(m_cbAllFrames->isChecked())
+ f->frameSet()->setNewFrameBehavior(nfb);
+ else
+ f->setNewFrameBehavior(nfb);
+
+ // aspect ratio
+ if ( m_cbAspectRatio && (m_frameType==FT_PICTURE))
+ {
+ typedef KoSetBasicPropCommand<bool, KWPictureFrameSet, &KWPictureFrameSet::setKeepAspectRatio> FramesetSetKeepAspectRatioCommand;
+ if(m_frame) {
+ KWPictureFrameSet * frm=static_cast<KWPictureFrameSet *>( m_frame->frameSet() );
+ if ( frm->keepAspectRatio() != m_cbAspectRatio->isChecked() )
+ {
+ if(!macroCmd)
+ macroCmd = new KMacroCommand( i18n("Frame Properties") );
+ FramesetSetKeepAspectRatioCommand* cmd = new FramesetSetKeepAspectRatioCommand( frm, QString::null, frm->keepAspectRatio(), m_cbAspectRatio->isChecked() );
+
+ cmd->execute();
+
+ macroCmd->addCommand(cmd);
+ }
+ } else if(m_cbAspectRatio->state() != QButton::NoChange) {
+ for(KWFrame *f=m_allFrames.first();f; f=m_allFrames.next()) {
+ KWPictureFrameSet *fs = dynamic_cast<KWPictureFrameSet *> (f->frameSet());
+ if(fs) {
+ if(fs->keepAspectRatio()!=m_cbAspectRatio->isChecked())
+ {
+ if(!macroCmd)
+ macroCmd = new KMacroCommand( i18n("Frame Properties") );
+ FramesetSetKeepAspectRatioCommand* cmd = new FramesetSetKeepAspectRatioCommand( fs, QString::null, fs->keepAspectRatio(), m_cbAspectRatio->isChecked() );
+
+ cmd->execute();
+
+ macroCmd->addCommand(cmd);
+ }
+ }
+ }
+ }
+ }
+ }
+ if ( m_tab2 ) { // TAB Text Runaround
+ // Run around
+ KWFrame::RunAround ra=KWFrame::RA_BOUNDINGRECT;
+ bool update=true;
+ if ( m_rRunNo->isChecked() )
+ ra = KWFrame::RA_NO;
+ else if ( m_rRunBounding->isChecked() )
+ ra = KWFrame::RA_BOUNDINGRECT;
+ else if ( m_rRunSkip->isChecked() )
+ ra = KWFrame::RA_SKIP;
+ else
+ update=false;
+ if(m_frame)
+ m_frame->setRunAround(ra);
+ else if (update) {
+ for(KWFrame *f=m_allFrames.first();f; f=m_allFrames.next())
+ f->setRunAround(ra);
+ }
+
+ // Run around side.
+ KWFrame::RunAroundSide rs=KWFrame::RA_BIGGEST;
+ update=true;
+ if ( m_rRunLeft->isChecked() )
+ rs = KWFrame::RA_LEFT;
+ else if ( m_rRunRight->isChecked() )
+ rs = KWFrame::RA_RIGHT;
+ else if ( m_rRunBiggest->isChecked() )
+ rs = KWFrame::RA_BIGGEST;
+ else
+ update=false;
+ if(m_frame)
+ m_frame->setRunAroundSide(rs);
+ else if (update) {
+ for(KWFrame *f=m_allFrames.first();f; f=m_allFrames.next())
+ f->setRunAroundSide(rs);
+ }
+
+ // Run around gap.
+ double runAroundLeft = m_raDistConfigWidget->leftValue();
+ double runAroundRight = m_raDistConfigWidget->rightValue();
+ double runAroundTop = m_raDistConfigWidget->topValue();
+ double runAroundBottom = m_raDistConfigWidget->bottomValue();
+
+ if(m_frame) {
+ m_frame->setRunAroundGap( runAroundLeft, runAroundRight, runAroundTop, runAroundBottom );
+ }
+ else
+ for(KWFrame *f=m_allFrames.first();f; f=m_allFrames.next())
+ f->setRunAroundGap( runAroundLeft, runAroundRight, runAroundTop, runAroundBottom );
+ }
+ if(m_tab5) { // Tab Background fill/color
+ QBrush tmpBrush=frameBrushStyle();
+ if(m_frame) {
+ if ( tmpBrush != KWDocument::resolveBgBrush( m_frame->backgroundColor() ) ) {
+ m_frame->setBackgroundColor(tmpBrush);
+ }
+ } else if(m_overwriteColor->isChecked()) {
+ for(KWFrame *f=m_allFrames.first();f; f=m_allFrames.next())
+ f->setBackgroundColor(tmpBrush);
+ }
+ }
+
+
+ double px=0.0;
+ double py=0.0;
+ double pw=0.0;
+ double ph=0.0;
+ double uLeft = 0.0;
+ double uTop = 0.0;
+ double uBottom = 0.0;
+ double uRight = 0.0;
+ if(m_tab4) { // TAB Geometry
+ if ( m_frame ) {
+ px = QMAX( 0, m_sx->value() );
+ int pageNum = m_doc->pageManager()->pageNumber(m_frame);
+ py = QMAX( 0, m_sy->value() ) + m_doc->pageManager()->topOfPage(pageNum);
+ }
+ pw = QMAX( m_sw->value(), 0 );
+ ph = QMAX( m_sh->value(), 0 );
+ if ( m_paddingConfigWidget )
+ {
+ uLeft = m_paddingConfigWidget->leftValue();
+ uRight = m_paddingConfigWidget->rightValue();
+ uTop = m_paddingConfigWidget->topValue();
+ uBottom = m_paddingConfigWidget->bottomValue();
+ }
+ }
+ KoRect rect( px, py, pw, ph );
+
+ //kdDebug() << "New geom: " << m_sx->text().toDouble() << ", " << m_sy->text().toDouble()
+ //<< " " << m_sw->text().toDouble() << "x" << m_sh->text().toDouble() << endl;
+ //kdDebug()<<" rect :"<<px <<" py :"<<py<<" pw :"<<pw <<" ph "<<ph<<endl;
+ // Undo/redo for frame properties
+ if(m_frame) { // only do undo/redo when we edit 1 frame for now..
+
+ if(m_frame->frameSet() == 0L ) { // if there is no frameset (anymore)
+ KWTextFrameSet *frameSet = new KWTextFrameSet( m_doc, name );
+ frameSet->addFrame( m_frame );
+ KWPage *page = m_doc->pageManager()->page(m_frame);
+ if( page->rect().contains(rect) ) {
+ m_frame->setRect( px, py, pw, ph );
+ //don't change margins when frame is protected.
+ if ( m_paddingConfigWidget && ( !m_tab1 || (m_tab1 && m_cbProtectContent && !m_cbProtectContent->isChecked())) )
+ m_frame->setFramePadding( uLeft, uTop, uRight, uBottom );
+ m_doc->frameChanged( m_frame );
+ } else {
+ KMessageBox::sorry( this,i18n("The frame will not be resized because the new size would be greater than the size of the page."));
+ }
+
+ m_doc->addFrameSet( frameSet );
+ if(!macroCmd)
+ macroCmd = new KMacroCommand( i18n("Create Text Frame") );
+ KWCreateFrameCommand *cmd=new KWCreateFrameCommand( i18n("Create Text Frame"), m_frame) ;
+ macroCmd->addCommand(cmd);
+ }
+ if(!isNewFrame && (frameCopy->isCopy()!=m_frame->isCopy()
+ || frameCopy->frameBehavior()!=m_frame->frameBehavior()
+ || frameCopy->newFrameBehavior()!=m_frame->newFrameBehavior()
+ || frameCopy->runAround()!=m_frame->runAround()
+ || frameCopy->runAroundSide()!=m_frame->runAroundSide()
+ || frameCopy->runAroundLeft()!=m_frame->runAroundLeft()
+ || frameCopy->runAroundRight()!=m_frame->runAroundRight()
+ || frameCopy->runAroundTop()!=m_frame->runAroundTop()
+ || frameCopy->runAroundBottom()!=m_frame->runAroundBottom()
+ || (m_tab5 && KWDocument::resolveBgBrush( frameCopy->backgroundColor() )!=frameBrushStyle())))
+ {
+ if(!macroCmd)
+ macroCmd = new KMacroCommand( i18n("Frame Properties") );
+
+ KWFramePropertiesCommand*cmd = new KWFramePropertiesCommand( QString::null, frameCopy, m_frame );
+ macroCmd->addCommand(cmd);
+ frameCopy = 0L;
+ } else
+ delete frameCopy;
+ }
+ if ( m_tab4 ) { // TAB Geometry
+
+ KWFrame *f=m_allFrames.first();
+ if(f==0L) f=m_frame;
+ while(f) {
+ // The floating attribute applies to the whole frameset...
+ KWFrameSet * fs = f->frameSet();
+ KWFrameSet * parentFs = fs->groupmanager() ? fs->groupmanager() : fs;
+
+ // Floating
+ if ( m_floating->isChecked() &&
+ m_floating->state() != QButton::NoChange &&
+ !parentFs->isFloating() )
+ {
+ if(!macroCmd)
+ macroCmd = new KMacroCommand( i18n("Make Frameset Inline") );
+
+ QValueList<FrameIndex> frameindexList;
+ QValueList<FrameMoveStruct> frameindexMove;
+
+ KoPoint oldPos = f->topLeft();
+
+ // turn non-floating frame into floating frame
+ KWFrameSetInlineCommand *cmd = new KWFrameSetInlineCommand( QString::null, parentFs, true );
+ cmd->execute();
+
+ frameindexList.append( FrameIndex( f ) );
+ frameindexMove.append( FrameMoveStruct( oldPos, f->topLeft() ) );
+
+ KWFrameMoveCommand *cmdMoveFrame = new KWFrameMoveCommand( QString::null, frameindexList, frameindexMove );
+
+ macroCmd->addCommand(cmdMoveFrame);
+ macroCmd->addCommand(cmd);
+ }
+ else if ( !m_floating->isChecked() &&
+ m_floating->state() != QButton::NoChange &&
+ parentFs->isFloating() )
+ {
+ if(!macroCmd)
+ macroCmd = new KMacroCommand( i18n("Make Frameset Non-Inline") );
+ // turn floating-frame into non-floating frame
+ KWFrameSetInlineCommand *cmd = new KWFrameSetInlineCommand( QString::null, parentFs, false );
+ macroCmd->addCommand(cmd);
+ cmd->execute();
+ }
+ if ( fs->isProtectSize() != m_protectSize->isChecked()
+ && m_protectSize->state() != QButton::NoChange )
+ {
+ if(!macroCmd)
+ macroCmd = new KMacroCommand( i18n("Protect Size") );
+ typedef KoSetBasicPropCommand<bool, KWFrameSet, &KWFrameSet::setProtectSize> FramesetSetProtectSizeCommand;
+ FramesetSetProtectSizeCommand* cmd = new FramesetSetProtectSizeCommand( fs, QString::null, fs->isProtectSize(), m_protectSize->isChecked() );
+ macroCmd->addCommand(cmd);
+ cmd->execute();
+ m_frameSetProtectedSize = m_protectSize->isChecked();
+ }
+ if ( !fs->isMainFrameset() &&
+ ( ( m_oldX != m_sx->value() && m_sx->isEnabled() )|| ( m_oldY != m_sy->value() && m_sy->isEnabled() ) || ( m_oldW != m_sw->value() && m_sw->isEnabled() ) || ( m_oldH != m_sh->value() && m_sh->isEnabled() ) ) )
+ {
+ //kdDebug() << "Old geom: " << m_oldX << ", " << m_oldY<< " " << m_oldW << "x" << m_oldH << endl;
+ //kdDebug() << "New geom: " << m_sx->text().toDouble() << ", " << m_sy->text().toDouble()
+ // << " " << m_sw->text().toDouble() << "x" << m_sh->text().toDouble() << endl;
+
+ if( m_doc->pageManager()->page(f)->rect().contains(rect) )
+ {
+ FrameIndex index( f );
+ KoRect initialRect = f->normalize();
+ double initialMinFrameHeight = f->minimumFrameHeight();
+ if ( m_frame ) // single frame: can be moved and resized
+ f->setRect( px, py, pw, ph );
+ else { // multiple frames: can only be resized
+ f->setWidth( pw );
+ f->setHeight( ph );
+ }
+ FrameResizeStruct tmpResize( initialRect, initialMinFrameHeight, f->normalize() );
+ if(!macroCmd)
+ macroCmd = new KMacroCommand( i18n("Resize Frame") );
+
+ KWFrameResizeCommand *cmd = new KWFrameResizeCommand( i18n("Resize Frame"), index, tmpResize ) ;
+ macroCmd->addCommand(cmd);
+ m_doc->frameChanged( f );
+ }
+ else
+ {
+ KMessageBox::sorry( this,i18n("The frame will not be resized because the new size would be greater than the size of the page."));
+ }
+ }
+ if ( m_paddingConfigWidget &&
+ (!m_tab1 || (m_tab1 && m_cbProtectContent && !m_cbProtectContent->isChecked())) &&
+ m_paddingConfigWidget->changed() )
+ {
+ FrameIndex index( f );
+ FramePaddingStruct tmpMargBegin(f);
+ FramePaddingStruct tmpMargEnd(uLeft, uTop, uRight, uBottom);
+ if(!macroCmd)
+ macroCmd = new KMacroCommand( i18n("Change Margin Frame") );
+ KWFrameChangeFramePaddingCommand *cmd = new KWFrameChangeFramePaddingCommand( i18n("Change Margin Frame"), index, tmpMargBegin, tmpMargEnd) ;
+ cmd->execute();
+ macroCmd->addCommand(cmd);
+ }
+ f=m_allFrames.next();
+ }
+ }
+ if ( m_tab6 ) // Border style
+ {
+ if ( m_mainFrame )
+ m_allFrames.append( m_mainFrame );
+
+ KWFrame *f = m_allFrames.first();
+ if(f==0L) f=m_frame;
+ for ( ; f ; f = m_allFrames.next() )
+ {
+ // TODO can't this become shorter??
+ if ( f->leftBorder() != m_leftBorder )
+ {
+ kdDebug() << "Changing borders!" << endl;
+ QPtrList<KWFrameBorderCommand::FrameBorderTypeStruct> tmpBorderList;
+ QPtrList<FrameIndex> frameindexList;
+ f = KWFrameSet::settingsFrame( f );
+ FrameIndex *index = new FrameIndex( f );
+ KWFrameBorderCommand::FrameBorderTypeStruct *tmp =new KWFrameBorderCommand::FrameBorderTypeStruct;
+ tmp->m_OldBorder = f->leftBorder();
+ tmp->m_EFrameType = KoBorder::LeftBorder;
+ tmpBorderList.append( tmp );
+ frameindexList.append( index );
+ if ( !macroCmd )
+ macroCmd = new KMacroCommand( i18n("Change Border"));
+ KWFrameBorderCommand *cmd = new KWFrameBorderCommand(i18n("Change Left Border Frame"), frameindexList, tmpBorderList, m_leftBorder);
+ cmd->execute();
+ macroCmd->addCommand( cmd);
+ }
+ if ( f->rightBorder() != m_rightBorder )
+ {
+ QPtrList<KWFrameBorderCommand::FrameBorderTypeStruct> tmpBorderList;
+ QPtrList<FrameIndex> frameindexList;
+ f = KWFrameSet::settingsFrame( f );
+ FrameIndex *index = new FrameIndex( f );
+ KWFrameBorderCommand::FrameBorderTypeStruct *tmp =new KWFrameBorderCommand::FrameBorderTypeStruct;
+ tmp->m_OldBorder = f->rightBorder();
+ tmp->m_EFrameType = KoBorder::RightBorder;
+ tmpBorderList.append( tmp );
+ frameindexList.append( index );
+ if ( !macroCmd )
+ macroCmd = new KMacroCommand( i18n("Change Border"));
+ KWFrameBorderCommand *cmd = new KWFrameBorderCommand(i18n("Change Right Border Frame"), frameindexList, tmpBorderList, m_rightBorder);
+ cmd->execute();
+ macroCmd->addCommand( cmd);
+ }
+ if ( f->topBorder() != m_topBorder )
+ {
+ QPtrList<KWFrameBorderCommand::FrameBorderTypeStruct> tmpBorderList;
+ QPtrList<FrameIndex> frameindexList;
+ f = KWFrameSet::settingsFrame( f );
+ FrameIndex *index = new FrameIndex( f );
+ KWFrameBorderCommand::FrameBorderTypeStruct *tmp =new KWFrameBorderCommand::FrameBorderTypeStruct;
+ tmp->m_OldBorder = f->topBorder();
+ tmp->m_EFrameType = KoBorder::TopBorder;
+ tmpBorderList.append( tmp );
+ frameindexList.append( index );
+ if ( !macroCmd )
+ macroCmd = new KMacroCommand( i18n("Change Border"));
+ KWFrameBorderCommand *cmd = new KWFrameBorderCommand(i18n("Change Top Border Frame"), frameindexList, tmpBorderList, m_topBorder);
+ cmd->execute();
+ macroCmd->addCommand( cmd);
+ }
+ if ( f->bottomBorder() != m_bottomBorder )
+ {
+ QPtrList<KWFrameBorderCommand::FrameBorderTypeStruct> tmpBorderList;
+ QPtrList<FrameIndex> frameindexList;
+ f = KWFrameSet::settingsFrame( f );
+ FrameIndex *index = new FrameIndex( f );
+ KWFrameBorderCommand::FrameBorderTypeStruct *tmp =new KWFrameBorderCommand::FrameBorderTypeStruct;
+ tmp->m_OldBorder = f->bottomBorder();
+ tmp->m_EFrameType = KoBorder::BottomBorder;
+ tmpBorderList.append( tmp );
+ frameindexList.append( index );
+ if ( !macroCmd )
+ macroCmd = new KMacroCommand( i18n("Change Border"));
+ KWFrameBorderCommand *cmd = new KWFrameBorderCommand(i18n("Change Bottom Border Frame"), frameindexList, tmpBorderList, m_bottomBorder);
+ cmd->execute();
+ macroCmd->addCommand( cmd);
+ }
+ }
+ }
+
+ if(macroCmd)
+ m_doc->addCommand(macroCmd);
+
+ updateFrames();
+ return true;
+}
+
+void KWFrameDia::updateFrames()
+{
+ m_doc->updateAllFrames();
+ m_doc->layout();
+ m_doc->repaintAllViews();
+}
+
+void KWFrameDia::slotApply()
+{
+ applyChanges();
+ if ( m_tab4 )
+ initGeometrySettings();
+ if ( m_tab6 )
+ initBorderSettings();
+}
+
+void KWFrameDia::slotOk()
+{
+ if (applyChanges())
+ {
+ KDialogBase::slotOk();
+ }
+}
+
+void KWFrameDia::connectListSelected( QListViewItem *item )
+{
+/* belongs to TAB3, is activated when the user selects another frameset from the list */
+ if ( !item )
+ item = m_lFrameSList->selectedItem();
+
+ if ( !item ) return; // assertion
+
+ m_rExistingFrameset->setChecked(true);
+ m_eFrameSetName->setText( item->text(1) );
+}
+
+bool KWFrameDia::mayDeleteFrameSet(KWTextFrameSet *fs) {
+ if(fs==0) return true;
+ if(fs->frameCount() > 1) return true;
+ KoTextParag * parag = fs->textDocument()->firstParag();
+ if(parag==0) return true;
+ bool isEmpty = parag->next() == 0L && parag->length() == 1;
+ if ( !isEmpty ) {
+ int result = KMessageBox::warningContinueCancel(this,
+ i18n( "You are about to reconnect the last frame of the "
+ "frameset '%1'. "
+ "The contents of this frameset will be deleted.\n"
+ "Are you sure you want to do that?").arg(fs->name()),
+ i18n("Reconnect Frame"), i18n("&Reconnect"));
+ if (result != KMessageBox::Continue)
+ return false;
+ }
+ return true;
+}
+
+KWFourSideConfigWidget::KWFourSideConfigWidget( KWDocument* doc, const QString& title,
+ QWidget* parent, const char* name )
+ : QGroupBox( title, parent, name ),
+ m_doc( doc ),
+ m_changed( false ), m_noSignal( false )
+{
+ QGroupBox *grp2 = this;
+ QGridLayout* mGrid = new QGridLayout( grp2, 4, 4, KDialog::marginHint(), KDialog::spacingHint() );
+
+ m_synchronize=new QCheckBox( i18n("Synchronize changes"), grp2 );
+ QWhatsThis::add(m_synchronize, i18n("<b>Synchronize changes:</b><br/>"
+ "When this is checked any change in margins will be used for all directions."));
+ mGrid->addMultiCellWidget( m_synchronize, 1, 1, 0, 1 );
+
+ QLabel* lml = new QLabel( i18n( "Left:" ), grp2 );
+ //lml->resize( lml->sizeHint() );
+ mGrid->addWidget( lml, 2, 0 );
+
+ m_inputLeft = new KoUnitDoubleSpinBox( grp2, 0, 9999, 1, 0.0, m_doc->unit() );
+
+ mGrid->addWidget( m_inputLeft, 2, 1 );
+
+ QLabel* lmt = new QLabel( i18n( "Top:" ), grp2 );
+ //lmt->resize( lmt->sizeHint() );
+ mGrid->addWidget( lmt, 2, 2 );
+
+ m_inputTop = new KoUnitDoubleSpinBox( grp2, 0, 9999, 1, 0.0, m_doc->unit() );
+
+ //m_inputTop->resize( m_inputTop->sizeHint() );
+
+ mGrid->addWidget( m_inputTop, 2, 3 );
+
+ QLabel* lmr = new QLabel( i18n( "Right:" ), grp2 );
+ //lmr->resize( lmr->sizeHint() );
+ mGrid->addWidget( lmr, 3, 0 );
+
+ m_inputRight = new KoUnitDoubleSpinBox( grp2, 0, 9999, 1, 0.0, m_doc->unit() );
+
+ //m_inputRight->resize( m_inputRight->sizeHint() );
+ mGrid->addWidget( m_inputRight, 3, 1 );
+
+ QLabel* lmb = new QLabel( i18n( "Bottom:" ), grp2 );
+ //lmb->resize( lmb->sizeHint() );
+ mGrid->addWidget( lmb, 3, 2 );
+
+ m_inputBottom = new KoUnitDoubleSpinBox( grp2, 0, 9999, 1, 0.0, m_doc->unit() );
+
+ //m_inputBottom->resize( m_inputBottom->sizeHint() );
+ mGrid->addWidget( m_inputBottom, 3, 3 );
+ mGrid->setRowSpacing( 0, KDialog::spacingHint() + 5 );
+
+ connect( m_inputLeft, SIGNAL( valueChanged(double)), this, SLOT( slotValueChanged( double )));
+ connect( m_inputRight, SIGNAL( valueChanged(double)), this, SLOT( slotValueChanged( double )));
+ connect( m_inputTop, SIGNAL( valueChanged(double)), this, SLOT( slotValueChanged( double )));
+ connect( m_inputBottom, SIGNAL( valueChanged(double)), this, SLOT( slotValueChanged( double )));
+}
+
+// Called right after the ctor, so m_synchronize can't be checked
+void KWFourSideConfigWidget::setValues( double left, double right, double top, double bottom )
+{
+ m_inputLeft->setValue( KoUnit::toUserValue( left, m_doc->unit() ) );
+ m_inputRight->setValue( KoUnit::toUserValue( right, m_doc->unit() ) );
+ m_inputTop->setValue( KoUnit::toUserValue( top, m_doc->unit() ) );
+ m_inputBottom->setValue( KoUnit::toUserValue( bottom, m_doc->unit() ) );
+}
+
+void KWFourSideConfigWidget::slotValueChanged( double val )
+{
+ m_changed = true;
+ if ( m_synchronize->isChecked() && !m_noSignal )
+ {
+ m_noSignal = true;
+ m_inputLeft->setValue( val );
+ m_inputBottom->setValue( val );
+ m_inputRight->setValue( val );
+ m_inputTop->setValue( val );
+ m_noSignal = false;
+ }
+}
+
+double KWFourSideConfigWidget::leftValue() const
+{
+ return m_inputLeft->value();
+}
+
+double KWFourSideConfigWidget::rightValue() const
+{
+ return m_inputRight->value();
+}
+
+double KWFourSideConfigWidget::topValue() const
+{
+ return m_inputTop->value();
+}
+
+double KWFourSideConfigWidget::bottomValue() const
+{
+ return m_inputBottom->value();
+}
+
+/*
+ TODO;
+ features that are present in the frames but not shown (yet)
+ - frames with 'copy' should have a radiogroup showing that its only going to be copied to
+ the even/odd side or to both sides.
+*/
diff --git a/kword/KWFrameDia.h b/kword/KWFrameDia.h
new file mode 100644
index 00000000..a1e4886d
--- /dev/null
+++ b/kword/KWFrameDia.h
@@ -0,0 +1,224 @@
+/* This file is part of the KDE project
+ Copyright (C) 1998, 1999 Reginald Stadlbauer <reggie@kde.org>
+ Copyright (C) 2005 Thomas Zander <zander@kde.org>
+
+ This library is free software; you can redistribute it and/m_or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, m_or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY m_or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+*/
+
+#ifndef framedia_h
+#define framedia_h
+
+#include "defs.h"
+#include "KWTextFrameSet.h"
+#include <kdialogbase.h>
+#include <KoUnit.h>
+#include <KoUnitWidgets.h>
+#include <qgroupbox.h>
+
+class KoBorderPreview;
+class KWFrame;
+class KWDocument;
+class KWPage;
+class QWidget;
+class QGridLayout;
+class QGroupBox;
+class QRadioButton;
+class QCheckBox;
+class QLabel;
+class QCloseEvent;
+class QListView;
+class QListViewItem;
+class QLineEdit;
+class KColorButton;
+class KDoubleNumInput;
+
+/******************************************************************/
+/* Class: KWBrushStylePreview */
+/******************************************************************/
+class KWBrushStylePreview : public QFrame
+{
+ Q_OBJECT
+public:
+ KWBrushStylePreview( QWidget* );
+ ~KWBrushStylePreview() {}
+ void setBrush( const QBrush& _brush ) { brush = _brush; }
+protected:
+ void drawContents( QPainter* );
+private:
+ QBrush brush;
+};
+
+/**
+ * A widget showing unitwidgets for 4 doubles (for left/right/top/bottom values)
+ * and a checkbox to synchronize changes to all values
+ */
+class KWFourSideConfigWidget : public QGroupBox
+{
+ Q_OBJECT
+public:
+ KWFourSideConfigWidget( KWDocument* m_doc, const QString& title, QWidget*, const char* name = 0 );
+
+ bool changed() const { return m_changed; }
+
+ void setValues( double left, double right, double top, double bottom ); // in pt
+ double leftValue() const; // in pt
+ double rightValue() const; // in pt
+ double topValue() const; // in pt
+ double bottomValue() const; // in pt
+
+signals:
+
+public slots:
+ void slotValueChanged( double );
+
+private:
+ KoUnitDoubleSpinBox *m_inputLeft, *m_inputRight, *m_inputTop, *m_inputBottom;
+ QCheckBox *m_synchronize;
+ KWDocument *m_doc;
+ bool m_changed;
+ bool m_noSignal;
+};
+
+/******************************************************************/
+/* Class: KWFrameDia */
+/******************************************************************/
+class KWFrameDia : public KDialogBase
+{
+ Q_OBJECT
+public:
+ /** Contructor when the dialog is used on creation of m_frame */
+ KWFrameDia( QWidget *parent, KWFrame *_frame,KWDocument *_doc,FrameSetType _ft);
+ KWFrameDia( QWidget *parent, KWFrame *_frame);
+ KWFrameDia( QWidget *parent, QPtrList<KWFrame> allFrames);
+ //KWFrameDia( QWidget *parent, KWCanvas *_canvas);
+
+ //void setCanvas(KWCanvas *_canvas) {canvas =_canvas;}
+
+protected:
+ void init();
+ bool applyChanges();
+ void setupTab1();
+ void setupTab2();
+ void setupTab3();
+ void setupTab4();
+ void setupTab5();
+ void setupTab6();
+ void initBorderSettings();
+ void initGeometrySettings();
+
+ void updateFrames();
+ void enableOnNewPageOptions();
+ void initBrush();
+ bool mayDeleteFrameSet(KWTextFrameSet *fs);
+ void enableSizeAndPosition();
+
+ QBrush frameBrushStyle() const;
+ void calcRatio();
+
+protected slots:
+ virtual void slotApply();
+ virtual void slotOk();
+ void connectListSelected( QListViewItem * );
+ void setFrameBehaviorInputOn();
+ void setFrameBehaviorInputOff();
+ void slotFloatingToggled(bool);
+ void slotProtectSizeToggled(bool);
+ void textNameFrameChanged ( const QString & );
+ //void updateBrushPreview();
+ void slotProtectContentChanged( bool );
+ void enableRunAround();
+ void selectExistingFrameset();
+ void selectNewFrameset(bool on);
+ void slotUpdateWidthForHeight(double height);
+ void slotUpdateHeightForWidth( double width );
+ void slotKeepRatioToggled(bool on);
+ void ensureValidFramesetSelected();
+ void brdLeftToggled( bool );
+ void brdRightToggled( bool );
+ void brdTopToggled( bool );
+ void brdBottomToggled( bool );
+ void slotPressEvent(QMouseEvent *_ev);
+private:
+ // TAB 1:
+ QWidget *m_tab1;
+ QGridLayout *m_grid1, *m_eofGrid, *m_onpGrid, *m_sideGrid;
+ QGroupBox *m_endOfFrame, *m_onNewPage, *m_sideHeads;
+ QCheckBox *m_cbCopy, *m_cbAspectRatio, *m_cbAllFrames;
+ QCheckBox *m_cbProtectContent;
+ QRadioButton *m_rResizeFrame, *m_rAppendFrame, *m_rNoShow, *m_reconnect, *m_noFollowup, *m_copyRadio;
+ QLabel *sideTitle1, *sideTitle2;
+ QLineEdit *m_sideWidth, *m_sideGap;
+ QComboBox *m_sideAlign;
+
+ // TAB 2:
+ QWidget *m_tab2;
+ QRadioButton *m_rRunNo, *m_rRunBounding, *m_rRunSkip;
+ QRadioButton *m_rRunLeft, *m_rRunRight, *m_rRunBiggest;
+ QGroupBox *m_runGroup, *m_runSideGroup;
+ KWFourSideConfigWidget* m_raDistConfigWidget;
+
+ // TAB 3:
+ QWidget *m_tab3;
+ QLineEdit *m_eFrameSetName;
+ QListView *m_lFrameSList;
+ QRadioButton *m_rExistingFrameset, *m_rNewFrameset;
+
+
+ // TAB 4:
+ QWidget *m_tab4;
+ QGroupBox *m_grp1;
+ QLabel *m_lx, *m_ly, *m_lw, *m_lh;
+ KoUnitDoubleSpinBox *m_sx, *m_sy, *m_sw, *m_sh;
+ KWFourSideConfigWidget* m_paddingConfigWidget;
+ QCheckBox *m_floating;
+ QCheckBox *m_protectSize;
+
+ // TAB 5:
+ QWidget *m_tab5;
+
+ // TAB 6:
+ QWidget *m_tab6;
+ QComboBox *m_cWidth, *m_cStyle;
+ QPushButton *m_bLeft, *m_bRight, *m_bTop, *m_bBottom;
+ KColorButton *m_bColor;
+ KoBorder m_leftBorder, m_rightBorder, m_topBorder, m_bottomBorder;
+ KoBorderPreview *m_prev3;
+
+ //QComboBox *brushStyle;
+ QCheckBox* m_transparentCB;
+ KColorButton *m_brushColor;
+ //KWBrushStylePreview *brushPreview;
+ QCheckBox *m_overwriteColor;
+
+ KWFrame *m_frame;
+ KWFrame *m_mainFrame;
+ QPtrList<KWFrame> m_allFrames;
+ KWDocument *m_doc;
+ FrameSetType m_frameType;
+ bool m_frameSetFloating;
+ bool m_frameSetProtectedSize;
+ bool m_mainFrameSetIncluded;
+ bool m_defaultFrameSetIncluded; // header, m_footer m_or m_footnote
+ double m_oldX, m_oldY, m_oldW, m_oldH;
+ double m_heightByWidthRatio;
+ int /*FrameBehavior*/ m_frameBehavior;
+ KoUnit::Unit m_frameUnits;
+ QString m_oldFrameSetName;
+ QBrush m_newBrushStyle;
+ bool m_noSignal;
+};
+
+#endif
diff --git a/kword/KWFrameLayout.cpp b/kword/KWFrameLayout.cpp
new file mode 100644
index 00000000..93c67e44
--- /dev/null
+++ b/kword/KWFrameLayout.cpp
@@ -0,0 +1,649 @@
+/* This file is part of the KOffice project
+ * Copyright (C) 2002-2005 David Faure <faure@kde.org>
+ * Copyright (C) 2005 Thomas Zander <zander@kde.org>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; version 2.
+
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public License
+ * along with this library; see the file COPYING.LIB. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ */
+#include "KWFrameLayout.h"
+#include "KWFrameList.h"
+#include "KWPageManager.h"
+#include "KWPage.h"
+#include "KWTextFrameSet.h"
+#include "KWDocument.h"
+#include <qtimer.h>
+
+// #define DEBUG_FRAMELAYOUT
+
+#ifdef NDEBUG
+#undef DEBUG_FRAMELAYOUT
+#endif
+
+KWFrameLayout::HeaderFooterFrameset::HeaderFooterFrameset( KWTextFrameSet* fs, int start, int end,
+ double spacing, OddEvenAll oea )
+ : m_frameset(fs), m_startAtPage(start), m_endAtPage(end), m_oddEvenAll(oea),
+ m_spacing(spacing), m_minY( 0 ), m_positioned( false )
+{
+ if ( fs->frameCount() > 0 )
+ m_height = fs->frame(0)->height();
+ else
+ m_height = 20; // whatever. The text layout will resize it.
+ Q_ASSERT( m_height > 0 );
+}
+
+
+void KWFrameLayout::HeaderFooterFrameset::debug()
+{
+#ifdef DEBUG_FRAMELAYOUT
+ HeaderFooterFrameset* hff = this;
+ kdDebug(32002) << " * " << hff->m_frameset->name()
+ << " pages:" << hff->m_startAtPage << "-" << (hff->m_endAtPage==-1?QString("(all)"):QString::number(hff->m_endAtPage))
+ << " page-selection:" << (hff->m_oddEvenAll==HeaderFooterFrameset::Odd ? "Odd" :
+ hff->m_oddEvenAll==HeaderFooterFrameset::Even ? "Even" : "All")
+ << " frames:" << hff->m_frameset->frameCount()
+ << " height:" << hff->m_height
+ << " spacing:" << hff->m_spacing << endl;
+#endif
+}
+
+bool KWFrameLayout::HeaderFooterFrameset::deleteFramesAfterLast( int lastPage )
+{
+ int lastFrame = lastFrameNumber( lastPage );
+#ifdef DEBUG_FRAMELAYOUT
+ //kdDebug(32002) << " Final cleanup: frameset " << m_frameset->name() << ": lastFrame=" << lastFrame << endl;
+#endif
+
+ KWTextFrameSet* fs = m_frameset;
+
+ // Special case for odd/even headers: keep at least one frame even if it doesn't appear,
+ // otherwise the frame properties are lost.
+ if ( fs->isHeaderOrFooter() && lastFrame == -1 ) {
+ fs->setVisible( false );
+ lastFrame = 0;
+ }
+
+ bool deleted = false;
+ while ( (int)fs->frameCount() - 1 > lastFrame ) {
+#ifdef DEBUG_FRAMELAYOUT
+ kdDebug(32002) << " Final cleanup: deleting frame " << fs->frameCount() - 1 << " of " << fs->name() << endl;
+#endif
+ fs->deleteFrame( fs->frameCount() - 1 );
+ deleted = true;
+ }
+ return deleted;
+}
+
+int KWFrameLayout::HeaderFooterFrameset::lastFrameNumber( int lastPage ) const {
+ if ( lastPage < m_startAtPage )
+ return -1; // we need none
+ int pg = lastPage;
+ if ( m_endAtPage > -1 )
+ pg = QMIN( m_endAtPage, pg );
+ pg -= m_startAtPage; // always >=0
+ Q_ASSERT( pg >= 0 );
+ switch (m_oddEvenAll) {
+ case Odd:
+ case Even:
+ return pg / 2; // page 0 and 1 -> 0. page 2 and 3 -> 1.
+ case All:
+ return pg; // page 0 -> 0 etc. ;)
+ default:
+ return -1;
+ }
+}
+
+int KWFrameLayout::HeaderFooterFrameset::frameNumberForPage( int page ) const
+{
+ if ( page < m_startAtPage || ( m_endAtPage != -1 && page > m_endAtPage ) )
+ return -1;
+ int pg = page - m_startAtPage; // always >=0
+ switch (m_oddEvenAll) {
+ case Odd:
+ // we test the absolute page number for odd/even, not pg!
+ if ( page % 2 )
+ return pg / 2; // page start+(0 or 1) -> frame 0, page start+(2 or 3) -> frame 1
+ else
+ return -1;
+ case Even:
+ if ( page % 2 == 0 )
+ return pg / 2; // page start+(0 or 1) -> frame 0, page start+(2 or 3) -> frame 1
+ else
+ return -1;
+ case All:
+ return pg; // page 0[+start] -> frame 0, etc.
+ default:
+ return -1;
+ }
+}
+
+/////
+
+void KWFrameLayout::layout( KWFrameSet* mainTextFrameSet, int numColumns,
+ int fromPage, int toPage, uint flags )
+{
+ //kdDebug(32002) << "KWFrameLayout::layout " << kdBacktrace() << endl;
+ // Just debug stuff
+#ifdef DEBUG_FRAMELAYOUT
+ kdDebug(32002) << "KWFrameLayout::layout " << fromPage << " to " << toPage << endl;
+ Q_ASSERT( toPage >= fromPage );
+ QPtrListIterator<HeaderFooterFrameset> itdbg( m_headersFooters );
+ for ( ; itdbg.current() ; ++itdbg )
+ itdbg.current()->debug();
+ QPtrListIterator<HeaderFooterFrameset> itdbg2( m_footnotes );
+ for ( ; itdbg2.current() ; ++itdbg2 )
+ itdbg2.current()->debug();
+ QPtrListIterator<HeaderFooterFrameset> itdbg3( m_endnotes );
+ for ( ; itdbg3.current() ; ++itdbg3 )
+ itdbg3.current()->debug();
+#endif
+#if 0 // old code
+ // Necessary for end notes: calculate where the text goes down to
+ Q_ASSERT( mainTextFrameSet->type() == FT_TEXT );
+ double textBottom = 0.0;
+ if ( mainTextFrameSet->hasFramesInPageArray() )
+ {
+ KoPoint textBottomPoint;
+ KoTextParag * lastParag = static_cast<KWTextFrameSet *>(mainTextFrameSet)->textDocument()->lastParag();
+ if ( lastParag->isValid() )
+ {
+ QRect rect = lastParag->rect();
+ int bottom = rect.top() + rect.height() + 2; // cf kwtextframeset
+#ifdef DEBUG_FRAMELAYOUT
+ kdDebug(32002) << "bottom LU=" << bottom << endl;
+#endif
+
+ if ( static_cast<KWTextFrameSet *>(mainTextFrameSet)->internalToDocument( QPoint(rect.left(), bottom), textBottomPoint ) )
+ textBottom = textBottomPoint.y();
+ }
+ }
+#ifdef DEBUG_FRAMELAYOUT
+ kdDebug(32002) << "textBottom = " << textBottom << "pt" << endl;
+#endif
+#endif
+ m_framesetsToUpdate.clear();
+ // Necessary for end notes: find out the last frame of the main textframeset
+ KWFrame* lastMainFrame = mainTextFrameSet->frameIterator().getLast();
+ double lastMainFrameBottom = lastMainFrame->bottom(); // before we change it below!
+
+ double ptColumnWidth = m_doc->ptColumnWidth();
+ int mainTextFrameResized = -1; // contains the page number of the first resized main textframe
+
+ // The main loop is: "for each page". We lay out each page separately.
+ for ( int pageNum = fromPage ; pageNum <= toPage ; ++pageNum )
+ {
+ KWPage *page = m_doc->pageManager()->page(pageNum);
+ double top = page->offsetInDocument() + page->topMargin();
+ double bottom = page->offsetInDocument() + page->height() - page->bottomMargin();
+ double left = page->leftMargin();
+ double right = page->width() - page->rightMargin();
+ Q_ASSERT( left < right );
+ KoRect oldColumnRect = firstColumnRect( mainTextFrameSet, pageNum, numColumns );
+#ifdef DEBUG_FRAMELAYOUT
+ kdDebug(32002) << " Page " << pageNum << endl;
+#endif
+
+ // For each header/footer....
+ for ( QPtrListIterator<HeaderFooterFrameset> it( m_headersFooters ); it.current() ; ++it )
+ {
+ int frameNum = it.current()->frameNumberForPage( pageNum );
+ if ( frameNum != -1 )
+ {
+ it.current()->m_positioned = true;
+ KWTextFrameSet* fs = it.current()->m_frameset;
+#ifdef DEBUG_FRAMELAYOUT
+ kdDebug(32002) << " Page " << pageNum << ": adding frame " << frameNum << " from " << fs->name() << endl;
+#endif
+ KoRect rect;
+ if ( fs->isAHeader() ) // add on top
+ {
+ rect.setRect( left, top, right - left, it.current()->m_height );
+ top += it.current()->m_height + it.current()->m_spacing;
+ } else // footer, add at bottom
+ {
+ double frameHeight = it.current()->m_height;
+ double frameTop = bottom - frameHeight;
+ rect.setRect( left, frameTop, right - left, frameHeight );
+ bottom -= frameHeight + it.current()->m_spacing;
+ }
+ Q_ASSERT( bottom > 0 );
+ Q_ASSERT( top < bottom );
+#ifdef DEBUG_FRAMELAYOUT
+ kdDebug(32002) << " rect:" << rect << " - new_top:" << top << " new_bottom:" << bottom << endl;
+#endif
+ resizeOrCreateHeaderFooter( fs, frameNum, rect );
+ }
+ }
+
+ // All headers/footers for this page have been done,
+ // now resize the frame from the main textframeset (if any)
+ // the first time _before_ doing the footnotes.
+ resizeMainTextFrame( mainTextFrameSet, pageNum, numColumns, ptColumnWidth, m_doc->ptColumnSpacing(), left, top, bottom, NoFootNote );
+
+ // Recalc footnote pages
+ checkFootNotes();
+
+ bool firstFootNote = true;
+
+ //// Stay seated... We need to know if there are any footnotes on top of us, although we're going
+ //// to lay them out _AFTER_. But we need their total height for the minY stuff.
+ //// So we first iterate over all footnotes of the page, to get their total height.
+ //// Then we'll reduce this height after every footnote being positionned, so it's always
+ //// the "height on top of us".
+ double totalFootNotesHeight = 0;
+ for ( QPtrListIterator<HeaderFooterFrameset> it( m_footnotes ); it.current() ; ++it )
+ {
+ int frameNum = it.current()->frameNumberForPage( pageNum );
+ if ( frameNum != -1 )
+ totalFootNotesHeight += it.current()->m_height;
+ }
+
+ // For each footnote (caller sorted them from bottom to top)
+ for ( QPtrListIterator<HeaderFooterFrameset> it( m_footnotes ); it.current() ; ++it )
+ {
+ int frameNum = it.current()->frameNumberForPage( pageNum );
+ if ( frameNum != -1 )
+ {
+ it.current()->m_positioned = true;
+ totalFootNotesHeight -= it.current()->m_height; // as discussed above
+ KWTextFrameSet* fs = it.current()->m_frameset;
+#ifdef DEBUG_FRAMELAYOUT
+ kdDebug(32002) << " Page " << pageNum << ": adding footnote frame " << frameNum << " from " << fs->name() << endl;
+#endif
+ KoRect rect;
+
+ // When two footnotes are in the same page there should be 0 spacing between them
+ // Yeah, write a generic frame layouter and then realize it's not flexible enough :(
+ if ( fs->isFootEndNote() && !firstFootNote )
+ {
+ // Undo "bottom -= spacing" (done below). This assumes equal spacing for all footnotes
+ bottom += it.current()->m_spacing;
+ bottom -= 1; // keep them one pixel apart though
+ }
+ double frameTop = bottom - it.current()->m_height;
+ double frameHeight = it.current()->m_height;
+
+ Q_ASSERT ( fs->isFootNote() );
+
+ // This is where we add the "total height of the footnotes on top of this one".
+ // The footnote variable can't be behind them....
+
+ double minY = it.current()->m_minY + totalFootNotesHeight;
+#ifdef DEBUG_FRAMELAYOUT
+ kdDebug(32002) << " footnote: frameHeight=" << frameHeight << " frameTop (" << frameTop << ") <? minY (" << minY << ")" << endl;
+#endif
+ if ( frameTop < minY )
+ {
+ // Ok, this is the complex case of a footnote var too far down in the page,
+ // and its footnote text is too big, so both won't fit.
+ // We do like other WPs: we create a frame on the next page
+ it.current()->m_endAtPage++; // this will do so
+
+ // In the current page we stop at minY
+ frameTop = minY;
+ frameHeight = bottom - frameTop;
+#ifdef DEBUG_FRAMELAYOUT
+ kdDebug(32002) << " footnote: new top=" << frameTop << " new height=" << frameHeight << " remaining height=" << it.current()->m_height - frameHeight << endl;
+#endif
+ Q_ASSERT( frameHeight < it.current()->m_height );
+ it.current()->m_height -= frameHeight; // calculate what remains to be done in the next frame
+ //fnFrameBehavior = KWFrame::Ignore;
+
+ // Make sure there'll actually be a next page
+ if ( pageNum == m_doc->pageCount()-1 ) {
+#ifdef DEBUG_FRAMELAYOUT
+ kdDebug(32002) << "Adding a page for the footnote overflow." << endl;
+#endif
+ m_doc->appendPage();
+ m_doc->updateAllFrames();
+ toPage = m_doc->pageCount()-1;
+ }
+ }
+
+ rect.setRect( left, frameTop, right - left, frameHeight );
+ bottom -= frameHeight + it.current()->m_spacing;
+ Q_ASSERT( bottom > 0 );
+ Q_ASSERT( top < bottom );
+#ifdef DEBUG_FRAMELAYOUT
+ kdDebug(32002) << " footnote rect:" << rect << " - new_top:" << top << " new_bottom:" << bottom << endl;
+#endif
+ resizeOrCreateHeaderFooter( fs, frameNum, rect );
+ firstFootNote = false;
+
+ // We added a footnote, update main text frame size
+#ifdef DEBUG_FRAMELAYOUT
+ kdDebug(32002) << " Laid out a footnote -> call resizeMainTextFrame/checkFootNotes again" << endl;
+#endif
+ resizeMainTextFrame( mainTextFrameSet, pageNum, numColumns, ptColumnWidth, m_doc->ptColumnSpacing(), left, top, bottom, WithFootNotes );
+ checkFootNotes();
+ }
+ } // for all footnotes
+
+ // Check for endnotes, on the last page of main text
+ // and on any end-notes-only page, i.e. after the last page of main text
+ if ( pageNum >= m_lastMainFramePage && m_doc->hasEndNotes() ) {
+ bool pageHasMainText = ( pageNum == m_lastMainFramePage );
+ if ( pageHasMainText )
+ lastMainFrame->setDrawFootNoteLine( true );
+ double textBottom = pageHasMainText ? lastMainFrameBottom : top;
+ // Leave some space on top of the endnotes, for the horizontal line
+ double endNoteTop = textBottom + m_doc->ptFootnoteBodySpacing();
+#ifdef DEBUG_FRAMELAYOUT
+ kdDebug(32002) << " Endnotes: textBottom=" << textBottom << "pt, endNoteTop=" << endNoteTop << "pt, bottom=" << bottom << "pt" << endl;
+#endif
+ bool firstEndNote = true;
+ for ( QPtrListIterator<HeaderFooterFrameset> it( m_endnotes ); it.current() ; ++it )
+ {
+ if ( ! it.current()->m_positioned )
+ {
+ KWTextFrameSet* fs = it.current()->m_frameset;
+#ifdef DEBUG_FRAMELAYOUT
+ kdDebug(32002) << " Page " << pageNum << ": adding endnote frame from " << fs->name() << endl;
+#endif
+ double frameHeight = it.current()->m_height;
+ if ( it.current()->m_startAtPage < 0 ) // not set yet
+ it.current()->m_startAtPage = pageNum;
+
+ // Check if the endnote is bigger than the available space
+ if ( endNoteTop + frameHeight > bottom )
+ {
+ // In the current page we stop at bottom
+ frameHeight = bottom - endNoteTop;
+
+ if ( frameHeight > 1E-10 ) // means, if frameHeight > 0
+ {
+#ifdef DEBUG_FRAMELAYOUT
+ kdDebug(32002) << " endnote: new height=" << frameHeight << " remaining height=" << it.current()->m_height - frameHeight << endl;
+#endif
+ Q_ASSERT( frameHeight < it.current()->m_height );
+ it.current()->m_height -= frameHeight; // calculate what remains to be done in the next frame
+ } else {
+ // No room at all on this page. Schedule for next page.
+ it.current()->m_startAtPage++;
+ break;
+ }
+ // Make sure there'll actually be a next page
+ if ( pageNum == m_doc->pageCount()-1 ) {
+#ifdef DEBUG_FRAMELAYOUT
+ kdDebug(32002) << "Adding a page for the endnote overflow." << endl;
+#endif
+ m_doc->appendPage();
+ m_doc->updateAllFrames();
+ toPage = m_doc->pageCount()-1;
+ }
+ }
+ else // It'll all fit in this page
+ {
+ it.current()->m_positioned = true;
+ }
+ KoRect rect( left, endNoteTop, right - left, frameHeight );
+ endNoteTop += frameHeight + 1; // not + it.current()->m_spacing;
+ Q_ASSERT( bottom > 0 );
+#ifdef DEBUG_FRAMELAYOUT
+ kdDebug(32002) << " rect:" << rect << " - new_top:" << endNoteTop << " new_bottom:" << bottom << endl;
+#endif
+ int frameNum = pageNum - it.current()->m_startAtPage;
+ resizeOrCreateHeaderFooter( fs, frameNum, rect );
+
+#if 0 // Disabled. The main frame is resized by KWTextFrameSet::slotAfterFormatting already.
+ if ( pageHasMainText && firstEndNote )
+ {
+ // We positionned the first endnote, update main text frame size
+#ifdef DEBUG_FRAMELAYOUT
+ kdDebug(32002) << " Laid out an endnote and the page has a maintextframe too -> call resizeMainTextFrame/checkFootNotes again top=" << top << " textBottom=" << textBottom << endl;
+#endif
+ resizeMainTextFrame( mainTextFrameSet, pageNum, numColumns, ptColumnWidth, m_doc->ptColumnSpacing(), left, top, textBottom, NoChange );
+ }
+#endif
+ } // if not positionned yet
+ firstEndNote = false; // yes, out of the if
+ } // for all endnotes
+ } // if page can have endnotes
+
+ if ( mainTextFrameResized == -1 ) {
+ // Test if the main text frame for this page was really resized or not.
+ KoRect newColumnRect = firstColumnRect( mainTextFrameSet, pageNum, numColumns );
+#ifdef DEBUG_FRAMELAYOUT
+ kdDebug(32002) << " Comparing old=" << oldColumnRect << " and new=" << newColumnRect << endl;
+#endif
+ if ( oldColumnRect != newColumnRect ) {
+ mainTextFrameResized = pageNum;
+#ifdef DEBUG_FRAMELAYOUT
+ kdDebug(32002) << " changed -> mainTextFrameResized=" << mainTextFrameResized << endl;
+#endif
+ }
+ }
+
+ } // for all pages
+ m_lastMainFramePage = lastMainFrame->pageNumber();
+#ifdef DEBUG_FRAMELAYOUT
+ kdDebug(32002) << "m_lastMainFramePage = " << m_lastMainFramePage << " lastMainFrameBottom=" << lastMainFrameBottom << endl;
+#endif
+
+ if ( ! ( flags & DontRemovePages ) )
+ {
+ m_doc->updateAllFrames( KWFrameSet::UpdateFramesInPage );
+ // Check if the last page is now empty (e.g. this can happen when removing
+ // some text above an endnote, so the endnote moves up)
+ (void)m_doc->tryRemovingPages();
+ }
+
+ const int lastPage = m_doc->lastPage();
+ // Final cleanup: delete all frames after lastFrameNumber in each frameset
+ QPtrListIterator<HeaderFooterFrameset> it( m_headersFooters );
+ for ( ; it.current() ; ++it )
+ if ( it.current()->deleteFramesAfterLast( lastPage ) )
+ m_framesetsToUpdate.insert( it.current()->m_frameset, true );
+ QPtrListIterator<HeaderFooterFrameset> it2( m_footnotes );
+ for ( ; it2.current() ; ++it2 )
+ if ( it2.current()->deleteFramesAfterLast( lastPage ) )
+ m_framesetsToUpdate.insert( it2.current()->m_frameset, true );
+ if ( mainTextFrameSet ) {
+ // For the last main text frameset, we use m_lastMainFramePage, so that
+ // there's no frame on the "end notes only" page(s).
+ int lastFrame = m_lastMainFramePage * numColumns + (numColumns-1);
+#ifdef DEBUG_FRAMELAYOUT
+ kdDebug(32002) << "lastFrame: " << lastFrame << " due to " << m_lastMainFramePage << endl;
+#endif
+ bool deleted = false;
+ while ( (int)mainTextFrameSet->frameCount() - 1 > lastFrame ) {
+#ifdef DEBUG_FRAMELAYOUT
+ kdDebug(32002) << " Final cleanup: deleting frame " << mainTextFrameSet->frameCount() - 1 << " of main textframeset (lastFrame=" << lastFrame << ")" << endl;
+#endif
+ mainTextFrameSet->deleteFrame( mainTextFrameSet->frameCount() - 1, true, false /*do not updateFrames!*/ );
+ deleted = true;
+ }
+ if ( deleted )
+ m_framesetsToUpdate.insert( mainTextFrameSet, true );
+ // The last frame before the first endnote, is in auto-extend mode
+ if ( m_doc->hasEndNotes() ) {
+ KWFrame* lastMainFrame = mainTextFrameSet->frameIterator().getLast();
+ if ( lastMainFrame->frameBehavior() != KWFrame::AutoExtendFrame )
+ {
+ lastMainFrame->setFrameBehavior( KWFrame::AutoExtendFrame );
+ // make sure it gets resized
+ if ( mainTextFrameResized == -1 )
+ mainTextFrameResized = lastMainFrame->pageNumber();
+ }
+ }
+ }
+
+ QMap<KWFrameSet*, bool>::iterator fsit = m_framesetsToUpdate.begin();
+ for ( ; fsit != m_framesetsToUpdate.end() ; ++fsit )
+ fsit.key()->updateFrames();
+
+ // ## TODO: only if something changed? (resizing, new frames, or deleted frames...)
+ KWFrameList::recalcFrames(m_doc, fromPage, toPage);
+
+ if ( mainTextFrameResized != -1 && mainTextFrameSet->type() == FT_TEXT ) {
+#ifdef DEBUG_FRAMELAYOUT
+ kdDebug(32002) << " Done. First maintextframe resized: " << mainTextFrameResized << endl;
+#endif
+ KWTextFrameSet* fs = static_cast<KWTextFrameSet *>(mainTextFrameSet);
+
+ // Not right now, this could be called during formatting...
+ //m_doc->invalidate();
+ // ### This means the layout will be done during painting. Not good.
+ // What about mainTextFrameSet->invalidate() or even layout()?
+ //QTimer::singleShot( 0, m_doc, SLOT( invalidate() ) );
+
+ // Invalidate main textframeset only, and from top of page only.
+ // Otherwise loading a long document (with headers/footers) takes ages,
+ // if we redo it all from the beginning at each new page!
+ int topLU, bottomLU;
+ if ( fs->minMaxInternalOnPage( mainTextFrameResized, topLU, bottomLU ) )
+ {
+ // Find parag at topLU
+ KoTextParag* parag = fs->paragAtLUPos( topLU );
+ if ( parag ) {
+#ifdef DEBUG_FRAMELAYOUT
+ kdDebug(32002) << " Invalidating from parag " << parag->paragId() << endl;
+#endif
+ fs->textObject()->setLastFormattedParag( parag );
+ fs->textObject()->formatMore( 2 );
+ }
+ }
+ }
+}
+
+void KWFrameLayout::resizeOrCreateHeaderFooter( KWTextFrameSet* headerFooter, uint frameNumber, const KoRect& rect )
+{
+ if ( frameNumber < headerFooter->frameCount() ) {
+ KWFrame* frame = headerFooter->frame( frameNumber );
+ if ( *frame == rect )
+ return;
+ frame->setRect( rect );
+#ifdef DEBUG_FRAMELAYOUT
+ kdDebug(32002) << "KWFrameLayout::resizeOrCreateHeaderFooter frame " << headerFooter->name() << " " << frame << " resized to " << rect << " pagenum=" << frame->pageNumber() << endl;
+#endif
+ }
+ else
+ {
+#ifdef DEBUG_FRAMELAYOUT
+ kdDebug(32002) << "KWFrameLayout::resizeOrCreateHeaderFooter creating frame for " << headerFooter->name() << endl;
+#endif
+ KWFrame* frame = new KWFrame( headerFooter, rect.x(), rect.y(), rect.width(), rect.height() );
+ frame->setFrameBehavior( KWFrame::AutoExtendFrame );
+ if ( headerFooter->isHeaderOrFooter() ) // not for footnotes!
+ {
+ frame->setNewFrameBehavior( KWFrame::Copy );
+ frame->setCopy( true );
+ }
+ else
+ frame->setNewFrameBehavior( KWFrame::NoFollowup );
+ headerFooter->addFrame( frame, false /*no recalc*/ );
+ }
+ // This updates e.g. availableHeight. Very important in the case
+ // of the footnote frameset with 2 frames.
+ headerFooter->updateFrames( 0 /*fast one*/ );
+ m_framesetsToUpdate.insert( headerFooter, true );
+}
+
+// Called at beginning and end of the layout for a given page,
+// to determine if the main-text-frame layout really changed or not.
+// Testing in resizeMainTextFrame doesn't work, we call it several times,
+// once for each footnote, so it can't detect the "no change" case.
+KoRect KWFrameLayout::firstColumnRect( KWFrameSet* mainTextFrameSet, int pageNum, int numColumns ) const
+{
+ uint frameNum = pageNum * numColumns /*+ col 0 here*/;
+ if ( mainTextFrameSet && frameNum < mainTextFrameSet->frameCount() )
+ return * mainTextFrameSet->frame( frameNum );
+ else
+ return KoRect();
+}
+
+bool KWFrameLayout::resizeMainTextFrame( KWFrameSet* mainTextFrameSet, int pageNum, int numColumns, double ptColumnWidth, double ptColumnSpacing, double left, double top, double bottom, HasFootNotes hasFootNotes )
+{
+ if ( !mainTextFrameSet )
+ return false;
+ bool mainTextFrameResized = false;
+ for ( int col = 0; col < numColumns; col++ ) {
+ Q_ASSERT( bottom > top );
+ // Calculate wanted rect for this frame
+ KoRect rect( left + col * ( ptColumnWidth + ptColumnSpacing ),
+ top, ptColumnWidth, bottom - top );
+ uint frameNum = (pageNum - m_doc->startPage()) * numColumns + col;
+ KWFrame* frame;
+ if ( frameNum < mainTextFrameSet->frameCount() ) {
+ // Resize existing frame
+ frame = mainTextFrameSet->frame( frameNum );
+ // Special case for last-frame-before-endnotes: don't resize its bottom
+ if ( m_doc->hasEndNotes() && pageNum >= m_lastMainFramePage )
+ rect.setBottom( frame->bottom() );
+ bool resized = (rect != *frame);
+ if ( resized ) {
+#ifdef DEBUG_FRAMELAYOUT
+ kdDebug(32002) << " Page " << pageNum << ": resizing main text frame " << frameNum << "(" << frame << ") to " << rect << endl;
+#endif
+ frame->setRect( rect );
+ frame->updateRulerHandles();
+ mainTextFrameResized = true;
+ mainTextFrameSet->updateFrames( 0xff - KWFrameSet::SortFrames ); // Don't sort frames yet!
+ }
+ } else {
+ // Create new frame
+ frame = new KWFrame( mainTextFrameSet, rect.x(), rect.y(), rect.width(), rect.height() );
+#ifdef DEBUG_FRAMELAYOUT
+ kdDebug(32002) << " Page " << pageNum << ": creating new main text frame " << frameNum << "(" << frame << ") to " << rect << endl;
+#endif
+ mainTextFrameSet->addFrame( frame );
+ Q_ASSERT( frameNum == mainTextFrameSet->frameCount()-1 );
+ mainTextFrameResized = true;
+ mainTextFrameSet->updateFrames( 0xff - KWFrameSet::SortFrames ); // Don't sort frames yet!
+ }
+ if ( hasFootNotes == NoFootNote )
+ frame->setDrawFootNoteLine( false );
+ else if ( hasFootNotes == WithFootNotes )
+ frame->setDrawFootNoteLine( true );
+ // unchanged in the other cases
+ // By default, all main-text frames are in "auto-create new frames" mode
+ frame->setFrameBehavior( KWFrame::AutoCreateNewFrame );
+ }
+ return mainTextFrameResized;
+}
+
+void KWFrameLayout::checkFootNotes()
+{
+ // We recalculate all footnotes pages, but we return true
+ // if those on pageNum have changed.
+ QPtrListIterator<HeaderFooterFrameset> it( m_footnotes );
+ for ( ; it.current() ; ++it )
+ {
+ HeaderFooterFrameset* hff = it.current();
+ if ( ! hff->m_positioned )
+ {
+ Q_ASSERT ( hff->m_frameset->isFootEndNote() );
+ KWFootNoteFrameSet* fnfs = static_cast<KWFootNoteFrameSet *>( hff->m_frameset );
+ KWFootNoteVariable* fnvar = fnfs->footNoteVariable();
+ //necessary to test paragraph because when we delete mutli
+ //footnote, first footnote who delete call setDelete(true)
+ //and force recalc, but with multi footnote deleted
+ //paragraph is null before we apply attribute to
+ //kotextcustom.
+ if ( !fnvar || !fnvar->paragraph() )
+ continue;
+ double varY = fnvar->varY();
+ if ( varY == 0 ) // not able to calculate it yet
+ continue;
+ hff->m_minY = varY + /*2 * */ hff->m_spacing + 2 /* some spacing */;
+ int pageNum = m_doc->pageManager()->pageNumber(varY);
+ if ( pageNum != hff->m_startAtPage ) {
+#ifdef DEBUG_FRAMELAYOUT
+ kdDebug(32002) << " checkFootNotes: found minY=" << hff->m_minY << " start/end=" << pageNum << " for footnote " << fnvar->text() << endl;
+#endif
+ hff->m_startAtPage = pageNum;
+ hff->m_endAtPage = pageNum;
+ }
+ }
+ }
+}
diff --git a/kword/KWFrameLayout.h b/kword/KWFrameLayout.h
new file mode 100644
index 00000000..c13d18b8
--- /dev/null
+++ b/kword/KWFrameLayout.h
@@ -0,0 +1,119 @@
+/* This file is part of the KOffice project
+ * Copyright (C) 2002 David Faure <faure@kde.org>
+ * Copyright (C) 2005 Thomas Zander <zander@kde.org>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; version 2.
+
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public License
+ * along with this library; see the file COPYING.LIB. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ */
+#ifndef KWFRAMELAYOUT_H
+#define KWFRAMELAYOUT_H
+
+#include <qptrlist.h>
+#include <kdebug.h>
+#include <KoRect.h>
+#include <qmap.h>
+
+class KWDocument;
+class KWFrameSet;
+class KWTextFrameSet;
+class KoRect;
+
+class KWFrameLayout
+{
+public:
+ // Maybe all that data should go into a KWHeaderFooterFrameSet
+ // (or rather a base class shared by KWFootNoteFrameSet....)
+ struct HeaderFooterFrameset {
+ enum OddEvenAll { Even, Odd, All };
+
+ HeaderFooterFrameset( KWTextFrameSet* fs, int start, int end,
+ double spacing, OddEvenAll oea = All );
+
+ // Frameset. Also gives the type (header, footer, footnote).
+ KWTextFrameSet* m_frameset;
+
+ // Future features - but already used for "first page" stuff
+ int m_startAtPage;
+ int m_endAtPage; // (-1 for no end)
+
+ // Odd/even/all
+ OddEvenAll m_oddEvenAll;
+
+ // Height in pt
+ double m_height;
+
+ // Space between this frame and the next one
+ // (the one at bottom for headers, the one on top for footers/footnotes).
+ // e.g. ptHeaderBodySpacing for headers/footers
+ double m_spacing;
+
+ // Minimum Y value - for footnotes
+ double m_minY;
+
+ // True once the footnote has been correctly positionned and
+ // shouldn't be moved by checkFootNotes anymore.
+ bool m_positioned;
+
+ // frame number for the given page.... -1 if no frame on that page
+ // The first frame is number 0.
+ int frameNumberForPage( int page ) const;
+ // The last frame we need (0-based), layout() will delete any frame after that
+ int lastFrameNumber( int lastPage ) const;
+
+ void debug();
+ bool deleteFramesAfterLast( int lastPage );
+ };
+
+ /**
+ * Constructor
+ * @param doc the KWDocument we're layouting
+ * @param headersFooters list of header and footer HFFs (see definition of HeaderFooterFrameset)
+ * @param footnotes list of footnotes framesets HFFs
+ * @param endnotes list of endnotes framesets HFFs
+ */
+ KWFrameLayout( KWDocument* doc, QPtrList<HeaderFooterFrameset>& headersFooters,
+ QPtrList<HeaderFooterFrameset>& footnotes, QPtrList<HeaderFooterFrameset>& endnotes )
+ : m_headersFooters( headersFooters ), m_footnotes( footnotes ), m_endnotes( endnotes ), m_doc( doc )
+ {}
+
+ enum { DontRemovePages = 1 };
+ /**
+ * The main method of this file. Do the frame layout.
+ * @param mainTextFrameSet if set, its frames will be resized. Usually: set in WP mode, not set in DTP mode.
+ * @param numColumns number of columns to create for the main textframeset. Only relevant if mainTextFrameSet!=0.
+ * @param fromPage first page to layout ( 0-based )
+ * @param toPage last page to layout ( 0-based )
+ * @param flags see enum above
+ */
+ void layout( KWFrameSet* mainTextFrameSet, int numColumns,
+ int fromPage, int toPage, uint flags );
+
+protected:
+ void resizeOrCreateHeaderFooter( KWTextFrameSet* headerFooter, uint frameNumber, const KoRect& rect );
+ KoRect firstColumnRect( KWFrameSet* mainTextFrameSet, int pageNum, int numColumns ) const;
+ enum HasFootNotes { NoFootNote, WithFootNotes, NoChange };
+ bool resizeMainTextFrame( KWFrameSet* mainTextFrameSet, int pageNum, int numColumns, double ptColumnWidth, double ptColumnSpacing, double left, double top, double bottom, HasFootNotes hasFootNotes );
+ void checkFootNotes();
+
+private:
+ // A _ref_ to a list. Must remain alive as long as this object.
+ QPtrList<HeaderFooterFrameset>& m_headersFooters;
+ QPtrList<HeaderFooterFrameset>& m_footnotes;
+ QPtrList<HeaderFooterFrameset>& m_endnotes;
+ QMap<KWFrameSet *, bool> m_framesetsToUpdate;
+ KWDocument* m_doc;
+ int m_lastMainFramePage;
+};
+
+#endif
diff --git a/kword/KWFrameList.cpp b/kword/KWFrameList.cpp
new file mode 100644
index 00000000..8df2da8d
--- /dev/null
+++ b/kword/KWFrameList.cpp
@@ -0,0 +1,197 @@
+/* This file is part of the KOffice project
+ * Copyright (C) 2005 Thomas Zander <zander@kde.org>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; version 2.
+
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public License
+ * along with this library; see the file COPYING.LIB. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ */
+#include <algorithm>
+#include "KWFrameList.h"
+#include "KWFrame.h"
+#include "KWFrameSet.h"
+#include "KWTextFrameSet.h"
+#include "KWDocument.h"
+#include "KWViewMode.h"
+#include "KWPageManager.h"
+
+//#define DEBUG_SPEED
+
+KWFrameList::KWFrameList(KWDocument *doc, KWFrame *theFrame) {
+ m_doc = doc;
+ m_frame = theFrame;
+
+ update();
+}
+
+QValueList<KWFrame *> KWFrameList::framesBelow() const {
+ QValueList<KWFrame *> frames;
+//kdDebug() << "framesBelow " << endl;
+
+ // Copy until we find m_frame
+ for ( QValueVector<KWFrame*>::const_iterator it = m_frames.begin(), end = m_frames.end(); it != end && *it != m_frame; ++it) {
+ frames.append( *it );
+ }
+
+ return frames;
+}
+
+QValueList<KWFrame *> KWFrameList::framesOnTop() const {
+//kdDebug() << "framesOnTop " << endl;
+ QValueList<KWFrame *> frames;
+
+ // Copy from m_frame to the end
+ bool found = false;
+ for ( QValueVector<KWFrame*>::const_iterator it = m_frames.begin(), end = m_frames.end(); it != end; ++it) {
+ KWFrame* frame = *it;
+ if ( found ) {
+ Q_ASSERT( !frame->frameSet()->isFloating() );
+ frames.append( frame );
+ }
+ else if ( frame == m_frame )
+ found = true;
+ }
+
+ return frames;
+}
+
+void KWFrameList::setFrames(const QPtrList<KWFrame> &frames) {
+ // kdDebug(31001) << "KWFrameList::setFrames for " << m_frame->frameSet()->name() << endl;
+ m_frames.clear();
+ if ( m_doc->layoutViewMode() && !m_doc->layoutViewMode()->hasFrames() )
+ return;
+
+ QPtrList<KWFrameSet> parentFramesets;
+ KWFrameSet *fs = m_frame->frameSet();
+ while(fs) {
+ parentFramesets.append(fs);
+ fs = (KWFrameSet*) fs->anchorFrameset();
+ }
+
+ // We now look at all other frames (in the same page)
+ // to check for intersections. This is o(n^2), but with n small.
+ QPtrListIterator<KWFrame> it( frames );
+ for ( ; it.current() ; ++it )
+ {
+ KWFrame* daFrame = it.current();
+ // kdDebug(32001) << "frame: " << daFrame->frameSet()->name() << endl;
+ if ( m_frame == daFrame ) {
+ m_frames.append( daFrame );
+ continue;
+ }
+ // Skip 'daFrame' if it belongs to a table.
+ // We trust that KWTableFrameSet will not make cells overlap ;)
+ if ( m_frame->frameSet()->groupmanager() || daFrame->frameSet()->groupmanager() )
+ continue;
+ // Skip all frames from the parent frameset, if 'm_frame' is floating
+ // ## might need a for loop for the case of inline-inside-inline,
+ // or maybe calling isPaintedBy instead [depending on what should happen for tables]
+ if ( daFrame->frameSet()->isFloating() &&
+ (parentFramesets.contains(daFrame->frameSet()->anchorFrameset()) ||
+ daFrame->frameSet()->isPaintedBy(m_frame->frameSet())) )
+ continue;
+ // Floating frames are not "on top", they are "inside".
+ // They are not "below" anything either - the parent frameset is.
+ if ( m_frame->frameSet()->isFloating() )
+ continue;
+ KoRect intersect = m_frame->intersect( daFrame->outerKoRect() );
+ if ( !intersect.isEmpty() )
+ m_frames.append( daFrame );
+ }
+ std::sort( m_frames.begin(), m_frames.end(), KWFrame::compareFrameZOrder );
+}
+
+void KWFrameList::updateAfterMove(int oldPageNum) {
+ int pageNumber = m_doc->pageManager()->pageNumber(m_frame);
+ updateZOrderFor(m_doc->framesInPage( pageNumber, false ));
+
+ if (pageNumber != oldPageNum)
+ updateZOrderFor(m_doc->framesInPage( oldPageNum, false ));
+}
+
+void KWFrameList::update() {
+ int pageNumber = m_doc->pageManager()->pageNumber(m_frame);
+ if(pageNumber == -1)
+ return;
+ updateZOrderFor(m_doc->framesInPage( pageNumber, false ));
+}
+
+void KWFrameList::updateZOrderFor(const QPtrList<KWFrame> &frames) {
+#ifdef DEBUG_SPEED
+ kdDebug(32001) << "KWFrameList::updateZOrderFor " << frames.count() << " frames"<< endl;
+ QTime dt;
+ dt.start();
+ int numberAdded = 0;
+#endif
+
+ QPtrListIterator<KWFrame> iter(frames);
+ while( iter.current() ) {
+ KWFrame *frame = iter.current();
+ Q_ASSERT( frame->frameStack() );
+
+ frame->frameStack()->setFrames(frames);
+#ifdef DEBUG_SPEED
+ numberAdded += frame->frameStack()->m_frames.count();
+#endif
+ ++iter;
+ }
+
+#ifdef DEBUG_SPEED
+ kdDebug(32001) << " updateZOrderFor took " << (float)(dt.elapsed()) / 1000 << " seconds, added " << numberAdded << " frames" << endl;
+#endif
+}
+
+// ****** statics ******
+KWFrameList *KWFrameList::getFirstFrameList(KWDocument *doc) {
+ for (QPtrListIterator<KWFrameSet> fsit = doc->framesetsIterator(); fsit.current() ; ++fsit ) {
+ KWFrame *frame = fsit.current()->frame(0);
+ if (frame && frame->frameStack())
+ return frame->frameStack();
+ }
+ return 0;
+}
+
+void KWFrameList::recalcFrames(KWDocument *doc, int pageFrom, int pageTo) {
+ for(int i=pageTo; i >= pageFrom; i--) {
+ QPtrList<KWFrame> framesOnPage = doc->framesInPage( i, false );
+ KWFrame *f = framesOnPage.first();
+ while(f) {
+ Q_ASSERT(f->frameStack());
+ f->frameStack()->setFrames(framesOnPage);
+ f = framesOnPage.next();
+ }
+ }
+}
+
+void KWFrameList::recalcAllFrames(KWDocument *doc) {
+ recalcFrames(doc, doc->startPage(), doc->lastPage());
+}
+
+void KWFrameList::createFrameList(KWFrame *f, KWDocument *doc) {
+ Q_ASSERT(f);
+ Q_ASSERT(doc);
+ if(f->frameStack())
+ return;
+ f->setFrameStack(new KWFrameList(doc, f));
+}
+
+void KWFrameList::createFrameList(KWFrameSet *fs, KWDocument *doc, bool forceUpdate) {
+ QPtrListIterator<KWFrame> iter( fs->frameIterator() );
+ KWFrame *f = iter.current();
+ while(f) {
+ createFrameList(f, doc);
+ if(forceUpdate)
+ f->frameStack()->update();
+ ++iter;
+ f = iter.current();
+ }
+}
diff --git a/kword/KWFrameList.h b/kword/KWFrameList.h
new file mode 100644
index 00000000..998b2a0d
--- /dev/null
+++ b/kword/KWFrameList.h
@@ -0,0 +1,111 @@
+/* This file is part of the KOffice project
+ * Copyright (C) 2005 Thomas Zander <zander@kde.org>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; version 2.
+
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public License
+ * along with this library; see the file COPYING.LIB. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ */
+#ifndef kw_framelist_h
+#define kw_framelist_h
+
+#include "KWFrame.h"
+
+#include <qptrlist.h>
+#include <qvaluevector.h>
+
+class KWDocument;
+
+/**
+ * This class calculates and caches a list of frames that are on top or below the KWFrame
+ * instance this class is created for.
+ */
+class KWFrameList {
+public:
+ /**
+ * Constructor.
+ * @param doc the document that will reference all framesets.
+ * @param theFrame the frame this framestack work for.
+ */
+ KWFrameList(KWDocument *doc, KWFrame *theFrame);
+
+ /**
+ * Fetches the frames below the frame this frameList is for.
+ */
+ QValueList<KWFrame *> framesBelow() const;
+
+ /**
+ * Fetches the frames on top of the frame this frameList is for.
+ */
+ QValueList<KWFrame *> framesOnTop() const;
+
+ /**
+ * Update the z-ordering around the frame we host the framelist for.
+ * This is typically called after this frame has been moved.
+ * This will make sure all frames on the same page will also be updated.
+ * @param oldPageNum a frame that has moved naturally has a previous page number which
+ * also needs to be updated because this frame has gone missing.
+ */
+ void updateAfterMove(int oldPageNum);
+
+ /**
+ * Update the z-ordering around the frame we host the framelist for.
+ * This will make sure all frames on the same page will also be updated.
+ */
+ void update();
+
+ /**
+ * Update the z-ordering for all frames of the whole document.
+ * @param doc the document where we can find the frames to be updated
+ */
+ static void recalcAllFrames(KWDocument *doc);
+
+ /**
+ * Update the z-ordering for all frames in the page section of the whole document.
+ * @param doc the document where we can find the frames to be updated
+ * @param pageFrom the first page that will be updated
+ * @param pageTo the last page (including) that will be updated
+ */
+ static void recalcFrames(KWDocument *doc, int pageFrom, int pageTo);
+
+ /**
+ * Factory method to create and attach a new instance of a framelist.
+ * Note; when an instance of a frameList already exists, calling this will do nothing.
+ * @param f the frame to add te new framelist to.
+ * @param doc the document that the frame belongs to.
+ */
+ static void createFrameList(KWFrame *f, KWDocument *doc);
+
+ /**
+ * Factory method to create and attach a new instance of a framelist to each frame
+ * on the frameset.
+ * Note; when an instance of a frameList already exists on a frame, calling this will
+ * not overwrite the one on that frame.
+ * @param fs the frameset to add te new framelists to.
+ * @param doc the document that the frame belongs to.
+ * @param forceUpdate when true, even already existing frameList instances will be
+ * updated.
+ * @see update();
+ */
+ static void createFrameList(KWFrameSet *fs, KWDocument *doc, bool forceUpdate=true);
+
+private:
+ static KWFrameList *getFirstFrameList(KWDocument *doc);
+ void updateZOrderFor(const QPtrList<KWFrame> &frames);
+ void setFrames(const QPtrList<KWFrame> &frames);
+
+ QValueVector<KWFrame *> m_frames; // sorted by Z Order
+ KWDocument *m_doc;
+ KWFrame *m_frame;
+};
+
+#endif
diff --git a/kword/KWFrameSet.cpp b/kword/KWFrameSet.cpp
new file mode 100644
index 00000000..154cd22b
--- /dev/null
+++ b/kword/KWFrameSet.cpp
@@ -0,0 +1,1277 @@
+/* This file is part of the KDE project
+ Copyright (C) 1998, 1999, 2000 Reginald Stadlbauer <reggie@kde.org>
+ Copyright (C) 2005 Thomas Zander <zander@kde.org>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+*/
+
+#include "KWFrameSet.h"
+#include "KWDocument.h"
+#include "KWViewMode.h"
+#include "KWCommand.h"
+#include "KWFrame.h"
+#include "KWTextFrameSet.h"
+#include "KWTableFrameSet.h"
+#include "KWAnchor.h"
+#include "KWordFrameSetIface.h"
+#include "KWFrameList.h"
+#include "KWPageManager.h"
+#include "KWPage.h"
+#include "KWFrameViewManager.h"
+#include "KWFrameView.h"
+
+#include <KoOasisContext.h>
+#include <KoXmlNS.h>
+#include <KoXmlWriter.h>
+
+#include <qpopupmenu.h>
+#include <qapplication.h>
+
+//#define DEBUG_DRAW
+
+KWFrameSet::KWFrameSet( KWDocument *doc )
+ : m_doc( doc ), m_frames(), m_framesInPage(), m_firstPage( 0 ), m_emptyList(),
+ m_info( FI_BODY ),
+ m_groupmanager( 0L ), m_visible( true ),
+ m_protectSize( false ),
+ m_anchorTextFs( 0L ), m_dcop( 0L ), m_pageManager( 0 )
+{
+ // Send our "repaintChanged" signals to the document.
+ setName("KWFrameSet");
+ if(m_doc) {
+ connect( this, SIGNAL( repaintChanged( KWFrameSet * ) ),
+ doc, SLOT( slotRepaintChanged( KWFrameSet * ) ) );
+ m_pageManager = doc->pageManager();
+ }
+ m_frames.setAutoDelete( true );
+ m_framesInPage.setAutoDelete( true ); // autodelete the lists in the array (not the frames;)
+}
+
+KWordFrameSetIface* KWFrameSet::dcopObject()
+ {
+ if ( !m_dcop )
+ m_dcop = new KWordFrameSetIface( this );
+
+ return m_dcop;
+}
+
+
+KWFrameSet::~KWFrameSet()
+{
+ delete m_dcop;
+}
+
+void KWFrameSet::addFrame( KWFrame *frame, bool recalc )
+{
+ if ( m_frames.findRef( frame ) != -1 )
+ return;
+
+ //kdDebug(32001) << k_funcinfo << name() << " adding frame" << frame << " recalc=" << recalc << endl;
+ if(m_doc)
+ KWFrameList::createFrameList(frame, m_doc);
+ frame->setFrameSet(this);
+ m_frames.append( frame );
+ if(recalc)
+ updateFrames();
+
+ emit sigFrameAdded(frame);
+}
+
+void KWFrameSet::deleteFrame( unsigned int num, bool remove, bool recalc )
+{
+ //kdDebug(32001) << k_funcinfo << name() << " deleting frame" << num << " remove=" << remove << " recalc=" << recalc << endl; //kdBacktrace();
+ KWFrame *frm = m_frames.at( num );
+ Q_ASSERT( frm );
+ m_frames.take( num );
+ Q_ASSERT( !m_frames.contains(frm) );
+
+ unsigned int index = frm->pageNumber() - m_firstPage;
+ if(m_framesInPage.count() >= index) {
+ QPtrList<KWFrame> *lst = m_framesInPage.at(index);
+ lst->remove(frm);
+ }
+
+ KWFrameList *stack = frm->frameStack();
+ if( stack ) {
+ stack->update(); // will update the other frames on the page.
+ frm->setFrameStack(0);
+ delete stack;
+ }
+ emit sigFrameRemoved(frm);
+ if ( !remove )
+ frm->setFrameSet(0L);
+ else {
+ // ###### should something similar be done when just removing a frame from the list?
+ frameDeleted( frm, recalc ); // inform kwtableframeset if necessary
+ delete frm;
+ //kdDebug(32001) << k_funcinfo << frm << " deleted. Now I have " << m_frames.count() << " m_frames" << endl;
+ }
+
+ if ( recalc )
+ updateFrames();
+}
+
+void KWFrameSet::deleteFrame( KWFrame *frm, bool remove, bool recalc )
+{
+ //kdDebug(32001) << "KWFrameSet::deleteFrame " << frm << " remove=" << remove << endl;
+ int num = m_frames.findRef( frm );
+ Q_ASSERT( num != -1 );
+ if ( num == -1 )
+ return;
+
+ deleteFrame( num, remove, recalc );
+}
+
+void KWFrameSet::deleteAllFrames()
+{
+ if ( !m_frames.isEmpty() )
+ {
+ for ( QPtrListIterator<KWFrame> frameIt( m_frames ); frameIt.current(); ++frameIt )
+ emit sigFrameRemoved( *frameIt );
+ m_frames.clear();
+ updateFrames();
+ }
+}
+
+void KWFrameSet::deleteAllCopies()
+{
+ if ( m_frames.count() > 1 )
+ {
+ KWFrame * firstFrame = m_frames.take(0);
+ deleteAllFrames();
+ m_frames.append( firstFrame );
+ updateFrames();
+ }
+}
+
+void KWFrameSet::createEmptyRegion( const QRect & crect, QRegion & emptyRegion, KWViewMode *viewMode )
+{
+ KWPage *page = m_doc->pageManager()->page( frame(0) );
+ if( !page ) {
+ kdWarning(31001) << "The first frame of '" << name() << "' is outside all pages!!" << endl;
+ return;
+ }
+ double paperHeight = page->height();
+ //kdDebug(32001) << "KWFrameSet::createEmptyRegion " << name() << endl;
+ for (QPtrListIterator<KWFrame> frameIt = frameIterator(); frameIt.current(); ++frameIt )
+ {
+ if ( !frameIt.current()->isTransparent() )
+ {
+ QRect outerRect( viewMode->normalToView( frameIt.current()->outerRect(viewMode) ) );
+ //kdDebug(32001) << "KWFrameSet::createEmptyRegion outerRect=" << outerRect << " crect=" << crect << endl;
+ outerRect &= crect; // This is important, to avoid calling subtract with a Y difference > 65536
+ if ( !outerRect.isEmpty() )
+ {
+ emptyRegion = emptyRegion.subtract( outerRect );
+ //kdDebug(32001) << "KWFrameSet::createEmptyRegion emptyRegion now: " << endl; DEBUGREGION( emptyRegion );
+ }
+ if ( crect.bottom() + paperHeight < outerRect.top() )
+ return; // Ok, we're far below the crect, abort.
+ }
+ }
+}
+
+void KWFrameSet::drawPadding( KWFrame *frame, QPainter *p, const QRect &crect, const QColorGroup &, KWViewMode *viewMode )
+{
+ QRect outerRect( viewMode->normalToView( frame->outerRect(viewMode) ) );
+ //kdDebug(32001) << "KWFrameSet::drawPadding frame: " << frameFromPtr( frame )
+ // << " outerRect: " << outerRect
+ // << " crect: " << crect << endl;
+
+ if ( !crect.intersects( outerRect ) )
+ {
+#ifdef DEBUG_DRAW
+ kdDebug(32001) << "KWFrameSet::drawPadding no intersection with " << crect << endl;
+#endif
+ return;
+ }
+ QRect frameRect( viewMode->normalToView( m_doc->zoomRect( *frame ) ) );
+ p->save();
+ QBrush bgBrush( frame->backgroundColor() );
+ bgBrush.setColor( KWDocument::resolveBgColor( bgBrush.color(), p ) );
+ p->setBrush( bgBrush );
+ int leftMargin = m_doc->zoomItX(frame->paddingLeft());
+ int topMargin = m_doc->zoomItY(frame->paddingTop());
+ int rightMargin = m_doc->zoomItX(frame->paddingRight());
+ int bottomMargin = m_doc->zoomItY(frame->paddingBottom());
+ //kdDebug(32001) << "KWFrameSet::drawPadding leftMargin=" << leftMargin << " topMargin=" << topMargin << " rightMargin=" << rightMargin << " bottomMargin=" << bottomMargin << endl;
+
+ if ( topMargin != 0 )
+ {
+ QRect r( frameRect.left(), frameRect.top(), frameRect.width(), topMargin );
+ p->fillRect( r, bgBrush );
+ }
+ if ( leftMargin != 0 )
+ {
+ QRect r( frameRect.left(), frameRect.top(), leftMargin, frameRect.height() );
+ p->fillRect( r, bgBrush );
+ }
+ if ( rightMargin != 0 )
+ {
+ QRect r( frameRect.right()-rightMargin, frameRect.top(), rightMargin, frameRect.height() );
+ p->fillRect( r, bgBrush );
+ }
+ if ( bottomMargin != 0 )
+ {
+ QRect r( frameRect.left(), frameRect.bottom()-bottomMargin, frameRect.width(), bottomMargin );
+ p->fillRect( r, bgBrush );
+ }
+ p->restore();
+
+}
+
+
+void KWFrameSet::drawFrameBorder( QPainter *painter, KWFrame *frame, KWFrame *settingsFrame, const QRect &crect, KWViewMode *viewMode )
+{
+ QRect outerRect( viewMode->normalToView( frame->outerRect( viewMode ) ) );
+ //kdDebug(32001) << "KWFrameSet::drawFrameBorder frame: " << frameFromPtr( frame )
+ // << " outerRect: " << outerRect << endl;
+
+ if ( !crect.intersects( outerRect ) )
+ {
+ //kdDebug(32001) << "KWFrameSet::drawFrameBorder no intersection with " << crect << endl;
+ return;
+ }
+
+ QRect frameRect( viewMode->normalToView( m_doc->zoomRect( *frame ) ) );
+
+ painter->save();
+ QBrush bgBrush( settingsFrame->backgroundColor() );
+ //bool defaultColor = !bgBrush.color().isValid();
+ bgBrush.setColor( KWDocument::resolveBgColor( bgBrush.color(), painter ) );
+ painter->setBrush( bgBrush );
+
+ // Draw default borders using view settings...
+ QPen viewSetting( QApplication::palette().color( QPalette::Active, QColorGroup::Mid ) );
+ int minBorder = 1;
+ // ...except when printing, or embedded doc, or disabled.
+ if ( !viewMode || !viewMode->drawFrameBorders() )
+ {
+ viewSetting = NoPen;
+ minBorder = 0;
+ }
+
+ // Draw borders either as the user defined them, or using the view settings.
+ // Borders should be drawn _outside_ of the frame area
+ // otherwise the frames will erase the border when painting themselves.
+
+ KoBorder::drawBorders( *painter, m_doc, frameRect,
+ settingsFrame->leftBorder(), settingsFrame->rightBorder(),
+ settingsFrame->topBorder(), settingsFrame->bottomBorder(),
+ minBorder, viewSetting );
+ painter->restore();
+}
+
+void KWFrameSet::setFloating()
+{
+ // Find main text frame
+ QPtrListIterator<KWFrameSet> fit = m_doc->framesetsIterator();
+ for ( ; fit.current() ; ++fit )
+ {
+ KWTextFrameSet * frameSet = dynamic_cast<KWTextFrameSet *>( fit.current() );
+ if ( !frameSet || frameSet->frameSetInfo() != FI_BODY )
+ continue;
+
+ KoTextParag* parag = 0L;
+ int index = 0;
+ KoPoint dPoint( m_frames.first()->topLeft() );
+ kdDebug(32001) << "KWFrameSet::setFloating looking for pos at " << dPoint.x() << " " << dPoint.y() << endl;
+ frameSet->findPosition( dPoint, parag, index );
+ // Create anchor. TODO: refcount the anchors!
+ setAnchored( frameSet, parag, index );
+ frameSet->layout();
+ m_doc->frameChanged( m_frames.first() );
+ return;
+ }
+}
+
+void KWFrameSet::setProtectSize( bool b)
+{
+ m_protectSize = b;
+}
+
+void KWFrameSet::setAnchored( KWTextFrameSet* textfs, int paragId, int index, bool placeHolderExists /* = false */, bool repaint )
+{
+ KWTextParag * parag = static_cast<KWTextParag *>( textfs->textDocument()->paragAt( paragId ) );
+ Q_ASSERT( parag );
+ if ( parag )
+ setAnchored( textfs, parag, index, placeHolderExists, repaint );
+}
+
+void KWFrameSet::setAnchored( KWTextFrameSet* textfs, KoTextParag* parag, int index, bool placeHolderExists /* = false */, bool repaint )
+{
+ kdDebug(32001) << "KWFrameSet::setAnchored " << textfs << " " << parag->paragId() << " " << index << " " << placeHolderExists << endl;
+ Q_ASSERT( textfs );
+ Q_ASSERT( parag );
+ if ( isFloating() )
+ deleteAnchors();
+ m_anchorTextFs = textfs;
+ KWFrameList::createFrameList(textfs, m_doc); // remove ourselves from others list now we are inline
+ if ( parag )
+ createAnchors( parag, index, placeHolderExists, repaint );
+
+ if ( !placeHolderExists ) // i.e. not while loading
+ {
+ m_doc->updateAllFrames(); // We just became floating, so we need to be removed from "frames on top/below".
+ // TODO pass page number to updateAllFrames - hmm, we could have several frames in theory
+ }
+}
+
+void KWFrameSet::setAnchored( KWTextFrameSet* textfs )
+{
+ m_anchorTextFs = textfs;
+ m_doc->updateAllFrames(); // We just became floating, so we need to be removed from "frames on top/below".
+ // TODO pass page number - hmm, we could have several frames in theory
+}
+
+// Find where our anchor is ( if we are anchored ).
+// We can't store a pointers to anchors, because over time we might change anchors
+// (Especially, undo/redo of insert/delete can reuse an old anchor and forget a newer one etc.)
+KWAnchor * KWFrameSet::findAnchor( int frameNum )
+{
+ Q_ASSERT( m_anchorTextFs );
+ // Yes, a linear search, but only among all customitems of the correct textdoc,
+ // whose number is assumed to be quite small.
+ QPtrListIterator<KoTextCustomItem> cit( m_anchorTextFs->textDocument()->allCustomItems() );
+ for ( ; cit.current() ; ++cit )
+ {
+ KWAnchor * anchor = dynamic_cast<KWAnchor *>( cit.current() );
+ if ( anchor && !anchor->isDeleted()
+ && anchor->frameSet() == this && anchor->frameNum() == frameNum )
+ return anchor;
+ }
+ kdWarning() << "KWFrameSet::findAnchor anchor not found (frameset='" << name()
+ << "' frameNum=" << frameNum << ")" << endl;
+ return 0L;
+}
+
+void KWFrameSet::setFixed()
+{
+ kdDebug(32001) << "KWFrameSet::setFixed" << endl;
+ if ( isFloating() )
+ deleteAnchors();
+ m_anchorTextFs = 0L;
+ // make sure the frames are on top
+ // (their z-order didn't matter when they were inline)
+ QPtrListIterator<KWFrame> frameIt = frameIterator();
+ for ( ; frameIt.current(); ++frameIt )
+ frameIt.current()->setZOrder( m_doc->maxZOrder( frameIt.current()->pageNumber(m_doc) ) + 1 );
+
+ m_doc->repaintAllViews();
+ m_doc->updateRulerFrameStartEnd();
+}
+
+KWAnchor * KWFrameSet::createAnchor( KoTextDocument *txt, int frameNum )
+{
+ KWAnchor * anchor = new KWAnchor( txt, this, frameNum );
+ return anchor;
+}
+
+void KWFrameSet::createAnchors( KoTextParag * parag, int index, bool placeHolderExists /*= false */ /*only used when loading*/,
+ bool repaint )
+{
+ kdDebug(32001) << "KWFrameSet::createAnchors" << endl;
+ Q_ASSERT( m_anchorTextFs );
+ QPtrListIterator<KWFrame> frameIt = frameIterator();
+ for ( ; frameIt.current(); ++frameIt, ++index )
+ {
+ //if ( ! frameIt.current()->anchor() )
+ {
+ // Anchor this frame, after the previous one
+ KWAnchor * anchor = createAnchor( m_anchorTextFs->textDocument(), frameFromPtr( frameIt.current() ) );
+ if ( !placeHolderExists )
+ parag->insert( index, KoTextObject::customItemChar() );
+ parag->setCustomItem( index, anchor, 0 );
+ }
+ }
+ parag->setChanged( true );
+ if ( repaint )
+ emit repaintChanged( m_anchorTextFs );
+}
+
+void KWFrameSet::deleteAnchor( KWAnchor * anchor )
+{
+ // Simple deletion, no undo/redo
+ KoTextCursor c( m_anchorTextFs->textDocument() );
+ c.setParag( anchor->paragraph() );
+ c.setIndex( anchor->index() );
+ anchor->setDeleted( true ); // this sets m_anchorTextFs to 0L
+
+ static_cast<KWTextParag*>(c.parag())->removeCustomItem(c.index());
+ c.remove(); // This deletes the character where the anchor was
+ // We don't delete the anchor since it might be in a customitemmap in a text-insert command
+ // TODO: refcount the anchors
+ c.parag()->setChanged( true );
+}
+
+void KWFrameSet::deleteAnchors()
+{
+ kdDebug(32002) << "KWFrameSet::deleteAnchors" << endl;
+ KWTextFrameSet * textfs = m_anchorTextFs;
+ Q_ASSERT( textfs );
+ if ( !textfs )
+ return;
+ //QPtrListIterator<KWFrame> frameIt = frameIterator();
+ int frameNum = 0;
+ // At the moment there's only one anchor per frameset
+ // With tables the loop below will be wrong anyway...
+ //for ( ; frameIt.current(); ++frameIt, ++frameNum )
+ {
+/* if ( frameIt.current()->anchor() )
+ deleteAnchor( frameIt.current()->anchor() );
+ frameIt.current()->setAnchor( 0L );
+*/
+ KWAnchor * anchor = findAnchor( frameNum );
+ deleteAnchor( anchor );
+ }
+ emit repaintChanged( textfs );
+}
+
+void KWFrameSet::moveFloatingFrame( int frameNum, const KoPoint &position )
+{
+ KWFrame * frame = m_frames.at( frameNum );
+ Q_ASSERT( frame );
+ if ( !frame ) return;
+
+ KoPoint pos( position );
+ // position includes the border, we need to adjust accordingly
+ pos.rx() += frame->leftBorder().width();
+ pos.ry() += frame->topBorder().width();
+ if ( frame->topLeft() != pos )
+ {
+ kdDebug(32002) << "KWFrameSet::moveFloatingFrame " << pos.x() << "," << pos.y() << endl;
+ int oldPageNum = frame->pageNumber();
+ frame->moveTopLeft( pos );
+
+ updateFrames();
+ if( frame->frameStack() )
+ frame->frameStack()->updateAfterMove( oldPageNum );
+ }
+ invalidate();
+}
+
+KoRect KWFrameSet::floatingFrameRect( int frameNum )
+{
+ KWFrame * frame = m_frames.at( frameNum );
+ Q_ASSERT( frame );
+ Q_ASSERT( isFloating() );
+
+ KWAnchor* anchor = findAnchor( frameNum );
+ Q_ASSERT( anchor );
+ QRect paragRect = anchor->paragraph()->rect();
+ int x = anchor->x() + paragRect.x(); // in LU
+ int y = anchor->y() + paragRect.y(); // in LU
+
+ KoPoint topLeft( m_doc->layoutUnitToPixelX( x ), m_doc->layoutUnitToPixelY( y ) );
+ return KoRect( topLeft, frame->outerKoRect().size() );
+}
+
+KoSize KWFrameSet::floatingFrameSize( int frameNum )
+{
+ KWFrame * frame = m_frames.at( frameNum );
+ Q_ASSERT( frame );
+ return frame->outerKoRect().size();
+}
+
+KCommand * KWFrameSet::anchoredObjectCreateCommand( int frameNum )
+{
+ KWFrame * frame = m_frames.at( frameNum );
+ Q_ASSERT( frame );
+ return new KWCreateFrameCommand( QString::null, frame );
+}
+
+KCommand * KWFrameSet::anchoredObjectDeleteCommand( int frameNum )
+{
+ KWFrame * frame = m_frames.at( frameNum );
+ Q_ASSERT( frame );
+ return new KWDeleteFrameCommand( QString::null, frame );
+}
+
+KWFrame * KWFrameSet::frameAtPos( double x, double y ) const
+{
+ KoPoint docPoint( x, y );
+ QPtrListIterator<KWFrame> frameIt = frameIterator();
+ for ( ; frameIt.current(); ++frameIt )
+ if ( frameIt.current()->contains( docPoint ) )
+ return frameIt.current();
+ return 0L;
+}
+
+KWFrame *KWFrameSet::frame( unsigned int num ) const
+{
+ // QPtrList sucks
+ return const_cast<KWFrameSet*>( this )->m_frames.at( num );
+}
+
+int KWFrameSet::frameFromPtr( KWFrame *frame )
+{
+ return m_frames.findRef( frame );
+}
+
+KWFrame * KWFrameSet::settingsFrame( const KWFrame* frame )
+{
+ if ( !frame->isCopy() )
+ return const_cast<KWFrame *>( frame );
+ KWFrame* lastRealFrame=0L;
+ QPtrListIterator<KWFrame> frameIt( frame->frameSet()->frameIterator() );
+ for ( ; frameIt.current(); ++frameIt )
+ {
+ KWFrame *curFrame = frameIt.current();
+ if ( curFrame == frame )
+ return lastRealFrame ? lastRealFrame : const_cast<KWFrame *>( frame );
+ if ( !lastRealFrame || !curFrame->isCopy() )
+ lastRealFrame = curFrame;
+ }
+ return const_cast<KWFrame *>( frame ); //fallback, should never happen
+}
+
+void KWFrameSet::updateFrames( int flags )
+{
+ if ( m_frames.isEmpty() )
+ return; // No frames. This happens when the frameset is deleted (still exists for undo/redo)
+
+ // Not visible ? Don't bother then.
+ if ( !isVisible() )
+ return;
+
+ //kdDebug(32001) << "KWFrameSet::updateFrames " << this << " " << name() << endl;
+
+ if ( flags & UpdateFramesInPage ) {
+ // For each of our frames, clear old list of frames on top, and grab min/max page nums
+ m_firstPage = m_frames.first()->pageNumber(); // we know m_frames is not empty here
+ int lastPage = m_firstPage;
+ QPtrListIterator<KWFrame> fIt( frameIterator() );
+ for ( ; fIt.current(); ++fIt ) {
+ int pg = fIt.current()->pageNumber();
+ m_firstPage = KMIN( m_firstPage, pg );
+ lastPage = KMAX( lastPage, pg );
+ }
+ //kdDebug(32001) << "firstPage=" << m_firstPage << " lastPage=" << lastPage << endl;
+
+ // Prepare the m_framesInPage structure
+ int oldSize = m_framesInPage.size();
+ m_framesInPage.resize( lastPage - m_firstPage + 1 );
+ // Clear the old elements
+ int oldElements = KMIN( oldSize, (int)m_framesInPage.size() );
+ for ( int i = 0 ; i < oldElements ; ++i )
+ m_framesInPage[i]->clear();
+ // Initialize the new elements.
+ for ( int i = oldElements ; i < (int)m_framesInPage.size() ; ++i )
+ m_framesInPage.insert( i, new QPtrList<KWFrame>() );
+
+ // Iterate over m_frames again, to fill the m_framesInPage array
+ fIt.toFirst();
+ for ( ; fIt.current(); ++fIt ) {
+ int pg = fIt.current()->pageNumber();
+ Q_ASSERT( pg <= lastPage );
+ m_framesInPage[pg - m_firstPage]->append( fIt.current() );
+ }
+ }
+
+ if ( isFloating() )
+ {
+ //kdDebug(32001) << "KWFrameSet::updateFrames " << name() << " is floating" << endl;
+ QPtrListIterator<KWFrame> frameIt = frameIterator();
+ int frameNum = 0;
+ // At the moment there's only one anchor per frameset
+ //for ( ; frameIt.current(); ++frameIt, ++frameNum )
+ {
+ KWAnchor * anchor = findAnchor( frameNum );
+ //kdDebug(32001) << "KWFrameSet::updateFrames anchor=" << anchor << endl;
+ if ( anchor )
+ anchor->resize();
+ }
+ }
+}
+
+bool KWFrameSet::isPaintedBy( KWFrameSet* fs ) const
+{
+ if ( fs == this )
+ return true;
+ if ( isFloating() )
+ {
+ KWFrameSet* parentFs = anchorFrameset();
+ if ( parentFs && parentFs->isPaintedBy( fs ) )
+ return true;
+ }
+ if ( groupmanager() )
+ {
+ if ( groupmanager()->isPaintedBy( fs ) )
+ return true;
+ }
+ return false;
+}
+
+const QPtrList<KWFrame> & KWFrameSet::framesInPage( int pageNum ) const
+{
+ if ( pageNum < m_firstPage || pageNum >= (int)m_framesInPage.size() + m_firstPage )
+ {
+#ifdef DEBUG_DTI
+ kdWarning(32002) << name() << " framesInPage called for pageNum=" << pageNum << ". "
+ << " Min value: " << m_firstPage
+ << " Max value: " << m_framesInPage.size() + m_firstPage - 1 << endl;
+#endif
+ return m_emptyList; // QPtrList<KWFrame>() doesn't work, it's a temporary
+ }
+ return * m_framesInPage[pageNum - m_firstPage];
+}
+
+void KWFrameSet::drawContents( QPainter *p, const QRect & crect, const QColorGroup &cg,
+ bool onlyChanged, bool resetChanged,
+ KWFrameSetEdit *edit, KWViewMode *viewMode,
+ KWFrameViewManager *frameViewManager )
+{
+#ifdef DEBUG_DRAW
+ kdDebug(32001) << "\nKWFrameSet::drawContents " << this << " " << name()
+ << " onlyChanged=" << onlyChanged << " resetChanged=" << resetChanged
+ << " crect= " << crect
+ << endl;
+#endif
+ if ( !viewMode->isTextModeFrameset( this ) )
+ {
+ QPtrListIterator<KWFrame> frameIt( frameIterator() );
+ KWFrame * lastRealFrame = 0L;
+ //double lastRealFrameTop = 0;
+ //double totalHeight = 0; // in pt, to avoid accumulating rounding errors
+ for ( ; frameIt.current(); )
+ {
+ KWFrame *frame = frameIt.current();
+ ++frameIt; // Point to the next one, to detect "last copy"
+ // The settings come from this frame
+ KWFrame * settingsFrame = ( frame->isCopy() && lastRealFrame ) ? lastRealFrame : frame;
+ bool lastCopy = !frameIt.current() || !frameIt.current()->isCopy();
+ drawFrameAndBorders( frame, p, crect, cg, onlyChanged,
+ // Only reset the changed flag in the last copy of a given frame (#60678)
+ resetChanged && lastCopy,
+ edit,
+ viewMode, settingsFrame, true /*transparency & double-buffering*/ );
+ if(viewMode->drawSelections() && frameViewManager) {
+ KWFrameView* view = frameViewManager->view(frame);
+ if(view)
+ view->paintFrameAttributes(p, crect, viewMode, m_doc);
+ }
+
+ if ( !lastRealFrame || !frame->isCopy() )
+ {
+ lastRealFrame = frame;
+ //lastRealFrameTop = totalHeight;
+ }
+ //totalHeight += frame->innerHeight();
+ }
+ }
+ else { // Text view mode
+ QRect normalRect = viewMode->viewToNormal(crect);
+ drawFrame( 0L /*frame*/, p, normalRect, crect, QPoint(KWViewModeText::OFFSET, 0),
+ 0L /*settingsFrame*/, cg, onlyChanged, resetChanged, edit, viewMode, true );
+ }
+}
+
+void KWFrameSet::drawFrameAndBorders( KWFrame *frame,
+ QPainter *painter, const QRect &crect,
+ const QColorGroup &cg, bool onlyChanged, bool resetChanged,
+ KWFrameSetEdit *edit, KWViewMode *viewMode,
+ KWFrame *settingsFrame, bool drawUnderlyingFrames )
+{
+ if ( !frame->isValid() )
+ {
+ kdDebug(32002) << "KWFrameSet::drawFrameAndBorders " << name() << " frame " << frameFromPtr( frame ) << " " << frame << " isn't valid" << endl;
+ return;
+ }
+
+ QRect normalOuterFrameRect( frame->outerRect( viewMode ) );
+ QRect outerFrameRect( viewMode->normalToView( normalOuterFrameRect ) );
+ QRect outerCRect = crect.intersect( outerFrameRect );
+#ifdef DEBUG_DRAW
+ kdDebug(32001) << "KWFrameSet::drawFrameAndBorders " << name() << " frame " << frameFromPtr( frame ) << " " << *frame << endl;
+ kdDebug(32001) << " (outer) normalFrameRect=" << normalOuterFrameRect << " frameRect=" << outerFrameRect << endl;
+ kdDebug(32001) << " crect=" << crect << " intersec=" << outerCRect << " todraw=" << !outerCRect.isEmpty() << endl;
+#endif
+ if ( !outerCRect.isEmpty() )
+ {
+ // Determine settingsFrame if not passed (for speedup)
+ if ( !settingsFrame )
+ settingsFrame = this->settingsFrame( frame );
+
+ QRect normalInnerFrameRect( m_doc->zoomRect( frame->innerRect() ) );
+ QRect innerFrameRect( viewMode->normalToView( normalInnerFrameRect ) );
+
+ // This translates the coordinates in the document contents
+ // ( frame and r are up to here in this system )
+ // into the frame's own coordinate system.
+ int offsetX = normalInnerFrameRect.left();
+ int offsetY = normalInnerFrameRect.top() - m_doc->zoomItY( frame->internalY() );
+
+ QRect innerCRect = outerCRect.intersect( innerFrameRect );
+ if ( !innerCRect.isEmpty() )
+ {
+ QRect fcrect = viewMode->viewToNormal( innerCRect );
+#ifdef DEBUG_DRAW
+ kdDebug(32001) << " (inner) normalFrameRect=" << normalInnerFrameRect << " frameRect=" << innerFrameRect << endl;
+ //kdDebug(32001) << " crect after view-to-normal:" << fcrect << "." << " Will move by (" << -offsetX << ", -(" << normalInnerFrameRect.top() << "-" << m_doc->zoomItY(frame->internalY()) << ") == " << -offsetY << ")." << endl;
+#endif
+ fcrect.moveBy( -offsetX, -offsetY );
+ Q_ASSERT( fcrect.x() >= 0 );
+ Q_ASSERT( fcrect.y() >= 0 );
+
+ // fcrect is now the portion of the frame to be drawn,
+ // in the frame's coordinates and in pixels
+#ifdef DEBUG_DRAW
+ kdDebug(32001) << "KWFrameSet::drawFrameAndBorders in frame coords:" << fcrect << ". Will translate painter by intersec-fcrect: " << innerCRect.x()-fcrect.x() << "," << innerCRect.y()-fcrect.y() << "." << endl;
+#endif
+ QRegion reg;
+ if ( drawUnderlyingFrames )
+ reg = frameClipRegion( painter, frame, outerCRect, viewMode );
+ else // false means we are being drawn _as_ an underlying frame, so no clipping!
+ reg = painter->xForm( outerCRect );
+ if ( !reg.isEmpty() )
+ {
+ painter->save();
+ painter->setClipRegion( reg );
+
+ drawFrame( frame, painter, fcrect, outerCRect,
+ innerCRect.topLeft() - fcrect.topLeft(), // This assume that viewToNormal() is only a translation
+ settingsFrame, cg, onlyChanged, resetChanged,
+ edit, viewMode, drawUnderlyingFrames );
+
+ if( !groupmanager() ) // not for table cells
+ drawFrameBorder( painter, frame, settingsFrame, outerCRect, viewMode );
+ painter->restore();
+ }
+ }
+ }
+}
+
+void KWFrameSet::drawFrame( KWFrame *frame, QPainter *painter, const QRect &fcrect, const QRect &outerCRect,
+ const QPoint& translationOffset,
+ KWFrame *settingsFrame, const QColorGroup &cg, bool onlyChanged, bool resetChanged,
+ KWFrameSetEdit *edit, KWViewMode* viewMode, bool drawUnderlyingFrames )
+{
+ // In this method the painter is NOT translated yet. It's still in view coordinates.
+ if ( outerCRect.isEmpty() )
+ return;
+#ifdef DEBUG_DRAW
+ kdDebug(32001) << "\nKWFrameSet::drawFrame " << name() << " outerCRect=" << outerCRect << " frameCrect=" << fcrect << " drawUnderlyingFrames=" << drawUnderlyingFrames << endl;
+#endif
+ Q_ASSERT( fcrect.isValid() );
+
+ QColorGroup frameColorGroup( cg );
+ if ( settingsFrame ) // 0L in text viewmode
+ {
+ QBrush bgBrush( settingsFrame->backgroundColor() );
+ bgBrush.setColor( KWDocument::resolveBgColor( bgBrush.color(), painter ) );
+ frameColorGroup.setBrush( QColorGroup::Base, bgBrush );
+ }
+
+ if ( drawUnderlyingFrames && frame && frame->frameStack()) {
+ QValueList<KWFrame*> below = frame->frameStack()->framesBelow();
+ if ( !below.isEmpty() )
+ {
+ // Double-buffering - not when printing
+ QPainter* doubleBufPainter = painter;
+ QPixmap* pix = 0L;
+ if ( painter->device()->devType() != QInternal::Printer )
+ {
+ pix = m_doc->doubleBufferPixmap( outerCRect.size() );
+ doubleBufPainter = new QPainter;
+ doubleBufPainter->begin( pix );
+ // Initialize the pixmap to the page background color
+ // (if the frame is over the page margins, no underlying frame will paint anything there)
+ doubleBufPainter->fillRect( 0, 0, outerCRect.width(), outerCRect.height(), QApplication::palette().active().brush( QColorGroup::Base ) );
+
+ // The double-buffer pixmap has (0,0) at outerCRect.topLeft(), so we need to
+ // translate the double-buffer painter; drawFrameAndBorders will draw using view coordinates.
+ doubleBufPainter->translate( -outerCRect.x(), -outerCRect.y() );
+#ifdef DEBUG_DRAW
+ // kdDebug(32001) << " ... using double buffering. Portion covered: " << outerCRect << endl;
+#endif
+ }
+
+ // Transparency handling
+#ifdef DEBUG_DRAW
+ kdDebug(32001) << " below: " << below.count() << endl;
+#endif
+ for (QValueListIterator<KWFrame*> it = below.begin(); it != below.end(); ++it )
+ {
+ KWFrame* f = (*it);
+
+#ifdef DEBUG_DRAW
+ kdDebug(32001) << " looking at frame below us: " << f->frameSet()->name() << " frame " << frameFromPtr( frame ) << endl;
+#endif
+ QRect viewFrameCRect = outerCRect.intersect( viewMode->normalToView( f->outerRect( viewMode ) ) );
+ if ( !viewFrameCRect.isEmpty() )
+ {
+#ifdef DEBUG_DRAW
+ kdDebug(32001) << " viewFrameRect=" << viewFrameCRect << " calling drawFrameAndBorders." << endl;
+#endif
+ f->frameSet()->drawFrameAndBorders( f, doubleBufPainter, viewFrameCRect, cg,
+ false, resetChanged, edit, viewMode, 0L, false );
+ }
+ }
+
+ if ( frame->paddingLeft() || frame->paddingTop() || frame->paddingRight() || frame->paddingBottom() )
+ drawPadding( frame, doubleBufPainter, outerCRect, cg, viewMode );
+ doubleBufPainter->save();
+#ifdef DEBUG_DRAW
+ kdDebug(32001) << " translating by " << translationOffset.x() << ", " << translationOffset.y() << " before drawFrameContents" << endl;
+#endif
+ doubleBufPainter->translate( translationOffset.x(), translationOffset.y() ); // This assume that viewToNormal() is only a translation
+ // We can't "repaint changed parags only" if we just drew the underlying frames, hence the "false"
+ drawFrameContents( frame, doubleBufPainter, fcrect, frameColorGroup, false, resetChanged, edit, viewMode );
+ doubleBufPainter->restore();
+
+ if ( painter->device()->devType() != QInternal::Printer )
+ {
+ doubleBufPainter->end();
+#ifdef DEBUG_DRAW
+ kdDebug(32001) << " painting double-buf pixmap at position " << outerCRect.topLeft() << " (real painter pos:" << painter->xForm( outerCRect.topLeft() ) << ")" << endl;
+#endif
+ painter->drawPixmap( outerCRect.topLeft(), *pix );
+ delete doubleBufPainter;
+ }
+ return; // done! :)
+ }
+ else
+ {
+ // nothing below? paint a bg color then
+ frameColorGroup.setBrush( QColorGroup::Base, m_doc->defaultBgColor( painter ) );
+ }
+ }
+ if ( frame && (frame->paddingLeft() || frame->paddingTop() ||
+ frame->paddingRight() || frame->paddingBottom()) )
+ drawPadding( frame, painter, outerCRect, cg, viewMode );
+ painter->save();
+ painter->translate( translationOffset.x(), translationOffset.y() );
+
+ drawFrameContents( frame, painter, fcrect, frameColorGroup, onlyChanged, resetChanged, edit, viewMode );
+ painter->restore();
+}
+
+void KWFrameSet::drawFrameContents( KWFrame *, QPainter *, const QRect &,
+ const QColorGroup &, bool, bool, KWFrameSetEdit*, KWViewMode * )
+{
+ kdWarning() << "Default implementation of drawFrameContents called for " << className() << " " << this << " " << name() << kdBacktrace();
+}
+
+void KWFrameSet::saveCommon( QDomElement &parentElem, bool saveFrames )
+{
+ if ( m_frames.isEmpty() ) // Deleted frameset -> don't save
+ return;
+
+ // Save all the common attributes for framesets.
+ parentElem.setAttribute( "frameType", static_cast<int>( type() ) );
+ parentElem.setAttribute( "frameInfo", static_cast<int>( m_info ) );
+ parentElem.setAttribute( "name", m_name );
+ parentElem.setAttribute( "visible", static_cast<int>( m_visible ) );
+ parentElem.setAttribute( "protectSize", static_cast<int>( m_protectSize ) );
+ if ( saveFrames )
+ {
+ QPtrListIterator<KWFrame> frameIt = frameIterator();
+ for ( ; frameIt.current(); ++frameIt )
+ {
+ KWFrame *frame = frameIt.current();
+ QDomElement frameElem = parentElem.ownerDocument().createElement( "FRAME" );
+ parentElem.appendChild( frameElem );
+
+ frame->save( frameElem );
+
+ if(m_doc->processingType() == KWDocument::WP) {
+ // Assume that all header/footer frames in the same frameset are
+ // perfect copies. This might not be the case some day though.
+ if(frameSetInfo() == FI_FIRST_HEADER ||
+ frameSetInfo() == FI_EVEN_HEADER ||
+ frameSetInfo() == FI_ODD_HEADER ||
+ frameSetInfo() == FI_FIRST_FOOTER ||
+ frameSetInfo() == FI_EVEN_FOOTER ||
+ frameSetInfo() == FI_ODD_FOOTER ||
+ frameSetInfo() == FI_FOOTNOTE) break;
+ }
+ }
+ }
+}
+
+//
+// This function is intended as a helper for all the derived classes. It reads
+// in all the attributes common to all framesets and loads all frames.
+//
+void KWFrameSet::load( QDomElement &framesetElem, bool loadFrames )
+{
+ m_info = static_cast<KWFrameSet::Info>( KWDocument::getAttribute( framesetElem, "frameInfo", KWFrameSet::FI_BODY ) );
+ m_visible = static_cast<bool>( KWDocument::getAttribute( framesetElem, "visible", true ) );
+ m_protectSize=static_cast<bool>( KWDocument::getAttribute( framesetElem, "protectSize", false ) );
+ if ( loadFrames )
+ {
+ // <FRAME>
+ QDomElement frameElem = framesetElem.firstChild().toElement();
+ for ( ; !frameElem.isNull() ; frameElem = frameElem.nextSibling().toElement() )
+ {
+ if ( frameElem.tagName() == "FRAME" )
+ {
+ KoRect rect;
+ rect.setLeft( KWDocument::getAttribute( frameElem, "left", 0.0 ) );
+ rect.setTop( KWDocument::getAttribute( frameElem, "top", 0.0 ) );
+ rect.setRight( KWDocument::getAttribute( frameElem, "right", 0.0 ) );
+ rect.setBottom( KWDocument::getAttribute( frameElem, "bottom", 0.0 ) );
+ KWFrame * frame = new KWFrame(this, rect.x(), rect.y(), rect.width(), rect.height() );
+ frame->load( frameElem, this, m_doc->syntaxVersion() );
+ addFrame( frame, false );
+ m_doc->progressItemLoaded();
+ }
+ }
+ }
+}
+
+KWFrame* KWFrameSet::loadOasisFrame( const QDomElement& tag, KoOasisContext& context )
+{
+ double width = 100;
+ if ( tag.hasAttributeNS( KoXmlNS::svg, "width" ) ) { // fixed width
+ // TODO handle percentage (of enclosing table/frame/page)
+ width = KoUnit::parseValue( tag.attributeNS( KoXmlNS::svg, "width", QString::null ) );
+ } else if ( tag.hasAttributeNS( KoXmlNS::fo, "min-width" ) ) {
+ // min-width is not supported in KWord. Let's use it as a fixed width.
+ width = KoUnit::parseValue( tag.attributeNS( KoXmlNS::fo, "min-width", QString::null ) );
+ } else {
+ kdWarning(32001) << "Error in frame " << tag.tagName() << " " << tag.attributeNS( KoXmlNS::draw, "name", QString::null ) << " : neither width nor min-width specified!" << endl;
+ }
+ double height = 100;
+ if ( tag.hasAttributeNS( KoXmlNS::svg, "height" ) ) { // fixed height
+ // TODO handle percentage (of enclosing table/frame/page)
+ height = KoUnit::parseValue( tag.attributeNS( KoXmlNS::svg, "height", QString::null ) );
+ }
+ //kdDebug(32001) << k_funcinfo << "width=" << width << " height=" << height << " pt" << endl;
+
+ KWFrame * frame = new KWFrame(this,
+ KoUnit::parseValue( tag.attributeNS( KoXmlNS::svg, "x", QString::null ) ),
+ KoUnit::parseValue( tag.attributeNS( KoXmlNS::svg, "y", QString::null ) ),
+ width, height );
+
+ frame->setZOrder( tag.attributeNS( KoXmlNS::draw, "z-index", QString::null ).toInt() );
+ // Copy-frames.
+ // We currently ignore the value of the copy-of attribute. It probably needs to
+ // be handled like chain-next-name (kwtextframeset.cc) but for all types of frameset.
+ frame->setCopy( tag.hasAttributeNS( KoXmlNS::draw, "copy-of" ) );
+ frame->loadCommonOasisProperties( context, this, "graphic" );
+
+ addFrame( frame, false );
+
+ // Protect (OASIS 14.27.7, also in OO-1.1)
+ // A frame with protected contents means that the frameset is protected (makes sense)
+ // A frame with protected size means that the frameset is size-protected (hmm, kword did it that way)
+ // TODO implement position protection
+ QString protectList = context.styleStack().attributeNS( KoXmlNS::style, "protect" );
+ if ( protectList.contains( "content" ) )
+ setProtectContent( true );
+ if ( protectList.contains( "size" ) )
+ m_protectSize = true;
+
+ // TODO m_visible ? User-toggeable or internal?
+
+ return frame;
+}
+
+void KWFrameSet::setVisible( bool v )
+{
+ m_visible = v;
+ if ( m_visible )
+ // updateFrames was disabled while we were invisible
+ updateFrames();
+}
+
+bool KWFrameSet::isVisible( KWViewMode* viewMode ) const
+{
+ if ( !m_visible || m_frames.isEmpty() )
+ return false;
+ if ( isAHeader() && !m_doc->isHeaderVisible() )
+ return false;
+ if ( isAFooter() && !m_doc->isFooterVisible() )
+ return false;
+ if ( viewMode && !viewMode->isFrameSetVisible(this) )
+ return false;
+ if ( isFloating() && !anchorFrameset()->isVisible( viewMode ) )
+ return false;
+
+ KoHFType ht = m_doc != 0 ? m_doc->headerType(): HF_FIRST_DIFF;
+ KoHFType ft = m_doc != 0 ? m_doc->footerType(): HF_FIRST_DIFF;
+ switch( m_info )
+ {
+ case FI_FIRST_HEADER:
+ return ( ht == HF_FIRST_DIFF || ht == HF_FIRST_EO_DIFF );
+ case FI_ODD_HEADER:
+ return true;
+ case FI_EVEN_HEADER:
+ return ( ht == HF_EO_DIFF || ht == HF_FIRST_EO_DIFF );
+ case FI_FIRST_FOOTER:
+ return ( ft == HF_FIRST_DIFF || ft == HF_FIRST_EO_DIFF );
+ case FI_ODD_FOOTER:
+ return true;
+ case FI_EVEN_FOOTER:
+ return ( ft == HF_EO_DIFF || ft == HF_FIRST_EO_DIFF );
+ default:
+ return true;
+ }
+}
+
+bool KWFrameSet::isAHeader() const
+{
+ return ( m_info == FI_FIRST_HEADER || m_info == FI_ODD_HEADER || m_info == FI_EVEN_HEADER );
+}
+
+bool KWFrameSet::isAFooter() const
+{
+ return ( m_info == FI_FIRST_FOOTER || m_info == FI_ODD_FOOTER || m_info == FI_EVEN_FOOTER );
+}
+
+bool KWFrameSet::isFootEndNote() const
+{
+ return m_info == FI_FOOTNOTE;
+}
+
+bool KWFrameSet::isMainFrameset() const
+{
+ return ( m_doc && m_doc->processingType() == KWDocument::WP &&
+ m_doc->frameSet( 0 ) == this );
+}
+
+bool KWFrameSet::isMoveable() const
+{
+ if ( isHeaderOrFooter() )
+ return false;
+ return !isMainFrameset() && !isFloating();
+}
+
+const char* KWFrameSet::headerFooterTag() const
+{
+ switch ( m_info ) {
+ case KWFrameSet::FI_ODD_HEADER:
+ return "style:header";
+ case KWFrameSet::FI_EVEN_HEADER:
+ return "style:header-left";
+ case KWFrameSet::FI_ODD_FOOTER:
+ return "style:footer";
+ case KWFrameSet::FI_EVEN_FOOTER:
+ return "style:footer-left";
+ case KWFrameSet::FI_FIRST_HEADER:
+ return "style:header-first"; // NOT OASIS COMPLIANT
+ case KWFrameSet::FI_FIRST_FOOTER:
+ return "style:footer-first"; // NOT OASIS COMPLIANT
+ default: // shouldn't be called for body or footnote
+ return 0;
+ }
+}
+
+void KWFrameSet::finalize()
+{
+ //kdDebug(32001) << "KWFrameSet::finalize ( calls updateFrames + zoom ) " << this << endl;
+ updateFrames();
+}
+
+QRegion KWFrameSet::frameClipRegion( QPainter * painter, KWFrame *frame, const QRect & crect,
+ KWViewMode * viewMode )
+{
+// KWDocument * doc = kWordDocument();
+ QRect rc = painter->xForm( crect );
+#ifdef DEBUG_DRAW
+ //kdDebug(32002) << "KWFrameSet::frameClipRegion rc initially " << rc << endl;
+#endif
+
+ Q_ASSERT( frame );
+#if 0 // done later
+ if ( clipFrame )
+ {
+ rc &= painter->xForm( viewMode->normalToView( doc->zoomRect( (*frame) ) ) ); // intersect
+#ifdef DEBUG_DRAW
+ kdDebug(32002) << "KWFrameSet::frameClipRegion frame=" << *frame
+ << " clip region rect=" << rc
+ << " rc.isEmpty()=" << rc.isEmpty() << endl;
+#endif
+ }
+#endif
+ if ( !rc.isEmpty() )
+ {
+ QRegion reg( rc );
+ // This breaks when a frame is under another one, it still appears if !onlyChanged.
+ // cvs log says this is about frame borders... hmm.
+ /// ### if ( onlyChanged )
+
+ Q_ASSERT( frame->frameStack() );
+
+ QValueList<KWFrame *> onTop = frame->frameStack()->framesOnTop();
+ for (QValueListIterator<KWFrame*> fIt = onTop.begin(); fIt != onTop.end(); ++fIt )
+ {
+ KWFrame* frameOnTop = (*fIt);
+ Q_ASSERT( frameOnTop->frameSet() );
+ QRect r = painter->xForm( viewMode->normalToView( frameOnTop->outerRect( viewMode ) ) );
+#ifdef DEBUG_DRAW
+ //kdDebug(32002) << "frameClipRegion subtract rect "<< r << endl;
+#endif
+ reg -= r; // subtract
+ }
+#ifdef DEBUG_DRAW
+ //kdDebug(32002) << "KWFrameSet::frameClipRegion result:" << reg << endl;
+#endif
+ return reg;
+ }
+ return QRegion();
+}
+
+bool KWFrameSet::canRemovePage( int num )
+{
+ QPtrListIterator<KWFrame> frameIt( frameIterator() );
+ for ( ; frameIt.current(); ++frameIt )
+ {
+ KWFrame * frame = frameIt.current();
+ if ( frame->pageNumber() == num ) // ## TODO: use framesInPage, see KWTextFrameSet
+ {
+ // Ok, so we have a frame on that page -> we can't remove it unless it's a copied frame
+ if ( ! ( frame->isCopy() && frameIt.current() != m_frames.first() ) )
+ {
+ kdDebug(32001) << "KWFrameSet::canRemovePage " << name() << " frame on page " << num << " -> false" << endl;
+ return false;
+ }
+ }
+ }
+ return true;
+}
+
+void KWFrameSet::setFrameBehavior( KWFrame::FrameBehavior fb ) {
+ for(KWFrame *f=m_frames.first();f;f=m_frames.next())
+ f->setFrameBehavior(fb);
+}
+
+void KWFrameSet::setNewFrameBehavior( KWFrame::NewFrameBehavior nfb ) {
+ for(KWFrame *f=m_frames.first();f;f=m_frames.next())
+ f->setNewFrameBehavior(nfb);
+}
+
+// ## this should pass the viewmode as argument, probably.
+bool KWFrameSet::isFrameAtPos( const KWFrame* frame, const QPoint& point, bool borderOfFrameOnly) const {
+ QRect outerRect( frame->outerRect( m_doc->layoutViewMode() ) );
+ // Give the user a bit of margin for clicking on it :)
+ const int margin = 2;
+ outerRect.rLeft() -= margin;
+ outerRect.rTop() -= margin;
+ outerRect.rRight() += margin;
+ outerRect.rBottom() += margin;
+ if ( outerRect.contains( point ) ) {
+ if(borderOfFrameOnly) {
+ QRect innerRect( m_doc->zoomRect( *frame ) );
+ innerRect.rLeft() += margin;
+ innerRect.rTop() += margin;
+ innerRect.rRight() -= margin;
+ innerRect.rBottom() -= margin;
+ return (!innerRect.contains(point) );
+ }
+ return true;
+ }
+ return false;
+}
+
+void KWFrameSet::setZOrder()
+{
+ //kdDebug(32001) << "KWFrameSet::setZOrder (to max) " << name() << endl;
+ QPtrListIterator<KWFrame> fit = frameIterator();
+ for ( ; fit.current() ; ++fit )
+ fit.current()->setZOrder( m_doc->maxZOrder( fit.current()->pageNumber(m_doc) ) + 1 );
+}
+
+void KWFrameSet::setName( const QString &name )
+{
+ m_name = name;
+ emit sigNameChanged(this);
+}
+
+#ifndef NDEBUG
+#include "KWFrameViewManager.h"
+#include "KWFrameView.h"
+void KWFrameSet::printDebug()
+{
+ static const char * typeFrameset[] = { "base", "txt", "picture", "part", "formula", "clipart",
+ "6", "7", "8", "9", "table",
+ "ERROR" };
+ static const char * infoFrameset[] = { "body", "first header", "even headers", "odd headers",
+ "first footer", "even footers", "odd footers", "footnote", "ERROR" };
+ static const char * frameBh[] = { "AutoExtendFrame", "AutoCreateNewFrame", "Ignore", "ERROR" };
+ static const char * newFrameBh[] = { "Reconnect", "NoFollowup", "Copy" };
+ static const char * runaround[] = { "No Runaround", "Bounding Rect", "Skip", "ERROR" };
+ static const char * runaroundSide[] = { "Biggest", "Left", "Right", "ERROR" };
+
+ KWFrameViewManager *fvm = 0;
+ if ( !m_doc->getAllViews().isEmpty() ) {
+ KWView *view = m_doc->getAllViews().first();
+ if(view)
+ fvm = view->frameViewManager();
+ }
+
+ kdDebug() << " | Visible: " << isVisible() << endl;
+ kdDebug() << " | Type: " << typeFrameset[ type() ] << endl;
+ kdDebug() << " | Info: " << infoFrameset[ frameSetInfo() ] << endl;
+ kdDebug() << " | Floating: " << isFloating() << endl;
+ kdDebug() << " | Frames in page array: " << endl;
+ for ( uint i = 0 ; i < m_framesInPage.size() ; ++i )
+ {
+ QPtrListIterator<KWFrame> it( *m_framesInPage[i] );
+ int pgNum = i + m_firstPage;
+ for ( ; it.current() ; ++it )
+ kdDebug() << " | " << pgNum << ": " << it.current() << " " << *it.current()
+ << " internalY=" << it.current()->internalY() << "pt "
+ << " (in LU pix:" << m_doc->ptToLayoutUnitPixY( it.current()->internalY() ) << ")"
+ << " innerHeight=" << it.current()->innerHeight()
+ << " (in LU pix:" << m_doc->ptToLayoutUnitPixY( it.current()->innerHeight() ) << ")"
+ << endl;
+ }
+
+ QPtrListIterator<KWFrame> frameIt = frameIterator();
+ for ( unsigned int j = 0; frameIt.current(); ++frameIt, ++j ) {
+ KWFrame * frame = frameIt.current();
+ QCString copy = frame->isCopy() ? "[copy]" : "";
+ kdDebug() << " +-- Frame " << j << " of "<< frameCount() << " (" << frame << ") " << copy << endl;
+ printDebug( frame );
+ kdDebug() << " Rectangle : " << frame->x() << "," << frame->y() << " " << frame->width() << "x" << frame->height() << endl;
+ kdDebug() << " RunAround: "<< runaround[ frame->runAround() ] << " side:" << runaroundSide[ frame->runAroundSide() ]<< endl;
+ kdDebug() << " FrameBehavior: "<< frameBh[ frame->frameBehavior() ] << endl;
+ kdDebug() << " NewFrameBehavior: "<< newFrameBh[ frame->newFrameBehavior() ] << endl;
+ QColor col = frame->backgroundColor().color();
+ kdDebug() << " BackgroundColor: "<< ( col.isValid() ? col.name().latin1() : "(default)" ) << endl;
+ kdDebug() << " SheetSide "<< frame->sheetSide() << endl;
+ kdDebug() << " Z Order: " << frame->zOrder() << endl;
+
+ if( frame->frameStack() ) {
+ QValueList<KWFrame*> onTop = frame->frameStack()->framesOnTop();
+ QValueList<KWFrame*> below = frame->frameStack()->framesBelow();
+
+ kdDebug() << " Frames below: " << below.count()
+ << ", frames on top: " << onTop.count() << endl;
+ }
+ else
+ kdDebug() << " no frameStack set." << endl;
+ kdDebug() << " minFrameHeight "<< frame->minimumFrameHeight() << endl;
+ QString page = pageManager() && pageManager()->pageCount() > 0 ? QString::number(frame->pageNumber()) : " [waiting for pages to be created]";
+
+ KWFrameView *fv = 0;
+ if(fvm) fv = fvm->view(frame);
+ if(fv && fv->selected())
+ kdDebug() << " * Page "<< page << endl;
+ else
+ kdDebug() << " Page "<< page << endl;
+ }
+}
+
+void KWFrameSet::printDebug( KWFrame * )
+{
+}
+
+#endif
+
+#include "KWFrameSet.moc"
diff --git a/kword/KWFrameSet.h b/kword/KWFrameSet.h
new file mode 100644
index 00000000..2bba5e54
--- /dev/null
+++ b/kword/KWFrameSet.h
@@ -0,0 +1,504 @@
+/* This file is part of the KDE project
+ Copyright (C) 1998, 1999, 2000 Reginald Stadlbauer <reggie@kde.org>
+ Copyright (C) 2005 Thomas Zander <zander@kde.org>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+*/
+
+#ifndef frame_set_h
+#define frame_set_h
+
+#include "KWFrame.h"
+#include <qptrvector.h>
+#include <qptrlist.h>
+#include "qdom.h"
+
+class KWAnchor;
+class KWFrame;
+class KWFrameSetEdit;
+class KWPageManager;
+class KWTableFrameSet;
+class KWTextFrameSet;
+class KWTextFrameSetEdit;
+class KWTextParag;
+class KWView;
+class KWordFrameSetIface;
+class KWFrameViewManager;
+
+class KoSavingContext;
+class KoTextDocument;
+class KoTextFormat;
+class KoTextParag;
+class KoXmlWriter;
+
+class KCommand;
+class QPoint;
+class QProgressDialog;
+
+
+/**
+ * Class: KWFrameSet
+ * Base type, a frameset holds content as well as frames to show that
+ * content.
+ * The different types of content are implemented in the different
+ * types of frameSet implementations (see below)
+ * @see KWTextFrameSet, KWPartFrameSet, KWPictureFrameSet,
+ * KWFormulaFrameSet, KWTableFrameSet
+ */
+class KWFrameSet : public QObject
+{
+ Q_OBJECT
+public:
+ /// constructor
+ KWFrameSet( KWDocument *doc );
+ /// destructor
+ virtual ~KWFrameSet();
+
+ virtual KWordFrameSetIface* dcopObject();
+
+ /** The type of frameset. Use this to differentiate between different instantiations of
+ * the framesets. Each implementation will return a different frameType.
+ */
+ virtual FrameSetType type() const { return FT_BASE; }
+
+ virtual void addTextFrameSets( QPtrList<KWTextFrameSet> & /*lst*/, bool /*onlyReadWrite*/ = false ) {};
+ virtual bool ownLine() const { return FALSE;}
+
+ /** The different types of textFramesets (that TEXT is important here!)
+ * FI_BODY = normal text frames.<br>
+ * FI_FIRST_HEADER = Header on page 1<br>
+ * FI_EVEN_HEADER = header on any even page<br>
+ * FI_ODD_HEADER = header on any odd page (can be including page 1)<br>
+ * FI_FIRST_FOOTER = footer on page 1<br>
+ * FI_EVEN_FOOTER = footer on any even page<br>
+ * FI_ODD_FOOTER = footer on any odd page (can be including page 1)<br>
+ * FI_FOOTNOTE = a footnote frame.
+ */
+ enum Info { FI_BODY = 0, FI_FIRST_HEADER = 1, FI_EVEN_HEADER = 2, FI_ODD_HEADER = 3,
+ FI_FIRST_FOOTER = 4, FI_EVEN_FOOTER = 5, FI_ODD_FOOTER = 6,
+ FI_FOOTNOTE = 7 };
+ /** Returns the type of TextFrameSet this is */
+ Info frameSetInfo()const { return m_info; }
+ /** Set the type of TextFrameSet this is */
+ void setFrameSetInfo( Info fi ) { m_info = fi; }
+
+ bool isAHeader() const;
+ bool isAFooter() const;
+ bool isHeaderOrFooter() const { return isAHeader() || isAFooter(); }
+ bool isFootEndNote() const;
+ const char* headerFooterTag() const; // for OASIS saving
+
+ virtual bool isFootNote() const { return false; }
+ virtual bool isEndNote() const { return false; }
+
+ bool isMainFrameset() const;
+ bool isMoveable() const;
+
+ // frame management
+ virtual void addFrame( KWFrame *_frame, bool recalc = true );
+
+ /** Delete a frame from the set of frames this frameSet has.
+ * @param num The frameNumber to be removed.
+ * @param remove passing true means that there can not be an undo of the action.
+ * @param recalc do an updateFrames()
+ */
+ virtual void deleteFrame( unsigned int num, bool remove = true, bool recalc = true );
+
+ /** Delete a frame from the set of frames this frameSet has.
+ * @param frm The frame that should be deleted
+ * @param remove passing true means that there can not be an undo of the action.
+ * @param recalc do an updateFrames()
+ */
+ void deleteFrame( KWFrame *frm, bool remove = true, bool recalc = true ); // calls the virtual one
+
+ /// Called by deleteFrame when it really deletes a frame (remove=true), to remove it from the table too
+ virtual void frameDeleted( KWFrame* /*frm*/, bool /*recalc*/ ) {}
+
+ void deleteAllFrames();
+ void deleteAllCopies(); /// \note for headers/footers only
+
+ /** retrieve frame from x and y coords (unzoomed coords) */
+ KWFrame *frameAtPos( double _x, double _y ) const;
+
+ /** Return if the point is on the frame.
+ * @param nPoint the point in normal coordinates.
+ * @param borderOfFrameOnly when true an additional check is done if the point
+ * is on the border.
+ * @param frame the frame to check inside of
+ */
+ bool isFrameAtPos( const KWFrame* frame, const QPoint& nPoint, bool borderOfFrameOnly=false ) const;
+
+ /** get a frame by number */
+ KWFrame *frame( unsigned int _num ) const;
+
+ /**
+ * Returns the original frame that the param frame is a copy off, or the frame itself.
+ * For changing a frame that is a copy of another (as found in KWFrame::isCopy()) you
+ * need a so called settings frame, or original frame. This method can savely be called
+ * on any frame to make sure you are dealing with the original frame.
+ * @param frame the frame to find the settings frame for.
+ * @return the frame itself if its not a copy, or the original frame if it is one.
+ */
+ static KWFrame * settingsFrame( const KWFrame* frame );
+
+ /** Iterator over the child frames */
+ const QPtrList<KWFrame> &frameIterator() const { return m_frames; }
+ /** Get frame number */
+ int frameFromPtr( KWFrame *frame );
+ /** Get number of child frames */
+ unsigned int frameCount() const { return m_frames.count(); }
+
+ /** True if the frameset was deleted (but not destroyed, since it's in the undo/redo) */
+ bool isDeleted() const { return m_frames.isEmpty(); }
+
+ /** Create a framesetedit object to edit this frameset in @p canvas */
+ virtual KWFrameSetEdit * createFrameSetEdit( KWCanvas * ) { return 0; }
+
+ /**
+ * Let the caller know which parts of @p emptyRegion we do not claim, and thus the caller is
+ * free to paint on without interfering with later paints from us.
+ * For painting all frames of all framesets the painter needs to find out what area we
+ * will fill with a background color and possibly paint over.
+ * What this method does is fill an QRegion with all the areas we are going to fill, which
+ * typically means we will paint the background of a frame there.
+ * @param emptyRegion The region is modified to subtract the areas painted, thus
+ * allowing the caller to determine which areas remain to be painted.
+ * Framesets that can be transparent should reimplement this and make it a no-op,
+ * so that the background is painted below the transparent frame.
+ * @param crect the cliprect; only parts inside this rect are of interrest to us
+ * @param viewMode For coordinate conversion, always set.
+ */
+ virtual void createEmptyRegion( const QRect & crect, QRegion & emptyRegion, KWViewMode *viewMode );
+
+ /**
+ * Paint this frameset
+ * @param painter The painter in which to draw the contents of the frameset
+ * @param crect The rectangle (in scrollview "contents coordinates", i.e. "view coords")
+ * to be painted
+ * @param cg The colorgroup from which to get the colors
+ * @param onlyChanged If true, only redraw what has changed (see KWCanvas::repaintChanged)
+ * @param resetChanged If true, set the changed flag to false after drawing.
+ * @param edit If set, this frameset is being edited, so a cursor is needed.
+ * @param viewMode For coordinate conversion, always set.
+ * @param frameViewManager the frameViewManager;
+ *
+ * The way this "onlyChanged/resetChanged" works is: when something changes,
+ * all views are asked to redraw themselves with onlyChanged=true.
+ * But all views except the last one shouldn't reset the changed flag to false,
+ * otherwise the other views wouldn't repaint anything.
+ * So resetChanged is called with "false" for all views except the last one,
+ * and with "true" for the last one, so that it resets the flag.
+ *
+ * Framesets shouldn't reimplement this one in theory [but KWTableFrameSet has to].
+ */
+ virtual void drawContents( QPainter *painter, const QRect &crect,
+ const QColorGroup &cg, bool onlyChanged, bool resetChanged,
+ KWFrameSetEdit *edit, KWViewMode *viewMode,
+ KWFrameViewManager *frameViewManager );
+
+ /**
+ * This one is called by drawContents for each frame.
+ * It sets up clip rect and painter translation, and calls drawFrame, drawFrameBorder and drawMargins
+ *
+ * @param drawUnderlyingFrames if the frame implements it, then it should draw underlying frames.
+ * This is set to false by the default drawFrame implementation, so that the frames under a
+ * transparent frame are simply drawn, without transparency handling (nor their own
+ * double-buffering).
+ * @param frame the frame to draw
+ * @param painter the painter to draw to
+ * @param settingsFrame The frame from which we take the settings (usually @p frame, but not with Copy behaviour)
+ * @param cg The colorgroup from which to get the colors
+ * @param edit If set, this frameset is being edited, so a cursor is needed.
+ * @param viewMode For coordinate conversion, always set.
+ * @param crect rectangle to be repainted, in view coordinates. Includes padding.
+ */
+ void drawFrameAndBorders( KWFrame *frame,
+ QPainter *painter, const QRect &crect,
+ const QColorGroup &cg, bool, bool,
+ KWFrameSetEdit *edit, KWViewMode *viewMode,
+ KWFrame *settingsFrame, bool drawUnderlyingFrames );
+
+ /**
+ * Paint the borders for one frame of this frameset.
+ * @param painter The painter in which to draw the contents of the frameset
+ * @param frame The frame to be drawn
+ * @param settingsFrame The frame from which we take the settings (usually @p frame, but not with Copy behaviour)
+ * @param crect The rectangle (in "contents coordinates") to be painted
+ * @param viewMode For coordinate conversion, always set.
+ */
+ void drawFrameBorder( QPainter *painter, KWFrame *frame, KWFrame *settingsFrame,
+ const QRect &crect, KWViewMode *viewMode );
+
+ /**
+ * Draw a particular frame of this frameset.
+ * This is called by drawContents and is what framesets must reimplement.
+ * @param fcrect rectangle to be repainted, in the _frame_'s coordinate system, in pixels.
+ * Doesn't include padding.
+ *
+ * @param crect rectangle to be repainted, in view coordinates. Includes padding.
+ * Default implementation does double-buffering and calls drawFrameContents.
+ * @param frame the frame to draw
+ * @param painter the painter to draw to
+ * @param settingsFrame The frame from which we take the settings (usually @p frame, but not with Copy behaviour)
+ * @param cg The colorgroup from which to get the colors
+ * @param onlyChanged If true, only redraw what has changed (see KWCanvas::repaintChanged)
+ * @param resetChanged If true, set the changed flag to false after drawing.
+ * @param edit If set, this frameset is being edited, so a cursor is needed.
+ * @param viewMode For coordinate conversion, always set.
+ * @param drawUnderlyingFrames if the frame implements it, then it should draw underlying frames.
+ * @param translationOffset offset this method will translate the paiter before doing its work.
+ */
+ virtual void drawFrame( KWFrame *frame, QPainter *painter, const QRect &fcrect, const QRect &crect,
+ const QPoint& translationOffset,
+ KWFrame *settingsFrame, const QColorGroup &cg, bool onlyChanged, bool resetChanged,
+ KWFrameSetEdit *edit, KWViewMode *viewMode, bool drawUnderlyingFrames );
+
+ /**
+ * Implement this one instead of drawFrame to benefit from double-buffering
+ * AND transparency handling (painting frames below this one) automatically.
+ * You MUST reimplement one or the other, or you'll get infinite recursion ;)
+ *
+ * In this method, the painter has been translated to the frame's coordinate system
+ * @param fcrect rectangle to be repainted, in the _frame_'s coordinate system, in pixels.
+ * Doesn't include padding.
+ * @param frame the frame to draw
+ * @param painter the painter to draw to
+ * @param cg The colorgroup from which to get the colors
+ * @param onlyChanged If true, only redraw what has changed (see KWCanvas::repaintChanged)
+ * @param resetChanged If true, set the changed flag to false after drawing.
+ * @param edit If set, this frameset is being edited, so a cursor is needed.
+ * @param viewMode For coordinate conversion, always set.
+ */
+ virtual void drawFrameContents( KWFrame * frame, QPainter *painter, const QRect& fcrect,
+ const QColorGroup &cg, bool onlyChanged, bool resetChanged,
+ KWFrameSetEdit * edit, KWViewMode *viewMode );
+
+ /**
+ * Draw the padding area inside of a specific frame of this frameSet
+ */
+ virtual void drawPadding( KWFrame *frame, QPainter *p, const QRect &fcrect, const QColorGroup &cg, KWViewMode *viewMode);
+
+ enum UpdateFramesFlags {
+ UpdateFramesInPage = 1,
+ SortFrames = 2 ///< kwtextframeset only
+ // next one is 4, not 3 ;)
+ };
+ /**
+ * Called when our frames change, or when another frameset's frames change.
+ * Framesets can reimplement it, but should always call the parent method.
+ */
+ virtual void updateFrames( int flags = 0xff );
+
+ /** Return list of frames in page @p pageNum.
+ * This is fast since it uses the m_framesInPage array.*/
+ const QPtrList<KWFrame> & framesInPage( int pageNum ) const;
+
+ /** Allows to detect that updateFrames() hasn't been called yet (e.g. on loading) */
+ bool hasFramesInPageArray() const { return !m_framesInPage.isEmpty(); }
+
+ /** relayout text in frames, so that it flows correctly around other frames */
+ virtual void layout() {}
+ virtual void invalidate() {}
+
+ /// save to XML - when saving
+ virtual QDomElement save( QDomElement &parentElem, bool saveFrames = true ) = 0;
+ /// save to XML - when copying to clipboard
+ virtual QDomElement toXML( QDomElement &parentElem, bool saveFrames = true )
+ { return save( parentElem, saveFrames ); }
+ /// Save to OASIS format
+ virtual void saveOasis( KoXmlWriter& writer, KoSavingContext& context, bool saveFrames ) const = 0;
+ /// If the frameset is inline, is it ok to save it inside an oasis <text:p>?
+ /// If not, KWAnchor will create a textbox around it.
+ virtual bool canBeSavedAsInlineCharacter() const { return true; }
+
+ /// load from XML - when loading
+ virtual void load( QDomElement &framesetElem, bool loadFrames = true );
+ KWFrame* loadOasisFrame( const QDomElement& tag, KoOasisContext& context );
+ /// load from XML - when pasting from clipboard
+ virtual void fromXML( QDomElement &framesetElem, bool loadFrames = true, bool /*useNames*/ = true )
+ { load( framesetElem, loadFrames ); }
+
+ virtual QString toPlainText() const { return QString::null; }
+
+ //virtual void preparePrinting( QPainter *, QProgressDialog *, int & ) { }
+
+ /** Called once the frameset has been completely loaded or constructed.
+ * The default implementation calls updateFrames() and zoom(). Call the parent :) */
+ virtual void finalize();
+
+ virtual int paragraphs() { return 0; }
+ virtual int paragraphsSelected() { return 0; }
+ virtual bool statistics( QProgressDialog * /*progress*/, ulong & /*charsWithSpace*/, ulong & /*charsWithoutSpace*/, ulong & /*words*/,
+ ulong & /*sentences*/, ulong & /*syllables*/, ulong & /*lines*/, bool /*process only selected */ ) { return true; }
+
+ KWDocument* kWordDocument() const { return m_doc; }
+
+ /// Return true if page @p num can be removed, as far as this frameset is concerned
+ virtual bool canRemovePage( int num );
+
+ //Note: none of those floating-frameset methods creates undo/redo
+ //They are _called_ by the undo/redo commands.
+
+ /// Make this frameset floating (anchored), as close to its current position as possible.
+ void setFloating();
+ /**
+ * Make this frameset anchored, with the anchor at @p paragId,@p index in the text frameset @p textfs.
+ * Also used during OASIS loading (placeHolderExists=true)
+ */
+ void setAnchored( KWTextFrameSet* textfs, KoTextParag* parag, int index, bool placeHolderExists = false, bool repaint = true );
+ /** Make this frameset floating, with the anchor at @p paragId,@p index in the text frameset @p textfs.
+ * \deprecated
+ */
+ void setAnchored( KWTextFrameSet* textfs, int paragId, int index, bool placeHolderExists = false, bool repaint = true );
+ /** Note that this frameset has been made floating already, and store anchor position */
+ void setAnchored( KWTextFrameSet* textfs );
+ /// Make this frameset fixed, i.e. not anchored
+ void setFixed();
+ /// Return true if this frameset is floating (inline), false if it's fixed
+ bool isFloating() const { return m_anchorTextFs; }
+ /// Return the frameset in which our anchor is - assuming isFloating()
+ KWTextFrameSet * anchorFrameset() const { return m_anchorTextFs; }
+ /// Sets the frameset in which we are about to become inline. Used for OASIS loading.
+ void setAnchorFrameset(KWTextFrameSet * textfs) { m_anchorTextFs = textfs; }
+ /// Return the anchor object for this frame number
+ KWAnchor * findAnchor( int frameNum );
+ /// Tell this frame the format of it's anchor
+ virtual void setAnchorFormat( KoTextFormat* /*format*/, int /*frameNum*/ ) {}
+
+ /// Create an anchor for the floating frame identified by frameNum
+ virtual KWAnchor * createAnchor( KoTextDocument *txt, int frameNum );
+
+ /** Move the frame frameNum to the given position - this is called when
+ the frame is anchored and the anchor moves (see KWAnchor). */
+ virtual void moveFloatingFrame( int frameNum, const KoPoint &position );
+ /** Get the size of the "floating frame" identified by frameNum.
+ By default a real frame but not for tables. */
+ virtual KoSize floatingFrameSize( int frameNum = 0 );
+ /** Get the rect of the "floating frame" identified by frameNum,
+ in coordinates RELATIVE TO THE PARENT FRAMESET.
+ This is especially important for multi-parent inline frames. */
+ KoRect floatingFrameRect( int frameNum = 0 );
+ /** Get the 'baseline' to use for the "floating frame" identified by frameNum.
+ -1 means same as the height (usual case) */
+ virtual int floatingFrameBaseline( int /*frameNum*/ ) { return -1; }
+ /// Store command for creating an anchored object
+ virtual KCommand * anchoredObjectCreateCommand( int frameNum );
+ /// Store command for deleting an anchored object
+ virtual KCommand * anchoredObjectDeleteCommand( int frameNum );
+
+ /** make this frameset part of a groupmanager
+ * @see KWTableFrameSet
+ */
+ void setGroupManager( KWTableFrameSet *gm ) { m_groupmanager = gm; }
+ /** returns the groupManager this frameset belongs to. A Groupmanager is better known as a table */
+ KWTableFrameSet *groupmanager()const { return m_groupmanager; }
+
+ bool isProtectSize()const { return m_protectSize; }
+ void setProtectSize( bool _b);
+
+ /**
+ * Returns true if the frameset is visible.
+ * A frameset is visible if setVisible(false) wasn't called,
+ * but also, for a header frameset, if m_doc->isHeaderVisible is true, etc.
+ * For an "even pages header" frameset, the corresponding headerType setting
+ * must be selected (i.e. different headers for even and odd pages).
+ * @param viewMode pass the current viewmode when using this method for any visual
+ * stuff (drawing, handling input etc.). Frameset visibility depends on the viewmode.
+ */
+ bool isVisible( KWViewMode* viewMode = 0L ) const;
+
+ /// set the visibility of the frameset.
+ virtual void setVisible( bool v );
+
+ /// get/set frameset name. For tables in particular, this _must_ be unique
+ QString name() const { return m_name; }
+ void setName( const QString &name );
+
+ /// set frameBehavior on all frames, see KWFrame for specifics
+ void setFrameBehavior( KWFrame::FrameBehavior fb );
+
+ /// set newFrameBehavior on all frames, see KWFrame for specifics
+ void setNewFrameBehavior( KWFrame::NewFrameBehavior nfb );
+
+#ifndef NDEBUG
+ virtual void printDebug();
+ virtual void printDebug( KWFrame * );
+#endif
+
+ virtual KWTextFrameSet* nextTextObject( KWFrameSet * ) { return 0L;}
+
+ bool isPaintedBy( KWFrameSet* fs ) const;
+
+ /// set z-order for all frames
+ virtual void setZOrder();
+
+ virtual void setProtectContent ( bool protect ) = 0;
+ virtual bool protectContent() const = 0;
+
+ void setPageManager(KWPageManager *pm) { m_pageManager = pm; }
+ KWPageManager* pageManager() const { return m_pageManager; }
+
+signals:
+
+ /// Emitted when something has changed in this frameset,
+ /// so that all views repaint it. KWDocument connects to it,
+ /// and KWCanvas connects to KWDocument.
+ void repaintChanged( KWFrameSet * frameset );
+
+ void sigFrameAdded(KWFrame*);
+ void sigFrameRemoved(KWFrame*);
+
+ void sigNameChanged(KWFrameSet*);
+
+protected:
+
+ /// save the common attributes for the frameset
+ void saveCommon( QDomElement &parentElem, bool saveFrames );
+
+ /**Determine the clipping rectangle for drawing the contents of @p frame with @p painter
+ * in the rectangle delimited by @p crect.
+ * This determines where to clip the painter to draw the contents of a given frame
+ */
+ QRegion frameClipRegion( QPainter * painter, KWFrame *frame, const QRect & crect,
+ KWViewMode * viewMode );
+
+ void deleteAnchor( KWAnchor * anchor );
+ virtual void deleteAnchors();
+ virtual void createAnchors( KoTextParag * parag, int index, bool placeHolderExists = false, bool repaint = true );
+
+
+ KWDocument *m_doc; // Document
+ QPtrList<KWFrame> m_frames; // Our frames
+
+ // Cached info for optimization
+ /// This array provides a direct access to the frames on page N
+ QPtrVector< QPtrList<KWFrame> > m_framesInPage;
+ /// always equal to m_framesInPage[0].first()->pageNumber() :)
+ int m_firstPage;
+ /// always empty, for convenience in @ref framesInPage
+ QPtrList<KWFrame> m_emptyList; // ## make static pointer to save memory ?
+
+ Info m_info;
+ KWTableFrameSet *m_groupmanager;
+ bool m_visible;
+ bool m_protectSize;
+ QString m_name;
+ KWTextFrameSet * m_anchorTextFs;
+ KWordFrameSetIface *m_dcop;
+ KWPageManager *m_pageManager;
+};
+
+#endif
diff --git a/kword/KWFrameSetEdit.cpp b/kword/KWFrameSetEdit.cpp
new file mode 100644
index 00000000..0a917638
--- /dev/null
+++ b/kword/KWFrameSetEdit.cpp
@@ -0,0 +1,68 @@
+/* This file is part of the KDE project
+ Copyright (C) 1998, 1999, 2000 Reginald Stadlbauer <reggie@kde.org>
+ Copyright (C) 2005 Thomas Zander <zander@kde.org>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+*/
+
+#include "KWFrameSetEdit.h"
+#include "KWView.h"
+#include "KWCanvas.h"
+#include "KWFrame.h"
+#include "KWAnchor.h"
+#include "KWFrameSet.h"
+#include "KWTextFrameSet.h"
+
+#include <KoTextParag.h>
+
+KWFrameSetEdit::KWFrameSetEdit( KWFrameSet * fs, KWCanvas * canvas )
+ : m_fs(fs), m_canvas(canvas), m_currentFrame( fs->frame(0) )
+{
+}
+
+void KWFrameSetEdit::drawContents( QPainter *p, const QRect &crect,
+ const QColorGroup &cg, bool onlyChanged, bool resetChanged,
+ KWViewMode *viewMode, KWFrameViewManager *fvm )
+{
+ //kdDebug(32001) << "KWFrameSetEdit::drawContents " << frameSet()->name() << endl;
+ frameSet()->drawContents( p, crect, cg, onlyChanged, resetChanged, this, viewMode, fvm );
+}
+
+bool KWFrameSetEdit::exitLeft()
+{
+ if ( m_fs->isFloating() ) {
+ KWAnchor* anchor = m_fs->findAnchor( 0 );
+ int index = anchor->index();
+ KoTextParag *parag = anchor->paragraph();
+ // This call deletes "this"!
+ m_canvas->editTextFrameSet( m_fs->anchorFrameset(), parag, index );
+ return true;
+ }
+ return false;
+}
+
+bool KWFrameSetEdit::exitRight()
+{
+ if ( m_fs->isFloating() ) {
+ KWAnchor* anchor = m_fs->findAnchor( 0 );
+ int index = anchor->index();
+ KoTextParag *parag = anchor->paragraph();
+ // This call deletes "this"!
+ m_canvas->editTextFrameSet( m_fs->anchorFrameset(), parag, index+1 );
+ return true;
+ }
+ return false;
+}
diff --git a/kword/KWFrameSetEdit.h b/kword/KWFrameSetEdit.h
new file mode 100644
index 00000000..edfe8756
--- /dev/null
+++ b/kword/KWFrameSetEdit.h
@@ -0,0 +1,120 @@
+/* This file is part of the KDE project
+ Copyright (C) 1998, 1999, 2000 Reginald Stadlbauer <reggie@kde.org>
+ Copyright (C) 2005 Thomas Zander <zander@kde.org>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+*/
+
+#ifndef frame_set_edit_h
+#define frame_set_edit_h
+
+#include <qrect.h>
+#include <KoPoint.h>
+#include <KoRect.h>
+
+class KWCanvas;
+class KWFrame;
+class KWFrameSet;
+class KWView;
+class KWViewMode;
+class KWFrameViewManager;
+
+class QDragEnterEvent;
+class QDragLeaveEvent;
+class QDragMoveEvent;
+class QDropEvent;
+class QIMEvent;
+class QKeyEvent;
+class QMimeSource;
+class QMouseEvent;
+class QPainter;
+class QPoint;
+
+/**
+ * This object is created to edit a particular frameset in a particular view
+ * The view's canvas creates it, and destroys it.
+ */
+class KWFrameSetEdit
+{
+public:
+ KWFrameSetEdit( KWFrameSet * fs, KWCanvas * canvas );
+ virtual ~KWFrameSetEdit() {}
+
+ KWFrameSet * frameSet() const { return m_fs; }
+ KWCanvas * canvas() const { return m_canvas; }
+ KWFrame * currentFrame() const { return m_currentFrame; }
+
+ /**
+ * Return the current most-low-level text edit object
+ */
+ virtual KWFrameSetEdit* currentTextEdit() { return 0L; }
+
+ /**
+ * Called before destruction, when terminating edition - use to e.g. hide cursor
+ */
+ virtual void terminate(bool /*removeselection*/ = true) {}
+
+ /**
+ * Paint this frameset in "has focus" mode (e.g. with a cursor)
+ * See KWFrameSet for explanation about the arguments.
+ * Most framesets don't need to reimplement that (the KWFrameSetEdit gets passed to drawFrame)
+ */
+ virtual void drawContents( QPainter *, const QRect &,
+ const QColorGroup &, bool onlyChanged, bool resetChanged,
+ KWViewMode *viewMode,
+ KWFrameViewManager *frameViewManager );
+
+ // Events forwarded by the canvas (when being in "edit" mode)
+ virtual void keyPressEvent( QKeyEvent * ) {}
+ virtual void keyReleaseEvent( QKeyEvent * ) {}
+ virtual void imStartEvent( QIMEvent * ) {}
+ virtual void imComposeEvent( QIMEvent * ) {}
+ virtual void imEndEvent( QIMEvent * ) {}
+ virtual void mousePressEvent( QMouseEvent *, const QPoint &, const KoPoint & ) {}
+ virtual void mouseMoveEvent( QMouseEvent *, const QPoint &, const KoPoint & ) {} // only called if button is pressed
+ virtual void mouseReleaseEvent( QMouseEvent *, const QPoint &, const KoPoint & ) {}
+ virtual void mouseDoubleClickEvent( QMouseEvent *, const QPoint &, const KoPoint & ) {}
+ virtual void dragEnterEvent( QDragEnterEvent * ) {}
+ virtual void dragMoveEvent( QDragMoveEvent *, const QPoint &, const KoPoint & ) {}
+ virtual void dragLeaveEvent( QDragLeaveEvent * ) {}
+ virtual void dropEvent( QDropEvent *, const QPoint &, const KoPoint &, KWView* ) {}
+ virtual void focusInEvent() {}
+ virtual void focusOutEvent() {}
+ virtual void copy() {}
+ virtual void cut() {}
+ virtual void paste() {}
+ virtual void selectAll() {}
+ virtual void pasteData( QMimeSource* /*data*/, int /*provides*/, bool /*drop*/ ) {}
+
+
+ /// Called if the cursor tries to leave the frameset at its beginning.
+ /// Returns true if the frameset was inline, and we did exit into another frameset.
+ bool exitLeft();
+ /// Called if the cursor tries to leave the frameset at its end.
+ /// Returns true if the frameset was inline, and we did exit into another frameset.
+ bool exitRight();
+
+protected:
+ KWFrameSet * m_fs;
+ KWCanvas * m_canvas;
+ /**
+ * The Frameset-Edit implementation is responsible for updating that one
+ * (to the frame where the current "cursor" is)
+ */
+ KWFrame * m_currentFrame;
+};
+
+#endif
diff --git a/kword/KWFrameStyle.cpp b/kword/KWFrameStyle.cpp
new file mode 100644
index 00000000..5889bc62
--- /dev/null
+++ b/kword/KWFrameStyle.cpp
@@ -0,0 +1,289 @@
+/* This file is part of the KDE project
+ Copyright (C) 2002 Nash Hoogwater <nrhoogwater@wanadoo.nl>
+ 2005 David Faure <faure@kde.org>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; using
+ version 2 of the License.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+*/
+
+#include "KWFrameStyle.h"
+#include "KWDocument.h"
+#include "KWFrame.h"
+
+#include <KoGenStyles.h>
+#include <KoOasisStyles.h>
+#include <KoOasisContext.h>
+#include <KoXmlNS.h>
+
+#include <kdebug.h>
+#include <klocale.h>
+#include <qdom.h>
+
+KWFrameStyleCollection::KWFrameStyleCollection()
+ : KoUserStyleCollection( QString::fromLatin1( "frame" ) )
+{
+}
+
+void KWFrameStyleCollection::saveOasis( KoGenStyles& mainStyles, KoSavingContext& savingContext ) const
+{
+ if ( !isDefault() ) {
+ for ( QValueList<KoUserStyle *>::const_iterator styleIt = m_styleList.begin(), styleEnd = m_styleList.end() ; styleIt != styleEnd ; ++styleIt )
+ {
+ KWFrameStyle* style = static_cast<KWFrameStyle *>( *styleIt );
+ style->saveOasis( mainStyles, savingContext );
+ }
+ }
+}
+
+int KWFrameStyleCollection::loadOasisStyles( KoOasisContext& context )
+{
+ QValueVector<QDomElement> userStyles = context.oasisStyles().userStyles();
+ bool defaultStyleDeleted = false;
+ int stylesLoaded = 0;
+ for (unsigned int item = 0; item < userStyles.count(); item++) {
+ QDomElement styleElem = userStyles[item];
+ Q_ASSERT( !styleElem.isNull() );
+
+ if ( styleElem.attributeNS( KoXmlNS::style, "family", QString::null ) != "graphic" )
+ continue;
+
+ if ( !defaultStyleDeleted ) {
+ KWFrameStyle *s = findStyle( defaultStyleName() );
+ //kdDebug() << "KWFrameStyleCollection::loadOasisStyles looking for " << defaultStyleName() << ", to delete it. Found " << s << endl;
+ if(s) // delete the standard style.
+ removeStyle(s);
+ defaultStyleDeleted = true;
+ }
+
+ KWFrameStyle *sty = new KWFrameStyle( QString::null );
+ // Load the style
+ sty->loadOasis( styleElem, context );
+ // Style created, now let's try to add it
+ sty = static_cast<KWFrameStyle *>( addStyle( sty ) );
+
+ kdDebug() << " Loaded frame style " << sty->name() << " - now " << count() << " styles" << endl;
+ ++stylesLoaded;
+ }
+ return stylesLoaded;
+}
+
+/******************************************************************/
+/* Class: KWFrameStyle */
+/******************************************************************/
+
+KWFrameStyle::KWFrameStyle( const QString & name )
+ : KoUserStyle( name )
+{
+ m_backgroundColor.setColor( Qt::white );
+}
+
+KWFrameStyle::KWFrameStyle( const QString & name, KWFrame * frame )
+ : KoUserStyle( name )
+{
+ m_backgroundColor = frame->backgroundColor();
+ m_borderLeft = frame->leftBorder();
+ m_borderRight = frame->rightBorder();
+ m_borderTop = frame->topBorder();
+ m_borderBottom = frame->bottomBorder();
+}
+
+KWFrameStyle::KWFrameStyle( QDomElement & parentElem, int /*docVersion=2*/ )
+ : KoUserStyle( QString::null )
+{
+ QDomElement element = parentElem.namedItem( "NAME" ).toElement();
+ if ( ( !element.isNull() ) && ( element.hasAttribute("value") ) ) {
+ m_name = element.attribute( "value" );
+ m_displayName = i18n( "Style name", m_name.utf8() );
+ } else
+ kdWarning() << "No NAME tag in frame style!" << endl;
+
+ element = parentElem.namedItem( "LEFTBORDER" ).toElement();
+ if ( !element.isNull() )
+ m_borderLeft = KoBorder::loadBorder( element );
+ else
+ m_borderLeft.setPenWidth( 0 );
+
+ element = parentElem.namedItem( "RIGHTBORDER" ).toElement();
+ if ( !element.isNull() )
+ m_borderRight = KoBorder::loadBorder( element );
+ else
+ m_borderRight.setPenWidth( 0 );
+
+ element = parentElem.namedItem( "TOPBORDER" ).toElement();
+ if ( !element.isNull() )
+ m_borderTop = KoBorder::loadBorder( element );
+ else
+ m_borderTop.setPenWidth( 0 );
+
+ element = parentElem.namedItem( "BOTTOMBORDER" ).toElement();
+ if ( !element.isNull() )
+ m_borderBottom = KoBorder::loadBorder( element );
+ else
+ m_borderBottom.setPenWidth( 0 );
+
+ QColor c("white");
+ if ( parentElem.hasAttribute("red") )
+ c.setRgb(
+ KWDocument::getAttribute( parentElem, "red", 0 ),
+ KWDocument::getAttribute( parentElem, "green", 0 ),
+ KWDocument::getAttribute( parentElem, "blue", 0 ) );
+
+ m_backgroundColor = QBrush( c );
+}
+
+KWFrameStyle::KWFrameStyle( const KWFrameStyle &rhs )
+ : KoUserStyle( QString::null )
+{
+ operator=( rhs );
+}
+
+void KWFrameStyle::operator=( const KWFrameStyle &rhs )
+{
+ KoUserStyle::operator=( rhs );
+ m_backgroundColor = rhs.m_backgroundColor;
+ m_borderLeft = rhs.m_borderLeft;
+ m_borderRight = rhs.m_borderRight;
+ m_borderTop = rhs.m_borderTop;
+ m_borderBottom = rhs.m_borderBottom;
+}
+
+int KWFrameStyle::compare( const KWFrameStyle & frameStyle ) const
+{
+ int flags = 0;
+ if ( m_borderLeft != frameStyle.m_borderLeft
+ || m_borderRight != frameStyle.m_borderRight
+ || m_borderTop != frameStyle.m_borderTop
+ || m_borderBottom != frameStyle.m_borderBottom )
+ flags |= Borders;
+ if ( m_backgroundColor.color() != frameStyle.m_backgroundColor.color() )
+ flags |= Background;
+
+ return flags;
+}
+
+
+void KWFrameStyle::saveFrameStyle( QDomElement & parentElem )
+{
+ QDomDocument doc = parentElem.ownerDocument();
+ QDomElement element = doc.createElement( "NAME" );
+ parentElem.appendChild( element );
+ element.setAttribute( "value", displayName() );
+
+ if ( m_borderLeft.width() > 0 )
+ {
+ element = doc.createElement( "LEFTBORDER" );
+ parentElem.appendChild( element );
+ m_borderLeft.save( element );
+ }
+ if ( m_borderRight.width() > 0 )
+ {
+ element = doc.createElement( "RIGHTBORDER" );
+ parentElem.appendChild( element );
+ m_borderRight.save( element );
+ }
+ if ( m_borderTop.width() > 0 )
+ {
+ element = doc.createElement( "TOPBORDER" );
+ parentElem.appendChild( element );
+ m_borderTop.save( element );
+ }
+ if ( m_borderBottom.width() > 0 )
+ {
+ element = doc.createElement( "BOTTOMBORDER" );
+ parentElem.appendChild( element );
+ m_borderBottom.save( element );
+ }
+
+ if(m_backgroundColor.color().isValid())
+ {
+ parentElem.setAttribute( "red", m_backgroundColor.color().red() );
+ parentElem.setAttribute( "green", m_backgroundColor.color().green() );
+ parentElem.setAttribute( "blue", m_backgroundColor.color().blue() );
+ }
+}
+
+KWFrameStyle *KWFrameStyle::loadStyle( QDomElement & parentElem, int docVersion )
+{
+ return new KWFrameStyle( parentElem, docVersion );
+}
+
+void KWFrameStyle::saveOasis( KoGenStyles& mainStyles, KoSavingContext& savingContext ) const
+{
+ Q_UNUSED( savingContext );
+
+ KoGenStyle frameStyle( KWDocument::STYLE_FRAME_USER, "graphic" );
+ frameStyle.addAttribute( "style:display-name", displayName() );
+
+ // Borders (taken from KWFrame::saveBorderProperties)
+ if ( ( m_borderLeft == m_borderRight )
+ && ( m_borderLeft == m_borderTop )
+ && ( m_borderLeft == m_borderBottom ) )
+ {
+ frameStyle.addProperty( "fo:border", m_borderLeft.saveFoBorder() );
+ }
+ else
+ {
+ frameStyle.addProperty( "fo:border-left", m_borderLeft.saveFoBorder() );
+ frameStyle.addProperty( "fo:border-right", m_borderRight.saveFoBorder() );
+ frameStyle.addProperty( "fo:border-top", m_borderTop.saveFoBorder() );
+ frameStyle.addProperty( "fo:border-bottom", m_borderBottom.saveFoBorder() );
+ }
+
+ // Background (taken from KWFrame::saveBorderProperties)
+ if ( m_backgroundColor.style() == Qt::NoBrush )
+ frameStyle.addProperty( "fo:background-color", "transparent" );
+ else if ( m_backgroundColor.color().isValid() )
+ frameStyle.addProperty( "fo:background-color", m_backgroundColor.color().name() );
+
+ // try to preserve existing internal name, if it looks adequate (no spaces)
+ // ## TODO: check XML-Schemacs NCName conformity
+ const bool nameIsConform = !m_name.isEmpty() && m_name.find( ' ' ) == -1;
+ QString newName = m_name;
+ if ( nameIsConform )
+ newName = mainStyles.lookup( frameStyle, m_name, KoGenStyles::DontForceNumbering );
+ else
+ newName = mainStyles.lookup( frameStyle, "fr" );
+ const_cast<KWFrameStyle*>( this )->m_name = newName;
+}
+
+void KWFrameStyle::loadOasis( QDomElement & styleElem, KoOasisContext& context )
+{
+ // Load name
+ m_name = styleElem.attributeNS( KoXmlNS::style, "name", QString::null );
+ m_displayName = styleElem.attributeNS( KoXmlNS::style, "display-name", QString::null );
+ if ( m_displayName.isEmpty() )
+ m_displayName = m_name;
+
+ KoStyleStack& styleStack = context.styleStack();
+ styleStack.setTypeProperties( "graphic" );
+
+ styleStack.save();
+ context.addStyles( &styleElem, "graphic" ); // Load all parents - only because we don't support inheritance.
+
+ if ( styleStack.hasAttributeNS( KoXmlNS::fo, "background-color" ) ) {
+ QString color = styleStack.attributeNS( KoXmlNS::fo, "background-color" );
+ if ( color == "transparent" )
+ m_backgroundColor = QBrush( QColor(), Qt::NoBrush );
+ else
+ m_backgroundColor = QBrush( QColor( color ) /*, brush style is a dead feature, ignored */ );
+ }
+
+ m_borderLeft.loadFoBorder( styleStack.attributeNS( KoXmlNS::fo, "border", "left") );
+ m_borderRight.loadFoBorder( styleStack.attributeNS( KoXmlNS::fo, "border", "right") );
+ m_borderTop.loadFoBorder( styleStack.attributeNS( KoXmlNS::fo, "border", "top") );
+ m_borderBottom.loadFoBorder( styleStack.attributeNS( KoXmlNS::fo, "border", "bottom") );
+
+ styleStack.restore();
+}
diff --git a/kword/KWFrameStyle.h b/kword/KWFrameStyle.h
new file mode 100644
index 00000000..b699cd32
--- /dev/null
+++ b/kword/KWFrameStyle.h
@@ -0,0 +1,139 @@
+/* This file is part of the KDE project
+ Copyright (C) 2002 Nash Hoogwater <nrhoogwater@wanadoo.nl>
+ 2005 David Faure <faure@kde.org>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; using
+ version 2 of the License.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+*/
+
+#ifndef kwframestyle_h
+#define kwframestyle_h
+
+#include <KoUserStyle.h>
+#include <KoUserStyleCollection.h>
+
+#include "KoBorder.h"
+#include <qbrush.h>
+
+class QDomElement;
+class KoOasisContext;
+class KoSavingContext;
+class KoGenStyles;
+class KWFrameStyle;
+class KWFrame;
+
+/**
+ * The user-visible style for frames
+ * (borders and background)
+ */
+class KWFrameStyle : public KoUserStyle
+{
+public:
+ /** Create a blank framestyle (with default attributes) */
+ KWFrameStyle( const QString & name );
+
+ KWFrameStyle( const QString & name, KWFrame * frame );
+ KWFrameStyle( QDomElement & parentElem, int docVersion=2 );
+
+ /** Copy another framestyle */
+ KWFrameStyle( const KWFrameStyle & rhs );
+ void operator=( const KWFrameStyle& rhs );
+
+ ~KWFrameStyle() {}
+
+ enum { Borders = 1,
+ Background = 2
+ } Flags;
+
+ int compare( const KWFrameStyle & frameStyle ) const;
+
+ // ATTRIBUTES
+ QBrush backgroundColor() const { return m_backgroundColor; }
+ void setBackgroundColor( const QBrush &_color ) { m_backgroundColor = _color; }
+
+ const KoBorder & leftBorder() const { return m_borderLeft; }
+ void setLeftBorder( KoBorder _left ) { m_borderLeft = _left; }
+
+ const KoBorder & rightBorder() const { return m_borderRight; }
+ void setRightBorder( KoBorder _right ) { m_borderRight = _right; }
+
+ const KoBorder & topBorder() const { return m_borderTop; }
+ void setTopBorder( KoBorder _top ) { m_borderTop = _top; }
+
+ const KoBorder & bottomBorder() const { return m_borderBottom; }
+ void setBottomBorder( KoBorder _bottom ) { m_borderBottom = _bottom; }
+
+ /// save (old xml format)
+ void saveFrameStyle( QDomElement & parentElem );
+ /// save (new oasis xml format)
+ void saveOasis( KoGenStyles& mainStyles, KoSavingContext& savingContext ) const;
+
+ /// load (old xml format)
+ static KWFrameStyle *loadStyle( QDomElement & parentElem, int docVersion=2 );
+ /// load (new oasis xml format)
+ void loadOasis( QDomElement & styleElem, KoOasisContext& context );
+
+private:
+ QBrush m_backgroundColor;
+ KoBorder m_borderLeft, m_borderRight, m_borderTop, m_borderBottom;
+};
+
+/**
+ * Collection of frame styles
+ */
+class KWFrameStyleCollection : public KoUserStyleCollection
+{
+public:
+ KWFrameStyleCollection();
+
+ static QString defaultStyleName() { return QString::fromLatin1( "Plain" ); }
+
+ /**
+ * Find style based on the untranslated name @p name.
+ * Overloaded for convenience
+ */
+ KWFrameStyle* findStyle( const QString & name ) const {
+ return static_cast<KWFrameStyle*>( KoUserStyleCollection::findStyle( name, defaultStyleName() ) );
+ }
+
+ /**
+ * Find style based on the display name @p name.
+ * This is only for the old XML loading.
+ * Overloaded for convenience
+ */
+ KWFrameStyle* findStyleByDisplayName( const QString & name ) const {
+ return static_cast<KWFrameStyle*>( KoUserStyleCollection::findStyleByDisplayName( name ) );
+ }
+
+ /**
+ * See KoUserStyleCollection::addStyle.
+ * Overloaded for convenience.
+ */
+ KWFrameStyle* addStyle( KWFrameStyle* sty ) {
+ return static_cast<KWFrameStyle*>( KoUserStyleCollection::addStyle( sty ) );
+ }
+
+ /**
+ * Return style number @p i.
+ */
+ KWFrameStyle* frameStyleAt( int i ) const {
+ return static_cast<KWFrameStyle*>( m_styleList[i] );
+ }
+
+ void saveOasis( KoGenStyles& mainStyles, KoSavingContext& savingContext ) const;
+ int loadOasisStyles( KoOasisContext& context );
+};
+
+#endif
diff --git a/kword/KWFrameStyleManager.cpp b/kword/KWFrameStyleManager.cpp
new file mode 100644
index 00000000..bf9be484
--- /dev/null
+++ b/kword/KWFrameStyleManager.cpp
@@ -0,0 +1,671 @@
+/* This file is part of the KDE project
+ Copyright (C) 2002 Nash Hoogwater <nrhoogwater@wanadoo.nl>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; using
+ version 2 of the License.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+*/
+
+#include "KWFrameStyleManager.h"
+#include "KWFrameStyleManager.moc"
+#include "KWImportStyleDia.h"
+
+#include "KWDocument.h"
+#include "KWFrameDia.h" // for KWBrushStylePreview
+
+#include <KoParagDia.h>
+
+#include <kcolorbutton.h>
+#include <klocale.h>
+#include <kiconloader.h>
+
+#include <qtabwidget.h>
+#include <qpushbutton.h>
+#include <qlabel.h>
+#include <qbrush.h>
+#include <qgroupbox.h>
+#include <qpainter.h>
+#include <qlayout.h>
+
+/******************************************************************/
+/* Class: KWTableStylePreview */
+/******************************************************************/
+
+#undef ptToPx
+#define ptToPx qRound
+
+void KWFrameStylePreview::paintEvent( QPaintEvent * )
+{
+ int wid = ( width() - 20 );
+ int hei = ( height() - 20 );
+
+ QPainter p;
+ p.begin( this );
+
+ // 1: create borders
+ if (frameStyle->topBorder().width()>0) {
+ p.setPen( KoBorder::borderPen(frameStyle->topBorder(), ptToPx( frameStyle->topBorder().width() ), black) ); // Top border
+ p.drawLine( 10 - int(frameStyle->leftBorder().width()/2), 10,
+ 10 + wid + int(frameStyle->rightBorder().width()/2), 10 );
+ }
+ if (frameStyle->leftBorder().width()>0) {
+ p.setPen( KoBorder::borderPen(frameStyle->leftBorder(), ptToPx( frameStyle->leftBorder().width() ), black) ); // Left border
+ p.drawLine( 10, 10 - int(frameStyle->topBorder().width()/2),
+ 10 , 10 + hei + int(frameStyle->bottomBorder().width()/2) );
+ }
+ if (frameStyle->bottomBorder().width()>0) {
+ p.setPen( KoBorder::borderPen(frameStyle->bottomBorder(), ptToPx( frameStyle->bottomBorder().width() ), black) ); // Bottom border
+ p.drawLine( 10 + wid + int(ceil(frameStyle->rightBorder().width()/2)), 10 + hei,
+ 10 - int(frameStyle->leftBorder().width()/2), 10 + hei );
+ }
+ if (frameStyle->rightBorder().width()>0) {
+ p.setPen( KoBorder::borderPen(frameStyle->rightBorder(), ptToPx( frameStyle->rightBorder().width() ), black) ); // Right border
+ p.drawLine( 10 + wid, 10 - int(frameStyle->topBorder().width()/2) ,
+ 10 + wid, 10 + hei + int(frameStyle->bottomBorder().width()/2) );
+ }
+
+ // 2.1: create background
+
+ p.fillRect( QRect( QPoint(10 + int(ceil(frameStyle->leftBorder().width()/2)), 10 + int(ceil(frameStyle->topBorder().width()/2))),
+ QPoint(10 + wid - int(floor(frameStyle->rightBorder().width()/2)+1), 10 + hei - int(floor(frameStyle->bottomBorder().width()/2)+1)) ),
+ frameStyle->backgroundColor() );
+
+ p.end();
+}
+
+void KWFrameStylePreview::setFrameStyle( KWFrameStyle *_frameStyle )
+{
+ if (!frameStyle) frameStyle = new KWFrameStyle("preview");
+
+ frameStyle = _frameStyle;
+
+ repaint( true );
+}
+
+/******************************************************************/
+/* Class: KWFrameStyleListItem */
+/******************************************************************/
+
+KWFrameStyleListItem::~KWFrameStyleListItem()
+{
+ delete m_changedFrameStyle;
+}
+
+void KWFrameStyleListItem::switchStyle()
+{
+ delete m_changedFrameStyle;
+ m_changedFrameStyle = 0;
+
+ if ( m_origFrameStyle )
+ m_changedFrameStyle = new KWFrameStyle( *m_origFrameStyle );
+}
+
+void KWFrameStyleListItem::deleteStyle( KWFrameStyle *current )
+{
+ Q_ASSERT( m_changedFrameStyle == current );
+ delete m_changedFrameStyle;
+ m_changedFrameStyle = 0;
+}
+
+void KWFrameStyleListItem::apply()
+{
+ *m_origFrameStyle = *m_changedFrameStyle;
+}
+
+/******************************************************************/
+/* Class: KWFrameStyleManager */
+/******************************************************************/
+
+KWFrameStyleManager::KWFrameStyleManager( QWidget *_parent, KWDocument *_doc,
+ const QString & activeStyleName )
+ : KDialogBase( _parent, "", true,
+ i18n("Frame Style Manager"),
+ KDialogBase::Ok | KDialogBase::Cancel | KDialogBase::Apply| KDialogBase::User1 )
+{
+ m_doc = _doc;
+
+ m_currentFrameStyle = 0;
+ noSignals=true;
+
+ m_frameStyles.setAutoDelete(false);
+
+ setupWidget(); // build the widget with the buttons and the list selector.
+
+ addGeneralTab();
+
+ KWFrameStyleBordersTab *bordersTab = new KWFrameStyleBordersTab( m_tabs );
+ bordersTab->setWidget( new KoParagDecorationWidget( bordersTab ) );
+ addTab( bordersTab );
+
+ KWFrameStyleBackgroundTab *bgTab = new KWFrameStyleBackgroundTab( m_tabs );
+ addTab( bgTab );
+
+ QListBoxItem * item = m_stylesList->findItem( activeStyleName );
+ m_stylesList->setCurrentItem( item ? m_stylesList->index(item) : 0 );
+
+ noSignals=false;
+ switchStyle();
+ setInitialSize( QSize( 600, 370 ) );
+ setButtonText( KDialogBase::User1, i18n("Import From File...") );
+ connect(this, SIGNAL(user1Clicked()), this, SLOT(importFromFile()));
+}
+
+KWFrameStyleManager::~KWFrameStyleManager()
+{
+ m_frameStyles.setAutoDelete( true );
+ m_frameStyles.clear();
+}
+
+void KWFrameStyleManager::addTab( KWFrameStyleManagerTab * tab )
+{
+ m_tabsList.append( tab );
+ m_tabs->insertTab( tab, tab->tabName() );
+}
+
+void KWFrameStyleManager::setupWidget()
+{
+ QFrame * frame1 = makeMainWidget();
+ QGridLayout *frame1Layout = new QGridLayout( frame1, 0, 0, // auto
+ 0, KDialog::spacingHint() );
+ KWFrameStyleCollection* collection = m_doc->frameStyleCollection();
+ numFrameStyles = collection->count();
+ m_stylesList = new QListBox( frame1, "stylesList" );
+ m_stylesList->insertStringList( collection->displayNameList() );
+ const QValueList<KoUserStyle*> styleList = collection->styleList();
+ for ( QValueList<KoUserStyle *>::const_iterator it = styleList.begin(), end = styleList.end();
+ it != end ; ++it )
+ {
+ KWFrameStyle* style = static_cast<KWFrameStyle *>( *it );
+ m_frameStyles.append( new KWFrameStyleListItem( style, new KWFrameStyle(*style) ) );
+ m_styleOrder << style->name();
+ }
+ Q_ASSERT( m_stylesList->count() == m_styleOrder.count() );
+ Q_ASSERT( m_styleOrder.count() == m_frameStyles.count() );
+
+ frame1Layout->addMultiCellWidget( m_stylesList, 0, 0, 0, 1 );
+
+
+ m_moveUpButton = new QPushButton( frame1, "moveUpButton" );
+ m_moveUpButton->setIconSet( SmallIconSet( "up" ) );
+ connect( m_moveUpButton, SIGNAL( clicked() ), this, SLOT( moveUpStyle() ) );
+ frame1Layout->addWidget( m_moveUpButton, 1, 1 );
+
+ m_moveDownButton = new QPushButton( frame1, "moveDownButton" );
+ m_moveDownButton->setIconSet( SmallIconSet( "down" ) );
+ connect( m_moveDownButton, SIGNAL( clicked() ), this, SLOT( moveDownStyle() ) );
+ frame1Layout->addWidget( m_moveDownButton, 1, 0 );
+
+
+ m_deleteButton = new QPushButton( frame1, "deleteButton" );
+ m_deleteButton->setText( i18n( "&Delete" ) );
+ connect( m_deleteButton, SIGNAL( clicked() ), this, SLOT( deleteStyle() ) );
+
+ frame1Layout->addWidget( m_deleteButton, 2, 1 );
+
+ m_newButton = new QPushButton( frame1, "newButton" );
+ m_newButton->setText( i18n( "New" ) );
+ connect( m_newButton, SIGNAL( clicked() ), this, SLOT( addStyle() ) );
+
+ frame1Layout->addWidget( m_newButton, 2, 0 );
+
+ m_tabs = new QTabWidget( frame1 );
+ frame1Layout->addMultiCellWidget( m_tabs, 0, 2, 2, 2 );
+
+ connect( m_stylesList, SIGNAL( selectionChanged() ), this, SLOT( switchStyle() ) );
+ connect( m_tabs, SIGNAL( currentChanged ( QWidget * ) ), this, SLOT( switchTabs() ) );
+}
+
+void KWFrameStyleManager::addGeneralTab()
+{
+ QWidget *tab = new QWidget( m_tabs );
+
+ QGridLayout *tabLayout = new QGridLayout( tab );
+ tabLayout->setSpacing( KDialog::spacingHint() );
+ tabLayout->setMargin( KDialog::marginHint() );
+
+ previewBox = new QGroupBox( 0, Qt::Vertical, i18n( "Preview" ), tab );
+ previewBox->layout()->setSpacing(KDialog::spacingHint());
+ previewBox->layout()->setMargin(KDialog::marginHint());
+ QGridLayout *previewLayout = new QGridLayout( previewBox->layout() );
+
+ preview = new KWFrameStylePreview( previewBox );
+ preview->resize(preview->sizeHint());
+
+ previewLayout->addWidget( preview, 0, 0 );
+
+ tabLayout->addMultiCellWidget( previewBox, 1, 1, 0, 1 );
+
+ m_nameString = new QLineEdit( tab );
+ m_nameString->resize(m_nameString->sizeHint() );
+ connect( m_nameString, SIGNAL( textChanged( const QString &) ), this, SLOT( renameStyle(const QString &) ) );
+
+ tabLayout->addWidget( m_nameString, 0, 1 );
+
+ QLabel *nameLabel = new QLabel( tab );
+ nameLabel->setText( i18n( "Name:" ) );
+ nameLabel->resize(nameLabel->sizeHint());
+ nameLabel->setAlignment( AlignRight | AlignVCenter );
+
+ tabLayout->addWidget( nameLabel, 0, 0 );
+
+ m_tabs->insertTab( tab, i18n( "General" ) );
+}
+
+void KWFrameStyleManager::switchStyle()
+{
+ kdDebug() << "KWFrameStyleManager::switchStyle noSignals=" << noSignals << endl;
+ if(noSignals) return;
+ noSignals=true;
+
+ if(m_currentFrameStyle !=0L)
+ save();
+
+ m_currentFrameStyle = 0L;
+ int num = frameStyleIndex( m_stylesList->currentItem() );
+
+ kdDebug() << "KWFrameStyleManager::switchStyle switching to " << num << endl;
+ if( m_frameStyles.at(num)->origFrameStyle() == m_frameStyles.at(num)->changedFrameStyle() )
+ m_frameStyles.at(num)->switchStyle();
+ else
+ m_currentFrameStyle = m_frameStyles.at(num)->changedFrameStyle();
+
+ updateGUI();
+
+ noSignals=false;
+}
+
+void KWFrameStyleManager::switchTabs()
+{
+ save();
+ updatePreview();
+}
+
+int KWFrameStyleManager::frameStyleIndex( int pos ) {
+ int p = 0;
+ for(unsigned int i=0; i < m_frameStyles.count(); i++) {
+ // Skip deleted styles, they're no in m_stylesList anymore
+ KWFrameStyle * style = m_frameStyles.at(i)->changedFrameStyle();
+ if ( !style ) continue;
+ if ( p == pos )
+ return i;
+ ++p;
+ }
+ kdWarning() << "KWFrameStyleManager::frameStyleIndex no style found at pos " << pos << " count=" << m_frameStyles.count() << endl;
+
+#ifdef __GNUC_
+#warning implement undo/redo
+#endif
+
+ return 0;
+}
+
+void KWFrameStyleManager::updateGUI()
+{
+ kdDebug() << "KWFrameStyleManager::updateGUI m_currentFrameStyle=" << m_currentFrameStyle << " " << m_currentFrameStyle->name() << endl;
+ QPtrListIterator<KWFrameStyleManagerTab> it( m_tabsList );
+ for ( ; it.current() ; ++it )
+ {
+ it.current()->setStyle( m_currentFrameStyle );
+ it.current()->update();
+ }
+
+ m_nameString->setText(m_currentFrameStyle->displayName());
+
+ // update delete button (can't delete first style);
+ m_deleteButton->setEnabled(m_stylesList->currentItem() != 0);
+
+ m_moveUpButton->setEnabled(m_stylesList->currentItem() != 0);
+ m_moveDownButton->setEnabled(m_stylesList->currentItem()!=(int)m_stylesList->count()-1);
+
+ updatePreview();
+}
+
+void KWFrameStyleManager::updatePreview()
+{
+ preview->setFrameStyle(m_currentFrameStyle);
+}
+
+void KWFrameStyleManager::save() {
+ if(m_currentFrameStyle) {
+ // save changes from UI to object.
+ QPtrListIterator<KWFrameStyleManagerTab> it( m_tabsList );
+ for ( ; it.current() ; ++it )
+ it.current()->save();
+
+ m_currentFrameStyle->setDisplayName( m_nameString->text() );
+ }
+}
+
+void KWFrameStyleManager::importFromFile()
+{
+ // ## why not just use collection->displayNameList()?
+ QStringList lst;
+ for ( int i = 0; i<(int)m_stylesList->count();i++)
+ {
+ lst << m_stylesList->text(i);
+ }
+
+ KWImportFrameTableStyleDia dia( m_doc, lst, KWImportFrameTableStyleDia::frameStyle, this, 0 );
+ if ( dia.listOfFrameStyleImported().count() > 0 && dia.exec() ) {
+ addStyles( dia.listOfFrameStyleImported() );
+ }
+}
+
+void KWFrameStyleManager::addStyles( const QPtrList<KWFrameStyle> &listStyle )
+{
+ save();
+
+ QPtrListIterator<KWFrameStyle> style( listStyle );
+ for ( ; style.current() ; ++style )
+ {
+ noSignals=true;
+ m_stylesList->insertItem( style.current()->displayName() );
+ m_frameStyles.append( new KWFrameStyleListItem( 0L,new KWFrameStyle(*style.current())) );
+ m_styleOrder<<style.current()->name();
+ noSignals=false;
+
+ }
+ updateGUI();
+}
+
+void KWFrameStyleManager::addStyle()
+{
+ save();
+
+ QString str = i18n( "New Framestyle Template (%1)" ).arg(numFrameStyles++);
+ if ( m_currentFrameStyle )
+ {
+ m_currentFrameStyle = new KWFrameStyle( *m_currentFrameStyle ); // Create a new style, initializing from the current one
+ m_currentFrameStyle->setDisplayName( str );
+ m_currentFrameStyle->setName( m_doc->frameStyleCollection()->generateUniqueName() );
+ }
+ else
+ m_currentFrameStyle = new KWFrameStyle( str );
+
+ noSignals=true;
+ m_frameStyles.append(new KWFrameStyleListItem(0L,m_currentFrameStyle));
+ m_stylesList->insertItem( str );
+ m_styleOrder<< str;
+ m_stylesList->setCurrentItem( m_stylesList->count() - 1 );
+ noSignals=false;
+
+ updateGUI();
+}
+
+void KWFrameStyleManager::deleteStyle()
+{
+ unsigned int cur = frameStyleIndex( m_stylesList->currentItem() );
+ m_styleOrder.remove( m_stylesList->currentText());
+ if ( !m_frameStyles.at(cur)->origFrameStyle() )
+ m_frameStyles.take(cur );
+ else {
+ m_frameStyles.at( cur )->deleteStyle( m_currentFrameStyle );
+ m_currentFrameStyle = 0L;
+ }
+
+ // Adjust GUI
+ m_stylesList->removeItem(m_stylesList->currentItem());
+ numFrameStyles--;
+ m_stylesList->setSelected( m_stylesList->currentItem(), true );
+}
+
+void KWFrameStyleManager::moveUpStyle()
+{
+ if(m_currentFrameStyle !=0L)
+ save();
+ unsigned int pos = 0;
+ QString currentStyleName = m_stylesList->currentText();
+ if ( currentStyleName.isEmpty() )
+ return;
+ int pos2 = m_styleOrder.findIndex( currentStyleName );
+ if ( pos2 > 0 ) // neither -1 nor 0
+ {
+ m_styleOrder.remove( m_styleOrder.at(pos2));
+ m_styleOrder.insert( m_styleOrder.at(pos2-1), currentStyleName);
+ }
+
+
+ pos=m_stylesList->currentItem();
+ noSignals=true;
+ m_stylesList->changeItem( m_stylesList->text ( pos-1 ),pos);
+
+ m_stylesList->changeItem( currentStyleName ,pos-1);
+
+ m_stylesList->setCurrentItem( m_stylesList->currentItem() );
+ noSignals=false;
+
+ updateGUI();
+}
+
+void KWFrameStyleManager::moveDownStyle()
+{
+ if(m_currentFrameStyle !=0L)
+ save();
+ unsigned int pos = 0;
+ QString currentStyleName=m_stylesList->currentText ();
+ if ( currentStyleName.isEmpty() )
+ return;
+
+ int pos2 = m_styleOrder.findIndex( currentStyleName );
+ if ( pos2 != -1 )
+ {
+ m_styleOrder.remove( m_styleOrder.at(pos2));
+ m_styleOrder.insert( m_styleOrder.at(pos2+1), currentStyleName);
+ }
+
+ pos=m_stylesList->currentItem();
+ noSignals=true;
+ m_stylesList->changeItem( m_stylesList->text ( pos+1 ),pos);
+ m_stylesList->changeItem( currentStyleName ,pos+1);
+ m_stylesList->setCurrentItem( m_stylesList->currentItem() );
+ noSignals=false;
+
+ updateGUI();
+}
+
+void KWFrameStyleManager::slotOk()
+{
+ save();
+ apply();
+ KDialogBase::slotOk();
+}
+
+void KWFrameStyleManager::slotApply()
+{
+ save();
+ apply();
+ KDialogBase::slotApply();
+}
+
+void KWFrameStyleManager::apply()
+{
+ // ##### missing: undo/redo support
+ noSignals=true;
+ for (unsigned int i =0 ; i < m_frameStyles.count() ; i++) {
+ if(m_frameStyles.at(i)->origFrameStyle() == 0) { // newly added style
+
+ kdDebug() << "adding new " << m_frameStyles.at(i)->changedFrameStyle()->name() << " (" << i << ")" << endl;
+
+ KWFrameStyle* style = m_doc->frameStyleCollection()->addStyle(m_frameStyles.take(i)->changedFrameStyle());
+ m_frameStyles.insert( i, new KWFrameStyleListItem(0, style) );
+
+ } else if(m_frameStyles.at(i)->changedFrameStyle() == 0) { // deleted style
+
+ kdDebug() << "deleting orig " << m_frameStyles.at(i)->origFrameStyle()->name() << " (" << i << ")" << endl;
+
+ KWFrameStyle *orig = m_frameStyles.at(i)->origFrameStyle();
+ m_doc->frameStyleCollection()->removeStyle( orig );
+
+ } else {
+
+ kdDebug() << "update style " << m_frameStyles.at(i)->changedFrameStyle()->name() << " (" << i << ")" << endl;
+ // TODO check if modified, so that we can do m_doc->setModified(true) only if a style was changed
+ m_frameStyles.at(i)->apply();
+ }
+ }
+ m_doc->frameStyleCollection()->updateStyleListOrder( m_styleOrder );
+ m_doc->updateAllFrameStyleLists();
+ m_doc->setModified( true );
+ noSignals=false;
+}
+
+void KWFrameStyleManager::renameStyle(const QString &theText) {
+ if(noSignals) return;
+ noSignals=true;
+
+ int index = m_stylesList->currentItem();
+ kdDebug() << "KWFrameStyleManager::renameStyle " << index << " to " << theText << endl;
+
+ // rename only in the GUI, not even in the underlying objects (save() does it).
+ m_stylesList->changeItem( theText, index );
+ m_styleOrder[index]=theText;
+
+ // Check how many styles with that name we have now
+ int synonyms = 0;
+ for ( uint i = 0; i < m_stylesList->count(); i++ ) {
+ if ( m_stylesList->text( i ) == m_stylesList->currentText() )
+ ++synonyms;
+ }
+ Q_ASSERT( synonyms > 0 ); // should have found 'index' at least !
+ noSignals=false;
+ // Can't close the dialog if two styles have the same name
+ bool state=!theText.isEmpty() && (synonyms == 1);
+ enableButtonOK(state );
+ enableButtonApply(state);
+ m_deleteButton->setEnabled(state&&(m_stylesList->currentItem() != 0));
+ m_newButton->setEnabled(state);
+ m_stylesList->setEnabled( state );
+ enableButton( KDialogBase::User1, state );
+
+ if ( state )
+ {
+ m_moveUpButton->setEnabled(m_stylesList->currentItem() != 0);
+ m_moveDownButton->setEnabled(m_stylesList->currentItem()!=(int)m_stylesList->count()-1);
+ }
+ else
+ {
+ m_moveUpButton->setEnabled(false);
+ m_moveDownButton->setEnabled(false);
+ }
+}
+
+/******************************************************************/
+/* Class: KWFrameStyleBackgroundTab */
+/******************************************************************/
+
+KWFrameStyleBackgroundTab::KWFrameStyleBackgroundTab( QWidget * parent )
+ : KWFrameStyleManagerTab( parent )
+{
+ bgwidget = this;
+ m_backgroundColor.setStyle( SolidPattern );
+
+ grid = new QGridLayout( bgwidget, 7, 2, KDialog::marginHint(), KDialog::spacingHint() );
+
+ int row=0;
+
+ brushPreview = new KWBrushStylePreview( bgwidget );
+ grid->addMultiCellWidget(brushPreview,row,5,1,1);
+
+ QLabel *l = new QLabel( i18n( "Frame background color:" ), bgwidget );
+
+ grid->addWidget(l,row++,0);
+
+ brushColor = new KColorButton( Qt::white, bgwidget );
+ grid->addWidget(brushColor,row++,0);
+
+ connect( brushColor, SIGNAL( changed( const QColor & ) ),
+ this, SLOT( updateBrushConfiguration( const QColor & ) ) );
+
+ QSpacerItem* spacer = new QSpacerItem( 10, 10, QSizePolicy::Minimum, QSizePolicy::Expanding);
+ grid->addItem( spacer,row,0 );
+
+ updateBrushConfiguration( Qt::white );
+}
+
+void KWFrameStyleBackgroundTab::updateBrushConfiguration( const QColor & _color )
+{
+ m_backgroundColor.setColor( _color );
+ brushPreview->show();
+ brushPreview->setBrush( m_backgroundColor );
+ brushPreview->repaint(true);
+}
+
+QString KWFrameStyleBackgroundTab::tabName()
+{
+ return i18n("Background");
+}
+
+void KWFrameStyleBackgroundTab::update()
+{
+ brushColor->setColor( m_style->backgroundColor().color() );
+ updateBrushConfiguration( m_style->backgroundColor().color() );
+}
+
+void KWFrameStyleBackgroundTab::save()
+{
+ m_style->setBackgroundColor( m_backgroundColor );
+}
+
+/******************************************************************/
+/* Class: KWFrameStyleBordersTab */
+/******************************************************************/
+
+KWFrameStyleBordersTab::KWFrameStyleBordersTab( QWidget * parent )
+ : KWFrameStyleManagerTab( parent )
+{
+ m_widget = 0L;
+ m_borders = new KoParagLayout();
+}
+
+KWFrameStyleBordersTab::~KWFrameStyleBordersTab()
+{
+ delete m_borders;
+}
+
+QString KWFrameStyleBordersTab::tabName()
+{
+ return m_widget->tabName();
+}
+
+void KWFrameStyleBordersTab::update()
+{
+ m_borders->leftBorder = m_style->leftBorder();
+ m_borders->rightBorder = m_style->rightBorder();
+ m_borders->topBorder = m_style->topBorder();
+ m_borders->bottomBorder = m_style->bottomBorder();
+
+
+ m_widget->display( *m_borders );
+}
+
+void KWFrameStyleBordersTab::save()
+{
+ m_widget->save( *m_borders );
+ m_style->setLeftBorder( m_borders->leftBorder );
+ m_style->setRightBorder( m_borders->rightBorder );
+ m_style->setTopBorder( m_borders->topBorder );
+ m_style->setBottomBorder( m_borders->bottomBorder );
+}
+
+void KWFrameStyleBordersTab::setWidget( KoParagLayoutWidget * widget )
+{
+ m_widget = widget;
+}
+
+void KWFrameStyleBordersTab::resizeEvent( QResizeEvent *e )
+{
+ QWidget::resizeEvent( e );
+ if ( m_widget ) m_widget->resize( size() );
+}
+
diff --git a/kword/KWFrameStyleManager.h b/kword/KWFrameStyleManager.h
new file mode 100644
index 00000000..4e73acc3
--- /dev/null
+++ b/kword/KWFrameStyleManager.h
@@ -0,0 +1,209 @@
+/* This file is part of the KDE project
+ Copyright (C) 2002 Nash Hoogwater <nrhoogwater@wanadoo.nl>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; using
+ version 2 of the License.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+*/
+
+#ifndef kwframestylemanager_h
+#define kwframestylemanager_h
+
+#include "KWFrameStyle.h"
+
+#include <kdialogbase.h>
+#include <qptrlist.h>
+
+
+class QGroupBox;
+class QGridLayout;
+class QLineEdit;
+class QListBox;
+class QPushButton;
+class QTabWidget;
+class QWidget;
+class KWDocument;
+class KWFrameStyleManagerTab;
+class KoParagLayoutWidget;
+class KoParagLayout;
+class KColorButton;
+class KWBrushStylePreview;
+
+/******************************************************************/
+/* Class: KWFrameStylePreview */
+/******************************************************************/
+
+class KWFrameStylePreview : public QWidget
+{
+ Q_OBJECT
+
+public:
+ KWFrameStylePreview( QWidget *parent )
+ : QWidget( parent ), frameStyle( 0 ) {
+ setBackgroundColor( white );
+ }
+
+ void setFrameStyle(KWFrameStyle *_frameStyle);
+
+protected:
+ void paintEvent( QPaintEvent *e );
+
+ void setTopBorder(KoBorder _bTop) { frameStyle->setTopBorder( _bTop ); repaint( true ); }
+ void setBottomBorder(KoBorder _bBottom) { frameStyle->setBottomBorder( _bBottom ); repaint( true ); }
+ void setRightBorder(KoBorder _bRight) { frameStyle->setRightBorder( _bRight ); repaint( true ); }
+ void setLeftBorder(KoBorder _bLeft) { frameStyle->setLeftBorder( _bLeft ); repaint( true ); }
+ void setBackground( const QColor & col ) { frameStyle->setBackgroundColor( col ); repaint( true ); }
+
+ KWFrameStyle *frameStyle;
+};
+
+
+class KWFrameStyleListItem
+{
+ public:
+ KWFrameStyleListItem() {}
+ ~KWFrameStyleListItem();
+ KWFrameStyleListItem(KWFrameStyle *orig, KWFrameStyle *changed) {
+ m_origFrameStyle = orig;
+ m_changedFrameStyle = changed;
+ }
+
+ KWFrameStyle *origFrameStyle()const { return m_origFrameStyle; }
+ KWFrameStyle *changedFrameStyle()const { return m_changedFrameStyle; }
+ void setOrigFrameStyle( KWFrameStyle *_orig ) { m_origFrameStyle = _orig; }
+ void setChangedFrameStyle( KWFrameStyle *_changed ) { m_changedFrameStyle = _changed; }
+ void deleteOrigFrameStyle() { delete m_changedFrameStyle; }
+ void deleteChangedFrameStyle() { delete m_changedFrameStyle; }
+
+ void switchStyle();
+ void deleteStyle( KWFrameStyle *current );
+ void apply();
+
+ protected:
+ KWFrameStyle *m_origFrameStyle;
+ KWFrameStyle *m_changedFrameStyle;
+};
+
+/******************************************************************/
+/* Class: KWFrameStyleManager */
+/******************************************************************/
+class KWFrameStyleManager : public KDialogBase
+{
+ Q_OBJECT
+
+public:
+ KWFrameStyleManager( QWidget *_parent, KWDocument *_doc,
+ const QString & activeStyleName );
+ ~KWFrameStyleManager();
+
+protected:
+ void addStyles(const QPtrList<KWFrameStyle> & style );
+ void setupWidget();
+ void addGeneralTab();
+ void apply();
+ void updateGUI();
+ void updatePreview();
+ void save();
+ int frameStyleIndex( int pos );
+
+ QTabWidget *m_tabs;
+ QListBox *m_stylesList;
+ QLineEdit *m_nameString;
+ QPushButton *m_deleteButton;
+ QPushButton *m_newButton;
+ QPushButton *m_moveUpButton;
+ QPushButton *m_moveDownButton;
+
+ QGroupBox *previewBox;
+ KWFrameStylePreview *preview;
+
+ KWFrameStyle *m_currentFrameStyle;
+ QStringList m_styleOrder;
+ QPtrList<KWFrameStyleListItem> m_frameStyles;
+ QPtrList<KWFrameStyleManagerTab> m_tabsList;
+ int numFrameStyles;
+ bool noSignals;
+
+ KWDocument *m_doc;
+
+protected slots:
+ virtual void slotOk();
+ virtual void slotApply();
+ void switchStyle();
+ void switchTabs();
+ void addStyle();
+ void deleteStyle();
+ void moveUpStyle();
+ void moveDownStyle();
+ void renameStyle(const QString &);
+ void importFromFile();
+protected:
+ void addTab( KWFrameStyleManagerTab * tab );
+};
+
+class KWFrameStyleManagerTab : public QWidget {
+ Q_OBJECT
+public:
+ KWFrameStyleManagerTab(QWidget *parent) : QWidget(parent) {};
+
+ /** the new style which is to be displayed */
+ void setStyle(KWFrameStyle *style) { m_style = style; }
+ /** update the GUI from the current Style*/
+ virtual void update() = 0;
+ /** return the (i18n-ed) name of the tab */
+ virtual QString tabName() = 0;
+ /** save the GUI to the style */
+ virtual void save() = 0;
+protected:
+ KWFrameStyle *m_style;
+};
+
+class KWFrameStyleBackgroundTab : public KWFrameStyleManagerTab
+{
+ Q_OBJECT
+public:
+ KWFrameStyleBackgroundTab( QWidget * parent );
+
+ virtual void update();
+ virtual void save();
+ virtual QString tabName();
+protected slots:
+ void updateBrushConfiguration( const QColor & );
+protected:
+ QBrush m_backgroundColor;
+ QWidget *bgwidget;
+ QGridLayout *grid;
+ KColorButton *brushColor;
+ KWBrushStylePreview *brushPreview;
+};
+
+class KWFrameStyleBordersTab : public KWFrameStyleManagerTab
+{
+ Q_OBJECT
+public:
+ KWFrameStyleBordersTab( QWidget * parent );
+ ~KWFrameStyleBordersTab();
+ void setWidget( KoParagLayoutWidget * widget );
+
+ virtual void update();
+ virtual void save();
+ virtual QString tabName();
+protected:
+ virtual void resizeEvent( QResizeEvent *e );
+
+ KoParagLayoutWidget * m_widget;
+ KoParagLayout *m_borders; // Pity that I'm using such an overdosis for just borders :-(
+};
+
+#endif
diff --git a/kword/KWFrameView.cpp b/kword/KWFrameView.cpp
new file mode 100644
index 00000000..d12a6b2d
--- /dev/null
+++ b/kword/KWFrameView.cpp
@@ -0,0 +1,481 @@
+/* This file is part of the KOffice project
+ * Copyright (C) 2005 Thomas Zander <zander@kde.org>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; version 2.
+
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public License
+ * along with this library; see the file COPYING.LIB. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ */
+#include "KWFrameView.h"
+#include "KWFrameViewManager.h"
+#include "KWFrame.h"
+#include "KWFrameSet.h"
+#include "KWTextFrameSet.h"
+#include "KWTableFrameSet.h"
+#include "KWPartFrameSet.h"
+#include "KWVariable.h"
+#include "KWPictureFrameSet.h"
+#include "KWViewMode.h"
+#include "KWDocument.h"
+#include "KWCanvas.h"
+
+#include "KoZoomHandler.h"
+
+#include <klocale.h>
+#include <kactionclasses.h>
+
+#include <qapplication.h>
+#include <qpopupmenu.h>
+
+static const double HORIZONTAL_SNAP = 6; // horizontal snap zone (in pt)
+static const double VERTICAL_SNAP = 6; // vertical snap zone (in pt)
+
+KWFrameView::KWFrameView(KWFrameViewManager *parent, KWFrame *frame) {
+ m_manager = parent;
+ Q_ASSERT(frame);
+ Q_ASSERT(frame->frameSet());
+ m_frame = frame;
+ m_selected = false;
+ if(frame->frameSet()->groupmanager() || dynamic_cast<KWTableFrameSet *>(frame->frameSet()) != 0)
+ m_policy = new TableFramePolicy(this);
+ else if(dynamic_cast<KWTextFrameSet *>(frame->frameSet()) != 0)
+ m_policy = new TextFramePolicy(this);
+ else if(dynamic_cast<KWPartFrameSet *>(frame->frameSet()) != 0)
+ m_policy = new PartFramePolicy(this);
+ else if(dynamic_cast<KWPictureFrameSet *>(frame->frameSet()) != 0)
+ m_policy = new ImageFramePolicy(this);
+ else {
+ m_policy = new TextFramePolicy(this);
+ kdWarning() << "Unknown frameset supplied!" << endl;
+ }
+}
+
+KWFrameView::~KWFrameView() {
+ delete m_policy;
+}
+
+bool KWFrameView::isBorderHit(const KoPoint &point) const {
+ return hit(point, true, true);
+}
+
+bool KWFrameView::contains(const KoPoint &point, bool fuzzy) const {
+ return hit(point, fuzzy, false);
+}
+
+bool KWFrameView::hit(const KoPoint &point, bool fuzzy , bool borderOnly) const {
+ //kdDebug() << "hit " << point << " " << fuzzy << ", " << borderOnly << endl;
+ double hs = 0, vs =0;
+ if(fuzzy) {
+ hs = HORIZONTAL_SNAP;
+ if(frame()->width() < HORIZONTAL_SNAP * 3)
+ hs = frame()->width() / 3;
+ vs = VERTICAL_SNAP;
+ if(frame()->height() < VERTICAL_SNAP * 3)
+ vs = frame()->height() / 3;
+ }
+ if(point.x() < frame()->x() - hs)
+ return false;
+ if(point.x() > frame()->right() + hs)
+ return false;
+ if(point.y() < frame()->y() - vs)
+ return false;
+ if(point.y() > frame()->bottom() + vs)
+ return false;
+
+ if(borderOnly) { // also exclude inner part.
+ if(point.x() > frame()->x() + hs && point.x() < frame()->right() - hs &&
+ point.y() > frame()->y() + vs && point.y() < frame()->bottom() - vs )
+ return false;
+ }
+ return true;
+}
+
+MouseMeaning KWFrameView::mouseMeaning( const KoPoint &point, int keyState ) {
+ if(isBorderHit(point)) {
+ MouseMeaning mm = m_policy->mouseMeaningOnBorder(point, keyState);
+ if(mm != MEANING_NONE && ( frame()->frameSet()->isProtectSize() ||
+ frame()->frameSet()->isMainFrameset() || frame()->frameSet()->isAHeader() ||
+ frame()->frameSet()->isAFooter() ))
+ mm = MEANING_FORBIDDEN;
+ return mm;
+ }
+ if(hit(point, false, false))
+ return m_policy->mouseMeaning(point, keyState);
+ return MEANING_NONE;
+}
+
+void KWFrameView::setSelected(bool selected, MouseMeaning selectPolicy) {
+ m_policy->setSelected(selectPolicy);
+ if( m_selected == selected ) return;
+ m_manager->slotFrameSelectionChanged();
+ m_selected = selected;
+}
+
+void KWFrameView::showPopup( const KoPoint &point, KWView *view, const QPoint &popupPoint) const {
+ view->unplugActionList( "tableactions" );
+ view->unplugActionList( "frameset_type_action" );
+ QPopupMenu *popup = m_policy->createPopup(point, view);
+ Q_ASSERT(popup);
+ popup->popup(popupPoint);
+}
+
+void KWFrameView::paintFrameAttributes(QPainter *painter, const QRect &crect, KWViewMode *vm, KoZoomHandler *zh) {
+ if( !m_selected )
+ return;
+
+ class ResizeHandle {
+ private:
+ const int GRIP_SIZE;
+ bool readOnly;
+ public:
+ ResizeHandle(KWFrameView *fv) : GRIP_SIZE(6) {
+ KWFrameSet *fs = fv->frame()->frameSet();
+ readOnly = fs->isProtectSize() || fs->isMainFrameset() ||
+ fs->isAHeader() || fs->isAFooter() || fs->isFloating();
+ }
+ void paint(QPainter *p, int x, int y) {
+ p->setPen( QPen( Qt::black, 1, QPen::SolidLine ) );
+ p->setBrush( QApplication::palette().color( QPalette::Active, QColorGroup::Highlight ) );
+ p->drawRect( x, y, GRIP_SIZE, GRIP_SIZE );
+ if( readOnly ) { //protected frame
+ QBrush brush = QApplication::palette().color( QPalette::Active,QColorGroup::Base );
+ p->fillRect( x+1, y+1, GRIP_SIZE-2, GRIP_SIZE-2, brush );
+ }
+ }
+ };
+
+ const QRect frameRect = vm->normalToView( zh->zoomRect( *frame() ) );
+ if ( crect.intersects( frameRect ) )
+ {
+ ResizeHandle handle(this);
+
+ const int width = frameRect.width();
+ const int height = frameRect.height();
+ for(int y=0; y < 3; y++) {
+ int offsetY = -1 + y + frameRect.y();
+ if(y > 0) offsetY += (height - 6) / (y == 1 ? 2:1);
+ for(int x=0; x < 3; x++) {
+ if(x == 1 && y == 1) continue; // don't draw in the center of the frame.
+ int offsetX = -1 + x + frameRect.x();
+ if(x > 0) offsetX += (width - 6) / (x == 1 ? 2:1);
+ handle.paint(painter, offsetX, offsetY);
+ }
+ }
+ }
+}
+
+// *********** Policies *********
+FramePolicy::FramePolicy(KWFrameView *view) {
+ m_separator = new KActionSeparator();
+ m_view = view;
+}
+void FramePolicy::addFloatingAction(KWView *view, QPtrList<KAction> &actionList) {
+ if(m_view->frame()->frameSet()->isMainFrameset())
+ return;
+ actionList.append(m_separator);
+ KToggleAction *action = dynamic_cast<KToggleAction*> (view->actionCollection()->
+ action("inline_frame"));
+ Q_ASSERT(action);
+ KWFrameSet *parentFs = m_view->frame()->frameSet()->groupmanager() ?
+ m_view->frame()->frameSet()->groupmanager() : m_view->frame()->frameSet();
+ action->setChecked(parentFs->isFloating());
+ actionList.append(action);
+}
+MouseMeaning FramePolicy::mouseMeaningOnBorder( const KoPoint &point, int keyState ) {
+ Q_UNUSED(keyState);
+ double hs = HORIZONTAL_SNAP;
+ KWFrame *frame = m_view->frame();
+ if(frame->width() < HORIZONTAL_SNAP * 3)
+ hs = frame->width() / 3;
+ double vs = VERTICAL_SNAP;
+ if(frame->height() < VERTICAL_SNAP * 3)
+ vs = frame->height() / 3;
+
+ // Corners
+ if( point.x() <= frame->x() + hs ) { // left edge
+ if(point.y() <= frame->y() + vs)
+ return MEANING_TOPLEFT;
+ if(point.y() >= frame->bottom() - vs)
+ return MEANING_BOTTOMLEFT;
+ if( QABS(frame->y() + frame->height() / 2 - point.y()) <= vs )
+ return MEANING_LEFT;
+ return MEANING_MOUSE_MOVE;
+ }
+ if( point.x() >= frame->right() - hs) { // right edge
+ if(point.y() <= frame->y() + vs)
+ return MEANING_TOPRIGHT;
+ if(point.y() >= frame->bottom() - vs)
+ return MEANING_BOTTOMRIGHT;
+ if( QABS(frame->y() + frame->height() / 2 - point.y()) <= vs )
+ return MEANING_RIGHT;
+ return MEANING_MOUSE_MOVE;
+ }
+
+ if( frame->y() + vs >= point.y() ) { // top edge
+ if( QABS(frame->x() + frame->width() / 2 - point.x() ) <= hs )
+ return MEANING_TOP;
+ return MEANING_MOUSE_MOVE;
+ }
+ if( frame->bottom() - vs <= point.y() ) { // bottom edge
+ if( QABS(frame->x() + frame->width() / 2 - point.x() ) <= hs )
+ return MEANING_BOTTOM;
+ return MEANING_MOUSE_MOVE;
+ }
+ return MEANING_NONE;
+}
+
+TableFramePolicy::TableFramePolicy(KWFrameView *view) : FramePolicy (view) {
+}
+MouseMeaning TableFramePolicy::mouseMeaning( const KoPoint &point, int keyState ) {
+ Q_UNUSED(point);
+ // Found a frame under the cursor
+ // Ctrl -> select
+ if ( keyState & Qt::ControlButton )
+ return MEANING_MOUSE_SELECT;
+ // Shift _and_ at least a frame is selected already
+ // (shift + no frame selected is used to select text)
+ if ( (keyState & Qt::ShiftButton) && m_view->parent()->selectedFrame() != 0 )
+ return MEANING_MOUSE_SELECT;
+
+ return MEANING_MOUSE_INSIDE_TEXT;
+}
+QPopupMenu* TableFramePolicy::createPopup( const KoPoint &point, KWView *view ) {
+ view->plugActionList( "tableactions", view->tableActions() );
+ if( m_view->isBorderHit(point) )
+ return view->popupMenu("frame_popup_table");
+ return view->popupMenu("text_popup");
+}
+MouseMeaning TableFramePolicy::mouseMeaningOnBorder(const KoPoint &point, int keyState) {
+ KWFrame *frame = m_view->frame();
+ double hs = HORIZONTAL_SNAP; // horizontal snap zone (in pt)
+ double vs = VERTICAL_SNAP; // vertical snap zone (in pt)
+ bool ctrl = keyState & Qt::ControlButton;
+
+ if ( QABS( frame->x() - point.x() ) < hs
+ && point.y() >= frame->y() && point.y() <= frame->bottom() ) {
+ if( static_cast<KWTableFrameSet::Cell *>(frame->frameSet())->firstColumn() == 0 )
+ return MEANING_SELECT_ROW;
+ if(!ctrl)
+ return MEANING_RESIZE_COLUMN;
+ }
+ if ( QABS( frame->y() - point.y() ) < vs
+ && point.x() >= frame->x() && point.x() <= frame->right() ) {
+ if( static_cast<KWTableFrameSet::Cell *>(frame->frameSet())->firstRow() == 0 )
+ return MEANING_SELECT_COLUMN;
+ if(!ctrl)
+ return MEANING_MOUSE_SELECT;
+ }
+
+ if (ctrl)
+ return MEANING_MOUSE_SELECT;
+ if ( QABS( frame->right() - point.x() ) < hs
+ && point.y() >= frame->y() && point.y() <= frame->bottom() )
+ return MEANING_RESIZE_COLUMN;
+ if ( QABS( frame->bottom() - point.y() ) < vs
+ && point.x() >= frame->x() && point.x() <= frame->right() )
+ return MEANING_MOUSE_SELECT;
+ return MEANING_NONE;
+}
+void TableFramePolicy::setSelected(MouseMeaning selectPolicy) {
+ KWFrameSet *fs = m_view->frame()->frameSet();
+ if( selectPolicy == MEANING_SELECT_COLUMN ) {
+ unsigned int column = static_cast<KWTableFrameSet::Cell *>(fs)->firstColumn();
+ for (KWTableFrameSet::TableIter cells(fs->groupmanager()); cells; ++cells) {
+ if(cells->firstColumn() >= column && cells->lastColumn() <= column) {
+ KWFrameView *fv = m_view->parent()->view(cells->frame(0));
+ if(fv)
+ fv->setSelected(true);
+ }
+ }
+ }
+ else if( selectPolicy == MEANING_SELECT_ROW ) {
+ unsigned int row = static_cast<KWTableFrameSet::Cell *>(fs)->firstRow();
+ for (KWTableFrameSet::TableIter cells(fs->groupmanager()); cells; ++cells) {
+ if(cells->firstRow() >= row && cells->lastRow() <= row) {
+ KWFrameView *fv = m_view->parent()->view(cells->frame(0));
+ if(fv)
+ fv->setSelected(true);
+ }
+ }
+ }
+ else if( selectPolicy == MEANING_SELECT_RANGE ) {
+kdDebug() << "not yet implemented; select table range\n"; // TODO
+ }
+}
+
+PartFramePolicy::PartFramePolicy(KWFrameView *view) : FramePolicy (view) {
+}
+MouseMeaning PartFramePolicy::mouseMeaning( const KoPoint &point, int keyState ) {
+ Q_UNUSED(point);
+ // Clicking on a selected part frame, but not on its border -> either resize or "activate part"
+ if( keyState & Qt::ControlButton ) {
+ return m_view->selected() ? MEANING_MOUSE_MOVE : MEANING_MOUSE_SELECT;
+ }
+ if ( m_view->selected() )
+ return MEANING_ACTIVATE_PART;
+ return MEANING_MOUSE_SELECT;
+}
+QPopupMenu* PartFramePolicy::createPopup( const KoPoint &point, KWView *view ) {
+ Q_UNUSED(point);
+ KWPartFrameSet *part = static_cast<KWPartFrameSet *>(m_view->frame()->frameSet());
+ KActionSeparator *separator=new KActionSeparator();
+ KActionCollection *actionCollection = view->actionCollection();
+ QPtrList<KAction> actionList;
+ actionList.append(separator);
+ if( !part->protectContent() ) {
+ KToggleAction *action = dynamic_cast<KToggleAction*>(actionCollection->action("embedded_store_internal"));
+ Q_ASSERT(action);
+ action->setChecked(part->getChild()->document()->storeInternal());
+ action->setEnabled(part->getChild()->document()->hasExternURL());
+ actionList.append(action);
+ }
+ addFloatingAction(view, actionList);
+ view->plugActionList( "frameset_type_action", actionList );
+
+ return view->popupMenu("frame_popup");
+}
+
+TextFramePolicy::TextFramePolicy(KWFrameView *view) : FramePolicy (view) {
+}
+MouseMeaning TextFramePolicy::mouseMeaning( const KoPoint &point, int keyState ) {
+ if( (keyState & Qt::ControlButton) == Qt::ControlButton )
+ return MEANING_MOUSE_SELECT;
+ KWTextFrameSet *fs = dynamic_cast<KWTextFrameSet*>(m_view->frame()->frameSet());
+ if(fs == 0 || fs->kWordDocument() == 0)
+ return MEANING_MOUSE_INSIDE_TEXT;
+ KWVariableCollection *varCol = fs->kWordDocument()->variableCollection();
+ if (varCol->variableSetting()->displayLink() && varCol->variableSetting()->underlineLink()
+ && fs->linkVariableUnderMouse( point ) )
+ return MEANING_MOUSE_OVER_LINK;
+ KoVariable* var = fs->variableUnderMouse(point);
+ if ( var ) {
+ KWFootNoteVariable * footNoteVar = dynamic_cast<KWFootNoteVariable *>( var );
+ if ( footNoteVar )
+ return MEANING_MOUSE_OVER_FOOTNOTE;
+ }
+ return MEANING_MOUSE_INSIDE_TEXT;
+}
+QPopupMenu* TextFramePolicy::createPopup( const KoPoint &point, KWView *view ) {
+ if( m_view->isBorderHit(point) ) {
+ KWFrameSet *fs = m_view->frame()->frameSet();
+ KActionSeparator *separator=new KActionSeparator();
+ KActionCollection *actionCollection = view->actionCollection();
+ QPtrList<KAction> actionList;
+ if(fs->isHeaderOrFooter()) {
+ actionList.append(separator);
+ actionList.append(actionCollection->action("configure_headerfooter"));
+ }
+ else if (fs->isFootEndNote()) {
+ actionList.append(separator);
+ KAction *action = actionCollection->action("goto_footendnote");
+ action->setText( fs->isFootNote() ?
+ i18n( "Go to Footnote" ) : i18n( "Go to Endnote" ) );
+ actionList.append(action);
+ }
+ addFloatingAction(view, actionList);
+ view->plugActionList( "frameset_type_action", actionList );
+ return view->popupMenu("frame_popup");
+ }
+
+ if ( view->getGUI()->canvasWidget()->currentFrameSetEdit()->frameSet()->type() == FT_FORMULA )
+ return view->popupMenu("Formula");
+
+ // yeah yeah, this is not great and needs a second look. (TZ)
+ KWTextFrameSetEdit *fse = static_cast<KWTextFrameSetEdit*> (view->getGUI()->
+ canvasWidget()->currentFrameSetEdit());
+
+ QString word = fse->wordUnderCursor( *fse->cursor() );
+
+ // Remove previous stuff
+ view->unplugActionList( "datatools" );
+ view->unplugActionList( "variable_action" );
+ view->unplugActionList( "spell_result_action" );
+ view->unplugActionList( "datatools_link" );
+
+ // Those lists are stored in the KWView. Grab a ref to them.
+ QPtrList<KAction> &actionList = view->dataToolActionList();
+ QPtrList<KAction> &variableList = view->variableActionList();
+
+ actionList.clear();
+ variableList.clear();
+
+ bool singleWord= false;
+ KWDocument * doc = m_view->frame()->frameSet()->kWordDocument();
+ actionList = fse->dataToolActionList(doc->instance(), word, singleWord);
+
+ KoVariable* var = fse->variable();
+ doc->variableCollection()->setVariableSelected(var);
+ if ( var )
+ variableList = doc->variableCollection()->popupActionList();
+
+ if( variableList.count()>0) {
+ view->plugActionList( "variable_action", variableList );
+ return view->popupMenu("variable_popup");
+ }
+
+ //kdDebug() << "TextFramePolicy::createPopup: plugging actionlist with " << actionList.count() << " actions" << endl;
+ KoLinkVariable* linkVar = dynamic_cast<KoLinkVariable *>( var );
+ if ( linkVar ) {
+ view->plugActionList( "datatools_link", actionList );
+ return view->popupMenu("text_popup_link");
+ }
+ view->plugActionList( "datatools", actionList );
+ KoNoteVariable * noteVar = dynamic_cast<KoNoteVariable *>( var );
+ if( noteVar )
+ return view->popupMenu("comment_popup");
+
+ KoCustomVariable * customVar = dynamic_cast<KoCustomVariable *>( var );
+ if( customVar )
+ return view->popupMenu("custom_var_popup");
+
+ KWFootNoteVariable * footNoteVar = dynamic_cast<KWFootNoteVariable *>( var );
+ if ( footNoteVar ) {
+ view->changeFootNoteMenuItem( footNoteVar->noteType() == FootNote );
+ return view->popupMenu("footnote_popup");
+ }
+ if ( singleWord ) {
+ QPtrList<KAction> actionCheckSpellList = view->listOfResultOfCheckWord( word );
+ if ( !actionCheckSpellList.isEmpty() ) {
+ view->plugActionList( "spell_result_action", actionCheckSpellList );
+ return view->popupMenu("text_popup_spell_with_result");
+ }
+ return view->popupMenu("text_popup_spell");
+ }
+
+ return view->popupMenu("text_popup");
+}
+
+
+ImageFramePolicy::ImageFramePolicy(KWFrameView *view) : FramePolicy (view) {
+}
+MouseMeaning ImageFramePolicy::mouseMeaning( const KoPoint &point, int keyState ) {
+ Q_UNUSED(point);
+ Q_UNUSED(keyState);
+ return m_view->selected() ? MEANING_MOUSE_MOVE: MEANING_MOUSE_SELECT;
+}
+QPopupMenu* ImageFramePolicy::createPopup( const KoPoint &point, KWView *view ) {
+ Q_UNUSED(point);
+ KActionSeparator *separator=new KActionSeparator();
+ KActionCollection *actionCollection = view->actionCollection();
+ QPtrList<KAction> actionList;
+ actionList.append(separator);
+ KAction *action = actionCollection->action("change_picture");
+ Q_ASSERT(action);
+ actionList.append(action);
+ action = actionCollection->action("save_picture");
+ Q_ASSERT(action);
+ actionList.append(action);
+ addFloatingAction(view, actionList);
+ view->plugActionList( "frameset_type_action", actionList );
+
+ return view->popupMenu("frame_popup");
+}
diff --git a/kword/KWFrameView.h b/kword/KWFrameView.h
new file mode 100644
index 00000000..85e6981d
--- /dev/null
+++ b/kword/KWFrameView.h
@@ -0,0 +1,190 @@
+/* This file is part of the KOffice project
+ * Copyright (C) 2005 Thomas Zander <zander@kde.org>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; version 2.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public License
+ * along with this library; see the file COPYING.LIB. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ */
+#ifndef kwframeview_h
+#define kwframeview_h
+
+#include "defs.h"
+class KWFrameView;
+class KWFrameViewManager;
+class KWFrame;
+class KWView;
+class KWViewMode;
+class KoZoomHandler;
+class KoPoint;
+class KActionSeparator;
+class KAction;
+class QPopupMenu;
+
+/**
+ * This base class is an interface for Policies used in the KWFrameView.
+ */
+class FramePolicy {
+public:
+ /** Constructor */
+ FramePolicy(KWFrameView *view);
+ /**
+ * Return the MouseMeaning enum value for the parent view.
+ * @param point the point where the mouse is hovering.
+ * @param keyState the bitmask of keys that are pressed. Same as Event::state();
+ */
+ virtual MouseMeaning mouseMeaning( const KoPoint &point, int keyState ) = 0;
+ /**
+ * Return a fully initialized popup for the context of frame at @p point
+ * @param point the point where the mouse is hovering.
+ * @param view the parent view widget
+ */
+ virtual QPopupMenu* createPopup( const KoPoint &point, KWView *view ) = 0;
+ /**
+ * Override this method to do more than select the parent frame-view
+ */
+ virtual void setSelected(MouseMeaning) { }
+
+protected:
+ /**
+ * Shared method for all policies called when the border of the frame is clicked.
+ * @param point the point where the mouse is hovering.
+ * @param keyState the bitmask of keys that are pressed. Same as Event::state();
+ */
+ virtual MouseMeaning mouseMeaningOnBorder(const KoPoint &point, int keyState);
+ /**
+ * Shared method for all policies to add the 'set floating' action to a popup menu.
+ * @param view the parent view widget
+ * @param actionList the list of actions where the floating action should be added to
+ */
+ void addFloatingAction(KWView *view, QPtrList<KAction> &actionList);
+
+ KWFrameView *m_view;
+ KActionSeparator *m_separator;
+
+ friend class KWFrameView; // so it can call mouseMeaningOnBorder which assumes some stuff
+};
+
+/**
+ * an instance of a KWFrameView represents the view in the MVC model of a frame; there can be
+ * multiple KWFrameView objects per frame. Typically there is one per view (KWView).
+ * This class registers selectedness and has methods to show the frame and its interaction methods
+ */
+class KWFrameView {
+public:
+ /**
+ * Constructor
+ * @param parent the parent
+ * @param frame the frame this view represents.
+ */
+ KWFrameView(KWFrameViewManager *parent, KWFrame *frame);
+ virtual ~KWFrameView();
+
+ /// returns if this frameView is selected. A selected frame is shown differently on screen.
+ bool selected() const { return m_selected; }
+ /**
+ * Set the selected state of this frameView.
+ * @param selected the new selected state
+ * @param selectPolicy an optionaly mouseMeaning at which the mouse was clicked to
+ * make this selection happen. See the FramePolicy::setSelected() for more info.
+ */
+ void setSelected(bool selected, MouseMeaning selectPolicy = MEANING_MOUSE_SELECT);
+
+ /// returns the frame this frameView represents
+ KWFrame *frame() const { return m_frame; }
+
+ /// returns if the @p point is on the border
+ bool isBorderHit(const KoPoint &point) const;
+ /// returns if the @p point is anywhere in te frame, if fuzzy is true; also a little outside
+ bool contains(const KoPoint &point, bool fuzzy = true) const;
+
+ /**
+ * Return the MouseMeaning enum value for the parent view.
+ * @param point the point where the mouse is hovering.
+ * @param keyState the bitmask of keys that are pressed. Same as Event::state();
+ */
+ MouseMeaning mouseMeaning( const KoPoint &point, int keyState );
+
+ /// Return the parent KWFrameViewManager this frameView belongs to
+ KWFrameViewManager *parent() const { return m_manager; }
+
+ /**
+ * Show a context-sensitive popup menu based on the location of 'point'.
+ * @param point the point at which the mouse was clicked. The context is based on
+ * what is present at that location.
+ * @param popupPoint the point in the same coordinate system as the parent widget of
+ * where the popup menu should be located.
+ * @param view the parent widget for the popup.
+ */
+ void showPopup( const KoPoint &point, KWView *view, const QPoint &popupPoint) const;
+
+ /**
+ * Paint view based items of the frameView, like selected state
+ * @param painter the painter to paint to
+ * @param crect the clip rect; nothing outside this rect is important
+ * @param zh the zoomHandler to convert from internal coordinates to view coordinates
+ * @param vm the current Viewmode.
+ */
+ void paintFrameAttributes(QPainter *painter, const QRect &crect, KWViewMode *vm, KoZoomHandler *zh);
+
+private:
+ /**
+ * Helper method for isBorderHit() and contains()
+ * @param point the point
+ * @param borderOnly if true; exclude the range inside the frame
+ * @param fuzzy don't take all the coordinates too strict, allow for some margin
+ */
+ bool hit(const KoPoint &point, bool fuzzy, bool borderOnly) const;
+
+private:
+ KWFrame *m_frame;
+ bool m_selected;
+ FramePolicy *m_policy;
+ KWFrameViewManager *m_manager;
+};
+
+/** A policy for Table Frames */
+class TableFramePolicy : public FramePolicy {
+public:
+ TableFramePolicy(KWFrameView *view);
+ MouseMeaning mouseMeaning( const KoPoint &point, int keyState );
+ QPopupMenu* createPopup( const KoPoint &point, KWView *view );
+ void setSelected(MouseMeaning selectPolicy);
+
+protected:
+ MouseMeaning mouseMeaningOnBorder( const KoPoint &point, int keyState);
+};
+
+/** A policy for Part Frames */
+class PartFramePolicy : public FramePolicy {
+public:
+ PartFramePolicy(KWFrameView *view);
+ MouseMeaning mouseMeaning( const KoPoint &point, int keyState );
+ QPopupMenu* createPopup( const KoPoint &point, KWView *view );
+};
+
+/** A policy for Text Frames */
+class TextFramePolicy : public FramePolicy {
+public:
+ TextFramePolicy(KWFrameView *view);
+ MouseMeaning mouseMeaning( const KoPoint &point, int keyState );
+ QPopupMenu* createPopup( const KoPoint &point, KWView *view );
+};
+
+/** A policy for Image (aka Picture) Frames */
+class ImageFramePolicy : public FramePolicy {
+public:
+ ImageFramePolicy(KWFrameView *view);
+ MouseMeaning mouseMeaning( const KoPoint &point, int keyState );
+ QPopupMenu* createPopup( const KoPoint &point, KWView *view );
+};
+#endif
diff --git a/kword/KWFrameViewManager.cpp b/kword/KWFrameViewManager.cpp
new file mode 100644
index 00000000..2e09ff5f
--- /dev/null
+++ b/kword/KWFrameViewManager.cpp
@@ -0,0 +1,434 @@
+/* This file is part of the KOffice project
+ * Copyright (C) 2005 Thomas Zander <zander@kde.org>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; version 2.
+
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public License
+ * along with this library; see the file COPYING.LIB. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ */
+#include "KWDocument.h"
+#include "KWFrameViewManager.h"
+#include <KWFrameView.h>
+#include <KWFrame.h>
+#include <KWFrameSet.h>
+
+#include <kdebug.h>
+#include <kcursor.h>
+#include <qcursor.h>
+#include <qtimer.h>
+#include "qpopupmenu.h"
+#include <algorithm>
+
+KWFrameViewManager::KWFrameViewManager() : QObject() {
+ setName("KWFrameViewManager");
+ m_queueRequested = false;
+ m_blockEvents = false;
+}
+
+KWFrameViewManager::KWFrameViewManager(KWDocument *doc) {
+ m_queueRequested = false;
+ m_blockEvents = true;
+ QPtrListIterator<KWFrameSet> frameSets = doc->framesetsIterator();
+ while(frameSets.current()) {
+ slotFrameSetAdded(*frameSets);
+ ++frameSets;
+ }
+ m_blockEvents = false;
+ connect(doc, SIGNAL( sigFrameSetAdded(KWFrameSet*)), SLOT( slotFrameSetAdded(KWFrameSet*)));
+ connect(doc, SIGNAL( sigFrameSetRemoved(KWFrameSet*)), SLOT( slotFrameSetRemoved(KWFrameSet*)));
+ recalculateFrameCache();
+}
+
+KWFrameViewManager::~KWFrameViewManager() {
+ QValueListIterator<FrameEvent *> events = m_frameEvents.begin();
+ while(events != m_frameEvents.end()) {
+ delete (*events);
+ ++events;
+ }
+}
+
+void KWFrameViewManager::addKWFramesListener(KWFramesListener *listener) {
+ m_framesListener.append(listener);
+}
+void KWFrameViewManager::removeKWFramesListener(KWFramesListener *listener) {
+ m_framesListener.remove(listener);
+}
+
+void KWFrameViewManager::slotFrameSetAdded(KWFrameSet *fs) {
+ if(! m_blockEvents)
+ m_frameEvents.append(new FrameEvent(FrameEvent::FrameSetAdded, fs));
+ connect(fs, SIGNAL( sigFrameAdded(KWFrame*)), SLOT( slotFrameAdded(KWFrame *)));
+ connect(fs, SIGNAL( sigFrameRemoved(KWFrame*)), SLOT( slotFrameRemoved(KWFrame *)));
+ connect(fs, SIGNAL( sigNameChanged(KWFrameSet*)), SLOT( slotFrameSetRenamed(KWFrameSet *)));
+ QPtrListIterator<KWFrame> frames = fs->frameIterator();
+ while(frames.current()) {
+ KWFrame *f = frames.current();
+ slotFrameAdded(f);
+ ++frames;
+ }
+ requestFireEvents();
+}
+void KWFrameViewManager::slotFrameSetRemoved(KWFrameSet *fs) {
+ if(! m_blockEvents)
+ m_frameEvents.append(new FrameEvent(FrameEvent::FrameSetRemoved, fs));
+ disconnect(fs, SIGNAL( sigFrameAdded(KWFrame*)), this, SLOT( slotFrameAdded(KWFrame *)));
+ disconnect(fs, SIGNAL( sigFrameRemoved(KWFrame*)), this, SLOT( slotFrameRemoved(KWFrame *)));
+ disconnect(fs, SIGNAL( sigNameChanged(KWFrameSet*)), this, SLOT( slotFrameSetRenamed(KWFrameSet *)));
+ QPtrListIterator<KWFrame> frames = fs->frameIterator();
+ while(frames.current()) {
+ KWFrame *f = frames.current();
+ slotFrameRemoved(f);
+ ++frames;
+ }
+ requestFireEvents();
+}
+void KWFrameViewManager::slotFrameAdded(KWFrame *f) {
+ if(! m_blockEvents)
+ m_frameEvents.append(new FrameEvent(FrameEvent::FrameAdded, f));
+ m_frames.append(new KWFrameView(this, f));
+ requestFireEvents();
+}
+void KWFrameViewManager::slotFrameRemoved(KWFrame *f) {
+ if(! m_blockEvents)
+ m_frameEvents.append(new FrameEvent(FrameEvent::FrameRemoved, f));
+ QValueListIterator<KWFrameView *> frames = m_frames.begin();
+ while(frames != m_frames.end()) {
+ KWFrameView *fv = *frames;
+ if(fv->frame() == f) {
+ if(fv->selected())
+ m_frameEvents.append(new FrameEvent(FrameEvent::FrameSelectionChanged));
+ m_frames.remove(frames);
+ delete fv;
+ break;
+ }
+ ++frames;
+ }
+ requestFireEvents();
+}
+void KWFrameViewManager::slotFrameMoved(KWFrame *f, double previousYPosition) {
+ Q_UNUSED(previousYPosition); // to be used for the page caches to mark them dirty
+ if(! m_blockEvents)
+ m_frameEvents.append(new FrameEvent(FrameEvent::FrameMoved, f));
+ // TODO; KWFrameList update??
+ // update our caches..
+ requestFireEvents();
+}
+void KWFrameViewManager::slotFrameResized(KWFrame *f) {
+ if(! m_blockEvents)
+ m_frameEvents.append(new FrameEvent(FrameEvent::FrameResized, f));
+ // update our caches..
+ requestFireEvents();
+}
+void KWFrameViewManager::slotFrameSelectionChanged() {
+ if(! m_blockEvents)
+ m_frameEvents.append(new FrameEvent(FrameEvent::FrameSelectionChanged));
+ // update our caches..
+ requestFireEvents();
+}
+
+void KWFrameViewManager::slotFrameSetRenamed(KWFrameSet *fs) {
+ if(! m_blockEvents)
+ m_frameEvents.append(new FrameEvent(FrameEvent::FrameSetRenamed, fs));
+ requestFireEvents();
+}
+
+void KWFrameViewManager::requestFireEvents() {
+ if(m_queueRequested && !m_blockEvents)
+ return;
+ m_queueRequested = true;
+ QTimer::singleShot ( 0, this, SLOT(fireEvents()) );
+}
+
+void KWFrameViewManager::fireEvents() {
+ m_queueRequested = false;
+ if(m_frameEvents.isEmpty())
+ return;
+ recalculateFrameCache();
+
+ QValueList<FrameEvent *> copy(m_frameEvents);
+ m_frameEvents.clear();
+
+ QValueList<KWFrame*> resizedFrames;
+ QValueList<KWFrame*> movedFrames;
+ QValueList<KWFramesListener *> listenersCopy(m_framesListener);
+ bool selectionChangedFired=false;
+
+ QValueListIterator<FrameEvent *> events = copy.begin();
+ while(events != copy.end()) {
+ FrameEvent *event = *events;
+
+ // emit based.
+ if(!selectionChangedFired && event->m_action == FrameEvent::FrameSelectionChanged) {
+ emit sigFrameSelectionChanged();
+ selectionChangedFired = true; // only fire ones.
+ } else if(event->m_action == FrameEvent::FrameSetRenamed) {
+ QPtrListIterator<KWFrame> frames = event->m_frameSet->frameIterator();
+ for(;frames.current();++frames) {
+ if(view(frames.current())->selected()) {
+ emit sigFrameSetRenamed();
+ break;
+ }
+ }
+ } else if(event->m_action == FrameEvent::FrameResized) {
+ resizedFrames.append(event->m_frame);
+ } else if(event->m_action == FrameEvent::FrameMoved) {
+ movedFrames.append(event->m_frame);
+ }
+
+ // listener based
+ QValueListIterator<KWFramesListener *> listeners = listenersCopy.begin();
+ while(listeners != listenersCopy.end()) {
+ if(event->m_action == FrameEvent::FrameRemoved)
+ (*listeners)->frameRemoved(event->m_frame);
+ else if(event->m_action == FrameEvent::FrameAdded)
+ (*listeners)->frameAdded(event->m_frame);
+ else if(event->m_action == FrameEvent::FrameSetRemoved)
+ (*listeners)->frameSetRemoved(event->m_frameSet);
+ else if(event->m_action == FrameEvent::FrameSetAdded)
+ (*listeners)->frameSetAdded(event->m_frameSet);
+ ++listeners;
+ }
+
+ delete event;
+ events = copy.remove(events);
+ }
+ if(resizedFrames.count() > 0)
+ emit sigFrameResized(resizedFrames);
+ if(movedFrames.count() > 0)
+ emit sigFrameMoved(movedFrames);
+}
+
+void KWFrameViewManager::recalculateFrameCache() {
+ // TODO :) design and implement a cache...
+ // list of frames sorted on y-coord, with an additional list containing a jump-index
+ kdDebug(31001) << "recalculateFrameCache " << m_frames.count() << " frames are currently registred" << endl;
+}
+
+KWFrameView *KWFrameViewManager::view(const KoPoint &point, SelectionType selected, bool borderOnly) const {
+ QValueVector<KWFrameView*> framesThatAreHit = framesAt(point, borderOnly);
+ bool foundCycleFrame = false;
+ QValueVector<KWFrameView*>::iterator sortedFrames = framesThatAreHit.begin();
+ while(sortedFrames != framesThatAreHit.end()) {
+ if(selected == nextUnselected) {
+ if((*sortedFrames)->selected() )
+ foundCycleFrame = true;
+ else if(foundCycleFrame && !(*sortedFrames)->selected() )
+ return *sortedFrames;
+ }
+ else if(selected == frameOnTop)
+ return *sortedFrames;
+ else { // not cycle, so simply a selected check.
+ if((*sortedFrames)->selected() == (selected == KWFrameViewManager::selected ))
+ return *sortedFrames;
+ }
+ ++sortedFrames;
+ }
+ if(selected == nextUnselected && framesThatAreHit.count() > 0)
+ return framesThatAreHit[0];
+ return 0;
+}
+
+QValueVector<KWFrameView*> KWFrameViewManager::framesAt(const KoPoint &point, bool borderOnly) const {
+ QValueVector<KWFrameView*> framesThatAreHit;
+ // This is probably the slowest and worst way to do it, mark this for optimalisation!
+ for(QValueListConstIterator<KWFrameView*> frames = m_frames.begin();
+ frames != m_frames.end(); ++frames) {
+ if(! (*frames)->frame()->frameSet()->isVisible())
+ continue;
+ if(borderOnly && (*frames)->isBorderHit(point) ||
+ !borderOnly && (*frames)->contains(point))
+ framesThatAreHit.append(*frames);
+ }
+ // sort on z-ordering; top on first
+ std::sort(framesThatAreHit.begin(), framesThatAreHit.end(), compareFrameViewZOrder);
+ return framesThatAreHit;
+}
+
+KWFrameView *KWFrameViewManager::view(const KWFrame *frame) const {
+ // This is probably the slowest and worst way to do it, mark this for optimalisation!
+ QValueListConstIterator<KWFrameView*> frames = m_frames.begin();
+ while(frames != m_frames.end()) {
+ if((*frames)->frame() == frame)
+ return *frames;
+ ++frames;
+ }
+ return 0;
+}
+
+bool KWFrameViewManager::compareFrameViewZOrder(KWFrameView *f1, KWFrameView *f2) {
+ return f1->frame()->zOrder() >= f2->frame()->zOrder();
+}
+
+QCursor KWFrameViewManager::mouseCursor( const KoPoint &point, int keyState ) const {
+ KWFrameView *view = 0;
+ QValueVector<KWFrameView*> framesThatAreHit = framesAt(point);
+ QValueVector<KWFrameView*>::iterator sortedFrames = framesThatAreHit.begin();
+ MouseMeaning meaning;
+ while(sortedFrames != framesThatAreHit.end()) {
+ meaning = (*sortedFrames)->mouseMeaning(point, keyState);
+ if(meaning != MEANING_NONE) {
+ view = (*sortedFrames);
+ break;
+ }
+ ++sortedFrames;
+ }
+
+ if(view == 0)
+ return QCursor(); // default arrow shape
+
+ KWFrameSet*frameSet = view->frame()->frameSet();
+ switch ( meaning ) {
+ case MEANING_NONE:
+ return Qt::ibeamCursor; // default cursor in margins
+ case MEANING_MOUSE_INSIDE:
+ return QCursor(); // default arrow shape
+ case MEANING_MOUSE_INSIDE_TEXT:
+ return Qt::ibeamCursor;
+ case MEANING_MOUSE_OVER_LINK:
+ return Qt::PointingHandCursor;
+ case MEANING_MOUSE_OVER_FOOTNOTE:
+ return Qt::PointingHandCursor;
+ case MEANING_MOUSE_MOVE:
+ return Qt::sizeAllCursor;
+ case MEANING_MOUSE_SELECT:
+ return KCursor::handCursor();
+ case MEANING_ACTIVATE_PART:
+ return KCursor::handCursor();
+ case MEANING_TOPLEFT:
+ case MEANING_BOTTOMRIGHT:
+ return Qt::sizeFDiagCursor;
+ case MEANING_LEFT:
+ case MEANING_RIGHT:
+ return Qt::sizeHorCursor;
+ case MEANING_BOTTOMLEFT:
+ case MEANING_TOPRIGHT:
+ return Qt::sizeBDiagCursor;
+ case MEANING_TOP:
+ case MEANING_BOTTOM:
+ if ( frameSet->isProtectSize() || frameSet->isMainFrameset())
+ return Qt::forbiddenCursor;
+ return Qt::sizeVerCursor;
+ case MEANING_RESIZE_COLUMN:
+ // Bug in Qt up to Qt-3.1.1 : Qt::splitVCursor and Qt::splitHCursor are swapped!
+#if QT_VERSION <= 0x030101
+ return Qt::splitVCursor;
+#else
+ return Qt::splitHCursor;
+#endif
+ case MEANING_RESIZE_ROW:
+#if QT_VERSION <= 0x030101
+ return Qt::splitHCursor;
+#else
+ return Qt::splitVCursor;
+#endif
+ case MEANING_SELECT_RANGE:
+ case MEANING_SELECT_COLUMN:
+ case MEANING_SELECT_ROW:
+ case MEANING_FORBIDDEN:
+ return KCursor::handCursor();
+ }
+ return QCursor(); // default arrow shape
+}
+
+MouseMeaning KWFrameViewManager::mouseMeaning( const KoPoint &point, int keyState) const {
+ QValueVector<KWFrameView*> framesThatAreHit = framesAt(point);
+ QValueVector<KWFrameView*>::iterator sortedFrames = framesThatAreHit.begin();
+ while(sortedFrames != framesThatAreHit.end()) {
+ MouseMeaning answer = (*sortedFrames)->mouseMeaning(point, keyState);
+ if(answer != MEANING_NONE) {
+ //kdDebug() << "mouseMeaning at " << point << " is " << answer << endl;
+ return answer;
+ }
+ ++sortedFrames;
+ }
+ return MEANING_NONE;
+}
+
+QValueList<KWFrameView*> KWFrameViewManager::selectedFrames() const {
+ QValueList<KWFrameView*> selectedFrames;
+
+ QValueList<KWFrameView*>::const_iterator frames = m_frames.begin();
+ for(; frames != m_frames.end(); ++frames )
+ if( (*frames)->selected() )
+ selectedFrames.append( *frames );
+ return selectedFrames;
+}
+
+KWFrameView* KWFrameViewManager::selectedFrame() const {
+ QValueList<KWFrameView*>::const_iterator frames = m_frames.begin();
+ for(; frames != m_frames.end(); ++frames )
+ if( (*frames)->selected() )
+ return *frames;
+ return 0;
+}
+
+void KWFrameViewManager::showPopup( const KoPoint &point, KWView *view, int keyState, const QPoint &popupPoint) const {
+ QValueVector<KWFrameView*> framesThatAreHit = framesAt(point);
+ if(framesThatAreHit.count() == 0) {
+ view->popupMenu("action_popup")->popup(popupPoint);
+ return;
+ }
+ if(keyState == Qt::ControlButton) {
+ // show the border popup of the top most frame.
+ framesThatAreHit[0]->showPopup(framesThatAreHit[0]->frame()->topLeft(), view, popupPoint);
+ return;
+ }
+ QValueVector<KWFrameView*>::iterator iter = framesThatAreHit.begin();
+ while(iter != framesThatAreHit.end()) {
+ if( (*iter)->selected() && keyState == Qt::ControlButton ) {
+ (*iter)->showPopup(point, view, popupPoint);
+ return;
+ }
+ ++iter;
+ }
+ framesThatAreHit[0]->showPopup(point, view, popupPoint);
+}
+
+void KWFrameViewManager::selectFrames(const KoPoint &point, int keyState, bool leftClick) {
+ MouseMeaning mm = mouseMeaning(point, keyState);
+ bool multiSelect = mm == MEANING_MOUSE_SELECT || ( keyState & Qt::ControlButton );
+ SelectionType se = frameOnTop;
+ if(leftClick && multiSelect)
+ se = nextUnselected;
+ KWFrameView *toBeSelected = view(point, se, !multiSelect);
+ //kdDebug() << "KWFrameViewManager::selectFrames" << point << " got: " << toBeSelected << endl;
+ if(toBeSelected == 0 || (keyState & Qt::ControlButton) == 0 || ( keyState & Qt::ShiftButton ) &&
+ !(leftClick && (mm == MEANING_TOPLEFT || mm == MEANING_TOPRIGHT || mm == MEANING_TOP ||
+ mm == MEANING_LEFT || mm == MEANING_RIGHT || mm == MEANING_MOUSE_MOVE ||
+ mm == MEANING_BOTTOMLEFT || mm == MEANING_BOTTOM || mm == MEANING_BOTTOMRIGHT))) {
+ // unselect all
+ for(QValueListConstIterator<KWFrameView*> frames = m_frames.begin();
+ frames != m_frames.end(); ++frames) {
+ (*frames)->setSelected(false);
+ }
+ }
+ if(toBeSelected == 0)
+ return;
+ toBeSelected->setSelected(true, mm);
+ slotFrameSelectionChanged();
+}
+
+// ********** FrameEvent **** */
+KWFrameViewManager::FrameEvent::FrameEvent (ActionType action) {
+ m_action = action;
+}
+KWFrameViewManager::FrameEvent::FrameEvent (ActionType action, KWFrame *frame) {
+ m_action = action;
+ m_frame = frame;
+}
+KWFrameViewManager::FrameEvent::FrameEvent (ActionType action, KWFrameSet *frameSet) {
+ m_action = action;
+ m_frameSet = frameSet;
+}
+
+
+#include "KWFrameViewManager.moc"
diff --git a/kword/KWFrameViewManager.h b/kword/KWFrameViewManager.h
new file mode 100644
index 00000000..765b8688
--- /dev/null
+++ b/kword/KWFrameViewManager.h
@@ -0,0 +1,238 @@
+/* This file is part of the KOffice project
+ * Copyright (C) 2005 Thomas Zander <zander@kde.org>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; version 2.
+
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public License
+ * along with this library; see the file COPYING.LIB. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ */
+#ifndef kwframeviewmanager_h
+#define kwframeviewmanager_h
+#include <qobject.h>
+#include <qptrlist.h>
+#include <qvaluelist.h>
+#include <qvaluevector.h>
+#include <defs.h>
+
+class KWDocument;
+class KWFrame;
+class KWFrameSet;
+class KWView;
+class KWViewMode;
+class KWFramesListener;
+class KWFrameSetEdit;
+class KWFrameView;
+
+class KoPoint;
+class KoRect;
+
+class QPointer;
+class QRegion;
+
+/**
+ * Class that knows about all the (visible) frames in the document and will act as
+ * a manager between the GUI code and the data objects to couple any GUI action to the
+ * right frame.
+ * There is one KWFrameViewManager per view (stored in KWCanvas).
+ *
+ * All coordinates used in this object are point (pt) based, i.e. the same as in KWFrame. Any
+ * coordinates in pixels should first be converted in the KoZoomHandler (in KWord
+ * that's the KWDocument)
+ */
+class KWFrameViewManager : public QObject {
+ Q_OBJECT
+
+public:
+ KWFrameViewManager();
+ /**
+ * Constructor that takes the already existing frames and framesets from doc and
+ * adds them.
+ */
+ KWFrameViewManager(KWDocument *doc);
+ virtual ~KWFrameViewManager();
+
+ /**
+ * Used to change the behavior of view()<dl>
+ * <dt>selected</dt>
+ * <dd>return the first selected with the highest z-ordering (i.e. on top).</dd>
+ * <dt>unselected</dt>
+ * <dd>return the first unselected on top.</dd>
+ * <dt>nextUnselected</dt>
+ * <dd>return the first unselected directly under a selected frame, or
+ * the top most one if nothing is selected.</dd>
+ * <dt>frameOnTop</dt>
+ * <dd>return the frame highest z-ordering, regardless of selection.</dd>
+ * </dl>
+ */
+ enum SelectionType { selected, unselected, nextUnselected, frameOnTop };
+ /**
+ * Returns a frameView representing a frame positioned at @p point, or 0 when no match found.
+ * @param point the position of the frame
+ * @param select this alters the behavior of which frame to return if more then one
+ * exist at the appointed location.
+ * @param borderOnly If true frames only frames that have the border at the point will be
+ * looked at.
+ */
+ KWFrameView *view(const KoPoint &point, SelectionType select, bool borderOnly = false) const;
+ /** Returns a frameView representing @p frame */
+ KWFrameView *view(const KWFrame *frame) const;
+
+ /**
+ * Return all currently selected frames.
+ */
+ QValueList<KWFrameView*> selectedFrames() const;
+ /**
+ * Returns the first selected frame.
+ * Is the same as selectedFrames()[0]
+ */
+ KWFrameView* selectedFrame() const;
+
+ // this should be changed to a real iterator when Qt4 is used.
+ const QValueList<KWFrameView*> frameViewsIterator() const { return m_frames; }
+
+ /**
+ * Return the MouseMeaning of what a click of the mouse would do at the @p point.
+ * All the frames that have a presence at the point are considered and depending on
+ * what kind of frame and where in the frame the mouse is the meaning is calculated.
+ * @param point the point where the mouse is hovering.
+ * @param keyState the bitmask of keys that are pressed. Same as Event::state();
+ */
+ MouseMeaning mouseMeaning( const KoPoint &point, int keyState) const;
+ /**
+ * Similar to mouseMeaning(), but instead of returning the meaning this will return
+ * a mouse cursor to represent the action.
+ * @param point the point where the mouse is hovering.
+ * @param keyState the bitmask of keys that are pressed. Same as Event::state();
+ */
+ QCursor mouseCursor( const KoPoint &point, int keyState ) const;
+
+ /**
+ * Show a context-sensitive popup menu based on the location of 'point'.
+ * @param point the point at which the mouse was clicked. The context is based on
+ * what is present at that location.
+ * @param keyState the bitmask of keys that are pressed. Same as Event::state();
+ * @param popupPoint the point in the same coordinate system as the parent widget of
+ * where the popup menu should be located.
+ * @param view the parent widget for the popup.
+ */
+ void showPopup( const KoPoint &point, KWView *view, int keyState, const QPoint &popupPoint) const;
+
+ // listeners; see the fireEvents method signature for more info.
+ void addKWFramesListener(KWFramesListener *listener);
+ void removeKWFramesListener(KWFramesListener *listener);
+
+ /**
+ * Select frames based on a mouse click at @p point using @p keystate.
+ * Handles the click of a mouse and searches for frames at the location selecting and
+ * / or unselecting any frames based on this information.
+ * @param leftClick true if this select is due to the main button being clicked.
+ * @param point the point clicked.
+ * @param keyState the bitmask of keys that are pressed. Same as Event::state();
+ */
+ void selectFrames(const KoPoint &point, int keyState, bool leftClick);
+
+public slots:
+ /// notify this slot if a FrameSet has been created and should become visible.
+ void slotFrameSetAdded(KWFrameSet *fs);
+ /// notify this slot if a FrameSet has been removed
+ void slotFrameSetRemoved(KWFrameSet *fs);
+ /// notify this slot if a Frame has been created and should become visible.
+ void slotFrameAdded(KWFrame *f);
+ /// notify this slot if a Frame has been removed
+ void slotFrameRemoved(KWFrame *f);
+ /**
+ * notify this slot if a Frame has been moved
+ * @param f the frame
+ * @param previousYPosition the pt-based location of the frame before it was moved.
+ * This is used to update any views in a more intelligent matter.
+ */
+ void slotFrameMoved(KWFrame *f, double previousYPosition);
+ /// notify this slot if a Frame has been resized
+ void slotFrameResized(KWFrame *f);
+ /// notify this slot if one or more frames have been selected or unselected.
+ void slotFrameSelectionChanged();
+ /// notify this slot if a frameset was renamed
+ void slotFrameSetRenamed(KWFrameSet *fs);
+
+signals:
+ /// emitted after one or more incoming slotFrameSelectionChanged events.
+ void sigFrameSelectionChanged();
+ /// emitted after a frameset that had at least one selected frame was renamed.
+ void sigFrameSetRenamed();
+ /// emitted after frames were resized
+ void sigFrameResized(const QValueList<KWFrame*>&);
+ /// emitted after frames were moved
+ void sigFrameMoved(const QValueList<KWFrame*>&);
+
+protected slots:
+ /**
+ * This method will propagate all the events saved up to the listeners.
+ * You don't normally want to call this method; call requestFireEvents() instead
+ * which will eventually call this method for you.
+ */
+ void fireEvents();
+
+protected:
+ /// prepare or update the singleshot timer to fire events.
+#ifndef NDEBUG
+ virtual
+#endif
+ void requestFireEvents();
+
+private:
+ /** Internal class to store FrameEvents in (from the slots) until they are fired later */
+ class FrameEvent {
+ public:
+ enum ActionType { FrameRemoved, FrameAdded, FrameSetRemoved, FrameSetAdded, FrameMoved,
+ FrameResized, FrameSelectionChanged, FrameSetRenamed };
+ FrameEvent (ActionType action);
+ FrameEvent (ActionType action, KWFrame *frame);
+ FrameEvent (ActionType action, KWFrameSet *frameSet);
+ private:
+ ActionType m_action;
+ KWFrame *m_frame;
+ KWFrameSet *m_frameSet;
+ friend class KWFrameViewManager;
+ };
+
+ /// make sure the caches for pages and frame-hit positions is uptodate.
+ void recalculateFrameCache();
+
+ /**
+ * Returns a sorted list of KWFrameView objects that represents frames present at @p point
+ * @param point the location the frame should occupy
+ * @param borderOnly if true, only return frames that are hit in the border by point.
+ */
+ QValueVector<KWFrameView*> framesAt(const KoPoint &point, bool borderOnly = false) const;
+ /**
+ * This is a method used to sort a list using the STL sorting methods.
+ * @param f1 the first object
+ * @param f2 the second object
+ */
+ static bool compareFrameViewZOrder(KWFrameView *f1, KWFrameView *f2);
+
+private:
+ QValueList<KWFrameView*> m_frames; // TODO QHash<KWFrame*,KWFrameView*>
+ QValueList<KWFramesListener*> m_framesListener;
+ QValueList<FrameEvent*> m_frameEvents;
+ bool m_queueRequested, m_blockEvents;
+};
+
+class KWFramesListener {
+public:
+ virtual void frameSetAdded(KWFrameSet *fs) = 0;
+ virtual void frameSetRemoved(KWFrameSet *fs) = 0;
+ virtual void frameAdded(KWFrame *f) = 0;
+ virtual void frameRemoved(KWFrame *f) = 0;
+};
+
+#endif
diff --git a/kword/KWImportStyleDia.cpp b/kword/KWImportStyleDia.cpp
new file mode 100644
index 00000000..b49a8bb4
--- /dev/null
+++ b/kword/KWImportStyleDia.cpp
@@ -0,0 +1,343 @@
+/* This file is part of the KDE project
+ Copyright (C) 2002 Montel Laurent <lmontel@mandrakesoft.com>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+*/
+
+#include <klocale.h>
+#include "KWDocument.h"
+
+#include <qvbox.h>
+#include <qlayout.h>
+#include <qlineedit.h>
+#include <qpushbutton.h>
+#include <qlistbox.h>
+#include <kmessagebox.h>
+#include "KWImportStyleDia.h"
+#include <KoStore.h>
+#include <qfile.h>
+
+#include <kfiledialog.h>
+#include <kdebug.h>
+#include <qlabel.h>
+
+#include "KWTextParag.h"
+
+KWImportStyleDia::KWImportStyleDia( KWDocument *_doc, KoStyleCollection* currentCollection, QWidget *parent, const char *name )
+ :KoImportStyleDia( currentCollection, parent, name ),
+ m_doc(_doc)
+{
+
+}
+
+KWImportStyleDia::~KWImportStyleDia()
+{
+}
+
+
+void KWImportStyleDia::loadFile()
+{
+ KFileDialog fd( QString::null, QString::null, 0, 0, TRUE );
+ QStringList lst = "application/x-kword";
+#if 0
+ lst << "application/vnd.oasis.opendocument.text";
+#endif
+ fd.setMimeFilter( lst );
+ fd.setCaption(i18n("Import Style"));
+ KURL url;
+ if ( fd.exec() != QDialog::Accepted )
+ return;
+ url = fd.selectedURL();
+ if( url.isEmpty() )
+ {
+ KMessageBox::sorry( this,
+ i18n("File name is empty."),
+ i18n("Import Style"));
+ return;
+ }
+ QMap<QString, QString>insertStyle;
+
+ KoStore* store=KoStore::createStore( this, url, KoStore::Read );
+ if (store )
+ {
+ if (store->open("maindoc.xml") )
+ {
+ clear();
+ m_listStyleName->clear();
+
+ QDomDocument doc;
+ doc.setContent( store->device() );
+ QDomElement word = doc.documentElement();
+ QDomElement stylesElem = word.namedItem( "STYLES" ).toElement();
+ if ( !stylesElem.isNull() )
+ {
+ //todo
+ //duplicate code try to remove it !
+ // TODO: use loadOasisStyleTemplates() for OASIS
+ // (and put as much code as possible in koimportstyledia of course)
+ //
+ // I guess we'll have to keep this old loading code forever though,
+ // so we can't really get rid of the subclasses.
+
+ QValueList<QString> followingStyles;
+ QDomNodeList listStyles = stylesElem.elementsByTagName( "STYLE" );
+ for (unsigned int item = 0; item < listStyles.count(); item++)
+ {
+ QDomElement styleElem = listStyles.item( item ).toElement();
+
+ KoParagStyle *sty = new KoParagStyle( QString::null );
+ // Load the paraglayout from the <STYLE> element
+ sty->loadStyle( styleElem, m_doc->syntaxVersion() ); //#### wrong syntaxVersion!
+
+ QString name = sty->displayName();
+ if ( currentCollection()->findStyle( name ) )
+ sty->setName(generateStyleName(sty->name() + "-%1"));
+ // ### TODO: we should offer the option of updating the
+ // existing style instead of creating a foo-1 style. Any ideas for a GUI?
+ if ( currentCollection()->findStyleByDisplayName( name ) )
+ sty->setDisplayName(generateStyleDisplayName(sty->displayName() + "-%1"));
+ insertStyle.insert( name, sty->name() ); // old name -> new name
+
+ QDomElement formatElem = styleElem.namedItem( "FORMAT" ).toElement();
+ if ( !formatElem.isNull() )
+ sty->format() = KWTextParag::loadFormat( formatElem, 0L, m_doc->defaultFont(), m_doc->globalLanguage(), m_doc->globalHyphenation() );
+ else
+ kdWarning(32001) << "No FORMAT tag in <STYLE>" << endl; // This leads to problems in applyStyle().
+
+ // Style created, now let's try to add it
+ sty = m_styleList.addStyle(sty);
+
+ if( m_styleList.count() >= 0 && uint( m_styleList.count() ) > followingStyles.count() )
+ {
+ QString following = styleElem.namedItem("FOLLOWING").toElement().attribute("name");
+ followingStyles.append( following );
+ }
+ else
+ kdWarning () << "Found duplicate style declaration, overwriting former " << sty->name() << endl;
+ }
+
+ Q_ASSERT( m_styleList.count() >= 0 && followingStyles.count() == uint( m_styleList.count() ) );
+
+ unsigned int i=0;
+ for( QValueList<QString>::Iterator it = followingStyles.begin(); it != followingStyles.end(); ++it ) {
+ QString newName =*it;
+ if ( insertStyle.contains( *it ) )
+ newName = (insertStyle)[ *it ];
+
+ KoParagStyle * style = m_styleList.findStyle(newName);
+ if ( style )
+ m_styleList.styleAt(i++)->setFollowingStyle( style );
+ }
+
+ }
+ initList();
+ if(m_styleList.count() == 0) {
+ KMessageBox::error( this,
+ i18n("File does not contain any styles. It may be the wrong version."),
+ i18n("Import Style"));
+ }
+
+ }
+ else if ( store->hasFile( "content.xml" ) )
+ {
+ //oasis file format (for koffice-1.5)
+ }
+ else
+ {
+ KMessageBox::error( this,
+ i18n("This file is not a KWord file!"),
+ i18n("Import Style"));
+ }
+ store->close();
+ }
+ delete store;
+}
+
+KWImportFrameTableStyleDia::KWImportFrameTableStyleDia( KWDocument *_doc, const QStringList &_list, StyleType _type, QWidget *parent, const char *name )
+ : KDialogBase( parent, name , true, "", Ok|Cancel, Ok, true )
+{
+ setCaption( i18n("Import Style") );
+ m_doc=_doc;
+ m_typeStyle = _type;
+ m_list =_list;
+ QVBox *page = makeVBoxMainWidget();
+ new QLabel(i18n("Select style to import:"), page);
+ m_listStyleName = new QListBox( page );
+ m_listStyleName->setSelectionMode( QListBox::Multi );
+ loadFile();
+ resize (300, 400);
+ setFocus();
+}
+
+KWImportFrameTableStyleDia::~KWImportFrameTableStyleDia()
+{
+ m_frameStyleList.setAutoDelete(true);
+ m_tableStyleList.setAutoDelete(true);
+ m_frameStyleList.clear();
+ m_tableStyleList.clear();
+}
+
+QString KWImportFrameTableStyleDia::generateStyleName( const QString & templateName )
+{
+ QString name;
+ int num = 1;
+ bool exists;
+ do {
+ name = templateName.arg( num );
+ exists = (m_list.findIndex( name )!=-1);
+ ++num;
+ } while ( exists );
+ return name;
+}
+
+
+void KWImportFrameTableStyleDia::loadFile()
+{
+ KFileDialog fd( QString::null, QString::null, 0, 0, TRUE );
+ QStringList lst = "application/x-kword";
+#if 0
+ lst << "application/vnd.oasis.opendocument.text";
+#endif
+ fd.setMimeFilter( lst );
+ fd.setCaption(i18n("Import Style"));
+ KURL url;
+ if ( fd.exec() != QDialog::Accepted )
+ return;
+ url = fd.selectedURL();
+ if( url.isEmpty() )
+ {
+ KMessageBox::sorry( this,
+ i18n("File name is empty."),
+ i18n("Import Style"));
+ return;
+ }
+ KoStore* store=KoStore::createStore( this, url, KoStore::Read );
+ if (store )
+ {
+ if (store->open("maindoc.xml") )
+ {
+ QDomDocument doc;
+ doc.setContent( store->device() );
+ QDomElement word = doc.documentElement();
+ if ( m_typeStyle ==frameStyle )
+ {
+ QDomNodeList listStyles = word.elementsByTagName( "FRAMESTYLE" );
+ for (unsigned int item = 0; item < listStyles.count(); item++) {
+ QDomElement styleElem = listStyles.item( item ).toElement();
+
+ KWFrameStyle *sty = new KWFrameStyle( styleElem );
+ QString name =sty->name();
+ if ( m_list.findIndex( name )!=-1 )
+ sty->setDisplayName(generateStyleName( sty->displayName() + QString( "-%1")));
+ m_frameStyleList.append( sty);
+ }
+ }
+ else
+ {
+ QDomNodeList listStyles = word.elementsByTagName( "TABLESTYLE" );
+ for (unsigned int item = 0; item < listStyles.count(); item++) {
+ QDomElement styleElem = listStyles.item( item ).toElement();
+ KWTableStyle *sty = new KWTableStyle( styleElem,m_doc,2 );
+ QString name =sty->name();
+ if ( m_list.findIndex( name )!=-1 )
+ sty->setName(generateStyleName( sty->displayName() + QString( "-%1")));
+ m_tableStyleList.append( sty);
+ }
+ }
+ initList();
+ if(m_tableStyleList.count() == 0 && m_frameStyleList.count()==0) {
+ KMessageBox::error( this,
+ i18n("File does not contain any styles. It may be the wrong version."),
+ i18n("Import Style"));
+ }
+
+ }
+ else if ( store->hasFile( "content.xml" ) )
+ {
+ //oasis file format (for koffice-1.5)
+ }
+ else
+ {
+ KMessageBox::error( this,
+ i18n("This file is not a KWord file!"),
+ i18n("Import Style"));
+ }
+
+ store->close();
+ }
+
+ delete store;
+}
+
+void KWImportFrameTableStyleDia::initList()
+{
+ QStringList lst;
+ if ( m_typeStyle ==frameStyle )
+ {
+ for ( KWFrameStyle * p = m_frameStyleList.first(); p != 0L; p = m_frameStyleList.next() )
+ {
+ lst<<p->displayName();
+ }
+ }
+ else
+ {
+ for ( KWTableStyle * p = m_tableStyleList.first(); p != 0L; p = m_tableStyleList.next() )
+ {
+ lst<<p->displayName();
+ }
+ }
+
+ m_listStyleName->insertStringList(lst);
+}
+
+void KWImportFrameTableStyleDia::slotOk()
+{
+ for (uint i = 0; i< m_listStyleName->count();i++)
+ {
+ if ( !m_listStyleName->isSelected( i ))
+ {
+ QString name = m_listStyleName->text(i );
+ if ( m_typeStyle ==frameStyle ) // frame styles
+ {
+ //remove this style from list
+ QPtrListIterator<KWFrameStyle> styleIt( m_frameStyleList );
+ for ( ; styleIt.current(); ++styleIt )
+ {
+ if ( styleIt.current()->displayName() == name )
+ {
+ m_frameStyleList.remove(styleIt.current());
+ break;
+ }
+ }
+ }
+ else // then it will have to be table styles
+ {
+ //remove this style from list
+ QPtrListIterator<KWTableStyle> styleIt( m_tableStyleList );
+ for ( ; styleIt.current(); ++styleIt )
+ {
+ if ( styleIt.current()->displayName() == name )
+ {
+ m_tableStyleList.remove(styleIt.current());
+ break;
+ }
+ }
+ }
+ }
+ }
+ KDialogBase::slotOk();
+}
+#include "KWImportStyleDia.moc"
diff --git a/kword/KWImportStyleDia.h b/kword/KWImportStyleDia.h
new file mode 100644
index 00000000..2b27c5b6
--- /dev/null
+++ b/kword/KWImportStyleDia.h
@@ -0,0 +1,76 @@
+/* This file is part of the KDE project
+ Copyright (C) 2002 Montel Laurent <lmontel@mandrakesoft.com>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+*/
+
+#ifndef __KWImportStyleDia__
+#define __KWImportStyleDia__
+
+#include <kdialogbase.h>
+#include <KoImportStyleDia.h>
+#include <qstringlist.h>
+
+#include "KWFrameStyle.h"
+#include "KWTableStyle.h"
+
+class QLineEdit;
+class QListBox;
+class KWDocument;
+class QPushButton;
+class KoParagStyle;
+
+class KWImportStyleDia : public KoImportStyleDia
+{
+ Q_OBJECT
+public:
+ KWImportStyleDia( KWDocument *_doc, KoStyleCollection* currentCollection, QWidget *parent, const char *name = 0 );
+ ~KWImportStyleDia();
+
+protected:
+ virtual void loadFile();
+
+private:
+ KWDocument *m_doc;
+};
+
+
+class KWImportFrameTableStyleDia : public KDialogBase
+{
+ Q_OBJECT
+public:
+ enum StyleType { frameStyle, TableStyle};
+ KWImportFrameTableStyleDia( KWDocument *_doc, const QStringList & _list, StyleType _type , QWidget *parent, const char *name );
+ ~KWImportFrameTableStyleDia();
+ QPtrList<KWFrameStyle> listOfFrameStyleImported() const { return m_frameStyleList;}
+ QPtrList<KWTableStyle> listOfTableStyleImported() const { return m_tableStyleList;}
+
+protected slots:
+ virtual void slotOk();
+
+protected:
+ QString generateStyleName( const QString & templateName );
+ void loadFile();
+ void initList();
+ QListBox *m_listStyleName;
+ KWDocument *m_doc;
+ QPtrList<KWFrameStyle> m_frameStyleList;
+ QPtrList<KWTableStyle> m_tableStyleList;
+ QStringList m_list;
+ StyleType m_typeStyle;
+};
+
+#endif
diff --git a/kword/KWInsertDia.cpp b/kword/KWInsertDia.cpp
new file mode 100644
index 00000000..cabae8a1
--- /dev/null
+++ b/kword/KWInsertDia.cpp
@@ -0,0 +1,85 @@
+/* This file is part of the KDE project
+ Copyright (C) 1998, 1999 Reginald Stadlbauer <reggie@kde.org>
+ Copyright (C) 2005 Thomas Zander <zander@kde.org>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+*/
+
+#include "KWInsertDia.h"
+#include "KWTableFrameSet.h"
+#include "KWView.h"
+
+#include <klocale.h>
+
+#include <qlabel.h>
+#include <qspinbox.h>
+#include <qradiobutton.h>
+#include <qbuttongroup.h>
+#include <qlayout.h>
+
+KWInsertDia::KWInsertDia( KWView *parent, KWTableFrameSet *table, InsertType type, int insertHint)
+ : KDialogBase( Plain, (type==insertRow?i18n("Insert Row") : i18n("Insert Column")), Ok | Cancel, Ok, parent, "Insert Table items dialog", true )
+{
+ m_type = type;
+ m_table = table;
+ m_view = parent;
+
+ setupTab1(insertHint);
+}
+
+void KWInsertDia::setupTab1(int insertHint)
+{
+ QWidget *tab1 = plainPage();
+ QGridLayout *grid1 = new QGridLayout( tab1, 2, 2, 0, KDialog::spacingHint() );
+
+ QButtonGroup *grp = new QButtonGroup( m_type == insertRow ? i18n( "Insert New Row" ) : i18n( "Insert New Column" ), tab1 );
+
+ QGridLayout *grid2 = new QGridLayout( grp, 3, 1, KDialog::marginHint(), KDialog::spacingHint() );
+
+ m_rBefore = new QRadioButton( i18n( "Before" ), grp, "before_radio_button" );
+ grp->insert( m_rBefore );
+ grid2->addWidget( m_rBefore, 1, 0 );
+
+ QRadioButton *rAfter = new QRadioButton( i18n( "After" ), grp, "after_radio_button");
+ grp->insert( rAfter );
+ grid2->addWidget( rAfter, 2, 0 );
+ rAfter->setChecked( true );
+
+ grid2->addRowSpacing( 0, 7 );
+
+ grid1->addMultiCellWidget ( grp, 0, 0, 0, 1 );
+
+ QLabel *rc = new QLabel( m_type == insertRow ? i18n( "Row:" ) : i18n( "Column:" ), tab1 );
+ grid1->addWidget( rc, 1, 0 );
+
+ m_value = new QSpinBox( 1, m_type == insertRow ? m_table->getRows() : m_table->getColumns(),
+ 1, tab1, "row_col_spinbox" );
+ m_value->setValue( insertHint + 1 ); // +1 due to the fact that humans count starting at 1
+
+ grid1->addWidget( m_value, 1, 1 );
+}
+
+void KWInsertDia::slotOk()
+{
+ unsigned int insert = m_value->value() - ( m_rBefore->isChecked() ? 1 : 0 );
+ if ( m_type == insertRow )
+ m_view->tableInsertRow(insert, m_table);
+ else
+ m_view->tableInsertCol(insert, m_table);
+ KDialogBase::slotOk();
+}
+
+#include "KWInsertDia.moc"
diff --git a/kword/KWInsertDia.h b/kword/KWInsertDia.h
new file mode 100644
index 00000000..163917de
--- /dev/null
+++ b/kword/KWInsertDia.h
@@ -0,0 +1,55 @@
+/* This file is part of the KDE project
+ Copyright (C) 1998, 1999 Reginald Stadlbauer <reggie@kde.org>
+ Copyright (C) 2005 Thomas Zander <zander@kde.org>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+*/
+
+#ifndef insdia_h
+#define insdia_h
+
+#include <kdialogbase.h>
+
+class KWTableFrameSet;
+class QRadioButton;
+class QSpinBox;
+class KWView;
+
+class KWInsertDia : public KDialogBase
+{
+ Q_OBJECT
+
+public:
+ enum InsertType {insertRow, insertColumn};
+ KWInsertDia( KWView *parent, KWTableFrameSet *table, InsertType type, int insertHint);
+
+protected:
+ void setupTab1(int insertHint);
+
+ QRadioButton *m_rBefore;
+ QSpinBox *m_value;
+
+ KWTableFrameSet *m_table;
+ InsertType m_type;
+ KWView *m_view;
+
+protected slots:
+ virtual void slotOk();
+};
+
+#endif
+
+
diff --git a/kword/KWInsertPageDia.cpp b/kword/KWInsertPageDia.cpp
new file mode 100644
index 00000000..d44713fa
--- /dev/null
+++ b/kword/KWInsertPageDia.cpp
@@ -0,0 +1,53 @@
+/* This file is part of the KDE project
+ Copyright (C) 2002 Montel Laurent <lmontel@mandrakesoft.com>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+*/
+
+
+
+#include "KWInsertPageDia.h"
+#include <klocale.h>
+#include <qradiobutton.h>
+#include <qgroupbox.h>
+#include <qlayout.h>
+#include <qbuttongroup.h>
+#include <qvbox.h>
+
+KWInsertPageDia::KWInsertPageDia( QWidget *parent, const char* name )
+ : KDialogBase( parent, name,TRUE,i18n("Insert Page"),Ok|Cancel )
+{
+ QVBox *page = makeVBoxMainWidget();
+
+ QButtonGroup *grp = new QButtonGroup( 1, QGroupBox::Horizontal, i18n( "Insert Page" ),page );
+ grp->setRadioButtonExclusive( TRUE );
+ grp->layout();
+ m_after = new QRadioButton( i18n("After"), grp );
+ m_before = new QRadioButton( i18n("Before"), grp );
+
+ grp->setRadioButtonExclusive( TRUE );
+ m_after->setChecked( true );
+ resize( 200, 150 );
+ setFocus();
+}
+
+InsertPagePos KWInsertPageDia::insertPagePos() const
+{
+ return m_after->isChecked() ? KW_INSERTPAGEAFTER : KW_INSERTPAGEBEFORE;
+}
+
+
+#include "KWInsertPageDia.moc"
diff --git a/kword/KWInsertPageDia.h b/kword/KWInsertPageDia.h
new file mode 100644
index 00000000..f7ac341e
--- /dev/null
+++ b/kword/KWInsertPageDia.h
@@ -0,0 +1,38 @@
+/* This file is part of the KDE project
+ Copyright (C) 2002 Montel Laurent <lmontel@mandrakesoft.com>
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+*/
+
+#ifndef __insertpagedia__
+#define __insertpagedia__
+
+#include <kdialogbase.h>
+#include "defs.h"
+class QRadioButton;
+
+class KWInsertPageDia : public KDialogBase
+{
+ Q_OBJECT
+public:
+ KWInsertPageDia( QWidget *parent, const char* name );
+ InsertPagePos insertPagePos() const;
+
+private:
+ QRadioButton *m_before;
+ QRadioButton *m_after;
+};
+
+#endif
diff --git a/kword/KWInsertPicDia.cpp b/kword/KWInsertPicDia.cpp
new file mode 100644
index 00000000..df29e330
--- /dev/null
+++ b/kword/KWInsertPicDia.cpp
@@ -0,0 +1,180 @@
+/* This file is part of the KDE project
+ Copyright (C) 2001 David Faure <faure@kde.org>
+ Copyright (C) 2002 Nicolas GOUTTE <goutte@kde.org>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+*/
+
+#include <qpainter.h>
+#include <qpushbutton.h>
+#include <qbitmap.h>
+#include <qlayout.h>
+#include <qcheckbox.h>
+#include <qscrollview.h>
+
+#include <kdebug.h>
+#include <klocale.h>
+#include <kfiledialog.h>
+#include <kimageio.h>
+#include <kio/netaccess.h>
+
+#include <KoPicture.h>
+#include <KoPictureFilePreview.h>
+
+#include "KWDocument.h"
+#include "KWInsertPicDia.h"
+#include <qtimer.h>
+
+/**
+ * This is the preview that appears on the right of the "Insert picture" dialog.
+ * Not to be confused with KoPictureFilePreview, the one inside the file dialog!
+ * (Note: this one has to remain separate, for the day we add options like flipping, rotating, etc.)
+ */
+class KWInsertPicPreview : public QScrollView
+{
+public:
+ KWInsertPicPreview( QWidget *parent )
+ : QScrollView( parent )
+ {
+ viewport()->setBackgroundMode( PaletteBase );
+ setMinimumSize( 300, 200 );
+ }
+
+ virtual ~KWInsertPicPreview() {}
+
+ bool setPicture( const KoPicture & picture )
+ {
+ if (!picture.isNull())
+ {
+ m_size = picture.getOriginalSize();
+ m_picture = picture;
+ resizeContents( m_size.width(), m_size.height() );
+ repaint( false );
+ return true;
+ }
+ else
+ return false;
+ }
+
+ void drawContents( QPainter *p, int, int, int, int )
+ {
+ p->setBackgroundColor( Qt::white );
+ // Be sure that the background is white (for transparency)
+ p->fillRect(0, 0, m_size.width(), m_size.height(), QBrush( Qt::white ));
+ m_picture.draw( *p, 0 ,0, m_size.width(), m_size.height());
+ }
+
+private:
+ KoPicture m_picture;
+ QSize m_size;
+};
+
+//////////////
+
+KWInsertPicDia::KWInsertPicDia( QWidget *parent, bool _inline, bool _keepRatio, KWDocument *_doc, const char *name )
+ : KDialogBase( Plain, i18n("Insert Picture"), Ok|Cancel, Ok, parent, name, true ),
+ m_bFirst ( true ), m_doc ( _doc )
+{
+ setInitialSize( QSize(400, 300) );
+ QWidget *page = plainPage();
+ QGridLayout *grid = new QGridLayout( page, 4, 2, KDialog::marginHint(), KDialog::spacingHint() );
+
+ QPushButton *pbImage = new QPushButton( i18n( "Choose &Picture..." ), page );
+ grid->addWidget( pbImage, 0, 0 );
+ connect( pbImage, SIGNAL( clicked() ), SLOT( slotChooseImage() ) );
+
+ m_cbInline = new QCheckBox( i18n( "Insert picture inline" ), page );
+ grid->addWidget( m_cbInline, 1, 0 );
+
+ m_cbKeepRatio= new QCheckBox( i18n("Retain original aspect ratio"),page);
+ grid->addWidget( m_cbKeepRatio, 2, 0);
+
+ m_preview = new KWInsertPicPreview( page );
+ grid->addMultiCellWidget( m_preview, 0, 3, 1, 1 );
+
+ // Stretch the buttons and checkboxes a little, but stretch the preview much more
+ grid->setRowStretch( 0, 1 );
+ grid->setRowStretch( 1, 1 );
+ grid->setRowStretch( 2, 1 );
+ grid->setRowStretch( 3, 10 );
+ grid->setColStretch( 0, 1 );
+ grid->setColStretch( 1, 10 );
+ m_cbKeepRatio->setChecked(_keepRatio);
+ m_cbInline->setChecked( _inline );
+ enableButtonOK( false );
+ setFocus();
+ slotChooseImage(); // save the user time, directly open the dialog
+}
+
+bool KWInsertPicDia::makeInline() const
+{
+ return m_cbInline->isChecked();
+}
+
+bool KWInsertPicDia::keepRatio() const
+{
+ return m_cbKeepRatio->isChecked();
+}
+
+void KWInsertPicDia::slotChooseImage()
+{
+ KoPicture tmppicture = KWInsertPicDia::selectPictureDia( ":picture", this );
+ if ( !tmppicture.isNull() ) // if canceled, keep current picture (#72827)
+ m_picture = tmppicture;
+ if ( m_picture.isNull() && m_bFirst)
+ {
+ kdDebug() << "KWInsertPicDia::slotChooseImage cancelled by user." << endl;
+ // Close, but delayed, otherwise it won't work (we only return from the ctor)
+ QTimer::singleShot( 0, this, SLOT( cancel() ) );
+ return;
+ }
+ enableButtonOK ( m_preview->setPicture( m_picture ) );
+ m_bFirst = false;
+}
+
+KoPicture KWInsertPicDia::selectPictureDia( const QString & _path, QWidget* parent )
+{
+ QStringList mimetypes ( KImageIO::mimeTypes( KImageIO::Reading ) );
+ mimetypes += KoPictureFilePreview::clipartMimeTypes();
+
+ KFileDialog fd( _path, QString::null, parent, 0, TRUE );
+ fd.setMimeFilter( mimetypes );
+ fd.setCaption(i18n("Choose Picture"));
+ return selectPicture( fd, parent );
+}
+
+KoPicture KWInsertPicDia::selectPicture( KFileDialog & fd, QWidget *parent )
+{
+ KoPicture picture;
+
+ fd.setPreviewWidget( new KoPictureFilePreview( &fd ) );
+ KURL url;
+ if ( fd.exec() == QDialog::Accepted )
+ url = fd.selectedURL();
+
+ if( !url.isEmpty() )
+ picture.setKeyAndDownloadPicture( url, parent );
+
+ return picture;
+}
+
+KoPicture KWInsertPicDia::picture ( void ) const
+{
+ kdDebug() << m_picture.getKey().toString() << " selected in KWInsertPicDia" << endl;
+ return m_picture;
+}
+
+#include "KWInsertPicDia.moc"
diff --git a/kword/KWInsertPicDia.h b/kword/KWInsertPicDia.h
new file mode 100644
index 00000000..b7e949b4
--- /dev/null
+++ b/kword/KWInsertPicDia.h
@@ -0,0 +1,62 @@
+/* This file is part of the KDE project
+ Copyright (C) 2001 David Faure <faure@kde.org>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+*/
+
+#ifndef kwinsertpicdia_h
+#define kwinsertpicdia_h
+
+#include <kdialogbase.h>
+class QCheckBox;
+class KWInsertPicPreview;
+class KFileDialog;
+class KWDocument;
+
+class KWInsertPicDia : public KDialogBase
+{
+ Q_OBJECT
+public:
+ KWInsertPicDia( QWidget *parent, bool _inline, bool _keepRatio, KWDocument *_doc, const char *name = 0 );
+
+ bool makeInline() const;
+
+ bool keepRatio() const;
+
+ /**
+ * @param _path the name of the old file
+ * @return the loaded picture (Picture is null if cancelled.)
+ */
+ static KoPicture selectPictureDia( const QString & _path, QWidget* parent );
+
+ KoPicture picture ( void ) const;
+
+protected slots:
+ void slotChooseImage();
+
+protected:
+ static KoPicture selectPicture( KFileDialog & fd, QWidget *parent );
+
+private:
+
+ bool m_bFirst;
+ QCheckBox *m_cbInline, *m_cbKeepRatio;
+ KWInsertPicPreview *m_preview;
+ KWDocument *m_doc;
+ KoPicture m_picture;
+};
+
+#endif
diff --git a/kword/KWInsertTOCCommand.cpp b/kword/KWInsertTOCCommand.cpp
new file mode 100644
index 00000000..5740e125
--- /dev/null
+++ b/kword/KWInsertTOCCommand.cpp
@@ -0,0 +1,261 @@
+/* This file is part of the KDE project
+ Copyright (C) 1998, 1999 Reginald Stadlbauer <reggie@kde.org>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+*/
+
+#include <KoParagCounter.h>
+
+#include "KWInsertTOCCommand.h"
+#include "KWDocument.h"
+#include "KWTextFrameSet.h"
+#include "KWTextDocument.h"
+#include "KWTextParag.h"
+
+#include <klocale.h>
+#include <kdebug.h>
+
+KWInsertTOCCommand::KWInsertTOCCommand( KWTextFrameSet * fs, KoTextParag *parag )
+ : KoTextDocCommand( fs->textDocument() ), m_paragId( parag->paragId() )
+{
+}
+
+KoTextCursor * KWInsertTOCCommand::execute( KoTextCursor *c )
+{
+ KWTextDocument * textdoc = static_cast<KWTextDocument *>(doc);
+ KWTextFrameSet * fs = textdoc->textFrameSet();
+
+ fs->kWordDocument()->setTocPresent(true);
+
+ KoTextParag *insertionParag = textdoc->paragAt( m_paragId );
+ if ( !insertionParag ) {
+ qWarning( "KWInsertTOCCommand:: can't locate parag at %d, last parag: %d", m_paragId, textdoc->lastParag()->paragId() );
+ return c;
+ }
+ KWTextParag *body = static_cast<KWTextParag *>( insertionParag );
+ // Create new very first paragraph
+ KWTextParag *parag = static_cast<KWTextParag *>( textdoc->createParag( textdoc, body->prev() /*prev*/, body /*next*/, true ) );
+ parag->append( i18n( "Table of Contents" ) );
+ KoParagStyle * style = findOrCreateTOCStyle( fs, -1 ); // "Contents Title"
+ parag->setParagLayout( style->paragLayout() );
+ parag->setFormat( 0, parag->string()->length(), textdoc->formatCollection()->format( &style->format() ) );
+ parag->setPartOfTableOfContents( true );
+
+ // Insert table and THEN set page numbers
+ // Otherwise the page numbers are incorrect
+
+ KWTextParag *p = static_cast<KWTextParag *>(textdoc->firstParag()/*parag->next()*/);
+ //ASSERT( p == body );
+ KWTextParag *prevTOCParag = parag;
+ QMap<KWTextParag *, KWTextParag *> paragMap; // Associate a paragraph form the TOC with the real one from the body
+ while ( p ) {
+ // Include this paragraph in the TOC depending on the isOutline flag of the style
+ if ( p->style() && p->style()->isOutline() )
+ {
+ parag = static_cast<KWTextParag *>(textdoc->createParag( textdoc, prevTOCParag /*prev*/, body /*next*/, true ));
+ parag->setPartOfTableOfContents( true );
+ QString txt = p->toString(); // includes the heading number, if any
+ parag->append( txt );
+ prevTOCParag = parag;
+
+ paragMap.insert( parag, p );
+ }
+ p = static_cast<KWTextParag *>(p->next());
+ }
+ // Set a hard frame break after the last TOC parag
+ kdDebug() << "KWInsertTOCCommand::execute setPageBreaking on " << prevTOCParag << " " << prevTOCParag->paragId() << endl;
+ prevTOCParag->setPageBreaking( prevTOCParag->pageBreaking() | KWParagLayout::HardFrameBreakAfter );
+
+ // Format paragraphs, to take this page break into account and update page numbers
+ fs->layout();
+ fs->updateFrames();
+
+ //kdDebug() << "KWInsertTOCCommand::execute layouting done, setting page numbers" << endl;
+
+ // Now add the page numbers, and apply the style
+ QMap<KWTextParag *, KWTextParag *>::Iterator mapIt = paragMap.begin();
+ for ( ; mapIt != paragMap.end() ; ++mapIt )
+ {
+ KWTextParag * parag = mapIt.key(); // Parag in the TOC
+ KWTextParag * p = mapIt.data(); // Parag in the body
+
+ // Find page number for paragraph
+ KoPoint pt;
+ KWFrame * frame = fs->internalToDocument( QPoint(0, p->rect().top()), pt );
+ if ( frame ) // let's be safe
+ {
+ parag->append( "\t" );
+ parag->append( QString::number( frame->pageNumber() ) );
+ }
+
+ // Apply style
+ int depth = p->counter() ? p->counter()->depth() : 0;
+ KoParagStyle * tocStyle = findOrCreateTOCStyle( fs, depth );
+ parag->setParagLayout( tocStyle->paragLayout() );
+ parag->setFormat( 0, parag->string()->length(), & tocStyle->format() );
+ }
+ // The setParagLayout ruined it, so here it is again :)
+ prevTOCParag->setPageBreaking( prevTOCParag->pageBreaking() | KWParagLayout::HardFrameBreakAfter );
+ return c;
+}
+
+KoTextCursor *KWInsertTOCCommand::unexecute( KoTextCursor *c )
+{
+ KWTextDocument * textdoc = static_cast<KWTextDocument *>(doc);
+ KWTextFrameSet * fs = textdoc->textFrameSet();
+
+ removeTOC( fs, c, 0L );
+ fs->kWordDocument()->setTocPresent(false);
+ return c;
+}
+
+KoTextCursor * KWInsertTOCCommand::removeTOC( KWTextFrameSet *fs, KoTextCursor *cursor, KMacroCommand * /*macroCmd*/ )
+{
+ KoTextDocument * textdoc = fs->textDocument();
+ // Remove existing table of contents, based on the style
+ KoTextCursor start( textdoc );
+ KoTextCursor end( textdoc );
+ // We start from the end, to avoid the parag shifting problem
+ KoTextParag *p = textdoc->lastParag();
+ KoTextCursor *posOfTable=0L;
+ KoTextParag *posOfToc=0L;
+
+ while ( p )
+ {
+ KWTextParag * parag = static_cast<KWTextParag *>(p);
+ if ( parag->partOfTableOfContents() )
+ {
+ kdDebug() << "KWContents::createContents Deleting paragraph " << p << " " << p->paragId() << endl;
+ // This paragraph is part of the TOC -> remove
+
+ /* This method aims to provide an "undo" that restores the previous version of the TOC.
+ Problem is, it screws up the parag style (due to removeSelectedText calling join),
+ and the first parag of the body ends up with the Contents Title style.
+ start.setParag( p );
+ start.setIndex( 0 );
+ textdoc->setSelectionStart( KoTextDocument::Temp, &start );
+ ASSERT( p->next() );
+ end.setParag( p->next() );
+ end.setIndex( 0 );
+ textdoc->setSelectionEnd( KoTextDocument::Temp, &end );
+ KCommand * cmd = fs->removeSelectedTextCommand( cursor, KoTextDocument::Temp );
+ if ( macroCmd )
+ macroCmd->addCommand( cmd );
+ */
+
+ // So instead, we do things by hand, and without undo....
+
+ KoTextParag *prev = p->prev();
+ KoTextParag *next = p->next();
+ // Move cursor out
+ if ( cursor->parag() == p )
+ cursor->setParag( next ? next : prev );
+ delete p;
+ kdDebug() << "KWInsertTOCCommand::removeTOC " << p << " deleted" << endl;
+ p = next;
+ posOfToc = p;
+ kdDebug() << "KWInsertTOCCommand::removeTOC prev=" << prev << " p=" << p << endl;
+ // Fix parag chain
+ if ( prev )
+ {
+ prev->setNext( p );
+ if ( p )
+ p->setParagId( prev->paragId() + 1 );
+ else
+ posOfToc = prev;
+ }
+ else
+ {
+ textdoc->setFirstParag( p );
+ if ( p )
+ {
+ p->setParagId( 0 );
+ } else // completely empty document !
+ {
+ textdoc->clear( true ); // recreate empty parag.
+ cursor->setParag( textdoc->firstParag() );
+ posOfToc = textdoc->firstParag();
+ break;
+ }
+ }
+ if(! p) { // see bug #131122
+ p = prev;
+ continue;
+ }
+ p->setPrev( prev );
+ }
+ p = p->prev();
+ }
+ textdoc->invalidate();
+ if(posOfToc)
+ {
+ posOfTable=new KoTextCursor( textdoc );
+ posOfTable->setParag(posOfToc );
+ posOfTable->setIndex( 0 );//start of parag
+ }
+ // ### TODO propagate parag ID changes.
+ return posOfTable;
+}
+
+KoParagStyle * KWInsertTOCCommand::findOrCreateTOCStyle( KWTextFrameSet *fs, int depth )
+{
+ // Determine style name.
+ QString name;
+ QString displayName;
+ if ( depth >= 0 ) {
+ // Don't add i18n to this one, those are internal names and must have no spaces.
+ name = QString( "Contents_Head_%1" ).arg( depth+1 );
+ displayName = i18n( "Contents Head %1" ).arg( depth+1 );
+ } else {
+ name = "Contents_Title";
+ displayName = i18n( "Contents Title" );
+ }
+ KoParagStyle * style = fs->kWordDocument()->styleCollection()->findStyle( name );
+ if ( !style )
+ {
+ style = new KoParagStyle( name );
+ style->setDisplayName( displayName );
+ style->format().setBold( ( ( depth==-1) || ( depth==0 ) ) ? true : false );
+ style->format().setPointSize( depth==-1 ? 20 : 12 );
+ if ( depth == -1 )
+ {
+ style->paragLayout().topBorder = KoBorder( Qt::black, KoBorder::SOLID, 1 );
+ style->paragLayout().bottomBorder = KoBorder( Qt::black, KoBorder::SOLID, 1 );
+ // Old kword had only top and bottom. But borders are drawn differently now
+ // (not the whole line anymore), so we need the 4 borders.
+ style->paragLayout().leftBorder = KoBorder( Qt::black, KoBorder::SOLID, 1 );
+ style->paragLayout().rightBorder = KoBorder( Qt::black, KoBorder::SOLID, 1 );
+ style->paragLayout().alignment = Qt::AlignHCenter;
+ }
+ else
+ {
+ KoTabulatorList tabList;
+ KoTabulator tab;
+
+ tab.ptPos = KoUnit::fromUserValue( floor( KoUnit::toMM( fs->frame( 0 )->width() ) ), KoUnit::unit("mm") );
+
+ tab.type = T_RIGHT;
+ tab.filling = TF_DOTS;
+ tab.ptWidth = 0.5;
+ tabList.append( tab );
+ style->paragLayout().setTabList( tabList );
+ style->paragLayout().margins[QStyleSheetItem::MarginLeft] = KoUnit::fromUserValue( (depth*4.5), KoUnit::unit("mm") );
+ }
+ style = fs->kWordDocument()->styleCollection()->addStyle( style ); // register the new style
+ fs->kWordDocument()->updateAllStyleLists(); // show it in the UI
+ }
+ return style;
+}
diff --git a/kword/KWInsertTOCCommand.h b/kword/KWInsertTOCCommand.h
new file mode 100644
index 00000000..e2bdcefc
--- /dev/null
+++ b/kword/KWInsertTOCCommand.h
@@ -0,0 +1,52 @@
+/* This file is part of the KDE project
+ Copyright (C) 1998, 1999 Reginald Stadlbauer <reggie@kde.org>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+*/
+
+#ifndef contents_h
+#define contents_h
+
+class KWTextFrameSet;
+class KMacroCommand;
+class KoParagStyle;
+#include <KoRichText.h>
+
+// This command inserts a TOC at the beginning of a frameset, and is able to undo that.
+// The reason we don't use KWTextFrameSet's insert, applyStyle etc. is that it would
+// generate many many subcommands (resulting in much memory use).
+class KWInsertTOCCommand : public KoTextDocCommand
+{
+public:
+ // The parag is where the TOC should be inserted
+ KWInsertTOCCommand( KWTextFrameSet *fs, KoTextParag *parag );
+ KoTextCursor *execute( KoTextCursor *c );
+ KoTextCursor *unexecute( KoTextCursor *c );
+
+ // Helper method, public for KWTextFrameSet::insertTOC().
+ // Remove a toc based on the parag styles
+ static KoTextCursor * removeTOC( KWTextFrameSet *fs, KoTextCursor *cursor, KMacroCommand *macroCmd );
+
+protected:
+ // Find or create a toc style
+ static KoParagStyle * findOrCreateTOCStyle( KWTextFrameSet *fs, int depth );
+
+ int m_paragId;
+};
+
+
+
+#endif
diff --git a/kword/KWLoadingInfo.cpp b/kword/KWLoadingInfo.cpp
new file mode 100644
index 00000000..eb37dbc2
--- /dev/null
+++ b/kword/KWLoadingInfo.cpp
@@ -0,0 +1,14 @@
+#include "KWLoadingInfo.h"
+#include "KWFrame.h"
+
+KWLoadingInfo::KWLoadingInfo()
+{
+ columns.columns = 1;
+ // columns.ptColumnSpacing must be initialized by KWDocument
+
+ hf.header = HF_SAME;
+ hf.footer = HF_SAME;
+ hf.ptHeaderBodySpacing = 10.0;
+ hf.ptFooterBodySpacing = 10.0;
+ hf.ptFootNoteBodySpacing = 10.0;
+}
diff --git a/kword/KWLoadingInfo.h b/kword/KWLoadingInfo.h
new file mode 100644
index 00000000..fd0645a8
--- /dev/null
+++ b/kword/KWLoadingInfo.h
@@ -0,0 +1,94 @@
+/* This file is part of the KDE project
+ Copyright (C) 2004 David Faure <faure@kde.org>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+*/
+
+#ifndef KWLOADINGINFO_H
+#define KWLOADINGINFO_H
+
+#include <qstring.h>
+#include <qvaluelist.h>
+#include <qdict.h>
+#include <KoPageLayout.h>
+
+class KoTextParag;
+class KWTextDocument;
+class KWFrame;
+
+/// Temporary information used only during loading
+class KWLoadingInfo
+{
+public:
+ KWLoadingInfo();
+ ~KWLoadingInfo() {}
+
+ /// Current master-page name (OASIS loading)
+ QString m_currentMasterPage;
+
+ /// Bookmarks (kword-1.3 XML: they need all framesets to be loaded first)
+ struct BookMark
+ {
+ QString bookname;
+ int paragStartIndex;
+ int paragEndIndex;
+ QString frameSetName;
+ int cursorStartIndex;
+ int cursorEndIndex;
+ };
+
+ typedef QValueList<BookMark> BookMarkList;
+ BookMarkList bookMarkList;
+
+ /// Bookmarks (OASIS XML). Only need to store bookmark starts, until hitting bookmark ends
+ struct BookmarkStart {
+ BookmarkStart() {} // for stupid QValueList
+ BookmarkStart( KWTextDocument* _doc, KoTextParag* par, int ind )
+ : doc( _doc ), parag( par ), pos( ind ) {}
+ KWTextDocument* doc;
+ KoTextParag* parag;
+ int pos;
+ };
+ typedef QMap<QString, BookmarkStart> BookmarkStartsMap;
+ BookmarkStartsMap m_bookmarkStarts;
+
+ // Text frame chains; see KWTextFrameSet::loadOasisText
+
+ void storeNextFrame( KWFrame* thisFrame, const QString& chainNextName ) {
+ m_nextFrameDict.insert( chainNextName, thisFrame );
+ }
+ KWFrame* chainPrevFrame( const QString& frameName ) const {
+ return m_nextFrameDict[frameName]; // returns 0 if not found
+ }
+
+ void storeFrameName( KWFrame* frame, const QString& name ) {
+ m_frameNameDict.insert( name, frame );
+ }
+ KWFrame* frameByName( const QString& name ) const {
+ return m_frameNameDict[name]; // returns 0 if not found
+ }
+
+ KoColumns columns;
+ KoKWHeaderFooter hf;
+
+private:
+ // Ignore warnings about operator delete from those dicts; we don't use it here...
+ QDict<KWFrame> m_nextFrameDict;
+ QDict<KWFrame> m_frameNameDict;
+};
+
+#endif /* KWLOADINGINFO_H */
+
diff --git a/kword/KWMailMergeDataBase.cpp b/kword/KWMailMergeDataBase.cpp
new file mode 100644
index 00000000..77c4b815
--- /dev/null
+++ b/kword/KWMailMergeDataBase.cpp
@@ -0,0 +1,559 @@
+/* This file is part of the KDE project
+ Copyright (C) 1998, 1999 Reginald Stadlbauer <reggie@kde.org>
+
+ Modified by Joseph wenninger, 2001
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+*/
+
+#include "KWDocument.h"
+#include "KWMailMergeDataBase.h"
+#include "KWMailMergeDataBase.moc"
+#include <KoCustomVariablesDia.h>
+#include "defs.h"
+
+#include <klocale.h>
+#include <kdebug.h>
+#include <kstdaction.h>
+#include <kaction.h>
+#include <kmessagebox.h>
+#include <kseparator.h>
+#include <kservice.h>
+#include <kmainwindow.h>
+
+#include <qfile.h>
+#include <qvbox.h>
+#include <qspinbox.h>
+#include <qlayout.h>
+#include <qlabel.h>
+#include <qpushbutton.h>
+
+/******************************************************************
+ *
+ * Class: KWMailMergeDataBase
+ *
+ ******************************************************************/
+
+KWMailMergeDataBase::KWMailMergeDataBase( KWDocument *doc_ )
+ : QObject(doc_,doc_->dcopObject()->objId()+".MailMergeDataBase"),
+ KWordMailMergeDatabaseIface(QCString(doc_->dcopObject()->objId()+".MailMergeDataBase")),
+ m_version(0),
+ doc( doc_ )
+{
+ plugin=0; //loadPlugin("classic");
+ rejectdcopcall=false;
+}
+
+QStringList KWMailMergeDataBase::availablePlugins()
+{
+ QStringList tmp;
+ KTrader::OfferList pluginOffers=KTrader::self()->query(QString::fromLatin1("KWord/MailMergePlugin"),QString::null);
+ for (KTrader::OfferList::Iterator it=pluginOffers.begin();*it;++it)
+ {
+ tmp.append((*it)->property("X-KDE-InternalName").toString());
+ kdDebug()<<"Found mail merge plugin: "<< (*it)->name()<<endl;
+ }
+ return tmp;
+}
+
+bool KWMailMergeDataBase::isConfigDialogShown()
+{
+ return rejectdcopcall;
+}
+
+bool KWMailMergeDataBase::loadPlugin(const QString &name,const QString &command)
+{
+ if (rejectdcopcall)return false;
+ QString constrain=QString("[X-KDE-InternalName] =='"+name+"'");
+ kdDebug()<<constrain<<endl;
+ KTrader::OfferList pluginOffers=KTrader::self()->query(QString::fromLatin1("KWord/MailMergePlugin"),constrain);
+ KService::Ptr it=pluginOffers.first();
+
+ QVariant verProp=it->property("X-KDE-PluginVersion");
+ int version=verProp.toInt();
+
+ if (it)
+ {
+ KWMailMergeDataSource *tmp=loadPlugin(it->library());
+ if (!tmp)
+ {
+ kdDebug()<<"Couldn't load plugin"<<endl;
+ return false; //Plugin couldn't be loaded
+ }
+ //Plugin found and loaded
+ if (command=="silent") {
+ return askUserForConfirmationAndConfig(tmp,false,0,version);
+ }
+ else
+ {
+ if (command=="open") action=KWSLOpen;
+ else if (command=="create") action=KWSLCreate;
+ else action=KWSLUnspecified;
+ return askUserForConfirmationAndConfig(tmp,true,0,version);
+ }
+ }
+ else
+ {
+ kdDebug()<<"No plugin found"<<endl;
+ return false; //No plugin with specified name found
+ }
+}
+
+KWMailMergeDataSource *KWMailMergeDataBase::openPluginFor(int type,int &version)
+{
+ version=0;
+ KWMailMergeDataSource *ret=0;
+ QString constrain=QString("'%1' in [X-KDE-Capabilities]").arg(((type==KWSLCreate)?KWSLCreate_text:KWSLOpen_text));
+ kdDebug()<<constrain<<endl;
+ KTrader::OfferList pluginOffers=KTrader::self()->query(QString::fromLatin1("KWord/MailMergePlugin"),constrain);
+
+ //Only for debugging
+ for (KTrader::OfferList::Iterator it=pluginOffers.begin();*it;++it)
+ {
+ kdDebug()<<"Found mail merge plugin: "<< (*it)->name()<<endl;
+ }
+
+ if (!pluginOffers.count())
+ {
+ //Sorry no suitable plugins found
+ kdDebug()<<"No plugins found"<<endl;
+ KMessageBox::sorry(0,i18n("No plugins supporting the requested action were found."));
+ }
+ else
+ {
+
+ KWMailMergeChoosePluginDialog *dia=new KWMailMergeChoosePluginDialog(pluginOffers);
+ if (dia->exec()==QDialog::Accepted)
+ {
+ QVariant verProp=(*(pluginOffers.at(dia->currentPlugin())))->property("X-KDE-PluginVersion");
+ version=verProp.toInt();
+
+ ret=loadPlugin((*(pluginOffers.at(dia->currentPlugin())))->library());
+ }
+
+ }
+ return ret;
+}
+
+KWMailMergeDataSource *KWMailMergeDataBase::loadPlugin(const QString& name)
+{
+ if (!name.isEmpty())
+ {
+ // get the library loader instance
+
+ KLibLoader *loader = KLibLoader::self();
+
+ // try to load the library
+ QString libname=name;
+// QString libname("lib%1");
+ KLibrary *lib = loader->library(QFile::encodeName(libname));
+ if (lib) {
+ // get the create_ function
+ QString factory=QString("create_%1").arg(name);
+ void *create = lib->symbol(QFile::encodeName(factory));
+
+ if (create)
+ {
+ // create the module
+ KWMailMergeDataSource * (*func)(KInstance*,QObject*);
+ func = (KWMailMergeDataSource* (*)(KInstance*,QObject*)) create;
+ KWMailMergeDataSource *tmpsource =func(KWFactory::instance(),this);
+ if (tmpsource)
+ {
+ QDataStream tmpstream(tmpsource->info,IO_WriteOnly);
+ tmpstream<<name;
+ }
+ return tmpsource;
+ }
+ }
+ kdWarning() << "Couldn't load plugin " << name << endl;
+ }
+ else
+ kdWarning()<< "No plugin name specified" <<endl;
+ return 0;
+}
+
+bool KWMailMergeDataBase::isSampleRecord() {
+ return (0>doc->mailMergeRecord());
+}
+
+QString KWMailMergeDataBase::getValue( const QString &name, int record ) const
+{
+ if (plugin)
+ {
+ if (record==-1) record=doc->mailMergeRecord();
+ return plugin->getValue(name,record);
+ }
+ else
+ return QString("");
+}
+
+
+void KWMailMergeDataBase::refresh(bool force)
+{
+ if (plugin) plugin->refresh(force);
+}
+
+const QMap< QString, QString > &KWMailMergeDataBase::getRecordEntries() const
+{
+ if (plugin)
+ return plugin->getRecordEntries();
+ else
+ return emptyMap;
+}
+
+int KWMailMergeDataBase::getNumRecords() const
+{
+ if (plugin)
+ return plugin->getNumRecords();
+ else
+ return 0;
+
+}
+
+
+void KWMailMergeDataBase::showConfigDialog(QWidget *par)
+{
+ rejectdcopcall=true;
+ KWMailMergeConfigDialog *dia=new KWMailMergeConfigDialog(par,this);
+ dia->exec();
+ delete dia;
+ rejectdcopcall=false;
+}
+
+
+bool KWMailMergeDataBase::askUserForConfirmationAndConfig(KWMailMergeDataSource *tmpPlugin,bool config,QWidget *par,int version)
+{
+ if (tmpPlugin)
+ {
+ bool replaceit=false;
+ if (!config) replaceit=true;
+ else
+ replaceit=tmpPlugin->showConfigDialog(par,action);
+ if (replaceit)
+ {
+ if (plugin)
+ {
+ if (KMessageBox::warningContinueCancel(par,
+ i18n("Do you really want to replace the current datasource?"),
+ QString::null,QString::null,QString::null,true)== KMessageBox::Cancel)
+ {
+ delete tmpPlugin;
+ tmpPlugin=0;
+ return false;
+ }
+ delete plugin;
+ }
+ m_version=version;
+ plugin=tmpPlugin;
+ }
+ else
+ {
+ delete tmpPlugin;
+ tmpPlugin=0;
+ return false;
+ }
+ }
+ tmpPlugin->setObjId(QCString(objId()+".MailMergePlugin"));
+ return true;
+}
+
+
+
+QDomElement KWMailMergeDataBase::save(QDomDocument &doc) const
+{
+ kdDebug()<<"KWMailMergeDataBase::save()"<<endl;
+ QDomElement parentElem=doc.createElement("MAILMERGE");
+ if (plugin)
+ {
+ kdDebug()<<"KWMailMergeDataBase::save() There is really something to save"<<endl;
+ QDomElement el=doc.createElement(QString::fromLatin1("PLUGIN"));
+
+ QDataStream ds(plugin->info,IO_ReadOnly);
+ QString libname;
+ ds>>libname;
+ el.setAttribute("library",libname);
+ parentElem.appendChild(el);
+ kdDebug()<<"KWMailMergeDataBase::save() Calling datasource save()"<<endl;
+ QDomElement el2=doc.createElement(QString::fromLatin1("DATASOURCE"));
+ plugin->save(doc,el2);
+ parentElem.appendChild(el2);
+
+ }
+ kdDebug()<<"KWMailMergeDataBase::save() leaving now"<<endl;
+ return parentElem;
+ // if (plugin) plugin->save(parentElem); // Not completely sure, perhaps the database itself has to save something too (JoWenn)
+}
+
+void KWMailMergeDataBase::load( const QDomElement& parentElem )
+{
+ QDomNode dn=parentElem.namedItem("PLUGIN");
+ if (dn.isNull()) return;
+ QDomElement el=dn.toElement();
+ plugin=loadPlugin(el.attribute("library"));
+
+ dn=parentElem.namedItem("DATASOURCE");
+ if (dn.isNull()) return;
+ el=dn.toElement();
+ if (plugin) plugin->load(el);
+}
+
+
+int KWMailMergeDataBase::version() {
+ kdDebug()<<"KWMailMergeDataBase::version:"<<m_version<<endl;
+ return m_version;
+}
+
+
+/******************************************************************
+ *
+ * Class: KWMailMerge ChoosePluginDialog
+ *
+ ******************************************************************/
+
+KWMailMergeChoosePluginDialog::KWMailMergeChoosePluginDialog( KTrader::OfferList offers )
+ : KDialogBase( Plain, i18n( "Mail Merge Setup" ), Ok | Cancel, Ok,
+ /*parent*/ 0, "", true ), pluginOffers( offers )
+{
+ QWidget *back = plainPage();
+ QVBoxLayout *layout = new QVBoxLayout( back, 0, spacingHint() );
+
+ QLabel *label = new QLabel( i18n( "&Available sources:" ), back );
+ chooser = new QComboBox( false, back );
+ label->setBuddy( chooser );
+ descriptionLabel = new QLabel( back );
+ descriptionLabel->hide();
+ descriptionLabel->setAlignment( WordBreak );
+ descriptionLabel->setFrameShape( QFrame::Box );
+ descriptionLabel->setFrameShadow( QFrame::Sunken );
+
+ QSize old_sizeHint;
+ for ( KTrader::OfferList::Iterator it = pluginOffers.begin(); *it; ++it )
+ {
+ chooser->insertItem( (*it)->name() );
+ old_sizeHint = descriptionLabel->sizeHint();
+ descriptionLabel->setText( (*it)->comment() );
+ if (descriptionLabel->sizeHint().width()*descriptionLabel->sizeHint().height() > old_sizeHint.width()*old_sizeHint.height())
+ descriptionLabel->setMinimumSize(descriptionLabel->sizeHint() );
+ }
+ descriptionLabel->show();
+
+ connect( chooser, SIGNAL( activated( int ) ),
+ this, SLOT( pluginChanged( int ) ) );
+
+ layout->addWidget( label );
+ layout->addWidget( chooser );
+ layout->addWidget( descriptionLabel );
+ layout->addStretch( 1 );
+
+ pluginChanged( 0 );
+}
+
+KWMailMergeChoosePluginDialog::~KWMailMergeChoosePluginDialog()
+{
+}
+
+int KWMailMergeChoosePluginDialog::currentPlugin() const
+{
+ return chooser->currentItem();
+}
+
+void KWMailMergeChoosePluginDialog::pluginChanged( int pos )
+{
+ descriptionLabel->setText( (*pluginOffers.at( pos ))->comment() );
+}
+
+/******************************************************************
+ *
+ * Class: KWMailMergeConfigDialog
+ *
+ ******************************************************************/
+
+KWMailMergeConfigDialog::KWMailMergeConfigDialog(QWidget *parent,KWMailMergeDataBase *db)
+ : KDialogBase(Plain, i18n( "Mail Merge Setup" ), Close, Close, parent, "", true )
+{
+ db_=db;
+ QWidget *back = plainPage();
+ QVBoxLayout *layout=new QVBoxLayout(back);
+// QVBox *back = new QVBox( page );
+ layout->setSpacing( KDialog::spacingHint() );
+
+// QVBox *row1 = new QVBox( back );
+// row1->setSpacing( KDialog::spacingHint() );
+
+ QLabel *l = new QLabel( i18n( "Datasource:" ),back );
+// l->setMaximumHeight( l->sizeHint().height() );
+ layout->addWidget(l);
+
+ QHBox *row1=new QHBox(back);
+ layout->addWidget(row1);
+ row1->setSpacing( KDialog::spacingHint() );
+ edit=new QPushButton(i18n("Edit Current..."),row1);
+ create=new QPushButton(i18n("Create New..."),row1);
+ open=new QPushButton(i18n("Open Existing..."),row1);
+
+ KSeparator *separator1 = new KSeparator(back);
+ layout->addWidget(separator1);
+
+ l = new QLabel( i18n( "Merging:" ),back );
+ layout->addWidget(l);
+// l->setMaximumHeight( l->sizeHint().height() );
+ QHBox *row2=new QHBox(back);
+ layout->addWidget(row2);
+ row2->setSpacing( KDialog::spacingHint() );
+ preview=new QPushButton(i18n("Print Preview..."),row2);
+ document=new QPushButton(i18n("Create New Document"),row2);
+ document->hide();
+ (void) new QWidget(row2);
+ layout->addStretch();
+
+ KSeparator *separator2 = new KSeparator(back);
+ layout->addWidget(separator2);
+
+ enableDisableEdit();
+
+ connect(edit,SIGNAL(clicked()), this, SLOT(slotEditClicked()));
+ connect(create,SIGNAL(clicked()),this,SLOT(slotCreateClicked()));
+ connect(open,SIGNAL(clicked()),this,SLOT(slotOpenClicked()));
+ connect(preview,SIGNAL(clicked()),this,SLOT(slotPreviewClicked()));
+ connect(document,SIGNAL(clicked()),this,SLOT(slotDocumentClicked()));
+}
+
+void KWMailMergeConfigDialog::enableDisableEdit()
+{
+ if (!db_->plugin)
+ {
+ preview->setEnabled(false);
+ document->setEnabled(false);
+ edit->setEnabled(false);
+ }
+ else
+ {
+ preview->setEnabled(true);
+ document->setEnabled(true);
+ edit->setEnabled(true);
+ }
+}
+
+void KWMailMergeConfigDialog::slotEditClicked()
+{db_->action=KWSLEdit;
+ if (db_->plugin) db_->plugin->showConfigDialog((QWidget*)parent(),KWSLEdit);
+}
+
+void KWMailMergeConfigDialog::slotCreateClicked()
+{
+ db_->action=KWSLCreate;
+ doNewActions();
+//done(QDialog::Accepted);
+}
+
+void KWMailMergeConfigDialog::doNewActions()
+{
+ int tmpVersion;
+ KWMailMergeDataSource *tmpPlugin=db_->openPluginFor(db_->action,tmpVersion);
+ if (tmpPlugin)
+ {
+ if (db_->askUserForConfirmationAndConfig(tmpPlugin,true,this,tmpVersion))
+
+ enableDisableEdit();
+ }
+}
+
+
+void KWMailMergeConfigDialog::slotOpenClicked()
+{
+ db_->action=KWSLOpen;
+ doNewActions();
+}
+
+void KWMailMergeConfigDialog::slotPreviewClicked()
+{
+ db_->action=KWSLMergePreview;
+ KMainWindow *mw=dynamic_cast<KMainWindow*>(((QWidget *)parent())->topLevelWidget());
+ if (mw)
+ {
+ KAction *ac=mw->actionCollection()->action(KStdAction::stdName(KStdAction::PrintPreview));
+ if (ac) ac->activate();
+ else kdWarning()<<"Toplevel doesn't provide a print preview action"<<endl;
+ }
+ else
+ kdWarning()<<"Toplevel is no KMainWindow->no preview"<<endl;
+}
+
+void KWMailMergeConfigDialog::slotDocumentClicked()
+{
+ db_->action=KWSLMergeDocument;
+ done(QDialog::Accepted);
+}
+
+KWMailMergeConfigDialog::~KWMailMergeConfigDialog()
+{
+}
+
+/******************************************************************
+ *
+ * Class: KWMailMergeVariableInsertDia
+ *
+ ******************************************************************/
+
+KWMailMergeVariableInsertDia::KWMailMergeVariableInsertDia( QWidget *parent, KWMailMergeDataBase *db )
+ : KDialogBase( Plain, i18n( "Mail Merge - Variable Name" ),
+ Ok | Cancel, Ok, parent, "", true )
+{
+ m_db=db;
+ QWidget *page = plainPage();
+
+ QVBoxLayout *layout = new QVBoxLayout( page, marginHint(), spacingHint() );
+ layout->setAutoAdd( true );
+
+ QLabel *l = new QLabel( i18n( "Name:" ), page );
+ l->setMaximumHeight( l->sizeHint().height() );
+ names = new QListBox( page );
+
+ QMap< QString, QString >::ConstIterator it = db->getRecordEntries().begin();
+ for ( ; it != db->getRecordEntries().end(); ++it )
+ names->insertItem( m_db->version() ?it.data():it.key(), -1 );
+
+ setInitialSize( QSize( 350, 400 ) );
+ connect( names, SIGNAL( selectionChanged() ),
+ this, SLOT( slotSelectionChanged() ) );
+ connect( names, SIGNAL( doubleClicked( QListBoxItem* ) ),
+ this, SLOT( slotOk() ) );
+
+ setFocus();
+ enableButtonOK( names->currentItem() != -1 );
+}
+
+void KWMailMergeVariableInsertDia::slotSelectionChanged()
+{
+ enableButtonOK( names->currentItem() != -1 );
+}
+
+QString KWMailMergeVariableInsertDia::getName() const
+{
+ if (m_db->version()>=1) {
+ QString description=names->text(names->currentItem());
+ QMap< QString, QString >::ConstIterator it = m_db->getRecordEntries().begin();
+ for ( ; it != m_db->getRecordEntries().end(); ++it )
+ if (description==it.data()) {
+ return it.key();
+ }
+ Q_ASSERT(0);
+ return ""; // can't happen
+ }
+ else
+ return names->text( names->currentItem() );
+}
diff --git a/kword/KWMailMergeDataBase.h b/kword/KWMailMergeDataBase.h
new file mode 100644
index 00000000..4b20e3e9
--- /dev/null
+++ b/kword/KWMailMergeDataBase.h
@@ -0,0 +1,164 @@
+/* This file is part of the KDE project
+ Copyright (C) 1998, 1999 Reginald Stadlbauer <reggie@kde.org>
+
+ Modified by Joseph wenninger, 2001
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+*/
+
+#ifndef mailmerge_h
+#define mailmerge_h
+
+#include <kdialogbase.h>
+#include <ktrader.h>
+
+
+#include <qmap.h>
+#include <qstring.h>
+#include <qstringlist.h>
+#include <qdom.h>
+#include <qtextstream.h>
+
+#include "KWMailMergeDataSource.h"
+#include "KWordMailMergeDatabaseIface.h"
+#include <koffice_export.h>
+
+class QListBox;
+class QPushButton;
+class QLineEdit;
+class QSpinBox;
+class KWDocument;
+class QVBox;
+
+//class KWMailMergeDataBase;
+
+
+
+
+/******************************************************************
+ *
+ * Class: KWMailMergeDataBase
+ *
+ ******************************************************************/
+
+class KWORD_EXPORT KWMailMergeDataBase: public QObject,KWordMailMergeDatabaseIface
+{
+Q_OBJECT
+
+public:
+ KWMailMergeDataBase( KWDocument *doc_ );
+ void showConfigDialog(QWidget *); // Select datasource type and / or configure datasource
+
+ QString getValue( const QString &name, int record = -1 ) const; //accesses the plugin
+ bool isSampleRecord();
+
+ const QMap< QString, QString > &getRecordEntries() const; //accesses the plugin
+ int getNumRecords() const; //accesses the plugin
+
+ QDomElement save(QDomDocument &doc) const; // save some global config + plugin config
+ void load( const QDomElement& elem ); // save some global config + plugin config
+
+ KWMailMergeDataSource *loadPlugin(const QString& name);
+ KWMailMergeDataSource *openPluginFor(int type,int &version);
+
+ virtual void refresh(bool force);
+ virtual QStringList availablePlugins();
+ virtual bool loadPlugin(const QString &name,const QString &command);
+ virtual bool isConfigDialogShown();
+
+ int version();
+private:
+ int m_version;
+protected:
+ friend class KWMailMergeConfigDialog;
+ KWDocument *doc;
+ int action;
+ class KWMailMergeDataSource *plugin;
+ QMap<QString, QString> emptyMap;
+ bool askUserForConfirmationAndConfig(KWMailMergeDataSource *tmpPlugin,bool config,QWidget *par,int version);
+ bool rejectdcopcall;
+};
+
+
+class KWMailMergeChoosePluginDialog : public KDialogBase
+{
+ Q_OBJECT
+
+ public:
+ KWMailMergeChoosePluginDialog( KTrader::OfferList );
+ ~KWMailMergeChoosePluginDialog();
+
+ int currentPlugin() const;
+
+ private slots:
+ void pluginChanged( int pos );
+
+ private:
+ class QComboBox *chooser;
+ class QLabel *descriptionLabel;
+ KTrader::OfferList pluginOffers;
+};
+
+class KWMailMergeConfigDialog : public KDialogBase
+{
+ Q_OBJECT
+
+public:
+ KWMailMergeConfigDialog ( QWidget *parent, KWMailMergeDataBase *db );
+ ~KWMailMergeConfigDialog();
+protected:
+ QPushButton *edit;
+ QPushButton *create;
+ QPushButton *open;
+ QPushButton *preview;
+ QPushButton *document;
+ KWMailMergeDataBase *db_;
+ void enableDisableEdit();
+ void doNewActions();
+
+protected slots:
+ void slotEditClicked();
+ void slotCreateClicked();
+ void slotOpenClicked();
+ void slotPreviewClicked();
+ void slotDocumentClicked();
+};
+
+/******************************************************************
+ *
+ * Class: KWMailMergeVariableInsertDia
+ *
+ ******************************************************************/
+
+class KWMailMergeVariableInsertDia : public KDialogBase
+{
+ Q_OBJECT
+
+ public:
+ KWMailMergeVariableInsertDia( QWidget *parent, KWMailMergeDataBase *db );
+ QString getName() const; // ### unused, can we remove this?
+
+ protected slots:
+ void slotSelectionChanged();
+
+ private:
+ KWMailMergeDataBase *m_db;
+
+ protected:
+ QListBox *names;
+};
+
+#endif
diff --git a/kword/KWMailMergeDataSource.cpp b/kword/KWMailMergeDataSource.cpp
new file mode 100644
index 00000000..abb17501
--- /dev/null
+++ b/kword/KWMailMergeDataSource.cpp
@@ -0,0 +1,8 @@
+#include "KWMailMergeDataSource.h"
+#include "KWMailMergeDataSource.moc"
+
+KWMailMergeDataSource::KWMailMergeDataSource(KInstance* inst,QObject *parent): QObject(parent),
+DCOPObject(QCString(parent->name())+".plugin_loading"),m_instance(inst)
+{
+}
+const QMap< QString, QString > &KWMailMergeDataSource::getRecordEntries() const {return sampleRecord;}
diff --git a/kword/KWMailMergeDataSource.h b/kword/KWMailMergeDataSource.h
new file mode 100644
index 00000000..9d1fc076
--- /dev/null
+++ b/kword/KWMailMergeDataSource.h
@@ -0,0 +1,76 @@
+/* This file is part of the KDE project
+ Original file (mailmerge.h): Copyright (C) 1998, 1999 Reginald Stadlbauer <reggie@kde.org>
+ Copyright (C) 2001 Joseph Wenninger <jowenn@kde.org>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+*/
+
+#ifndef _SERIALLETTER_INTERFACE_H_
+#define _SERIALLETTER_INTERFACE_H_
+#include <qcstring.h>
+#include <qdom.h>
+#include <kinstance.h>
+#include <qmap.h>
+#include <qobject.h>
+#include <dcopobject.h>
+#include <koffice_export.h>
+typedef QMap<QString,QString> DbRecord;
+#define KWSLUnspecified 0
+#define KWSLEdit 1
+#define KWSLCreate 2
+#define KWSLOpen 3
+#define KWSLMergePreview 4
+#define KWSLMergeDocument 5
+
+#define KWSLCreate_text "create"
+#define KWSLOpen_text "open"
+/******************************************************************
+ *
+ * Class: KWMailMergeDataSource
+ *
+ ******************************************************************/
+
+class KWORD_EXPORT KWMailMergeDataSource: public QObject, public DCOPObject
+{
+ Q_OBJECT
+ K_DCOP
+ public:
+ KWMailMergeDataSource(KInstance* inst,QObject *parent);
+ virtual ~KWMailMergeDataSource(){;}
+ virtual class QString getValue( const class QString &name, int record = -1 ) const=0;
+
+ const QMap< QString, QString > &getRecordEntries() const;
+
+ KInstance *KWInstance(){return m_instance;}
+ virtual bool showConfigDialog(class QWidget*,int) =0;
+
+ virtual void save(QDomDocument&, QDomElement&)=0;
+ virtual void load( class QDomElement& elem )=0;
+
+ virtual void refresh(bool force)=0;
+ QByteArray info;
+ protected:
+ DbRecord sampleRecord;
+ private:
+ KInstance *m_instance;
+k_dcop:
+ virtual int getNumRecords() const =0;
+};
+
+
+
+
+#endif
diff --git a/kword/KWMailMergeLabelAction.cpp b/kword/KWMailMergeLabelAction.cpp
new file mode 100644
index 00000000..79d06378
--- /dev/null
+++ b/kword/KWMailMergeLabelAction.cpp
@@ -0,0 +1,152 @@
+/* This file is part of the KDE project
+
+ Copyright (C) 2002 Joseph Wenninger <jowenn@kde.org>
+
+ Large parts are taken from kdebase/konqueror/konq_actions.*
+ Copyright (C) 2000 Simon Hausmann <hausmann@kde.org>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+*/
+
+#include "KWMailMergeLabelAction.h"
+#include "KWMailMergeLabelAction.moc"
+#include <KoMainWindow.h>
+#include <kstyle.h>
+#include <kpopupmenu.h>
+
+class MailMergeDraggableLabel : public QToolButton
+{
+public:
+ MailMergeDraggableLabel( KoMainWindow * mw, const QString & text, QWidget * parent = 0, const char * name = 0 )
+ : QToolButton( parent, name ), m_mw(mw)
+ {
+ setText(text);
+ setAcceptDrops(true);
+ validDrag = false;
+ }
+protected:
+ void mousePressEvent( QMouseEvent * ev )
+ {
+ validDrag = true;
+ startDragPos = ev->pos();
+ }
+ void mouseMoveEvent( QMouseEvent * ev )
+ {
+ if ((startDragPos - ev->pos()).manhattanLength() > QApplication::startDragDistance())
+ {
+ validDrag = false;
+
+#if 0 // what was the goal here?
+ KWTextDrag *drag=new KWTextDrag(m_mw);
+// drag->setKWord(" <!DOCTYPE PARAGRAPHS> <PARAGRAPHS> <PARAGRAPH> <TEXT>fsfsd</TEXT> <LAYOUT> <NAME value=\"Standard\" /> <FLOW align=\"left\" /> <FORMAT id=\"1\" pos=\"0\" len=\"5\" > <WEIGHT value=\"50\" /> <FONT name=\"helvetica\" /> <SIZE value=\"12\" /> <ITALIC value=\"0\" /> <UNDERLINE value=\"0\" /> <STRIKEOUT value=\"0\" /> <VERTALIGN value=\"0\" /> </FORMAT> </LAYOUT> </PARAGRAPH></PARAGRAPHS>");
+ drag->setKWord(" <!DOCTYPE PARAGRAPHS> <PARAGRAPHS> <PARAGRAPH> <TEXT>fsfsd</TEXT> </PARAGRAPH> </PARAGRAPHS>");
+// drag->setKWord("<TEXT>fsfsd</TEXT>");
+
+ drag->dragCopy();
+#endif
+ }
+ }
+ void mouseReleaseEvent( QMouseEvent * )
+ {
+ validDrag = false;
+ }
+ QSize sizeHint() const
+ {
+ int w = fontMetrics().width( text() );
+ int h = fontMetrics().height();
+ return QSize( w, h );
+ }
+ void drawButton( QPainter * p )
+ {
+ // Draw the background
+ style().drawComplexControl( QStyle::CC_ToolButton, p, this, rect(), colorGroup(),
+ QStyle::Style_Enabled, QStyle::SC_ToolButton );
+ // Draw the label
+ style().drawControl( QStyle::CE_ToolButtonLabel, p, this, rect(), colorGroup(),
+ QStyle::Style_Enabled );
+ }
+ void enterEvent( QEvent* ) {};
+ void leaveEvent( QEvent* ) {};
+#if 0
+ void dragEnterEvent( QDragEnterEvent *ev ) {
+ if ( KURLDrag::canDecode( ev ) )
+ ev->acceptAction();
+ }
+ void dropEvent( QDropEvent* ev ) {
+ KURL::List lst;
+ if ( KURLDrag::decode( ev, lst ) ) {
+ m_mw->openURL( 0L, lst.first() );
+ }
+ }
+#endif
+private:
+ QPoint startDragPos;
+ bool validDrag;
+ KoMainWindow * m_mw;
+};
+
+
+
+
+
+KWMailMergeLabelAction::KWMailMergeLabelAction( const QString &text, int accel,
+ QObject* receiver, const char* slot, QObject *parent, const char *name )
+ : KAction( text, accel, receiver, slot, parent, name ), m_label( 0L )
+{
+}
+
+int KWMailMergeLabelAction::plug( QWidget *widget, int index )
+{
+ //do not call the previous implementation here
+
+ if ( widget->inherits( "KToolBar" ) )
+ {
+ KToolBar *tb = (KToolBar *)widget;
+
+ int id = KAction::getToolButtonID();
+
+ m_label = new MailMergeDraggableLabel( static_cast<KoMainWindow*>(tb->mainWindow()), text(), widget );
+ tb->insertWidget( id, m_label->width(), m_label, index );
+
+ addContainer( tb, id );
+
+ connect( tb, SIGNAL( destroyed() ), this, SLOT( slotDestroyed() ) );
+
+ return containerCount() - 1;
+ }
+
+ return -1;
+}
+
+void KWMailMergeLabelAction::unplug( QWidget *widget )
+{
+ if ( widget->inherits( "KToolBar" ) )
+ {
+ KToolBar *bar = (KToolBar *)widget;
+
+ int idx = findContainer( bar );
+
+ if ( idx != -1 )
+ {
+ bar->removeItem( itemId( idx ) );
+ removeContainer( idx );
+ }
+
+ m_label = 0;
+ return;
+ }
+}
+
diff --git a/kword/KWMailMergeLabelAction.h b/kword/KWMailMergeLabelAction.h
new file mode 100644
index 00000000..a0aacfed
--- /dev/null
+++ b/kword/KWMailMergeLabelAction.h
@@ -0,0 +1,44 @@
+/* This file is part of the KDE project
+
+ Copyright (C) 2002 Joseph Wenninger <jowenn@kde.org>
+
+ Large parts are taken from kdebase/konqueror/konq_actions.*
+ Copyright (C) 2000 Simon Hausmann <hausmann@kde.org>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+*/
+
+#ifndef _MAILMERGE_ACTIONS_
+#define _MAILMERGE_ACTIONS_
+
+#include <kaction.h>
+#include <qtoolbutton.h>
+
+class KWMailMergeLabelAction : public KAction
+{
+ Q_OBJECT
+public:
+ KWMailMergeLabelAction( const QString &text, int accel,
+ QObject* receiver, const char* slot, QObject *parent = 0, const char *name = 0 );
+
+ virtual int plug( QWidget *widget, int index = -1 );
+ virtual void unplug( QWidget *widget );
+ QToolButton * label() { return m_label; }
+private:
+ QToolButton * m_label;
+};
+
+#endif
diff --git a/kword/KWOasisLoader.cpp b/kword/KWOasisLoader.cpp
new file mode 100644
index 00000000..27cdcf54
--- /dev/null
+++ b/kword/KWOasisLoader.cpp
@@ -0,0 +1,358 @@
+/* This file is part of the KDE project
+ Copyright (C) 2005 David Faure <faure@kde.org>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License version 2 as published by the Free Software Foundation.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+*/
+
+#include "KWOasisLoader.h"
+#include "KWDocument.h"
+#include "KWTextDocument.h"
+#include "KWTextFrameSet.h"
+#include "KWFrameSet.h"
+#include "KWPictureFrameSet.h"
+#include "KWLoadingInfo.h"
+#include "KWTableFrameSet.h"
+#include "KWPartFrameSet.h"
+#include "KWPageManager.h"
+#include "KWFormulaFrameSet.h"
+
+#include <KoStore.h>
+#include <KoOasisContext.h>
+#include <KoOasisStyles.h>
+#include <KoOasisStore.h>
+#include <KoOasisSettings.h>
+#include <KoXmlNS.h>
+#include <KoDom.h>
+#include <KoXmlNS.h>
+
+#include <kdebug.h>
+#include <klocale.h>
+
+#include <qvaluelist.h>
+#include <qdom.h>
+
+KWOasisLoader::KWOasisLoader( KWDocument* doc )
+ : m_doc( doc )
+{
+}
+
+// Warning, this method has no undo/redo support, it is *called* by the undo/redo commands.
+// cursor is set when pasting into a textframesetedit (kwcommand), 0 otherwise.
+QValueList<KWFrame *> KWOasisLoader::insertOasisData( KoStore* store, KoTextCursor* cursor )
+{
+ QValueList<KWFrame *> frames;
+ if ( store->bad() || !store->hasFile( "content.xml" ) )
+ {
+ kdError(32001) << "Invalid ZIP store in memory" << endl;
+ if ( !store->hasFile( "content.xml" ) )
+ kdError(32001) << "No content.xml file" << endl;
+ return frames;
+ }
+ store->disallowNameExpansion();
+
+ KoOasisStore oasisStore( store );
+ QDomDocument contentDoc;
+ QString errorMessage;
+ bool ok = oasisStore.loadAndParse( "content.xml", contentDoc, errorMessage );
+ if ( !ok ) {
+ kdError(32001) << "Error parsing content.xml: " << errorMessage << endl;
+ return frames;
+ }
+
+ KoOasisStyles oasisStyles;
+ QDomDocument stylesDoc;
+ (void)oasisStore.loadAndParse( "styles.xml", stylesDoc, errorMessage );
+ // Load styles from style.xml
+ oasisStyles.createStyleMap( stylesDoc, true );
+ // Also load styles from content.xml
+ oasisStyles.createStyleMap( contentDoc, false );
+
+ m_doc->createLoadingInfo();
+
+ QDomElement content = contentDoc.documentElement();
+
+ QDomElement body( KoDom::namedItemNS( content, KoXmlNS::office, "body" ) );
+ if ( body.isNull() ) {
+ kdError(32001) << "No office:body found!" << endl;
+ return frames;
+ }
+ // We then want to use whichever element is the child of <office:body>,
+ // whether that's <office:text> or <office:presentation> or whatever.
+ QDomElement iter, realBody;
+ forEachElement( iter, body ) {
+ realBody = iter;
+ }
+ if ( realBody.isNull() ) {
+ kdError(32001) << "No element found inside office:body!" << endl;
+ return frames;
+ }
+
+ KoOasisContext context( m_doc, *m_doc->variableCollection(), oasisStyles, store );
+ if ( cursor )
+ {
+ KWTextDocument * textdoc = static_cast<KWTextDocument *>(cursor->parag()->document());
+ KWTextFrameSet * textFs = textdoc->textFrameSet();
+
+ *cursor = textFs->textObject()->pasteOasisText( realBody, context, *cursor, m_doc->styleCollection() );
+
+ textFs->textObject()->setNeedSpellCheck( true );
+ }
+ else // No cursor available, load only the frames
+ {
+ // The main loop from KoTextDocument::loadOasisText but for frames only
+ // (can't paste text if there is no text-frameset being edited, where would it go?)
+ QDomElement tag;
+ forEachElement( tag, realBody )
+ {
+ context.styleStack().save();
+ const QString bodyTagLocalName = tag.localName();
+ kdDebug() << k_funcinfo << bodyTagLocalName << endl;
+ if ( bodyTagLocalName == "frame" && tag.namespaceURI() == KoXmlNS::draw )
+ {
+ KWFrame * frame = loadFrame( tag, context, KoPoint( 10, 10 ) /*offset pasted object*/ );
+ if ( frame )
+ {
+ frames.append( frame );
+ }
+ }
+#if 0 // TODO OASIS table:table
+ else if ( bodyTagLocalName == "table" && tag.namespaceURI() == KoXmlNS::table )
+ ;
+#endif
+ }
+ }
+
+ //kdDebug() << "KWOasisLoader::execute calling doc->completePasting" << endl;
+ m_doc->completeOasisPasting();
+ m_doc->deleteLoadingInfo();
+ return frames;
+}
+
+void KWOasisLoader::loadOasisSettings( const QDomDocument& settingsDoc )
+{
+ KoOasisSettings settings( settingsDoc );
+ KoOasisSettings::Items viewSettings = settings.itemSet( "view-settings" );
+ if ( !viewSettings.isNull() )
+ {
+ m_doc->setUnit( KoUnit::unit(viewSettings.parseConfigItemString("unit")) );
+ }
+ loadOasisIgnoreList( settings );
+ m_doc->variableCollection()->variableSetting()->loadOasis( settings );
+}
+
+static QString headerTypeToFramesetName( const QString& localName, bool hasEvenOdd )
+{
+ if ( localName == "header" )
+ return hasEvenOdd ? i18n("Odd Pages Header") : i18n( "Header" );
+ if ( localName == "header-left" )
+ return i18n("Even Pages Header");
+ if ( localName == "footer" )
+ return hasEvenOdd ? i18n("Odd Pages Footer") : i18n( "Footer" );
+ if ( localName == "footer-left" )
+ return i18n("Even Pages Footer");
+ if ( localName == "header-first" ) // NOT OASIS COMPLIANT
+ return i18n("First Page Header");
+ if ( localName == "footer-first" ) // NOT OASIS COMPLIANT
+ return i18n("First Page Footer");
+ kdWarning(32001) << "Unknown tag in headerTypeToFramesetName: " << localName << endl;
+ return QString::null;
+}
+
+static KWFrameSet::Info headerTypeToFrameInfo( const QString& localName, bool /*hasEvenOdd*/ )
+{
+ if ( localName == "header" )
+ return KWFrameSet::FI_ODD_HEADER;
+ if ( localName == "header-left" )
+ return KWFrameSet::FI_EVEN_HEADER;
+ if ( localName == "footer" )
+ return KWFrameSet::FI_ODD_FOOTER;
+ if ( localName == "footer-left" )
+ return KWFrameSet::FI_EVEN_FOOTER;
+
+ // ######## KWord extension, because I'm too lazy.
+ // TODO: the real solution is a separate page layout for the first page.
+ if ( localName == "header-first" ) // NOT OASIS COMPLIANT
+ return KWFrameSet::FI_FIRST_HEADER;
+ if ( localName == "footer-first" ) // NOT OASIS COMPLIANT
+ return KWFrameSet::FI_FIRST_FOOTER;
+ return KWFrameSet::FI_BODY;
+}
+
+void KWOasisLoader::loadOasisHeaderFooter( const QDomElement& headerFooter, bool hasEvenOdd, QDomElement& style, KoOasisContext& context )
+{
+ const QString localName = headerFooter.localName();
+ bool isHeader = localName.startsWith( "header" );
+
+ KWTextFrameSet *fs = new KWTextFrameSet( m_doc, headerTypeToFramesetName( localName, hasEvenOdd ) );
+ fs->setFrameSetInfo( headerTypeToFrameInfo( localName, hasEvenOdd ) );
+ m_doc->addFrameSet( fs, false );
+
+ if ( !style.isNull() )
+ context.styleStack().push( style );
+ KWFrame* frame = new KWFrame( fs, 29, isHeader?0:567, 798-29, 41 );
+ frame->loadCommonOasisProperties( context, fs, "header-footer" );
+ const QString minHeight = context.styleStack().attributeNS( KoXmlNS::fo, "min-height" );
+ if ( !minHeight.isEmpty() )
+ frame->setMinimumFrameHeight( KoUnit::parseValue( minHeight ) );
+
+ frame->setFrameBehavior( KWFrame::AutoExtendFrame );
+ frame->setNewFrameBehavior( KWFrame::Copy );
+ fs->addFrame( frame );
+ if ( !style.isNull() )
+ context.styleStack().pop(); // don't let it be active when parsing the text
+
+ context.setUseStylesAutoStyles( true ); // use auto-styles from styles.xml, not those from content.xml
+ fs->loadOasisContent( headerFooter, context );
+ context.setUseStylesAutoStyles( false );
+
+ if ( isHeader )
+ m_doc->m_headerVisible = true;
+ else
+ m_doc->m_footerVisible = true;
+}
+
+void KWOasisLoader::loadOasisIgnoreList( const KoOasisSettings& settings )
+{
+ KoOasisSettings::Items configurationSettings = settings.itemSet( "configuration-settings" );
+ if ( !configurationSettings.isNull() )
+ {
+ const QString ignorelist = configurationSettings.parseConfigItemString( "SpellCheckerIgnoreList" );
+ kdDebug()<<" ignorelist :"<<ignorelist<<endl;
+ m_doc->setSpellCheckIgnoreList( QStringList::split( ',', ignorelist ) );
+ }
+}
+
+KWFrame* KWOasisLoader::loadFrame( const QDomElement& frameTag, KoOasisContext& context, const KoPoint& offset )
+{
+ KWFrame* frame = 0;
+ QDomElement elem;
+ forEachElement( elem, frameTag )
+ {
+ if ( elem.namespaceURI() != KoXmlNS::draw )
+ continue;
+ const QString localName = elem.localName();
+ if ( localName == "text-box" )
+ {
+ //kdDebug()<<" append text-box\n";
+ frame = loadOasisTextBox( frameTag, elem, context );
+ break;
+ }
+ else if ( localName == "image" )
+ {
+ KWFrameSet* fs = new KWPictureFrameSet( m_doc, frameTag, elem, context );
+ m_doc->addFrameSet( fs, false );
+ frame = fs->frame(0);
+ break;
+ } else if ( localName == "object" )
+ {
+ QDomElement mathElem; // will be set if we find <math:math>
+ QDomElement childElem;
+ forEachElement( childElem, elem )
+ {
+ if ( childElem.localName() == "math"
+ && childElem.namespaceURI() == KoXmlNS::math ) {
+ mathElem = childElem;
+ }
+ }
+ if ( !mathElem.isNull() ) {
+ KWFormulaFrameSet* fs = new KWFormulaFrameSet( m_doc, frameTag, mathElem, context );
+ m_doc->addFrameSet( fs, false );
+ frame = fs->frame(0);
+ } else {
+ KWPartFrameSet* fs = new KWPartFrameSet( m_doc, frameTag, elem, context );
+ m_doc->addFrameSet( fs, false );
+ frame = fs->frame(0);
+ }
+ break;
+ }
+ }
+ if ( frame ) {
+ const QString anchorType = frameTag.attributeNS( KoXmlNS::text, "anchor-type", QString::null );
+ if ( anchorType == "page" ) {
+ double x = KoUnit::parseValue( frameTag.attributeNS( KoXmlNS::svg, "x", QString::null ) );
+ double y = KoUnit::parseValue( frameTag.attributeNS( KoXmlNS::svg, "y", QString::null ) );
+ int pageNum = frameTag.attributeNS( KoXmlNS::text, "anchor-page-number", QString::null ).toInt();
+ // Ensure that we have enough pages
+ KWPageManager* pageManager = m_doc->pageManager();
+ while ( pageNum > pageManager->lastPageNumber() )
+ pageManager->appendPage();
+ frame->moveTopLeft( KoPoint( x, y + pageManager->topOfPage(pageNum) ) );
+ }
+ frame->moveBy( offset.x(), offset.y() );
+ }
+ return frame;
+}
+
+KWFrame* KWOasisLoader::loadOasisTextBox( const QDomElement& frameTag, const QDomElement& tag,
+ KoOasisContext& context )
+{
+ // Text frame chains. When seeing frame 'B' is chained to this frame A when loading,
+ // we store 'B' -> A, so that when loading B we can add it to A's frameset.
+ // If we load B first, no problem: when loading A we can chain.
+ // This is all made simpler by the fact that we don't have manually configurable order in KWord...
+ // But it's made more complex by the fact that frames don't have names in KWord (framesets do).
+ // Hence the framename temporary storage in KWLoadingInfo
+
+ KWLoadingInfo* loadingInfo = m_doc->loadingInfo();
+ KWTextFrameSet* fs = 0;
+ QString frameName = frameTag.attributeNS( KoXmlNS::draw, "name", QString::null );
+ QString chainNextName = tag.attributeNS( KoXmlNS::draw, "chain-next-name", QString::null );
+ if ( !chainNextName.isEmpty() && loadingInfo ) { // 'B' in the above example
+ kdDebug(32001) << "Loading " << frameName << " : next-in-chain=" << chainNextName << endl;
+ // Check if we already loaded that frame (then we need to go 'before' it)
+ KWFrame* nextFrame = loadingInfo->frameByName( chainNextName );
+ if ( nextFrame ) {
+ fs = dynamic_cast<KWTextFrameSet *>( nextFrame->frameSet() );
+ chainNextName = QString::null; // already found, no need to store it
+ kdDebug(32001) << " found " << nextFrame << " -> frameset " << ( fs ? fs->name() : QString::null ) << endl;
+ }
+ }
+ KWFrame* prevFrame = loadingInfo->chainPrevFrame( frameName );
+ //kdDebug(32001) << "Loading " << frameName << " : chainPrevFrame=" << prevFrame << endl;
+ if ( prevFrame ) {
+ if ( fs ) // we are between prevFrame and nextFrame. They'd better be for the same fs!!
+ Q_ASSERT( fs == prevFrame->frameSet() );
+ fs = dynamic_cast<KWTextFrameSet *>( prevFrame->frameSet() );
+ //kdDebug(32001) << " found " << prevFrame << " -> frameset " << fs->name() << endl;
+ }
+ KWFrame* frame = 0;
+ if ( !fs ) {
+ fs = new KWTextFrameSet( m_doc, frameTag, context );
+ m_doc->addFrameSet( fs, false );
+ frame = fs->loadOasis( frameTag, tag, context );
+ } else { // Adding frame to existing frameset
+ context.styleStack().save();
+ context.fillStyleStack( frameTag, KoXmlNS::draw, "style-name", "graphic" ); // get the style for the graphics element
+ frame = fs->loadOasisTextFrame( frameTag, tag, context );
+ context.styleStack().restore();
+ }
+
+ loadingInfo->storeFrameName( frame, frameName );
+
+ if ( !chainNextName.isEmpty() ) {
+ loadingInfo->storeNextFrame( frame, chainNextName );
+ }
+ return frame;
+}
+
+KWTableFrameSet* KWOasisLoader::loadOasisTable( const QDomElement& tag,
+ KoOasisContext& context )
+{
+ const QString name = tag.attributeNS( KoXmlNS::table, "name", i18n( "Unnamed Table" ) ); // ### check for unicity?
+ KWTableFrameSet* table = new KWTableFrameSet( m_doc, name );
+ table->loadOasis( tag, context );
+ m_doc->addFrameSet(table, false);
+ return table;
+}
diff --git a/kword/KWOasisLoader.h b/kword/KWOasisLoader.h
new file mode 100644
index 00000000..36f76dde
--- /dev/null
+++ b/kword/KWOasisLoader.h
@@ -0,0 +1,64 @@
+/* This file is part of the KDE project
+ Copyright (C) 2005 David Faure <faure@kde.org>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License version 2 as published by the Free Software Foundation.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+*/
+
+#ifndef KWOASISLOADER_H
+#define KWOASISLOADER_H
+
+class KoPoint;
+class KWTableFrameSet;
+class KWLoadingInfo;
+class KoOasisContext;
+class QDomDocument;
+class KoOasisSettings;
+class QDomElement;
+class KWFrame;
+class KoStore;
+class KoTextCursor;
+class KWDocument;
+template <class T> class QValueList;
+
+// KWDocument delegates to this class the loading of OASIS documents or fragments
+class KWOasisLoader
+{
+public:
+ KWOasisLoader( KWDocument* doc );
+
+ /// Insert everything from an oasis store - used when pasting
+ /// (either text or entire frames)
+ /// TODO: dontCreateFootNote
+ QValueList<KWFrame *> insertOasisData( KoStore* store, KoTextCursor* cursor );
+
+ void loadOasisSettings( const QDomDocument&settingsDoc );
+ void loadOasisHeaderFooter( const QDomElement& headerFooter, bool hasEvenOdd,
+ QDomElement& style, KoOasisContext& context );
+
+ KWFrame* loadFrame( const QDomElement& frameTag, KoOasisContext& context, const KoPoint& offset );
+ KWFrame* loadOasisTextBox( const QDomElement& frame, const QDomElement& tag,
+ KoOasisContext& context );
+ KWTableFrameSet* loadOasisTable( const QDomElement& tag,
+ KoOasisContext& context );
+
+private:
+ void loadOasisIgnoreList( const KoOasisSettings& settings );
+
+private:
+ KWDocument* m_doc;
+};
+
+
+#endif
diff --git a/kword/KWOasisSaver.cpp b/kword/KWOasisSaver.cpp
new file mode 100644
index 00000000..b4f3fd54
--- /dev/null
+++ b/kword/KWOasisSaver.cpp
@@ -0,0 +1,158 @@
+/* This file is part of the KDE project
+ Copyright (C) 2005 David Faure <faure@kde.org>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License version 2 as published by the Free Software Foundation.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+*/
+
+#include "KWOasisSaver.h"
+#include <KoStore.h>
+#include <KoOasisStore.h>
+#include <KoOasisContext.h>
+#include <KoXmlWriter.h>
+#include "KWDocument.h"
+
+KWOasisSaver::KWOasisSaver( KWDocument* doc )
+ : m_doc( doc )
+{
+ const QCString mimeType = selectionMimeType();
+ m_store = KoStore::createStore( &m_buffer, KoStore::Write, mimeType );
+ Q_ASSERT( m_store );
+ Q_ASSERT( !m_store->bad() );
+
+ m_oasisStore = new KoOasisStore( m_store );
+
+ //KoXmlWriter* manifestWriter = oasisStore.manifestWriter( mimeType );
+
+ m_savingContext = new KoSavingContext( m_mainStyles, 0, false, KoSavingContext::Store );
+
+ KoXmlWriter* bodyWriter = m_oasisStore->bodyWriter();
+ bodyWriter->startElement( "office:body" );
+ bodyWriter->startElement( "office:text" );
+}
+
+void KWOasisSaver::saveParagraphs( const QValueList<const KoTextParag *>& paragraphs )
+{
+ for ( QValueList<const KoTextParag *>::const_iterator it = paragraphs.begin(),
+ end = paragraphs.end();
+ it != end ; ++it ) {
+ saveParagraph( *it );
+ }
+}
+
+void KWOasisSaver::saveParagraph( const KoTextParag* parag )
+{
+ // keep in sync with KoTextDocument::copySelection
+ KoXmlWriter* bodyWriter = m_oasisStore->bodyWriter();
+ parag->saveOasis( *bodyWriter, *m_savingContext, 0, parag->length()-2, true );
+}
+
+QByteArray KWOasisSaver::data() const
+{
+ Q_ASSERT( !m_store ); // forgot to call finish() (or to check its return value) ?
+ return m_buffer.buffer();
+}
+
+KWOasisSaver::~KWOasisSaver()
+{
+ delete m_store;
+ delete m_oasisStore;
+ delete m_savingContext;
+}
+
+bool KWOasisSaver::finish()
+{
+ KoXmlWriter* bodyWriter = m_oasisStore->bodyWriter();
+ bodyWriter->endElement(); // office:text
+ bodyWriter->endElement(); // office:body
+
+ KoXmlWriter* contentWriter = m_oasisStore->contentWriter();
+ Q_ASSERT( contentWriter );
+
+ m_savingContext->writeFontFaces( *contentWriter );
+ contentWriter->startElement( "office:automatic-styles" );
+ writeAutomaticStyles( *contentWriter, m_mainStyles, false );
+ contentWriter->endElement(); // office:automatic-styles
+
+ m_oasisStore->closeContentWriter();
+
+ if ( !m_store->open( "styles.xml" ) )
+ return false;
+ //manifestWriter->addManifestEntry( "styles.xml", "text/xml" );
+ m_doc->saveOasisDocumentStyles( m_store, m_mainStyles, *m_savingContext,
+ KWDocument::SaveSelected /* simply means not SaveAll */,
+ QByteArray() /* no headers/footers */ );
+ if ( !m_store->close() ) // done with styles.xml
+ return false;
+
+ delete m_oasisStore; m_oasisStore = 0;
+ delete m_store; m_store = 0;
+
+ return true;
+}
+
+void KWOasisSaver::writeAutomaticStyles( KoXmlWriter& contentWriter, KoGenStyles& mainStyles, bool stylesDotXml )
+{
+ QValueList<KoGenStyles::NamedStyle> styles = mainStyles.styles( KoGenStyle::STYLE_AUTO, stylesDotXml );
+ QValueList<KoGenStyles::NamedStyle>::const_iterator it = styles.begin();
+ for ( ; it != styles.end() ; ++it ) {
+ (*it).style->writeStyle( &contentWriter, mainStyles, "style:style", (*it).name, "style:paragraph-properties" );
+ }
+
+ styles = mainStyles.styles( KoGenStyle::STYLE_AUTO_LIST, stylesDotXml );
+ it = styles.begin();
+ for ( ; it != styles.end() ; ++it ) {
+ (*it).style->writeStyle( &contentWriter, mainStyles, "text:list-style", (*it).name, 0 );
+ }
+
+ styles = mainStyles.styles( KWDocument::STYLE_FRAME_AUTO, stylesDotXml );
+ it = styles.begin();
+ for ( ; it != styles.end() ; ++it ) {
+ (*it).style->writeStyle( &contentWriter, mainStyles, "style:style", (*it).name , "style:graphic-properties" );
+ }
+
+ styles = mainStyles.styles( KWDocument::STYLE_TABLE, stylesDotXml );
+ it = styles.begin();
+ for ( ; it != styles.end() ; ++it ) {
+ (*it).style->writeStyle( &contentWriter, mainStyles, "style:style", (*it).name , "style:table-properties" );
+ }
+
+ styles = mainStyles.styles( KWDocument::STYLE_TABLE_COLUMN, stylesDotXml );
+ it = styles.begin();
+ for ( ; it != styles.end() ; ++it ) {
+ (*it).style->writeStyle( &contentWriter, mainStyles, "style:style", (*it).name , "style:table-column-properties" );
+ }
+
+ styles = mainStyles.styles( KWDocument::STYLE_TABLE_CELL_AUTO, stylesDotXml );
+ it = styles.begin();
+ for ( ; it != styles.end() ; ++it ) {
+ (*it).style->writeStyle( &contentWriter, mainStyles, "style:style", (*it).name , "style:table-cell-properties" );
+ }
+
+ styles = mainStyles.styles( KoGenStyle::STYLE_NUMERIC_DATE, stylesDotXml );
+ it = styles.begin();
+ for ( ; it != styles.end() ; ++it ) {
+ (*it).style->writeStyle( &contentWriter, mainStyles, "number:date-style", (*it).name, 0 /*TODO ????*/ );
+ }
+ styles = mainStyles.styles( KoGenStyle::STYLE_NUMERIC_TIME, stylesDotXml );
+ it = styles.begin();
+ for ( ; it != styles.end() ; ++it ) {
+ (*it).style->writeStyle( &contentWriter, mainStyles, "number:time-style", (*it).name, 0 /*TODO ????*/ );
+ }
+}
+
+const char* KWOasisSaver::selectionMimeType()
+{
+ return "application/vnd.oasis.opendocument.text";
+}
diff --git a/kword/KWOasisSaver.h b/kword/KWOasisSaver.h
new file mode 100644
index 00000000..fe5e6ca7
--- /dev/null
+++ b/kword/KWOasisSaver.h
@@ -0,0 +1,78 @@
+/* This file is part of the KDE project
+ Copyright (C) 2005 David Faure <faure@kde.org>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License version 2 as published by the Free Software Foundation.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+*/
+
+#ifndef KWOASISSAVER_H
+#define KWOASISSAVER_H
+
+#include <qbuffer.h>
+#include <KoGenStyles.h>
+#include <KoOasisStore.h>
+
+class KWDocument;
+class KoSavingContext;
+class KoXmlWriter;
+class KoTextParag;
+class KoStore;
+template <class T> class QValueList;
+
+/**
+ * This is used to save a bunch of paragraphs into a oasis store in memory,
+ * as some features do (e.g. sort text, or convert table to text)
+ *
+ * Note: this is NOT used for File/Save!
+ */
+class KWOasisSaver
+{
+public:
+ /// @param doc only needed for the user-style-collection
+ KWOasisSaver( KWDocument* doc );
+ ~KWOasisSaver();
+
+ /// Save a list of paragraphs
+ void saveParagraphs( const QValueList<const KoTextParag *>& paragraphs );
+
+ /// Save a paragraph
+ void saveParagraph( const KoTextParag* parag );
+
+ /// Another way to save paragraphs is to use KoTextObject::saveOasisContent
+ /// It needs a body writer and a saving context.
+ KoXmlWriter& bodyWriter() { return *m_oasisStore->bodyWriter(); }
+ KoSavingContext& savingContext() { return *m_savingContext; }
+
+ /// You MUST call this after saving the paragraphs and before calling data()
+ /// Return true on success
+ bool finish();
+
+ /// Return the entire ZIP store as a byte array
+ QByteArray data() const;
+
+ /// Helper function, also used by KWDocument.
+ static void writeAutomaticStyles( KoXmlWriter& contentWriter, KoGenStyles& mainStyles, bool stylesDotXml );
+
+ static const char* selectionMimeType();
+
+private:
+ QBuffer m_buffer;
+ KoStore* m_store;
+ KoOasisStore* m_oasisStore;
+ KoGenStyles m_mainStyles;
+ KoSavingContext* m_savingContext;
+ KWDocument* m_doc;
+};
+
+#endif
diff --git a/kword/KWPage.cpp b/kword/KWPage.cpp
new file mode 100644
index 00000000..b2645980
--- /dev/null
+++ b/kword/KWPage.cpp
@@ -0,0 +1,139 @@
+/* This file is part of the KOffice project
+ * Copyright (C) 2005 Thomas Zander <zander@kde.org>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; version 2.
+
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public License
+ * along with this library; see the file COPYING.LIB. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#include "KWPage.h"
+#include "KoZoomHandler.h"
+
+#include <qrect.h>
+
+KWPage::KWPage(KWPageManager *parent, int pageNum) {
+ m_parent = parent;
+ m_pageNum = pageNum;
+ m_pageLayout.ptWidth = -1.0;
+ m_pageLayout.ptHeight = -1.0;
+ m_pageLayout.ptLeft = -1.0;
+ m_pageLayout.ptRight = -1.0;
+ m_pageLayout.ptBottom = -1.0;
+ m_pageLayout.ptTop = -1.0;
+ m_pageLayout.ptPageEdge = -1.0;
+ m_pageLayout.ptBindingSide = -1.0;
+ m_pageSide = pageNum%2==0 ? Left : Right;
+}
+
+double KWPage::width() const {
+ if(m_pageLayout.ptWidth != -1)
+ return m_pageLayout.ptWidth;
+ return m_parent->m_defaultPageLayout.ptWidth;
+}
+
+double KWPage::height() const {
+ if(m_pageLayout.ptHeight != -1)
+ return m_pageLayout.ptHeight;
+ return m_parent->m_defaultPageLayout.ptHeight;
+}
+
+void KWPage::setWidth(const double &x) {
+ m_pageLayout.ptWidth = x == m_parent->m_defaultPageLayout.ptWidth ? -1 : x;
+}
+void KWPage::setHeight(const double &y) {
+ m_pageLayout.ptHeight = y == m_parent->m_defaultPageLayout.ptHeight ? -1 : y;
+}
+void KWPage::setTopMargin(const double &t) {
+ m_pageLayout.ptTop = t == m_parent->m_defaultPageLayout.ptTop ? -1 : t;
+}
+void KWPage::setBottomMargin(const double &b) {
+ m_pageLayout.ptBottom = b == m_parent->m_defaultPageLayout.ptBottom ? -1 : b;
+}
+void KWPage::setPageEdgeMargin(const double &m) {
+ m_pageLayout.ptPageEdge = m == m_parent->m_defaultPageLayout.ptPageEdge ? -1 : m;
+ m_pageLayout.ptLeft = -1;
+ m_pageLayout.ptRight = -1;
+}
+void KWPage::setMarginClosestBinding(const double &m) {
+ m_pageLayout.ptBindingSide = m == m_parent->m_defaultPageLayout.ptBindingSide ? -1 : m;
+ m_pageLayout.ptLeft = -1;
+ m_pageLayout.ptRight = -1;
+}
+void KWPage::setLeftMargin(const double &l) {
+ m_pageLayout.ptLeft = l == m_parent->m_defaultPageLayout.ptLeft ? -1 : l;
+ m_pageLayout.ptBindingSide = -1;
+ m_pageLayout.ptPageEdge = -1;
+ if(rightMargin() == -1)
+ m_pageLayout.ptRight = 0; // never leave this object in an illegal state
+}
+void KWPage::setRightMargin(const double &r) {
+ m_pageLayout.ptRight = r == m_parent->m_defaultPageLayout.ptRight ? -1 : r;
+ m_pageLayout.ptBindingSide = -1;
+ m_pageLayout.ptPageEdge = -1;
+ if(leftMargin() == -1)
+ m_pageLayout.ptLeft = 0; // never leave this object in an illegal state
+}
+
+double KWPage::topMargin() const {
+ if(m_pageLayout.ptTop != -1)
+ return m_pageLayout.ptTop;
+ return m_parent->m_defaultPageLayout.ptTop;
+}
+double KWPage::bottomMargin() const {
+ if(m_pageLayout.ptBottom != -1)
+ return m_pageLayout.ptBottom;
+ return m_parent->m_defaultPageLayout.ptBottom;
+}
+double KWPage::leftMargin() const {
+ // first try local left.
+ if(m_pageLayout.ptLeft != -1)
+ return m_pageLayout.ptLeft;
+
+ // then see if the margin is in use.
+ double answer = m_pageSide == Right ? marginClosestBinding() : pageEdgeMargin();
+ if(answer != -1)
+ return answer;
+ return m_parent->m_defaultPageLayout.ptLeft;
+}
+double KWPage::rightMargin() const {
+ if(m_pageLayout.ptRight != -1)
+ return m_pageLayout.ptRight;
+
+ double answer = m_pageSide == Left ? marginClosestBinding() : pageEdgeMargin();
+ if(answer != -1)
+ return answer;
+ return m_parent->m_defaultPageLayout.ptRight;
+}
+double KWPage::pageEdgeMargin() const {
+ if(m_pageLayout.ptPageEdge != -1)
+ return m_pageLayout.ptPageEdge;
+ return m_parent->m_defaultPageLayout.ptPageEdge;
+}
+double KWPage::marginClosestBinding() const {
+ if(m_pageLayout.ptBindingSide != -1)
+ return m_pageLayout.ptBindingSide;
+ return m_parent->m_defaultPageLayout.ptBindingSide;
+}
+
+double KWPage::offsetInDocument() const { // the y coordinate
+ return m_parent->topOfPage(m_pageNum);
+}
+
+QRect KWPage::zoomedRect(KoZoomHandler *zoomHandler) {
+ return QRect(0, zoomHandler->zoomItY(offsetInDocument()),
+ zoomHandler->zoomItX(width()), zoomHandler->zoomItY(height()));
+}
+
+const KoRect KWPage::rect() const {
+ return KoRect(0, offsetInDocument(), width(), height());
+}
diff --git a/kword/KWPage.h b/kword/KWPage.h
new file mode 100644
index 00000000..b650a383
--- /dev/null
+++ b/kword/KWPage.h
@@ -0,0 +1,128 @@
+/* This file is part of the KOffice project
+ * Copyright (C) 2005 Thomas Zander <zander@kde.org>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; version 2.
+
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public License
+ * along with this library; see the file COPYING.LIB. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ */
+#ifndef kw_page_h
+#define kw_page_h
+
+#include <KoRect.h>
+#include "KWPageManager.h"
+#include "KoPageLayout.h"
+
+class KoZoomHandler;
+
+/**
+ * This class represents a printed page of the document.
+ */
+class KWPage {
+public:
+ /// An enum to define if this is a page that is printed to be a left or a right page
+ enum PageSideEnum {Left, Right}; //future:, PageSpread };
+
+ /// set the width of the page in pt
+ void setWidth(const double &x);
+ /// set the height of the page in pt
+ void setHeight(const double &y);
+ /// set height of the top margin in pt
+ void setTopMargin(const double &x);
+ /// set height of the bottom margin in pt
+ void setBottomMargin(const double &y);
+
+ /**
+ * set width of the margin that is the closest to the page edge, i.e. left for even pages.
+ * Any page should either use valid left and right margins, or valid pageedge/binding ones,
+ * setting this one will remove the left/right ones.
+ */
+ void setPageEdgeMargin(const double &x);
+ /**
+ * set width of the margin that is the closest to the binding, i.e. right for even pages.
+ * Any page should either use valid left and right margins, or valid pageedge/binding ones,
+ * setting this one will remove the left/right ones.
+ */
+ void setMarginClosestBinding(const double &y);
+ /**
+ * set width of the left margin.
+ * Any page should either use valid left and right margins, or valid pageedge/binding ones,
+ * setting this one will remove the pageedge/closest-binding ones.
+ */
+ void setLeftMargin(const double &l);
+ /**
+ * set width of the right margin.
+ * Any page should either use valid left and right margins, or valid pageedge/binding ones,
+ * setting this one will remove the pageedge/closest-binding ones.
+ */
+ void setRightMargin(const double &r);
+
+ /// return the width of this page (in pt)
+ double width() const;
+ /// return the height of this page (in pt)
+ double height() const;
+ /// return the height of the margin at top (in pt);
+ double topMargin() const;
+ /// return the height of the margin at bottom (in pt);
+ double bottomMargin() const;
+ /// return the width of the margin at left (in pt);
+ double leftMargin() const;
+ /// return the width of the margin at left (in pt);
+ double rightMargin() const;
+ /// return width of the margin that is the closest to the page edge, i.e. left for even pages
+ double pageEdgeMargin() const;
+ /// return width of the margin that is the closest to the binding, i.e. right for even pages
+ double marginClosestBinding() const;
+
+ // the y coordinate
+ /**
+ * All Pages are in a document-wide coordinate system that simply puts every page under
+ * the next page and keeps the Y coordinate counting throughout the doc. The X coordinate
+ * off each page in the document is zero, i.e. aligned to the left.
+ * This method returns the offset of this page in the whole document which means it will
+ * add the height of all the pages that come before this one.
+ */
+ double offsetInDocument() const;
+
+ /// Return the pageSide of this page, see the PageSideEnum
+ PageSideEnum pageSide() const { return m_pageSide; }
+ /// set the pageSide of this page, see the PageSideEnum
+ void setPageSide(PageSideEnum ps) { m_pageSide = ps; }
+
+ /// returns the number of this page as it will be shown to the user.
+ int pageNumber() const { return m_pageNum; }
+
+ /**
+ * return a QRect with the size of this page in pixels.
+ * @param zoomHandler the zoomhandler knows the current zoom levels. The KWDocument currently
+ * implements that interface.
+ */
+ QRect zoomedRect(KoZoomHandler *zoomHandler);
+ /// return a KoRect with the (pt) sizes of this page. Margins are ignored for this function.
+ const KoRect rect() const;
+
+private:
+ /** private constructor, only for our friends
+ * @param parent the KWPageManager that we belong to.
+ * @param pageNum the number of the page as the user will see it.
+ */
+ KWPage(KWPageManager *parent, int pageNum);
+ int m_pageNum;
+ PageSideEnum m_pageSide;
+ KoPageLayout m_pageLayout;
+
+ KWPageManager *m_parent;
+
+friend class KWPageManager;
+};
+
+#endif
diff --git a/kword/KWPageManager.cpp b/kword/KWPageManager.cpp
new file mode 100644
index 00000000..2e1c81fd
--- /dev/null
+++ b/kword/KWPageManager.cpp
@@ -0,0 +1,251 @@
+/* This file is part of the KOffice project
+ * Copyright (C) 2005 Thomas Zander <zander@kde.org>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; version 2.
+
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public License
+ * along with this library; see the file COPYING.LIB. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ */
+#include "KWPageManager.h"
+#include "KWPage.h"
+#include "KoRect.h"
+
+//#define DEBUG_PAGES
+
+KWPageManager::KWPageManager() {
+ m_firstPage = 1;
+ m_onlyAllowAppend = false;
+ m_pageList.setAutoDelete(true);
+ m_defaultPageLayout = KoPageLayout::standardLayout();
+}
+
+int KWPageManager::pageNumber(const KoRect &frame) const {
+ int page=m_firstPage;
+ double startOfpage = 0.0;
+ QPtrListIterator<KWPage> pages(m_pageList);
+ while(pages.current() && startOfpage < frame.top()) {
+ startOfpage += pages.current()->height();
+ if(startOfpage >= frame.top())
+ break;
+ page++;
+ ++pages;
+ }
+ // Disable strict checks. Testcase: F10, drag rectangle, move the mouse under the bottom of the last page.
+ // Instead of a bunch of warnings and making the insertion-rectangle disappear, we simply want to bound
+ // the mouse position to the last page.
+ if ( !pages.current() )
+ page = m_firstPage + m_pageList.count() - 1;
+#if 0
+ if(!pages.current() || frame.right() > pages.current()->width() ||
+ frame.top() > pages.current()->height() + startOfpage) {
+#ifdef DEBUG_PAGES
+ if(!pages.current())
+ kdDebug(31001) << " KWPageManager::pageNumber of "<< frame << " is too high, no page there\n";
+ else if(frame.right() > pages.current()->width())
+ kdDebug(31001) << " KWPageManager::pageNumber right of "<< frame << " is out of bounds\n";
+ else if(frame.top() > pages.current()->height() + startOfpage)
+ kdDebug(31001) << " KWPageManager::pageNumber "<< frame << " spans multiple pages\n";
+
+kdDebug(31001) << kdBacktrace() << endl;
+#endif
+ return -1; // not inside the page...
+ }
+#endif
+ return page;
+}
+int KWPageManager::pageNumber(const KoPoint &point) const {
+ return pageNumber(KoRect(point, point));
+}
+int KWPageManager::pageNumber(const double ptY) const {
+ return pageNumber(KoRect(0, ptY, 0, 0));
+}
+int KWPageManager::pageNumber(const KoRect *rect) const {
+ KoRect tmp(*rect);
+ return pageNumber(tmp);
+}
+
+int KWPageManager::pageCount() const {
+ return m_pageList.count();
+}
+
+KWPage* KWPageManager::page(int pageNum) const {
+ QPtrListIterator<KWPage> pages(m_pageList);
+ while(pages.current()) {
+ if(pages.current()->pageNumber() == pageNum)
+ return pages.current();
+ ++pages;
+ }
+ kdWarning(31001) << "KWPageManager::page(" << pageNum << ") failed; Requested page does not exist ["<< m_firstPage << "-"<< lastPageNumber() << "]"<< endl;
+#ifdef DEBUG_PAGES
+ kdDebug(31001) << kdBacktrace();
+#endif
+ return 0;
+}
+KWPage* KWPageManager::page(const KoRect &frame) const {
+ return page(pageNumber(frame));
+}
+KWPage* KWPageManager::page(const KoPoint &point) const {
+ return page(pageNumber(point));
+}
+KWPage* KWPageManager::page(double ptY) const {
+ return page(pageNumber(ptY));
+}
+KWPage* KWPageManager::page(const KoRect *rect) const {
+ KoRect tmp(*rect);
+ return page(tmp);
+}
+
+void KWPageManager::setStartPage(int startPage) {
+ int offset = startPage - m_firstPage;
+ bool switchSides = startPage % 2 != m_firstPage % 2;
+ for(QPtrListIterator<KWPage> pages(m_pageList); pages.current(); ++pages) {
+ KWPage *page = pages.current();
+ page->m_pageNum = page->m_pageNum + offset;
+ if(switchSides)
+ page->m_pageSide = page->m_pageSide == KWPage::Left ? KWPage::Right : KWPage::Left;
+ }
+ m_firstPage = startPage;
+}
+
+int KWPageManager::lastPageNumber() const {
+ return pageCount() + m_firstPage - 1;
+}
+
+KWPage* KWPageManager::insertPage(int index) {
+ if(m_onlyAllowAppend)
+ return appendPage();
+ KWPage *page = new KWPage(this, QMIN( QMAX(index, m_firstPage), lastPageNumber()+1 ));
+ QPtrListIterator<KWPage> pages(m_pageList);
+ while(pages.current() && pages.current()->pageNumber() < index)
+ ++pages;
+ while(pages.current()) {
+ pages.current()->m_pageNum++;
+ ++pages;
+ }
+ m_pageList.inSort(page);
+ return page;
+}
+
+KWPage* KWPageManager::appendPage() {
+ KWPage *page = new KWPage(this, lastPageNumber() + 1);
+ m_pageList.append(page);
+ return page;
+}
+
+const KoPageLayout KWPageManager::pageLayout(int pageNumber) const {
+ KoPageLayout lay = m_defaultPageLayout;
+ if(pageNumber >= m_firstPage && pageNumber <= lastPageNumber()) {
+ KWPage *page = this->page(pageNumber);
+ lay.ptHeight = page->height();
+ lay.ptWidth = page->width();
+ lay.ptTop = page->topMargin();
+ lay.ptLeft = page->leftMargin();
+ lay.ptBottom = page->bottomMargin();
+ lay.ptRight = page->rightMargin();
+ }
+ return lay;
+}
+
+double KWPageManager::topOfPage(int pageNum) const {
+ return pageOffset(pageNum, false);
+}
+double KWPageManager::bottomOfPage(int pageNum) const {
+ return pageOffset(pageNum, true);
+}
+
+double KWPageManager::pageOffset(int pageNum, bool bottom) const {
+ if(pageNum < m_firstPage)
+ return 0;
+ QPtrListIterator<KWPage> pages(m_pageList);
+ double offset = 0.0;
+ while(pages.current()) {
+ if(pages.current()->pageNumber() == pageNum) {
+ if(bottom)
+ offset += pages.current()->height();
+ break;
+ }
+ offset += pages.current()->height();
+ ++pages;
+ }
+ return offset;
+}
+
+void KWPageManager::removePage(int pageNumber) {
+ removePage(page(pageNumber));
+}
+void KWPageManager::removePage(KWPage *page) {
+ if(!page)
+ return;
+ QPtrListIterator<KWPage> pages(m_pageList);
+ while(pages.current() && pages.current()->pageNumber() <= page->pageNumber())
+ ++pages;
+ while(pages.current()) {
+ pages.current()->m_pageNum--;
+ ++pages;
+ }
+ // TODO make the deletion of object page occur in a single shot
+ m_pageList.remove(page);
+}
+
+void KWPageManager::setDefaultPage(const KoPageLayout &layout) {
+ m_defaultPageLayout = layout;
+ // make sure we have 1 default, either pageBound or left/right bound.
+ if(m_defaultPageLayout.ptLeft < 0 || m_defaultPageLayout.ptRight < 0) {
+ m_defaultPageLayout.ptLeft = -1;
+ m_defaultPageLayout.ptRight = -1;
+ } else {
+ m_defaultPageLayout.ptPageEdge = -1;
+ m_defaultPageLayout.ptBindingSide = -1;
+ m_defaultPageLayout.ptLeft = QMAX(m_defaultPageLayout.ptLeft, 0);
+ m_defaultPageLayout.ptRight = QMAX(m_defaultPageLayout.ptRight, 0);
+ }
+ //kdDebug() << "setDefaultPage l:" << m_defaultPageLayout.ptLeft << ", r: " << m_defaultPageLayout.ptRight << ", a: " << m_defaultPageLayout.ptPageEdge << ", b: " << m_defaultPageLayout.ptBindingSide << endl;
+}
+
+KoPoint KWPageManager::clipToDocument(const KoPoint &point) {
+ int page=m_firstPage;
+ double startOfpage = 0.0;
+ QPtrListIterator<KWPage> pages(m_pageList);
+ while(pages.current()) {
+ startOfpage += pages.current()->height();
+ if(startOfpage >= point.y())
+ break;
+ page++;
+ ++pages;
+ }
+ page = QMIN(page, lastPageNumber());
+ KoRect rect = this->page(page)->rect();
+ if(rect.contains(point))
+ return point;
+
+ KoPoint rc(point);
+ if(rect.top() > rc.y())
+ rc.setY(rect.top());
+ else if(rect.bottom() < rc.y())
+ rc.setY(rect.bottom());
+
+ if(rect.left() > rc.x())
+ rc.setX(rect.left());
+ else if(rect.right() < rc.x())
+ rc.setX(rect.right());
+ return rc;
+}
+
+// **** PageList ****
+int KWPageManager::PageList::compareItems(QPtrCollection::Item a, QPtrCollection::Item b)
+{
+ int pa = ((KWPage *)a)->pageNumber();
+ int pb = ((KWPage *)b)->pageNumber();
+ if (pa == pb) return 0;
+ if (pa < pb) return -1;
+ return 1;
+}
diff --git a/kword/KWPageManager.h b/kword/KWPageManager.h
new file mode 100644
index 00000000..300bef99
--- /dev/null
+++ b/kword/KWPageManager.h
@@ -0,0 +1,142 @@
+/* This file is part of the KOffice project
+ * Copyright (C) 2005 Thomas Zander <zander@kde.org>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; version 2.
+
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public License
+ * along with this library; see the file COPYING.LIB. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ */
+#ifndef kw_pagemanager_h
+#define kw_pagemanager_h
+
+#include "KoPageLayout.h"
+
+#include <qptrlist.h>
+
+class KWPage;
+class KoPoint;
+class KoRect;
+
+/**
+ * The Page Manager manages all the pages a document contains and separates all the frames
+ * the document contains into actual printed pages.
+ */
+class KWPageManager {
+public:
+ KWPageManager();
+
+ /// return pageNumber of @p frame, pagenumbers for a normal document start at 1.
+ int pageNumber(const KoRect *rect) const;
+ /// return pageNumber of @p rect, pagenumbers for a normal document start at 1.
+ int pageNumber(const KoRect &rect) const;
+ /// return pageNumber of @p point, pagenumbers for a normal document start at 1.
+ int pageNumber(const KoPoint &point) const;
+ /** return pageNumber of page with document-offset (in the Y direction) of @p ptY,
+ * pagenumbers for a normal document start at 1.
+ */
+ int pageNumber(double ptY) const;
+ /// return total number of pages in this document.
+ int pageCount() const;
+ /// return the highest page number we have in this document.
+ int lastPageNumber() const;
+ /// return the KWPage of a specific page number. Returns 0 if page does not exist.
+ KWPage* page(int pageNumber) const;
+ /// return the KWPage instance where the rect is on. Returns 0 if page does not exist.
+ KWPage* page(const KoRect &rect) const;
+ /// return the KWPage instance where the rect or frame is on. Returns 0 if page does not exist.
+ KWPage* page(const KoRect *frame) const;
+ /// return the KWPage instance where the point is on. Returns 0 if page does not exist.
+ KWPage* page(const KoPoint &point) const;
+ /// return the KWPage instance of the y-coordinate in the document. Returns 0 if page does not exist.
+ KWPage* page(double ptY) const;
+
+ /**
+ * Return the y-offset in this document of the top of page with @p pageNumber
+ * Note that pageNumber is NOT an offset in the document, but the real number
+ * of the page.
+ * @see setStartPage(int)
+ */
+ double topOfPage(int pageNumber) const; // in pt
+ /**
+ * Return the y-offset in this document of the bottom of page with @p pageNumber
+ * Note that pageNumber is NOT an offset in the document, but the real number
+ * of the page.
+ * @see setStartPage(int)
+ */
+ double bottomOfPage(int pageNumber) const; // in pt
+
+ /// Set a new startpage for this document, renumbering all pages already added.
+ void setStartPage(int startPage);
+
+ /// return the first pagenumber of this document
+ int startPage() const { return m_firstPage; }
+
+ /**
+ * Register if new pages can only be appended after the last one and not
+ * somewhere in between.
+ * @param appendOnly the new value
+ */
+ void setOnlyAllowAppend(bool appendOnly) { m_onlyAllowAppend = appendOnly; }
+ /**
+ * return if new pages can only be appended after the last one and not
+ * somewhere in between.
+ */
+ bool onlyAllowAppend() { return m_onlyAllowAppend; }
+
+ /**
+ * Inserts a new page at the specified position in the document.
+ * Shifts the page currently at that position (if any) and any subsequent pages after.
+ * if onlyAllowAppend is set to true the pagenumber will be ignored and the new page
+ * will always be appended.
+ * @param pageNumber page number of the new page
+ */
+ KWPage* insertPage(int pageNumber);
+ /// Append a new page at the end of the document
+ KWPage* appendPage();
+
+ /// Remove the page with @p pageNumber renumbering all pages after pages already added
+ void removePage(int pageNumber);
+ /// Remove @p page renumbering all pages after pages already added
+ void removePage(KWPage *page);
+
+ /// return the effective pageLayout of @p pageNumber combining the default and the page specific ones
+ const KoPageLayout pageLayout(int pageNumber) const;
+
+ void setDefaultPage(const KoPageLayout &layout);
+
+ /**
+ * Returns the argument point, with altered coordinats if the point happens to be
+ * outside all pages.
+ * The resulting point is the shortest distance from the argument inside the document.
+ * @param point the point to test
+ */
+ KoPoint clipToDocument(const KoPoint &point);
+
+private:
+ /// helper method for the topOfPage and bottomOfPage
+ double pageOffset(int pageNumber, bool bottom) const;
+ /// sorter for numbered pages.
+ class PageList : public QPtrList<KWPage> {
+ protected:
+ virtual int compareItems(QPtrCollection::Item a, QPtrCollection::Item b);
+ };
+
+ PageList m_pageList;
+ int m_firstPage;
+ bool m_onlyAllowAppend; // true for WP style documents.
+
+ KoPageLayout m_defaultPageLayout;
+
+friend class KWPage;
+};
+
+#endif
diff --git a/kword/KWPartFrameSet.cpp b/kword/KWPartFrameSet.cpp
new file mode 100644
index 00000000..88367743
--- /dev/null
+++ b/kword/KWPartFrameSet.cpp
@@ -0,0 +1,378 @@
+/* This file is part of the KDE project
+ Copyright (C) 2000-2005 David Faure <faure@kde.org>
+ Copyright (C) 2005 Thomas Zander <zander@kde.org>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+*/
+
+#include "KWPartFrameSet.h"
+#include "KWDocument.h"
+#include "KWCommand.h"
+#include "KWordPartFrameSetIface.h"
+#include "KWFrameViewManager.h"
+#include "KWFrameView.h"
+#include "KWViewMode.h"
+
+#include <KoOasisContext.h>
+#include <KoXmlWriter.h>
+#include <KoXmlNS.h>
+
+#include <klocale.h>
+#include <kapplication.h>
+
+#include <assert.h>
+
+KWPartFrameSet::KWPartFrameSet( KWDocument *_doc, KWDocumentChild *_child, const QString & name )
+ : KWFrameSet( _doc ), m_child( 0 ), m_cmdMoveChild( 0 ), m_protectContent( false )
+{
+ if ( _child )
+ setChild( _child );
+
+ kdDebug(32001) << "KWPartFrameSet::KWPartFrameSet" << endl;
+ if ( name.isEmpty() )
+ m_name = _doc->generateFramesetName( i18n( "Object %1" ) );
+ else
+ m_name = name;
+}
+
+KWPartFrameSet::KWPartFrameSet( KWDocument* doc, const QDomElement& frameTag,
+ const QDomElement& objectTag, KoOasisContext& context )
+ : KWFrameSet( doc ), m_child( 0 ), m_cmdMoveChild( 0 ), m_protectContent( false )
+{
+ m_name = frameTag.attributeNS( KoXmlNS::draw, "name", QString::null );
+ if ( doc->frameSetByName( m_name ) ) // already exists!
+ m_name = doc->generateFramesetName( m_name + " %1" );
+
+ context.styleStack().save();
+ context.fillStyleStack( frameTag, KoXmlNS::draw, "style-name", "graphic" ); // get the style for the graphics element
+ KWFrame* frame = loadOasisFrame( frameTag, context );
+ context.styleStack().restore();
+
+ // Create a KWDocumentChild, without KoDocument inside
+ KWDocumentChild* child = doc->createChildDoc( frame->rect(), 0 );
+ setChild( child );
+ child->loadOasis( frameTag, objectTag );
+ updateChildGeometry();
+
+ // This is what loads the KoDocument
+ (void)child->loadOasisDocument( context.store(), context.manifestDocument() );
+}
+
+void KWPartFrameSet::setChild( KWDocumentChild* child )
+{
+ assert( !m_child );
+ m_child = child;
+ m_child->setPartFrameSet( this );
+ QObject::connect( m_child, SIGNAL( changed( KoChild * ) ),
+ this, SLOT( slotChildChanged() ) );
+}
+
+KWPartFrameSet::~KWPartFrameSet()
+{
+}
+
+KWordFrameSetIface* KWPartFrameSet::dcopObject()
+{
+ if ( !m_dcop )
+ m_dcop = new KWordPartFrameSetIface( this );
+
+ return m_dcop;
+}
+
+
+void KWPartFrameSet::drawFrameContents( KWFrame* frame, QPainter * painter, const QRect & /*crect TODO*/,
+ const QColorGroup &, bool onlyChanged, bool,
+ KWFrameSetEdit *, KWViewMode * )
+{
+ if (!onlyChanged)
+ {
+ if ( !m_child || !m_child->document() )
+ {
+ kdDebug(32001) << "KWPartFrameSet::drawFrameContents " << this << " aborting. child=" << m_child
+ << " child->document()=" << (m_child?m_child->document():0) << endl;
+ return;
+ }
+
+ KoTextZoomHandler* zh = kWordDocument();
+
+ // We have to define better the merning of the rect that we pass. Does it include zooming ? (yes I think)
+ // Does it define the area to be repainted only? (no, that's the painter clip rect)
+ // So it defines the whole area covered by the embedded document, in pixels.
+ QRect rframe( 0, 0,
+ zh->zoomItX( frame->innerWidth() ),
+ zh->zoomItY( frame->innerHeight() ) );
+ //kdDebug(32001) << "rframe=" << rframe << endl;
+
+ double zoomX = static_cast<double>( zh->zoom() ) / 100;
+ double zoomY = static_cast<double>( zh->zoom() ) / 100;
+ m_child->document()->paintEverything( *painter, rframe, true, 0L, zoomX, zoomY );
+
+ } //else kdDebug(32001) << "KWPartFrameSet::drawFrameContents " << this << " onlychanged=true!" << endl;
+}
+
+void KWPartFrameSet::updateChildGeometry()
+{
+ if( m_frames.isEmpty() ) // Deleted frameset
+ return;
+ m_child->setGeometry( m_frames.first()->toQRect() );
+}
+
+void KWPartFrameSet::slotChildChanged()
+{
+ // This is called when the KoDocumentChild is resized (using the KoFrame)
+ QPtrListIterator<KWFrame> listFrame = frameIterator();
+ KWFrame *frame = listFrame.current();
+ if ( frame )
+ {
+ frame->setRect( KoRect::fromQRect( getChild()->geometry() ) );
+
+ //kdDebug(32001) << "KWPartFrameSet::slotChildChanged child's geometry " << getChild()->geometry()
+ // << " frame set to " << *frame << endl;
+ m_doc->frameChanged( frame );
+ //there is just a frame
+ if(m_cmdMoveChild)
+ m_cmdMoveChild->listFrameMoved().newRect = frame->normalize();
+ }
+ else
+ kdDebug(32001) << "Frame not found!" << endl;
+}
+
+QDomElement KWPartFrameSet::save( QDomElement &parentElem, bool saveFrames )
+{
+ if ( m_frames.isEmpty() ) // Deleted frameset -> don't save
+ return QDomElement();
+ KWFrameSet::saveCommon( parentElem, saveFrames );
+ // Ok, this one is a bit hackish. KWDocument calls us for saving our stuff into
+ // the SETTINGS element, which it creates for us. So our save() doesn't really have
+ // the same behaviour as a normal KWFrameSet::save()....
+ return QDomElement();
+}
+
+void KWPartFrameSet::saveOasis( KoXmlWriter& writer, KoSavingContext& context, bool ) const
+{
+ if ( m_frames.isEmpty() ) // Deleted frameset -> don't save
+ return;
+ // Save first frame with the whole contents
+ KWFrame* frame = m_frames.getFirst();
+ frame->startOasisFrame( writer, context.mainStyles(), name() );
+
+ writer.startElement( "draw:object" );
+ // #### let's hope name() is unique...
+ m_child->saveOasisAttributes( writer, name() );
+
+ writer.endElement(); // draw:object
+ writer.endElement(); // draw:frame
+}
+
+void KWPartFrameSet::load( QDomElement &attributes, bool loadFrames )
+{
+ KWFrameSet::load( attributes, loadFrames );
+}
+
+void KWPartFrameSet::startEditing()
+{
+ // Content is protected -> can't edit. Maybe we should open part in readonly mode?
+ if ( m_protectContent )
+ return;
+ kdDebug() << k_funcinfo << endl;
+ //create undo/redo move command
+ KWFrame* frame = m_frames.first();
+ if (!frame)
+ return;
+ FrameIndex index( frame );
+ FrameResizeStruct tmpMove( frame->normalize(), 0, KoRect() );
+
+ if(!m_cmdMoveChild)
+ m_cmdMoveChild=new KWFramePartMoveCommand( i18n("Move/Resize Frame"), index, tmpMove );
+}
+
+void KWPartFrameSet::endEditing()
+{
+ kdDebug() << k_funcinfo << endl;
+ if( m_cmdMoveChild && m_cmdMoveChild->frameMoved() )
+ m_doc->addCommand(m_cmdMoveChild);
+ else
+ delete m_cmdMoveChild;
+ m_cmdMoveChild=0L;
+
+}
+
+void KWPartFrameSet::moveFloatingFrame( int frameNum, const KoPoint &position )
+{
+ //kdDebug()<<k_funcinfo<<" frame no="<<frameNum<<" to pos="<<position.x()<<","<<position.y()<<endl;
+ KWFrame * frame = m_frames.at( frameNum );
+ if ( frame )
+ {
+ KWFrameSet::moveFloatingFrame( frameNum, position );
+ m_child->setGeometry( frame->toQRect(), true /* avoid circular events */ );
+ }
+}
+
+KWFrameSetEdit * KWPartFrameSet::createFrameSetEdit( KWCanvas * /*canvas*/ )
+{
+ return 0L; // new KWPartFrameSetEdit( this, canvas );
+}
+
+#ifndef NDEBUG
+void KWPartFrameSet::printDebug()
+{
+ KWFrameSet::printDebug();
+ kdDebug() << " +-- Object Document: " << endl;
+ if ( getChild() )
+ {
+ if ( getChild()->document() )
+ kdDebug() << " Url : " << getChild()->document()->url().url()<<endl;
+ else
+ kdWarning() << "NO DOCUMENT" << endl;
+ kdDebug() << " Rectangle : " << getChild()->geometry().x() << "," << getChild()->geometry().y() << " " << getChild()->geometry().width() << "x" << getChild()->geometry().height() << endl;
+ } else
+ kdWarning() << "NO CHILD" << endl;
+}
+
+#endif
+
+void KWPartFrameSet::setDeleted( bool on)
+{
+ m_child->setDeleted( on );
+}
+
+void KWPartFrameSet::deleteFrame( unsigned int _num, bool remove, bool recalc )
+{
+ KWFrameSet::deleteFrame( _num, remove, recalc );
+ if ( m_frames.isEmpty() ) // then the whole frameset and thus the child is deleted
+ m_child->setDeleted();
+}
+
+void KWPartFrameSet::KWPartFrameSet::createEmptyRegion( const QRect &crect, QRegion &emptyRegion, KWViewMode *viewMode ) {
+ Q_UNUSED(crect);
+ Q_UNUSED(emptyRegion);
+ Q_UNUSED(viewMode);
+
+ // empty implementation since embedded parts can be transparant.
+}
+
+#if 0
+KWPartFrameSetEdit::KWPartFrameSetEdit( KWPartFrameSet * fs, KWCanvas * canvas )
+ : KWFrameSetEdit( fs, canvas )
+{
+ kdDebug(32001) << "KWPartFrameSetEdit::KWPartFrameSetEdit " << endl;
+ m_dcop=0L;
+ fs->startEditing();
+ QObject::connect( m_canvas->gui()->getView(), SIGNAL( activated( bool ) ),
+ this, SLOT( slotChildActivated( bool ) ) );
+}
+
+KWPartFrameSetEdit::~KWPartFrameSetEdit()
+{
+ kdDebug(32001) << "KWPartFrameSetEdit::~KWPartFrameSetEdit" << endl;
+ delete m_dcop;
+}
+
+DCOPObject* KWPartFrameSetEdit::dcopObject()
+{
+ if ( !m_dcop )
+ m_dcop = new KWordPartFrameSetEditIface( this );
+ return m_dcop;
+}
+
+void KWPartFrameSetEdit::slotChildActivated(bool b)
+{
+ kdDebug() << "KWPartFrameSetEdit::slotChildActivated " << b << endl;
+ //we store command when we deactivate the child.
+ if( !b )
+ partFrameSet()->endEditing();
+
+}
+#endif
+
+void KWPartFrameSet::storeInternal()
+{
+ if ( getChild()->document()->storeInternal() )
+ {
+ KWFramePartExternalCommand* cmd =new KWFramePartExternalCommand( i18n("Make Document External"), this );
+ m_doc->addCommand(cmd);
+ getChild()->document()->setStoreInternal(false);
+ }
+ else
+ {
+ KWFramePartInternalCommand* cmd =new KWFramePartInternalCommand( i18n("Make Document Internal"), this );
+ m_doc->addCommand(cmd);
+ getChild()->document()->setStoreInternal(true);
+ }
+
+ kdDebug()<<k_funcinfo<<"url: "<<getChild()->url().url()<<" store internal="<<getChild()->document()->storeInternal()<<endl;
+}
+
+
+/******************************************************************/
+/* Class: KWDocumentChild */
+/******************************************************************/
+
+KWDocumentChild::KWDocumentChild( KWDocument *_wdoc, const QRect& _rect, KoDocument *_doc )
+ : KoDocumentChild( _wdoc, _doc, _rect ), m_partFrameSet( 0 )
+{
+}
+
+KWDocumentChild::KWDocumentChild( KWDocument *_wdoc )
+ : KoDocumentChild( _wdoc ), m_partFrameSet( 0 )
+{
+}
+
+KWDocumentChild::~KWDocumentChild()
+{
+}
+
+void KWDocumentChild::setDocument( KoDocument *doc, const QRect &geometry )
+{
+ // When hitTest returns true, we want to activate the part right away.
+ // PartManager supports selecting parts, but not in a doc/view separated way.
+ doc->setSelectable( false );
+ KoDocumentChild::setDocument( doc, geometry );
+}
+
+KoDocument* KWDocumentChild::hitTest( const QPoint& p, const QWMatrix& _matrix )
+{
+ Q_ASSERT( m_partFrameSet );
+ if ( isDeleted() || !document() ) {
+ return 0;
+ }
+
+#if KDE_IS_VERSION( 3, 4, 0 )
+ int keyState = kapp->keyboardMouseState();
+#else
+ int keyState = 0;
+ if ( kapp->keyboardModifiers() & KApplication::ControlModifier )
+ keyState = Qt::ControlButton;
+#endif
+
+ // Only activate when it's already selected, and when not clicking on the border.
+ // KWFrameView and the part frame policy have that logic already.
+ KWView* kwView = ::qt_cast<KWView *>( parentDocument()->hitTestView() );
+ Q_ASSERT( kwView );
+ if ( kwView ) {
+ KWFrame* frame = m_partFrameSet->frame(0);
+ KWFrameView* frameView = kwView->frameViewManager()->view( frame );
+ Q_ASSERT( frameView );
+ MouseMeaning mouseMeaning = frameView->mouseMeaning( KoPoint( p ), keyState );
+ if ( mouseMeaning != MEANING_ACTIVATE_PART ) {
+ return 0;
+ }
+ }
+
+ return document()->hitTest( p, _matrix );
+}
+
+#include "KWPartFrameSet.moc"
diff --git a/kword/KWPartFrameSet.h b/kword/KWPartFrameSet.h
new file mode 100644
index 00000000..43150089
--- /dev/null
+++ b/kword/KWPartFrameSet.h
@@ -0,0 +1,169 @@
+/* This file is part of the KDE project
+ Copyright (C) 2002 David Faure <faure@kde.org>
+ Copyright (C) 2005 Thomas Zander <zander@kde.org>
+
+ This program is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License version 2, as published by the Free Software Foundation.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this program; see the file COPYING. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+*/
+
+#ifndef KWPARTFRAMESET_H
+#define KWPARTFRAMESET_H
+
+#include "KWFrameSet.h"
+class KWDocumentChild;
+class KWFramePartMoveCommand;
+/**
+ * @short A frameset that contains an embedded object (a KWDocumentChild)
+ */
+class KWPartFrameSet : public KWFrameSet
+{
+ Q_OBJECT
+public:
+ KWPartFrameSet( KWDocument *_doc, KWDocumentChild *_child, const QString & name );
+
+ /// Used for OASIS loading
+ KWPartFrameSet( KWDocument* doc, const QDomElement& frameTag,
+ const QDomElement& objectTag, KoOasisContext& context );
+
+ virtual ~KWPartFrameSet();
+
+ virtual KWordFrameSetIface* dcopObject();
+
+
+ /** The type of frameset. Use this to differentiate between different instantiations of
+ * the framesets. Each implementation will return a different frameType.
+ */
+ virtual FrameSetType type() const { return FT_PART; }
+
+ virtual KWFrameSetEdit * createFrameSetEdit( KWCanvas * );
+
+ KWDocumentChild *getChild() const { return m_child; }
+ void setChild( KWDocumentChild* child );
+
+ /**
+ * Update the geometry of m_child based on the geometry of the frame.
+ */
+ void updateChildGeometry();
+
+ virtual void drawFrameContents( KWFrame * frame, QPainter *painter, const QRect & fcrect,
+ const QColorGroup &cg, bool onlyChanged, bool resetChanged,
+ KWFrameSetEdit * edit, KWViewMode *viewMode );
+
+ virtual void createEmptyRegion( const QRect &crect, QRegion &emptyRegion, KWViewMode *viewMode );
+
+ virtual QDomElement save( QDomElement &parentElem, bool saveFrames = true );
+ virtual void load( QDomElement &attributes, bool loadFrames = true );
+ virtual void saveOasis( KoXmlWriter& writer, KoSavingContext& context, bool saveFrames ) const;
+
+
+ /**
+ * Called by KWView when the object is being edited (activated).
+ * Allows to store the initial position.
+ */
+ void startEditing();
+ /**
+ * Called by KWView when the object is not being edited anymore (deactivated).
+ * Allows to create a frame-move command if the frame was moved.
+ */
+ void endEditing();
+
+ /**
+ * Move the frame 'frameNum' to the given position and
+ * move the document child window with it
+ * This is called when the frame is anchored and the anchor moves (see KWAnchor).
+ */
+ virtual void moveFloatingFrame( int frameNum, const KoPoint &position );
+
+#ifndef NDEBUG
+ virtual void printDebug();
+#endif
+
+ /**
+ * Delete a frame from the set of frames this frameSet has.
+ * @param num The frameNumber to be removed.
+ * @param remove passing true means that there can not be an undo of the action.
+ * @param recalc do an updateFrames()
+ */
+ void deleteFrame( unsigned int num, bool remove = true, bool recalc = true );
+
+ void setDeleted( bool on = true );
+
+ virtual void storeInternal();
+
+ virtual void setProtectContent ( bool protect ) { m_protectContent = protect; }
+ virtual bool protectContent() const { return m_protectContent; }
+
+private slots:
+ void slotChildChanged();
+
+private:
+ KWDocumentChild *m_child;
+ KWFramePartMoveCommand *m_cmdMoveChild;
+ bool m_protectContent;
+};
+
+#if 0
+class KWPartFrameSetEdit : public QObject, public KWFrameSetEdit
+{
+ //Q_OBJECT
+public:
+ KWPartFrameSetEdit( KWPartFrameSet * fs, KWCanvas * canvas );
+ virtual ~KWPartFrameSetEdit();
+
+ virtual DCOPObject* dcopObject();
+
+
+ KWPartFrameSet * partFrameSet() const
+ {
+ return static_cast<KWPartFrameSet*>(frameSet());
+ }
+
+ // Events forwarded by the canvas (when being in "edit" mode)
+ //virtual void mousePressEvent( QMouseEvent *, const QPoint &, const KoPoint & );
+ //virtual void mouseDoubleClickEvent( QMouseEvent *, const QPoint &, const KoPoint & );
+//private slots:
+ void slotChildActivated(bool);
+private:
+ DCOPObject *m_dcop;
+};
+#endif
+
+#include <KoDocumentChild.h>
+class KWDocument;
+
+/******************************************************************/
+/* Class: KWDocumentChild */
+/******************************************************************/
+class KWDocumentChild : public KoDocumentChild
+{
+public:
+ KWDocumentChild( KWDocument *_wdoc, const QRect& _rect, KoDocument *_doc );
+ KWDocumentChild( KWDocument *_wdoc );
+ ~KWDocumentChild();
+
+ KWDocument* parent()const
+ { return m_pKWordDoc; }
+
+ virtual void setDocument( KoDocument *doc, const QRect &geometry );
+
+ void setPartFrameSet( KWPartFrameSet* fs ) { m_partFrameSet = fs; }
+ KWPartFrameSet * partFrameSet() const { return m_partFrameSet; }
+ virtual KoDocument* hitTest( const QPoint& p, const QWMatrix& _matrix = QWMatrix() );
+
+private:
+ KWDocument *m_pKWordDoc;
+ KWPartFrameSet *m_partFrameSet;
+};
+
+#endif // KWPARTFRAMESET_H
diff --git a/kword/KWPictureFrameSet.cpp b/kword/KWPictureFrameSet.cpp
new file mode 100644
index 00000000..dcaf69bf
--- /dev/null
+++ b/kword/KWPictureFrameSet.cpp
@@ -0,0 +1,258 @@
+/* This file is part of the KDE project
+ Copyright (C) 1998, 1999, 2000 Reginald Stadlbauer <reggie@kde.org>
+ Copyright (C) 2005 Thomas Zander <zander@kde.org>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+*/
+
+#include "KWPictureFrameSet.h"
+#include "KWDocument.h"
+#include "KWordPictureFrameSetIface.h"
+#include <KoStoreDevice.h>
+#include <KoOasisContext.h>
+#include <KoPictureCollection.h>
+#include <KoDom.h>
+#include <KoXmlNS.h>
+#include <KoXmlWriter.h>
+#include <klocale.h>
+#include <kdebug.h>
+
+//#define DEBUG_DRAW
+
+KWPictureFrameSet::KWPictureFrameSet( KWDocument *_doc, const QString & name )
+ : KWFrameSet( _doc ), m_keepAspectRatio( true ), m_finalSize( false )
+{
+ if ( name.isEmpty() )
+ m_name = _doc->generateFramesetName( i18n( "Picture %1" ) );
+ else
+ m_name = name;
+}
+
+KWPictureFrameSet::KWPictureFrameSet( KWDocument* doc, const QDomElement& frame, const QDomElement& imageTag, KoOasisContext& context )
+ : KWFrameSet( doc ), m_keepAspectRatio( true ), m_finalSize( false )
+{
+ m_name = frame.attributeNS( KoXmlNS::draw, "name", QString::null );
+ if ( doc->frameSetByName( m_name ) ) // already exists!
+ m_name = doc->generateFramesetName( m_name + " %1" );
+ loadOasis( frame, imageTag, context );
+}
+
+KWPictureFrameSet::~KWPictureFrameSet() {
+}
+
+KWordFrameSetIface* KWPictureFrameSet::dcopObject()
+{
+ if ( !m_dcop )
+ m_dcop = new KWordPictureFrameSetIface( this );
+
+ return m_dcop;
+}
+
+void KWPictureFrameSet::loadPicture( const QString & fileName )
+{
+ KoPictureCollection *collection = m_doc->pictureCollection();
+
+ m_picture = collection->loadPicture( fileName );
+}
+
+void KWPictureFrameSet::insertPicture( const KoPicture& picture )
+{
+ KoPictureCollection *collection = m_doc->pictureCollection();
+
+ m_picture = collection->insertPicture( picture.getKey(), picture );
+}
+
+void KWPictureFrameSet::reloadPicture( const KoPictureKey& key )
+{
+ KoPictureCollection *collection = m_doc->pictureCollection();
+ // If the picture is not already in the collection, then it gives a blank picture
+ m_picture = collection->insertPicture( key, KoPicture() );
+}
+
+QDomElement KWPictureFrameSet::save( QDomElement & parentElem, bool saveFrames )
+{
+ if ( m_frames.isEmpty() ) // Deleted frameset -> don't save
+ return QDomElement();
+ QDomElement framesetElem = parentElem.ownerDocument().createElement( "FRAMESET" );
+ parentElem.appendChild( framesetElem );
+
+ KWFrameSet::saveCommon( framesetElem, saveFrames );
+
+ QDomElement imageElem = parentElem.ownerDocument().createElement( "PICTURE" );
+ framesetElem.appendChild( imageElem );
+ imageElem.setAttribute( "keepAspectRatio", m_keepAspectRatio ? "true" : "false" );
+
+ QDomElement elem = parentElem.ownerDocument().createElement( "KEY" );
+ imageElem.appendChild( elem );
+ m_picture.getKey().saveAttributes( elem );
+ return framesetElem;
+}
+
+void KWPictureFrameSet::load( QDomElement &attributes, bool loadFrames )
+{
+ KWFrameSet::load( attributes, loadFrames );
+
+ QString defaultRatio="true";
+ // <PICTURE>
+ QDomNode node=attributes.namedItem( "PICTURE" );
+ if ( node.isNull() )
+ {
+ node=attributes.namedItem( "IMAGE" );
+ if ( node.isNull() )
+ {
+ node=attributes.namedItem( "CLIPART" );
+ defaultRatio="false";
+ }
+ }
+
+ QDomElement image = node.toElement();
+ if ( !image.isNull() ) {
+ m_keepAspectRatio = image.attribute( "keepAspectRatio", defaultRatio ) == "true";
+ // <KEY>
+ QDomElement keyElement = image.namedItem( "KEY" ).toElement();
+ if ( !keyElement.isNull() )
+ {
+ KoPictureKey key;
+ key.loadAttributes( keyElement );
+ m_picture.clear();
+ m_picture.setKey( key );
+ m_doc->addPictureRequest( this );
+ }
+ else
+ {
+ // <FILENAME> (old format, up to KWord-1.1-beta2)
+ QDomElement filenameElement = image.namedItem( "FILENAME" ).toElement();
+ if ( !filenameElement.isNull() )
+ {
+ QString filename = filenameElement.attribute( "value" );
+ m_picture.clear();
+ m_picture.setKey( KoPictureKey( filename ) );
+ m_doc->addPictureRequest( this );
+ }
+ else
+ {
+ kdError(32001) << "Missing KEY tag in IMAGE" << endl;
+ }
+ }
+ } else {
+ kdError(32001) << "Missing PICTURE/IMAGE/CLIPART tag in FRAMESET" << endl;
+ }
+}
+
+void KWPictureFrameSet::saveOasis( KoXmlWriter& writer, KoSavingContext& context, bool /*saveFrames*/ ) const
+{
+ if( m_frames.isEmpty() ) // Deleted frameset -> don't save
+ return;
+ KWFrame* frame = m_frames.getFirst();
+ frame->startOasisFrame( writer, context.mainStyles(), name() ); // draw:frame
+ writer.startElement( "draw:image" );
+ writer.addAttribute( "xlink:type", "simple" );
+ writer.addAttribute( "xlink:show", "embed" );
+ writer.addAttribute( "xlink:actuate", "onLoad" );
+ if ( context.savingMode() == KoSavingContext::Store )
+ writer.addAttribute( "xlink:href", m_doc->pictureCollection()->getOasisFileName(m_picture) );
+ else {
+ writer.startElement( "office:binary-data" );
+ m_picture.saveAsBase64( writer );
+ writer.endElement();
+ }
+ writer.endElement();
+
+ writer.endElement(); // draw:frame
+
+}
+
+void KWPictureFrameSet::loadOasis( const QDomElement& frame, const QDomElement& tag, KoOasisContext& context )
+{
+ kdDebug() << k_funcinfo << endl;
+ KoPictureKey key;
+ QDomNode binaryData = KoDom::namedItemNS( tag, KoXmlNS::office, "binary-data" );
+ if ( !binaryData.isNull() )
+ {
+ QCString data = binaryData.toElement().text().latin1();
+ m_picture.loadFromBase64( data );
+ key = KoPictureKey("nofile", QDateTime::currentDateTime(Qt::UTC));
+ m_picture.setKey(key);
+ }
+ else
+ {
+ const QString href( tag.attributeNS( KoXmlNS::xlink, "href", QString::null) );
+ if ( !href.isEmpty() /*&& href[0] == '#'*/ )
+ {
+ QString strExtension;
+ const int result=href.findRev(".");
+ if (result>=0)
+ {
+ strExtension=href.mid(result+1); // As we are using KoPicture, the extension should be without the dot.
+ }
+ QString filename(href/*.mid(1)*/);
+ key = KoPictureKey(filename, QDateTime::currentDateTime(Qt::UTC));
+ m_picture.setKey(key);
+
+ KoStore* store = context.store();
+ Q_ASSERT( store );
+ if ( store->open( filename ) )
+ {
+ KoStoreDevice dev(store);
+ if ( !m_picture.load( &dev, strExtension ) )
+ kdWarning(32001) << "Cannot load picture: " << filename << " " << href << endl;
+ store->close();
+ }
+ }
+ }
+
+ m_doc->pictureCollection()->insertPicture( key, m_picture );
+ context.styleStack().save();
+ context.fillStyleStack( frame, KoXmlNS::draw, "style-name", "graphic" ); // get the style for the graphics element
+ loadOasisFrame( frame, context );
+ context.styleStack().restore();
+}
+
+void KWPictureFrameSet::drawFrameContents( KWFrame *frame, QPainter *painter, const QRect &crect,
+ const QColorGroup &, bool, bool, KWFrameSetEdit *, KWViewMode * )
+{
+#ifdef DEBUG_DRAW
+ kdDebug(32001) << "KWPictureFrameSet::drawFrameContents crect=" << crect << " size=" << kWordDocument()->zoomItX( frame->innerWidth() ) << "x" << kWordDocument()->zoomItY( frame->innerHeight() ) << endl;
+#endif
+ m_picture.draw( *painter, 0, 0, kWordDocument()->zoomItX( frame->innerWidth() ), kWordDocument()->zoomItY( frame->innerHeight() ),
+ crect.x(), crect.y(), crect.width(), crect.height(), !m_finalSize);
+}
+
+FrameSetType KWPictureFrameSet::type() const
+{
+ return FT_PICTURE;
+}
+
+bool KWPictureFrameSet::keepAspectRatio() const
+{
+ return m_keepAspectRatio;
+}
+
+void KWPictureFrameSet::setKeepAspectRatio( bool b )
+{
+ m_keepAspectRatio = b;
+}
+
+#ifndef NDEBUG
+void KWPictureFrameSet::printDebug( KWFrame *frame )
+{
+ KWFrameSet::printDebug( frame );
+ if ( !isDeleted() )
+ {
+ kdDebug(32001) << "Image: key=" << m_picture.getKey().toString() << endl;
+ }
+}
+#endif
diff --git a/kword/KWPictureFrameSet.h b/kword/KWPictureFrameSet.h
new file mode 100644
index 00000000..e5bd58e1
--- /dev/null
+++ b/kword/KWPictureFrameSet.h
@@ -0,0 +1,96 @@
+/* This file is part of the KDE project
+ Copyright (C) 1998, 1999, 2000 Reginald Stadlbauer <reggie@kde.org>
+ Copyright (C) 2005 Thomas Zander <zander@kde.org>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+*/
+
+#ifndef frame_picture_frame_set_h
+#define frame_picture_frame_set_h
+
+#include "KWFrameSet.h"
+#include <KoPicture.h>
+
+class KWPictureFrameSet : public KWFrameSet
+{
+public:
+ KWPictureFrameSet( KWDocument *_doc, const QString & name );
+ /// Used for OASIS loading
+ KWPictureFrameSet( KWDocument* doc, const QDomElement& frame, const QDomElement& imageTag, KoOasisContext& context );
+ virtual ~KWPictureFrameSet();
+
+ virtual KWordFrameSetIface* dcopObject();
+
+ /**
+ * The type of frameset. Use this to differentiate between different instantiations of
+ * the framesets. Each implementation will return a different frameType.
+ */
+ virtual FrameSetType type() const;
+
+ void setPicture( const KoPicture &picture ) { m_picture = picture; }
+ KoPicture picture() const { return m_picture; }
+
+ KoPictureKey key() const { return m_picture.getKey(); }
+
+ void loadPicture( const QString &fileName );
+ void insertPicture( const KoPicture& picture );
+
+ /**
+ * Reload a picture, which already exists in the picture collection
+ * (if not, it gives a defaulft KoPicture() )
+ */
+ void reloadPicture( const KoPictureKey& key );
+
+ virtual QDomElement save( QDomElement &parentElem, bool saveFrames = true );
+ virtual void load( QDomElement &attributes, bool loadFrames = true );
+ virtual void saveOasis( KoXmlWriter& writer, KoSavingContext& context, bool saveFrames ) const;
+
+ virtual void drawFrameContents( KWFrame * frame, QPainter *painter, const QRect & crect,
+ const QColorGroup &cg, bool onlyChanged, bool resetChanged,
+ KWFrameSetEdit * edit, KWViewMode *viewMode );
+
+ /// Pixmaps can be transparent
+ virtual void createEmptyRegion( const QRect &, QRegion &, KWViewMode * ) { }
+
+#ifndef NDEBUG
+ virtual void printDebug( KWFrame* frame );
+#endif
+
+ bool keepAspectRatio() const;
+ void setKeepAspectRatio( bool b );
+
+ /**
+ * This method is part of the KWFrameSet API and is left empty here,
+ * protect content is irrelevant for picture frame sets.
+ */
+ virtual void setProtectContent ( bool ) { };
+ /**
+ * This method is part of the KWFrameSet API and is left empty here,
+ * protect content is irrelevant for picture frame sets.
+ */
+ virtual bool protectContent() const { return false; }
+
+protected:
+ void loadOasis( const QDomElement& frame, const QDomElement& imageTag, KoOasisContext& context );
+
+ /// The picture
+ KoPicture m_picture;
+ bool m_keepAspectRatio;
+ /// Cache the finalSize parameter of the method resizeFrame for drawFrame
+ bool m_finalSize;
+};
+
+#endif
diff --git a/kword/KWResizeTableDia.cpp b/kword/KWResizeTableDia.cpp
new file mode 100644
index 00000000..ab81d52b
--- /dev/null
+++ b/kword/KWResizeTableDia.cpp
@@ -0,0 +1,102 @@
+/* This file is part of the KDE project
+ Copyright (C) 2002 Montel Laurent <lmontel@mandrakesoft.com>
+ Copyright (C) 2005 Thomas Zander <zander@kde.org>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+*/
+
+#include "KWDocument.h"
+#include "KWResizeTableDia.h"
+#include "KWTableFrameSet.h"
+#include "KWCommand.h"
+
+#include <KoUnitWidgets.h>
+#include <klocale.h>
+#include <qlabel.h>
+#include <qvbox.h>
+
+KWResizeTableDia::KWResizeTableDia( QWidget *parent, KWTableFrameSet *table, KWDocument *doc, int resizeColumn )
+ : KDialogBase( parent, "resize column dialog" , true, "", Ok | Cancel | User1 | Apply )
+{
+ setButtonText( KDialogBase::User1, i18n("Reset") );
+ setCaption( i18n( "Resize Column" ) );
+
+ m_table = table;
+ m_doc = doc;
+
+ setupTab1(resizeColumn);
+}
+
+void KWResizeTableDia::setupTab1(int resizeColumn) {
+ QVBox *page = makeVBoxMainWidget();
+ QLabel *rc = new QLabel( i18n( "Column:" ), page );
+ rc->resize( rc->sizeHint() );
+ rc->setAlignment( AlignLeft | AlignBottom );
+ m_value = new QSpinBox( 1, m_table->getColumns(), 1, page );
+ m_value->resize( m_value->sizeHint() );
+ m_value->setValue( resizeColumn );
+
+ rc = new QLabel( i18n( "Width:" ), page );
+ m_position= new KoUnitDoubleSpinBox( page, 0.01, m_table->anchorFrameset()->isFloating() ? m_table->anchorFrameset()->frame(0)->width(): 9999, 1, 0.0, m_doc->unit(), m_doc->unit() );
+ slotValueChanged( m_value->value());
+ connect( m_value, SIGNAL( valueChanged ( int )), this, SLOT( slotValueChanged( int )));
+}
+
+bool KWResizeTableDia::doResize()
+{
+ unsigned int resize= m_value->value() - 1;
+ KWFrame *frm = m_table->cell( 0, resize )->frame(0);
+ if (frm) {
+ FrameIndex index( frm );
+ KoRect newRect( frm->normalize() );
+ newRect.setWidth( m_position->value() );
+ FrameResizeStruct resizeStruct( frm->normalize(), frm->minimumFrameHeight(), newRect );
+ KWFrameResizeCommand * cmd =new KWFrameResizeCommand( i18n("Resize Column"), index, resizeStruct );
+ cmd->execute();
+ m_doc->addCommand( cmd );
+ }
+ return true;
+}
+
+void KWResizeTableDia::slotValueChanged( int pos)
+{
+ KWFrame *frm = m_table->cell( 0, pos-1 )->frame(0);
+ if (frm) {
+ m_position->setValue( KoUnit::toUserValue( QMAX(0.00, frm->normalize().width()), m_doc->unit() ) );
+ m_resetValue = m_position->value();
+ }
+}
+
+void KWResizeTableDia::slotUser1()
+{
+ m_position->setValue( KoUnit::toUserValue(m_resetValue, m_doc->unit() ) );
+ doResize();
+}
+
+void KWResizeTableDia::slotApply()
+{
+ doResize();
+}
+
+void KWResizeTableDia::slotOk()
+{
+ if (doResize())
+ {
+ KDialogBase::slotOk();
+ }
+}
+
+#include "KWResizeTableDia.moc"
diff --git a/kword/KWResizeTableDia.h b/kword/KWResizeTableDia.h
new file mode 100644
index 00000000..162afb77
--- /dev/null
+++ b/kword/KWResizeTableDia.h
@@ -0,0 +1,65 @@
+/* This file is part of the KDE project
+ Copyright (C) 2002 Montel Laurent <lmontel@mandrakesoft.com>
+ Copyright (C) 2005 Thomas Zander <zander@kde.org>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+*/
+
+#ifndef resizetabledia_h
+#define resizetabledia_h
+
+#include <kdialogbase.h>
+
+class KWTableFrameSet;
+class KWDocument;
+class QWidget;
+class QSpinBox;
+class KoUnitDoubleSpinBox;
+
+/**
+ * A dialog that can be used to resize columns of a table using numeric input.
+ */
+class KWResizeTableDia : public KDialogBase
+{
+ Q_OBJECT
+public:
+ /**
+ * Constructor.
+ * @param parent parent widget for dialog
+ * @param table the table to do the resizes on
+ * @param doc the document this table belongs to, for undo information
+ * @param resizeColumn the initial column that the user can resize.
+ */
+ KWResizeTableDia( QWidget *parent, KWTableFrameSet *table, KWDocument *doc, int resizeColumn);
+
+protected:
+ void setupTab1( int resizeColumn);
+ bool doResize();
+ QSpinBox *m_value;
+ KWTableFrameSet *m_table;
+ KWDocument *m_doc;
+ KoUnitDoubleSpinBox *m_position;
+ double m_resetValue;
+protected slots:
+ virtual void slotOk();
+ virtual void slotApply();
+ virtual void slotUser1();
+ void slotValueChanged( int pos);
+};
+
+#endif
+
+
diff --git a/kword/KWSelectBookmarkDiaBase.ui b/kword/KWSelectBookmarkDiaBase.ui
new file mode 100644
index 00000000..71437a39
--- /dev/null
+++ b/kword/KWSelectBookmarkDiaBase.ui
@@ -0,0 +1,76 @@
+<!DOCTYPE UI><UI version="3.1" stdsetdef="1">
+<class>KWSelectBookmarkDiaBase</class>
+<widget class="QWidget">
+ <property name="name">
+ <cstring>KWSelectBookmarkDia</cstring>
+ </property>
+ <property name="geometry">
+ <rect>
+ <x>0</x>
+ <y>0</y>
+ <width>369</width>
+ <height>215</height>
+ </rect>
+ </property>
+ <property name="caption">
+ <string>Select Bookmark</string>
+ </property>
+ <hbox>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="QGroupBox">
+ <property name="name">
+ <cstring>bookmarksGroup</cstring>
+ </property>
+ <property name="title">
+ <string>Bookmarks</string>
+ </property>
+ <grid>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="QListBox" row="0" column="0" rowspan="3" colspan="1">
+ <property name="name">
+ <cstring>bookmarkList</cstring>
+ </property>
+ </widget>
+ <widget class="QPushButton" row="0" column="1">
+ <property name="name">
+ <cstring>buttonRename</cstring>
+ </property>
+ <property name="text">
+ <string>&amp;Rename...</string>
+ </property>
+ </widget>
+ <widget class="QPushButton" row="1" column="1">
+ <property name="name">
+ <cstring>buttonDelete</cstring>
+ </property>
+ <property name="text">
+ <string>&amp;Delete</string>
+ </property>
+ </widget>
+ <spacer row="2" column="1">
+ <property name="name">
+ <cstring>Spacer4</cstring>
+ </property>
+ <property name="orientation">
+ <enum>Vertical</enum>
+ </property>
+ <property name="sizeType">
+ <enum>Expanding</enum>
+ </property>
+ <property name="sizeHint">
+ <size>
+ <width>20</width>
+ <height>20</height>
+ </size>
+ </property>
+ </spacer>
+ </grid>
+ </widget>
+ </hbox>
+</widget>
+<layoutdefaults spacing="6" margin="11"/>
+</UI>
diff --git a/kword/KWSortDia.cpp b/kword/KWSortDia.cpp
new file mode 100644
index 00000000..fd254ebb
--- /dev/null
+++ b/kword/KWSortDia.cpp
@@ -0,0 +1,53 @@
+/* This file is part of the KDE project
+ Copyright (C) 2002 Montel Laurent <lmontel@mandrakesoft.com>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+*/
+
+
+
+#include "KWSortDia.h"
+#include <qlayout.h>
+#include <klocale.h>
+#include <qradiobutton.h>
+#include <qgroupbox.h>
+#include <qbuttongroup.h>
+#include <qvbox.h>
+
+KWSortDia::KWSortDia( QWidget *parent, const char* name )
+ : KDialogBase( parent, name,TRUE,i18n("Sort Text"),Ok|Cancel )
+{
+ QVBox *page = makeVBoxMainWidget();
+
+ QButtonGroup *grp = new QButtonGroup( 1, QGroupBox::Horizontal, i18n( "Sort" ),page );
+ grp->setRadioButtonExclusive( TRUE );
+ grp->layout();
+ m_increase = new QRadioButton( i18n("Increase"), grp );
+ m_decrease = new QRadioButton( i18n("Decrease"), grp );
+
+ grp->setRadioButtonExclusive( TRUE );
+ m_increase->setChecked( true );
+ resize( 200, 150 );
+ setFocus();
+}
+
+SortType KWSortDia::getSortType() const
+{
+ return m_increase->isChecked() ? KW_SORTINCREASE : KW_SORTDECREASE;
+}
+
+
+#include "KWSortDia.moc"
diff --git a/kword/KWSortDia.h b/kword/KWSortDia.h
new file mode 100644
index 00000000..be32df2f
--- /dev/null
+++ b/kword/KWSortDia.h
@@ -0,0 +1,38 @@
+/* This file is part of the KDE project
+ Copyright (C) 2002 Montel Laurent <lmontel@mandrakesoft.com>
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+*/
+
+#ifndef __sortdia__
+#define __sortdia__
+
+#include <kdialogbase.h>
+#include "defs.h"
+class QRadioButton;
+
+class KWSortDia : public KDialogBase
+{
+ Q_OBJECT
+public:
+ KWSortDia( QWidget *parent, const char* name );
+ SortType getSortType() const;
+
+private:
+ QRadioButton *m_increase;
+ QRadioButton *m_decrease;
+};
+
+#endif
diff --git a/kword/KWSplitCellDia.cpp b/kword/KWSplitCellDia.cpp
new file mode 100644
index 00000000..0a29d438
--- /dev/null
+++ b/kword/KWSplitCellDia.cpp
@@ -0,0 +1,97 @@
+/* This file is part of the KDE project
+ Copyright (C) 2001 Thomas Zander <zander@kde.org>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+*/
+
+#include "KWSplitCellDia.h"
+#include "KWSplitCellDia.moc"
+#include "KWTableDia.h"
+
+#include <qlayout.h>
+#include <qlabel.h>
+#include <qspinbox.h>
+
+#include <klocale.h>
+
+KWSplitCellDia::KWSplitCellDia( QWidget* parent, const char* name, unsigned int columns, unsigned int rows)
+ : KDialogBase( Plain, i18n("Split Cell"), Ok | Cancel, Ok, parent, name, true)
+{
+ m_cols = columns;
+ m_rows = rows;
+
+ setInitialSize( QSize(400, 300) );
+
+ QWidget *page = plainPage();
+ QGridLayout *grid = new QGridLayout( page, 4, 2, KDialog::marginHint(), KDialog::spacingHint() );
+
+ QLabel *lRows = new QLabel( i18n( "Number of rows:" ), page );
+ grid->addWidget( lRows, 0, 0 );
+
+ nRows = new QSpinBox( 1, 128, 1, page );
+ nRows->setValue( m_rows );
+ grid->addWidget( nRows, 1, 0 );
+
+ QLabel *lCols = new QLabel( i18n( "Number of columns:" ), page );
+ grid->addWidget( lCols, 2, 0 );
+
+ nCols = new QSpinBox( 1, 128, 1, page );
+ nCols->setValue( m_cols );
+ grid->addWidget( nCols, 3, 0 );
+
+ preview = new KWTablePreview( page, m_rows, m_cols );
+ preview->setBackgroundColor( white );
+ grid->addMultiCellWidget( preview, 0, 4, 1, 1 );
+
+ grid->addRowSpacing( 0, lRows->height() );
+ grid->addRowSpacing( 1, nRows->height() );
+ grid->addRowSpacing( 2, lCols->height() );
+ grid->addRowSpacing( 3, nCols->height() );
+ grid->addRowSpacing( 4, 150 - ( lRows->height() + nRows->height() + lCols->height() + nCols->height() ) );
+ grid->setRowStretch( 0, 0 );
+ grid->setRowStretch( 1, 0 );
+ grid->setRowStretch( 2, 0 );
+ grid->setRowStretch( 3, 0 );
+ grid->setRowStretch( 4, 1 );
+
+ grid->addColSpacing( 0, lRows->width() );
+ grid->addColSpacing( 0, nRows->width() );
+ grid->addColSpacing( 0, lCols->width() );
+ grid->addColSpacing( 0, nCols->width() );
+ grid->addColSpacing( 1, 150 );
+ grid->setColStretch( 0, 0 );
+ grid->setColStretch( 1, 1 );
+
+ grid->activate();
+ enableButtonOK( !(m_rows==1 && m_cols==1) );
+
+ connect( nRows, SIGNAL( valueChanged( int ) ), this, SLOT( rowsChanged( int ) ) );
+ connect( nCols, SIGNAL( valueChanged( int ) ), this, SLOT( colsChanged( int ) ) );
+ setFocus();
+}
+
+void KWSplitCellDia::rowsChanged( int rows ) {
+ m_rows=rows;
+ preview->setRows( m_rows );
+ enableButtonOK( !(m_rows==1 && m_cols==1) );
+}
+
+void KWSplitCellDia::colsChanged( int cols ) {
+ m_cols=cols;
+ preview->setCols( m_cols );
+ enableButtonOK( !(m_rows==1 && m_cols==1) );
+}
+
diff --git a/kword/KWSplitCellDia.h b/kword/KWSplitCellDia.h
new file mode 100644
index 00000000..6b373ef6
--- /dev/null
+++ b/kword/KWSplitCellDia.h
@@ -0,0 +1,56 @@
+/* This file is part of the KDE project
+ Copyright (C) 2001 Thomas Zander <zander@kde.org>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+*/
+
+#ifndef splitcelldia_h
+#define splitcelldia_h
+
+#include <kdialogbase.h>
+#include <qptrlist.h>
+
+#include "defs.h"
+
+class QGridLayout;
+class QLabel;
+class QCheckBox;
+class QSpinBox;
+class KWTablePreview;
+
+class KWSplitCellDia : public KDialogBase {
+ Q_OBJECT
+
+public:
+ KWSplitCellDia( QWidget *parent, const char *name, unsigned int numcols, unsigned int numrows);
+
+ unsigned int rows()const { return m_rows; }
+ unsigned int columns()const { return m_cols; }
+
+protected:
+ QSpinBox *nRows, *nCols;
+ KWTablePreview *preview;
+
+ unsigned int m_rows, m_cols;
+
+protected slots:
+ void rowsChanged( int );
+ void colsChanged( int );
+};
+
+#endif
+
+
diff --git a/kword/KWStartupWidget.cpp b/kword/KWStartupWidget.cpp
new file mode 100644
index 00000000..fe22f534
--- /dev/null
+++ b/kword/KWStartupWidget.cpp
@@ -0,0 +1,93 @@
+/* This file is part of the KOffice project
+ * Copyright (C) 2005 Thomas Zander <zander@kde.org>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; version 2.
+
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public License
+ * along with this library; see the file COPYING.LIB. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#include <KWStartupWidget.h>
+#include <KWStartupWidgetBase.h>
+#include <KWDocument.h>
+#include <KoPageLayoutSize.h>
+#include <KoPageLayoutColumns.h>
+
+#include <kdebug.h>
+#include <qpushbutton.h>
+#include <qcheckbox.h>
+#include <qlayout.h>
+
+KWStartupWidget::KWStartupWidget(QWidget *parent, KWDocument *doc, const KoColumns &columns)
+ : KWStartupWidgetBase(parent) {
+ m_columns = columns;
+ m_layout = KoPageLayout::standardLayout();
+ m_doc = doc;
+
+ setFocusProxy(m_createButton);
+
+ QVBoxLayout *lay = new QVBoxLayout(m_sizeTab, KDialog::marginHint());
+ m_sizeWidget = new KoPageLayoutSize(m_sizeTab, m_layout, m_doc->unit(), m_columns , true, true);
+ lay->addWidget(m_sizeWidget);
+
+ lay = new QVBoxLayout(m_columnsTab, KDialog::marginHint());
+ m_columnsWidget = new KoPageLayoutColumns(m_columnsTab, m_columns, m_doc->unit(), m_layout);
+ lay->addWidget(m_columnsWidget);
+
+ connect (m_columnsWidget, SIGNAL( propertyChange(KoColumns&)),
+ this, SLOT (columnsUpdated( KoColumns&)));
+
+ connect (m_sizeWidget, SIGNAL( propertyChange(KoPageLayout&)),
+ this, SLOT (sizeUpdated( KoPageLayout&)));
+
+ connect (m_createButton, SIGNAL( clicked() ), this, SLOT (buttonClicked()) );
+
+ connect (m_WpStyleCheckbox, SIGNAL(toggled(bool)), m_sizeWidget, SLOT(setEnableBorders(bool)));
+ connect (m_WpStyleCheckbox, SIGNAL(toggled(bool)), m_columnsWidget, SLOT(setEnableColumns(bool)));
+}
+
+void KWStartupWidget::sizeUpdated(KoPageLayout &layout) {
+ m_layout = layout;
+ m_columnsWidget->setLayout(layout);
+}
+
+void KWStartupWidget::columnsUpdated(KoColumns &columns) {
+ m_columns.columns = columns.columns;
+ m_columns.ptColumnSpacing = columns.ptColumnSpacing;
+ m_sizeWidget->setColumns(columns);
+}
+
+void KWStartupWidget::buttonClicked() {
+ if(m_WpStyleCheckbox->isChecked())
+ m_doc->initEmpty();
+ else {
+ m_doc->m_processingType = KWDocument::DTP;
+ m_doc->clear();
+ m_doc->loadDefaultFrameStyleTemplates();
+ m_doc->loadDefaultTableStyleTemplates();
+ m_doc->loadDefaultTableTemplates();
+
+ }
+ KoKWHeaderFooter hf;
+ hf.header = HF_SAME;
+ hf.footer = HF_SAME;
+ hf.ptHeaderBodySpacing = 10.0;
+ hf.ptFooterBodySpacing = 10.0;
+ hf.ptFootNoteBodySpacing = 10.0;
+ m_doc->setPageLayout( m_layout, m_columns, hf, false );
+ m_doc->delayedRecalcFrames(1);
+ m_doc->setUnit(m_sizeWidget->unit());
+
+ emit documentSelected();
+}
+
+#include "KWStartupWidget.moc"
diff --git a/kword/KWStartupWidget.h b/kword/KWStartupWidget.h
new file mode 100644
index 00000000..534d3084
--- /dev/null
+++ b/kword/KWStartupWidget.h
@@ -0,0 +1,62 @@
+/* This file is part of the KOffice project
+ * Copyright (C) 2005 Thomas Zander <zander@kde.org>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; version 2.
+
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public License
+ * along with this library; see the file COPYING.LIB. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ */
+#ifndef kw_startup_widget_h
+#define kw_startup_widget_h
+
+#include <KWStartupWidgetBase.h>
+#include <KoPageLayout.h>
+
+class KoPageLayoutSize;
+class KoPageLayoutColumns;
+class KWDocument;
+
+/**
+ * The 'Custom Document' widget in the KWord startup widget.
+ * This class embeds the page size/columns tabs to allow the user to select the document
+ * markup for his new empty document.
+ */
+class KWStartupWidget : public KWStartupWidgetBase {
+ Q_OBJECT
+public:
+ /**
+ * Constructor. Please note that this class is being used/created by KWDocument.
+ * @param parent the parent widget
+ * @param doc the document that wants to be altered
+ * @param columns the suggested columns to be shown initially
+ */
+ KWStartupWidget(QWidget *parent, KWDocument *doc, const KoColumns &columns);
+
+private slots:
+ void sizeUpdated(KoPageLayout &layout);
+ void columnsUpdated(KoColumns &columns);
+ void buttonClicked();
+
+signals:
+ /// this signal is emitted (as defined by KoDocument) the moment the document is 'ready'
+ void documentSelected();
+
+private:
+ KoPageLayoutSize *m_sizeWidget;
+ KoPageLayoutColumns *m_columnsWidget;
+
+ KoPageLayout m_layout;
+ KoColumns m_columns;
+ KWDocument *m_doc;
+};
+
+#endif
diff --git a/kword/KWStartupWidgetBase.ui b/kword/KWStartupWidgetBase.ui
new file mode 100644
index 00000000..9dd70d30
--- /dev/null
+++ b/kword/KWStartupWidgetBase.ui
@@ -0,0 +1,103 @@
+<!DOCTYPE UI><UI version="3.3" stdsetdef="1">
+<class>KWStartupWidgetBase</class>
+<widget class="QWidget">
+ <property name="name">
+ <cstring>KWStartupWidgetBase</cstring>
+ </property>
+ <property name="geometry">
+ <rect>
+ <x>0</x>
+ <y>0</y>
+ <width>367</width>
+ <height>280</height>
+ </rect>
+ </property>
+ <grid>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <property name="margin">
+ <number>0</number>
+ </property>
+ <widget class="QCheckBox" row="0" column="0" rowspan="1" colspan="2">
+ <property name="name">
+ <cstring>m_WpStyleCheckbox</cstring>
+ </property>
+ <property name="text">
+ <string>Provide main text area</string>
+ </property>
+ <property name="checked">
+ <bool>true</bool>
+ </property>
+ <property name="whatsThis" stdset="0">
+ <string>&lt;p&gt;&lt;b&gt;Check this option to have a text area created automatically for each page.&lt;/b&gt;&lt;br&gt;
+For letters and notes with one main text, possibly on several pages, you should keep this checked. You should only uncheck it if you want to define completely where each text frame should be positioned.&lt;/p&gt;</string>
+ </property>
+ </widget>
+ <widget class="QTabWidget" row="1" column="0" rowspan="1" colspan="2">
+ <property name="name">
+ <cstring>tabs</cstring>
+ </property>
+ <widget class="QWidget">
+ <property name="name">
+ <cstring>m_sizeTab</cstring>
+ </property>
+ <attribute name="title">
+ <string>Page Size &amp;&amp; Margins</string>
+ </attribute>
+ </widget>
+ <widget class="QWidget">
+ <property name="name">
+ <cstring>m_columnsTab</cstring>
+ </property>
+ <attribute name="title">
+ <string>Columns</string>
+ </attribute>
+ </widget>
+ </widget>
+ <spacer row="2" column="0">
+ <property name="name">
+ <cstring>spacer1</cstring>
+ </property>
+ <property name="orientation">
+ <enum>Horizontal</enum>
+ </property>
+ <property name="sizeType">
+ <enum>Expanding</enum>
+ </property>
+ <property name="sizeHint">
+ <size>
+ <width>20</width>
+ <height>20</height>
+ </size>
+ </property>
+ </spacer>
+ <widget class="QPushButton" row="2" column="1">
+ <property name="name">
+ <cstring>m_createButton</cstring>
+ </property>
+ <property name="text">
+ <string>Create</string>
+ </property>
+ </widget>
+ <spacer row="3" column="0" rowspan="1" colspan="2">
+ <property name="name">
+ <cstring>spacer3</cstring>
+ </property>
+ <property name="orientation">
+ <enum>Vertical</enum>
+ </property>
+ <property name="sizeType">
+ <enum>Expanding</enum>
+ </property>
+ <property name="sizeHint">
+ <size>
+ <width>20</width>
+ <height>20</height>
+ </size>
+ </property>
+ </spacer>
+ </grid>
+</widget>
+<layoutdefaults spacing="6" margin="11"/>
+</UI>
diff --git a/kword/KWStatisticsDialog.cpp b/kword/KWStatisticsDialog.cpp
new file mode 100644
index 00000000..d323992d
--- /dev/null
+++ b/kword/KWStatisticsDialog.cpp
@@ -0,0 +1,354 @@
+/* This file is part of the KOffice project
+ * Copyright (C) 2005 Thomas Zander <zander@kde.org>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; version 2.
+
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public License
+ * along with this library; see the file COPYING.LIB. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#include "KWStatisticsDialog.h"
+#include "KWDocument.h"
+#include "KWFrameSet.h"
+#include <klocale.h>
+#include <qtabwidget.h>
+#include <qvbox.h>
+#include <qlabel.h>
+#include <qlayout.h>
+#include <qprogressdialog.h>
+#include <qcheckbox.h>
+
+KWStatisticsDialog::KWStatisticsDialog( QWidget *parent, KWDocument *document )
+ : KDialogBase(parent, "statistics", true, i18n("Statistics"),KDialogBase::Ok, KDialogBase::Ok, false )
+{
+ QWidget *page = new QWidget( this );
+ setMainWidget(page);
+ QVBoxLayout *topLayout = new QVBoxLayout( page, 0, KDialog::spacingHint() );
+
+ QTabWidget *tab = new QTabWidget( page );
+ QFrame *pageAll = 0;
+ QFrame *pageGeneral = 0;
+ QFrame *pageSelected = 0;
+ for (int i=0; i < 7; ++i) {
+ m_resultLabelAll[i] = 0;
+ m_resultLabelSelected[i] = 0;
+ if ( i < 6 )
+ m_resultGeneralLabel[i]=0;
+ }
+ m_doc = document;
+ m_parent = parent;
+ m_canceled = true;
+
+
+ // add Tab "General"
+ pageGeneral = new QFrame( this );
+ tab->addTab( pageGeneral, i18n( "General" ) );
+
+ addBoxGeneral( pageGeneral, m_resultGeneralLabel );
+ calcGeneral( m_resultGeneralLabel );
+
+ // add Tab "All"
+ pageAll = new QFrame( this );
+ tab->addTab( pageAll, i18n( "Text" ) );
+
+ addBox( pageAll, m_resultLabelAll, true );
+
+ m_canceled = true;
+ pageSelected = new QFrame( this );
+ tab->addTab( pageSelected, i18n( "Selected Text" ) );
+ // let's see if there's selected text
+ bool b = docHasSelection();
+ tab->setTabEnabled(pageSelected, b);
+ if ( b ) {
+ addBox( pageSelected, m_resultLabelSelected, false);
+ // assign results to 'selected' tab.
+ if ( !calcStats( m_resultLabelSelected, true,true ) )
+ return;
+ if ( !calcStats( m_resultLabelAll, false,false ) )
+ return;
+ showPage( 2 );
+ } else {
+ // assign results
+ if ( !calcStats( m_resultLabelAll, false, false ) )
+ return;
+ showPage( 1 );
+ }
+ topLayout->addWidget( tab );
+ m_canceled = false;
+
+}
+
+void KWStatisticsDialog::slotRefreshValue(bool state)
+{
+ m_canceled = true;
+ // let's see if there's selected text
+ bool b = docHasSelection();
+ if ( b )
+ {
+ if ( !calcStats( m_resultLabelSelected, true, true ) )
+ return;
+ if ( !calcStats( m_resultLabelAll, false, state ) )
+ return;
+ }
+ else
+ {
+ // assign results
+ if ( !calcStats( m_resultLabelAll, false, state ) )
+ return;
+ }
+ m_canceled = false;
+}
+
+void KWStatisticsDialog::calcGeneral( QLabel **resultLabel )
+{
+ KLocale *locale = KGlobal::locale();
+
+ resultLabel[0]->setText( locale->formatNumber( m_doc->pageCount(), 0) );
+ int table =0;
+ int picture = 0;
+ int part = 0;
+ int nbFrameset = 0;
+ int nbFormula = 0;
+ QPtrListIterator<KWFrameSet> framesetIt( m_doc->framesetsIterator() );
+ for ( framesetIt.toFirst(); framesetIt.current(); ++framesetIt ) {
+ KWFrameSet *frameSet = framesetIt.current();
+ if ( frameSet && frameSet->isVisible())
+ {
+ if ( frameSet->type() == FT_TABLE)
+ table++;
+ else if ( frameSet->type() == FT_PICTURE)
+ picture++;
+ else if ( frameSet->type() == FT_PART )
+ part++;
+ else if ( frameSet->type() == FT_FORMULA )
+ nbFormula++;
+ nbFrameset++;
+ }
+ }
+
+ resultLabel[1]->setText( locale->formatNumber( nbFrameset, 0 ) );
+ resultLabel[2]->setText( locale->formatNumber( picture, 0 ) );
+ resultLabel[3]->setText( locale->formatNumber( table, 0 ) );
+ resultLabel[4]->setText( locale->formatNumber( part, 0 ) );
+ resultLabel[5]->setText( locale->formatNumber( nbFormula, 0 ) );
+}
+
+bool KWStatisticsDialog::calcStats( QLabel **resultLabel, bool selection, bool useFootEndNote )
+{
+ ulong charsWithSpace = 0L;
+ ulong charsWithoutSpace = 0L;
+ ulong words = 0L;
+ ulong sentences = 0L;
+ ulong lines = 0L;
+ ulong syllables = 0L;
+
+ // safety check result labels
+ for (int i=0; i < 7; ++i) {
+ if ( !resultLabel[i] ) {
+ kdDebug() << "Warning: KWStatisticsDiaolog::calcStats result table not initialized." << endl;
+ return false;
+ }
+ }
+
+ // count paragraphs for progress dialog:
+ ulong paragraphs = 0L;
+ QPtrListIterator<KWFrameSet> framesetIt( m_doc->framesetsIterator() );
+ for ( framesetIt.toFirst(); framesetIt.current(); ++framesetIt ) {
+ KWFrameSet *frameSet = framesetIt.current();
+ if ( (frameSet->frameSetInfo() == KWFrameSet::FI_FOOTNOTE || frameSet->frameSetInfo() == KWFrameSet::FI_BODY) && frameSet->isVisible() )
+ {
+ if ( (useFootEndNote && frameSet->frameSetInfo() == KWFrameSet::FI_FOOTNOTE) ||
+ frameSet->frameSetInfo() == KWFrameSet::FI_BODY ) {
+ paragraphs += frameSet->paragraphs();
+ }
+ }
+ }
+ QProgressDialog progress( i18n( "Counting..." ), i18n( "Cancel" ), paragraphs, this, "count", true );
+ progress.setMinimumDuration( 1000 );
+ progress.setProgress( 0 );
+
+ // do the actual counting
+ for ( framesetIt.toFirst(); framesetIt.current(); ++framesetIt ) {
+ KWFrameSet *frameSet = framesetIt.current();
+ // Exclude headers and footers
+ if ( (frameSet->frameSetInfo() == KWFrameSet::FI_FOOTNOTE || frameSet->frameSetInfo() == KWFrameSet::FI_BODY) && frameSet->isVisible() ) {
+ if ( (useFootEndNote && frameSet->frameSetInfo() == KWFrameSet::FI_FOOTNOTE) || frameSet->frameSetInfo() == KWFrameSet::FI_BODY )
+ {
+
+ if( ! frameSet->statistics( &progress, charsWithSpace, charsWithoutSpace,
+ words, sentences, syllables, lines, selection ) ) {
+ // someone pressed "Cancel"
+ return false;
+ }
+ }
+ }
+ }
+
+ // assign results
+ KLocale *locale = KGlobal::locale();
+ resultLabel[0]->setText( locale->formatNumber( charsWithSpace, 0) );
+ resultLabel[1]->setText( locale->formatNumber( charsWithoutSpace, 0 ) );
+ resultLabel[2]->setText( locale->formatNumber( syllables, 0 ) );
+ resultLabel[3]->setText( locale->formatNumber( words, 0 ) );
+ resultLabel[4]->setText( locale->formatNumber( sentences, 0 ) );
+ resultLabel[5]->setText( locale->formatNumber( lines, 0 ) );
+ // add flesch
+ double f = calcFlesch( sentences, words, syllables );
+ QString flesch = locale->formatNumber( f , 1 );
+ if( words < 200 ) {
+ // a kind of warning if too few words:
+ flesch = i18n("approximately %1").arg( flesch );
+ }
+ resultLabel[6]->setText( flesch );
+ return true;
+}
+
+double KWStatisticsDialog::calcFlesch( ulong sentences, ulong words, ulong syllables )
+{
+ // calculate Flesch reading ease score:
+ float flesch_score = 0;
+ if( words > 0 && sentences > 0 )
+ flesch_score = 206.835 - (1.015 * (words / sentences)) - (84.6 * syllables / words);
+ return flesch_score;
+}
+
+void KWStatisticsDialog::addBoxGeneral( QFrame *page, QLabel **resultLabel )
+{
+ // Layout Managers
+ QVBoxLayout *topLayout = new QVBoxLayout( page, 0, 7 );
+ QGroupBox *box = new QGroupBox( i18n( "Statistics" ), page );
+ QGridLayout *grid = new QGridLayout( box, 9, 3, KDialog::marginHint(), KDialog::spacingHint() );
+ grid->setRowStretch (9, 1);
+ // margins
+ int fHeight = box->fontMetrics().height();
+ grid->setMargin( fHeight );
+ grid->addColSpacing( 1, fHeight );
+ grid->addRowSpacing( 0, fHeight );
+
+ // insert labels
+ QLabel *label1 = new QLabel( i18n( "Number of pages:" ), box );
+ grid->addWidget( label1, 1, 0, 1 );
+ resultLabel[0] = new QLabel( "", box );
+ grid->addWidget( resultLabel[0], 1, 2, 2 );
+
+ QLabel *label2 = new QLabel( i18n( "Number of frames:" ), box );
+ grid->addWidget( label2, 2, 0, 1 );
+ resultLabel[1] = new QLabel( "", box );
+ grid->addWidget( resultLabel[1], 2, 2, 2 );
+
+ QLabel *label3 = new QLabel( i18n( "Number of pictures:" ), box );
+ grid->addWidget( label3, 3, 0, 1 );
+ resultLabel[2] = new QLabel( "", box );
+ grid->addWidget( resultLabel[2], 3, 2, 2 );
+
+
+ QLabel *label4 = new QLabel( i18n( "Number of tables:" ), box );
+ grid->addWidget( label4, 4, 0, 1 );
+ resultLabel[3] = new QLabel( "", box );
+ grid->addWidget( resultLabel[3], 4, 2, 2 );
+
+ QLabel *label5 = new QLabel( i18n( "Number of embedded objects:" ), box );
+ grid->addWidget( label5, 5, 0, 1 );
+ resultLabel[4] = new QLabel( "", box );
+ grid->addWidget( resultLabel[4], 5, 2, 2 );
+
+ QLabel *label6 = new QLabel( i18n( "Number of formula frameset:" ), box );
+ grid->addWidget( label6, 6, 0, 1 );
+ resultLabel[5] = new QLabel( "", box );
+ grid->addWidget( resultLabel[5], 6, 2, 2 );
+
+ topLayout->addWidget( box );
+}
+
+void KWStatisticsDialog::addBox( QFrame *page, QLabel **resultLabel, bool calcWithFootNoteCheckbox )
+{
+ // Layout Managers
+ QVBoxLayout *topLayout = new QVBoxLayout( page, 0, 7 );
+ if ( calcWithFootNoteCheckbox )
+ {
+ QWidget *w = new QWidget(page);
+ topLayout->addWidget( w );
+ QVBoxLayout *noteLayout = new QVBoxLayout( w, KDialog::marginHint(), 0 );
+ QCheckBox *calcWithFootNote = new QCheckBox( i18n("&Include text from foot- and endnotes"), w);
+ noteLayout->addWidget( calcWithFootNote );
+ connect( calcWithFootNote, SIGNAL(toggled ( bool )), this, SLOT( slotRefreshValue(bool)));
+ }
+
+
+ QGroupBox *box = new QGroupBox( i18n( "Statistics" ), page );
+ QGridLayout *grid = new QGridLayout( box, 9, 3, KDialog::marginHint(), KDialog::spacingHint() );
+ grid->setRowStretch (9, 1);
+
+ // margins
+ int fHeight = box->fontMetrics().height();
+ grid->setMargin( fHeight );
+ grid->addColSpacing( 1, fHeight );
+ grid->addRowSpacing( 0, fHeight );
+
+ //maximum size for result column (don't know how to do this better..)
+ QString init = i18n("approximately %1").arg( "00000000" );
+
+ // insert labels
+ QLabel *label1 = new QLabel( i18n( "Characters including spaces:" ), box );
+ grid->addWidget( label1, 1, 0, 1 );
+ resultLabel[0] = new QLabel( "", box );
+ grid->addWidget( resultLabel[0], 1, 2, 2 );
+
+ QLabel *label2 = new QLabel( i18n( "Characters without spaces:" ), box );
+ grid->addWidget( label2, 2, 0, 1 );
+ resultLabel[1] = new QLabel( "", box );
+ grid->addWidget( resultLabel[1], 2, 2, 2 );
+
+ QLabel *label3 = new QLabel( i18n( "Syllables:" ), box );
+ grid->addWidget( label3, 3, 0, 1 );
+ resultLabel[2] = new QLabel( "", box );
+ grid->addWidget( resultLabel[2], 3, 2, 2 );
+
+ QLabel *label4 = new QLabel( i18n( "Words:" ), box );
+ grid->addWidget( label4, 4, 0, 1 );
+ resultLabel[3] = new QLabel( "", box );
+ grid->addWidget( resultLabel[3], 4, 2, 2 );
+
+ QLabel *label5 = new QLabel( i18n( "Sentences:" ), box );
+ grid->addWidget( label5, 5, 0, 1 );
+ resultLabel[4] = new QLabel( "", box );
+ grid->addWidget( resultLabel[4], 5, 2, 2 );
+
+ QLabel *label6 = new QLabel( i18n( "Lines:" ), box );
+ grid->addWidget( label6, 6, 0, 1 );
+ resultLabel[5] = new QLabel( "", box );
+ grid->addWidget( resultLabel[5], 6, 2, 2 );
+
+
+ QLabel *label7 = new QLabel( i18n( "Flesch reading ease:" ), box );
+ grid->addWidget( label7, 7, 0, 1 );
+ resultLabel[6] = new QLabel( init, box );
+ grid->addWidget( resultLabel[6], 7, 2, 2 );
+
+ topLayout->addWidget( box );
+}
+
+bool KWStatisticsDialog::docHasSelection()const
+{
+ QPtrListIterator<KWFrameSet> fsIt( m_doc->framesetsIterator() );
+
+ for ( ; fsIt.current(); ++fsIt ) {
+ KWFrameSet *fs = fsIt.current();
+ if ( fs->paragraphsSelected() ) {
+ return true;
+ }
+ }
+ return false;
+}
+
+#include "KWStatisticsDialog.moc"
+
diff --git a/kword/KWStatisticsDialog.h b/kword/KWStatisticsDialog.h
new file mode 100644
index 00000000..54fc1b62
--- /dev/null
+++ b/kword/KWStatisticsDialog.h
@@ -0,0 +1,61 @@
+/* This file is part of the KOffice project
+ * Copyright (C) 2005 Thomas Zander <zander@kde.org>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; version 2.
+
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public License
+ * along with this library; see the file COPYING.LIB. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#ifndef kwstatistics_h
+#define kwstatistics_h
+
+class KWFrameSet;
+class KWDocument;
+class QVBoxLayout;
+class QTabWidget;
+class QLabel;
+
+#include <defs.h>
+#include <kdialogbase.h>
+
+/**
+ * A class that calculates and show the statistics for a certain KWDocument
+ */
+class KWStatisticsDialog : public KDialogBase
+{
+ Q_OBJECT
+
+public:
+ KWStatisticsDialog( QWidget *parent, KWDocument *doc );
+ bool wasCanceled()const { return m_canceled; }
+
+private:
+ KWDocument *m_doc;
+ QWidget *m_parent;
+ bool m_canceled;
+ QLabel *m_resultLabelAll[7];
+ QLabel *m_resultLabelSelected[7];
+ QLabel *m_resultGeneralLabel[6];
+
+ void addBox( QFrame *page, QLabel **resultLabel, bool calcWithFootNoteCheckbox );
+ void addBoxGeneral( QFrame *page, QLabel **resultLabel );
+
+ bool calcStats( QLabel **resultLabel, bool selection, bool useFootEndNote );
+ void calcGeneral( QLabel **resultLabel );
+ bool docHasSelection()const;
+ double calcFlesch(ulong sentences, ulong words, ulong syllables);
+private slots:
+ void slotRefreshValue(bool);
+};
+
+#endif
diff --git a/kword/KWStyleManager.cpp b/kword/KWStyleManager.cpp
new file mode 100644
index 00000000..a8126627
--- /dev/null
+++ b/kword/KWStyleManager.cpp
@@ -0,0 +1,68 @@
+/* This file is part of the KDE project
+ Copyright (C) 1998, 1999 Reginald Stadlbauer <reggie@kde.org>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+*/
+
+#include "KWDocument.h"
+#include "KWStyleManager.h"
+#include "KWStyleManager.moc"
+
+#include <KoUnit.h>
+#include <KoStyleCollection.h>
+#include <kdebug.h>
+/******************************************************************/
+/* Class: KWStyleManager */
+/******************************************************************/
+
+KWStyleManager::KWStyleManager( QWidget *_parent, KoUnit::Unit unit,
+ KWDocument *_doc, const KoStyleCollection & styles,
+ const QString & activeStyleName)
+ : KoStyleManager( _parent, unit,
+ styles, activeStyleName,
+ ShowIncludeInToc )
+{
+ m_doc = _doc;
+}
+
+KoParagStyle* KWStyleManager::addStyleTemplate(KoParagStyle *style)
+{
+ m_doc->setModified( true);
+ return m_doc->styleCollection()->addStyle(style);
+}
+
+void KWStyleManager::applyStyleChange( KoStyleChangeDefMap changed )
+{
+ m_doc->applyStyleChange( changed );
+}
+
+void KWStyleManager::removeStyleTemplate( KoParagStyle *style )
+{
+ m_doc->setModified( true);
+ m_doc->styleCollection()->removeStyle(style);
+}
+
+void KWStyleManager::updateAllStyleLists()
+{
+ m_doc->updateAllStyleLists();
+}
+
+void KWStyleManager::updateStyleListOrder( const QStringList & list)
+{
+ m_doc->styleCollection()->updateStyleListOrder( list );
+}
+
+
diff --git a/kword/KWStyleManager.h b/kword/KWStyleManager.h
new file mode 100644
index 00000000..e8712cfa
--- /dev/null
+++ b/kword/KWStyleManager.h
@@ -0,0 +1,49 @@
+/* This file is part of the KDE project
+ Copyright (C) 1998, 1999 Reginald Stadlbauer <reggie@kde.org>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+*/
+
+#ifndef KWSTYLEMANAGER_H
+#define KWSTYLEMANAGER_H
+
+#include <KoStyleManager.h>
+
+class KWDocument;
+class KoParagStyle;
+class KoUnit;
+/******************************************************************/
+/* Class: KWStyleManager */
+/******************************************************************/
+class KWStyleManager : public KoStyleManager
+{
+ Q_OBJECT
+
+public:
+ KWStyleManager( QWidget *_parent, KoUnit::Unit unit, KWDocument *_doc,
+ const KoStyleCollection& styleCollection,
+ const QString & activeStyleName = QString::null );
+
+ virtual KoParagStyle* addStyleTemplate(KoParagStyle *style);
+ virtual void applyStyleChange( KoStyleChangeDefMap changed );
+ virtual void removeStyleTemplate( KoParagStyle *style );
+ virtual void updateAllStyleLists();
+ virtual void updateStyleListOrder( const QStringList & list);
+protected:
+ KWDocument *m_doc;
+};
+
+#endif
diff --git a/kword/KWTableDia.cpp b/kword/KWTableDia.cpp
new file mode 100644
index 00000000..28df4ca8
--- /dev/null
+++ b/kword/KWTableDia.cpp
@@ -0,0 +1,366 @@
+/* This file is part of the KDE project
+ Copyright (C) 1998, 1999 Reginald Stadlbauer <reggie@kde.org>
+ Copyright (C) 2005 Thomas Zander <zander@kde.org>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+*/
+
+#include "KWCanvas.h"
+#include "KWTableDia.h"
+#include "KWTableDia.moc"
+
+#include "KWTableTemplateSelector.h"
+#include "KWCommand.h"
+#include "KWDocument.h"
+#include "KWTableFrameSet.h"
+#include "KWTableTemplate.h"
+#include "KWPageManager.h"
+#include "KWPage.h"
+#include <kcommand.h>
+
+#include <qlabel.h>
+#include <qlayout.h>
+#include <qspinbox.h>
+#include <qcheckbox.h>
+#include <qbuttongroup.h>
+#include <qcombobox.h>
+
+#include <klocale.h>
+
+#include <stdlib.h>
+
+
+/******************************************************************/
+/* Class: KWTablePreview */
+/******************************************************************/
+
+void KWTablePreview::paintEvent( QPaintEvent * )
+{
+ int wid = ( width() - 10 ) / cols;
+ int hei = ( height() - 10 ) / rows;
+
+ QPainter p;
+ p.begin( this );
+
+ p.setPen( QPen( black ) );
+
+ for ( int i = 0; i < rows; i++ )
+ {
+ for ( int j = 0; j < cols; j++ )
+ p.drawRect( j * wid + 5, i * hei + 5, wid + 1, hei + 1 );
+ }
+
+ p.end();
+}
+
+/******************************************************************/
+/* Class: KWTableDia */
+/******************************************************************/
+
+KWTableDia::KWTableDia( QWidget* parent, const char* name, UseMode _useMode, KWCanvas *_canvas, KWDocument *_doc,
+ int rows, int cols, CellSize wid, CellSize hei, bool floating , const QString & _templateName, int format)
+ : KDialogBase( Tabbed, i18n("Table Settings"), Ok | Cancel, Ok, parent, name, true)
+{
+ m_useMode = _useMode;
+ canvas = _canvas;
+ doc = _doc;
+
+ setupTab1( rows, cols, wid, hei, floating );
+ setupTab2( _templateName,format );
+
+ setInitialSize( QSize(500, 480) );
+
+ oldRowCount = rows;
+ oldColCount = cols;
+ oldTemplateName = _templateName;
+#ifdef ALLOW_NON_INLINE_TABLES
+ if ( m_useMode==NEW )
+ {
+ slotInlineTable( cbIsFloating->isChecked());
+ }
+#endif
+}
+
+void KWTableDia::setupTab1( int rows, int cols, CellSize wid, CellSize hei, bool floating )
+{
+ tab1 = addPage( i18n( "Geometry" ) );
+
+ QGridLayout *grid = new QGridLayout( tab1, 9, 2, 0, KDialog::spacingHint() );
+
+ lRows = new QLabel( i18n( "Number of rows:" ), tab1 );
+ grid->addWidget( lRows, 0, 0 );
+
+ nRows = new QSpinBox( 1, 128, 1, tab1 );
+ nRows->setValue( rows );
+ grid->addWidget( nRows, 1, 0 );
+
+ lCols = new QLabel( i18n( "Number of columns:" ), tab1 );
+ grid->addWidget( lCols, 2, 0 );
+
+ nCols = new QSpinBox( 1, 128, 1, tab1 );
+ nCols->setValue( cols );
+ grid->addWidget( nCols, 3, 0 );
+
+#ifdef ALLOW_NON_INLINE_TABLES
+ if ( m_useMode==NEW )
+ {
+ lHei = new QLabel( i18n( "Cell heights:" ), tab1 );
+ grid->addWidget( lHei, 4, 0 );
+
+ cHei = new QComboBox( FALSE, tab1 );
+ cHei->insertItem( i18n( "Automatic" ) );
+ cHei->insertItem( i18n( "Manual" ) );
+ cHei->setCurrentItem( (int)hei );
+ grid->addWidget( cHei, 5, 0 );
+
+ lWid = new QLabel( i18n( "Cell widths:" ), tab1 );
+ grid->addWidget( lWid, 6, 0 );
+
+ cWid = new QComboBox( FALSE, tab1 );
+ cWid->insertItem( i18n( "Automatic" ) );
+ cWid->insertItem( i18n( "Manual" ) );
+ cWid->setCurrentItem( (int)wid );
+ grid->addWidget( cWid, 7, 0 );
+ }
+#else
+ Q_UNUSED( wid );
+ Q_UNUSED( hei );
+ Q_UNUSED( floating );
+#endif
+
+ preview = new KWTablePreview( tab1, rows, cols );
+ preview->setBackgroundColor( white );
+ grid->addMultiCellWidget( preview, 0, 8, 1, 1 );
+
+ if ( m_useMode==NEW )
+ {
+#ifdef ALLOW_NON_INLINE_TABLES
+ // Checkbox for floating/fixed location. The default is floating (aka inline).
+ cbIsFloating = new QCheckBox( i18n( "The table is &inline" ), tab1 );
+ //cbIsFloating->setEnabled(false);
+ cbIsFloating->setChecked( floating );
+
+ grid->addMultiCellWidget( cbIsFloating, 9, 9, 0, 2 );
+ connect( cbIsFloating, SIGNAL( toggled ( bool ) ), this, SLOT( slotInlineTable( bool ) ) );
+#endif
+ }
+ else
+ if (m_useMode==EDIT)
+ {
+ cbReapplyTemplate1 = new QCheckBox( i18n("Reapply template to table"), tab1 );
+ grid->addMultiCellWidget( cbReapplyTemplate1, 9, 9, 0, 2);
+
+ connect( cbReapplyTemplate1, SIGNAL( toggled ( bool ) ), this, SLOT( slotSetReapply( bool ) ) );
+ }
+
+ grid->addRowSpacing( 0, lRows->height() );
+ grid->addRowSpacing( 1, nRows->height() );
+ grid->addRowSpacing( 2, lCols->height() );
+ grid->addRowSpacing( 3, nCols->height() );
+#ifdef ALLOW_NON_INLINE_TABLES
+ if ( m_useMode==NEW )
+ {
+ grid->addRowSpacing( 4, lHei->height() );
+ grid->addRowSpacing( 5, cHei->height() );
+ grid->addRowSpacing( 6, lWid->height() );
+ grid->addRowSpacing( 7, cWid->height() );
+ }
+#endif
+ grid->addRowSpacing( 8, 150 - ( lRows->height() + nRows->height() + lCols->height() + nCols->height() ) );
+#ifdef ALLOW_NON_INLINE_TABLES
+ if ( m_useMode==NEW )
+ grid->addRowSpacing( 9, cbIsFloating->height() );
+#endif
+ grid->setRowStretch( 0, 0 );
+ grid->setRowStretch( 1, 0 );
+ grid->setRowStretch( 2, 0 );
+ grid->setRowStretch( 3, 0 );
+ grid->setRowStretch( 4, 0 );
+ grid->setRowStretch( 5, 0 );
+ grid->setRowStretch( 6, 0 );
+ grid->setRowStretch( 7, 0 );
+ grid->setRowStretch( 8, 1 );
+ grid->setRowStretch( 9, 0 );
+
+ grid->addColSpacing( 0, lRows->width() );
+ grid->addColSpacing( 0, nRows->width() );
+ grid->addColSpacing( 0, lCols->width() );
+ grid->addColSpacing( 0, nCols->width() );
+#ifdef ALLOW_NON_INLINE_TABLES
+ if ( m_useMode==NEW )
+ {
+ grid->addColSpacing( 0, lHei->width() );
+ grid->addColSpacing( 0, cHei->width() );
+ grid->addColSpacing( 0, lWid->width() );
+ grid->addColSpacing( 0, cWid->width() );
+ }
+#endif
+ grid->addColSpacing( 1, 150 );
+ grid->setColStretch( 0, 0 );
+ grid->setColStretch( 1, 1 );
+
+ grid->activate();
+
+ connect( nRows, SIGNAL( valueChanged( int ) ), this, SLOT( rowsChanged( int ) ) );
+ connect( nCols, SIGNAL( valueChanged( int ) ), this, SLOT( colsChanged( int ) ) );
+}
+
+void KWTableDia::setupTab2(const QString & _templateName, int format )
+{
+ QWidget *tab2 = addPage( i18n("Templates"));
+
+ QGridLayout *grid = new QGridLayout( tab2, 2, 1, 0, KDialog::spacingHint() );
+
+ tableTemplateSelector = new KWTableTemplateSelector( doc, tab2, _templateName,format );
+ grid->addWidget(tableTemplateSelector, 0, 0);
+
+ if (m_useMode==EDIT)
+ {
+ cbReapplyTemplate2 = new QCheckBox( i18n("Reapply template to table"), tab2 );
+ grid->addWidget( cbReapplyTemplate2, 1, 0);
+
+ grid->setRowStretch( 0, 1);
+ grid->setRowStretch( 1, 0);
+
+ connect( cbReapplyTemplate2, SIGNAL( toggled ( bool ) ), this, SLOT( slotSetReapply( bool ) ) );
+ }
+ grid->activate();
+}
+
+void KWTableDia::slotOk()
+{
+ if ( m_useMode==NEW )
+ /// ###### This should be done AFTER this dialog is closed.
+ // Otherwise we have two modal dialogs fighting each other
+ canvas->createTable( nRows->value(), nCols->value(),
+#ifdef ALLOW_NON_INLINE_TABLES
+ cWid->currentItem(),
+ cHei->currentItem(),
+ cbIsFloating->isChecked(),
+#else
+ 0,
+ 0,
+ true,
+#endif
+ tableTemplateSelector->getTableTemplate(),
+ tableTemplateSelector->getFormatType());
+ else
+ {
+ KWTableFrameSet *table = canvas->getCurrentTable();
+ if ( table )
+ {
+ KMacroCommand *macroCmd = 0L;
+ KCommand *cmd = 0L;
+
+ // Add or delete rows
+ int rowsDiff = nRows->value()-oldRowCount;
+ if ( rowsDiff!=0 )
+ {
+ macroCmd = new KMacroCommand( (rowsDiff>0 ) ? i18n("Add New Rows to Table") : i18n("Remove Rows From Table") );
+ for ( int i = 0 ; i < abs( rowsDiff ) ; i++ )
+ {
+ if ( rowsDiff < 0 )
+ cmd = new KWRemoveRowCommand( i18n("Remove Row"), table, oldRowCount-i-1 );
+ else
+ {
+ cmd = new KWInsertRowCommand( i18n("Insert Row"), table, oldRowCount+i );
+ }
+
+ if (cmd)
+ macroCmd->addCommand( cmd );
+ }
+ canvas->setTableRows( nRows->value() );
+ }
+
+ // Add or delete cols
+ int colsDiff = nCols->value()-oldColCount;
+ if ( colsDiff!=0 )
+ {
+ double maxRightOffset;
+ if (table->isFloating())
+ // inline table: max offset of containing frame
+ maxRightOffset = table->anchorFrameset()->frame(0)->right();
+ else { // non inline table: max offset of the page
+ KWPage *page = doc->pageManager()->page(table->cell(0,0)->frame(0));
+ maxRightOffset = page->width() - page->rightMargin();
+ }
+ if ( !macroCmd )
+ macroCmd = new KMacroCommand( (colsDiff>0 ) ? i18n("Add New Columns to Table") : i18n("Remove Columns From Table") );
+ cmd = 0L;
+ for ( int i = 0 ; i < abs( colsDiff ) ; i++ )
+ {
+ if ( colsDiff < 0 )
+ cmd = new KWRemoveColumnCommand( i18n("Remove Column"), table, oldColCount-i-1 );
+ else
+ {
+ cmd = new KWInsertColumnCommand( i18n("Insert Column"), table, oldColCount+i, maxRightOffset);
+ }
+
+ if (cmd)
+ macroCmd->addCommand( cmd );
+ }
+ canvas->setTableCols( nCols->value() );
+ }
+
+ // Apply template
+ if ( tableTemplateSelector->getTableTemplate() && (( oldTemplateName!=tableTemplateSelector->getTableTemplate()->name() ) || (cbReapplyTemplate1->isChecked()) ))
+ {
+ if ( !macroCmd )
+ macroCmd = new KMacroCommand( i18n("Apply Template to Table") );
+ KWTableTemplateCommand *ttCmd=new KWTableTemplateCommand( i18n("Apply Template to Table"), table, tableTemplateSelector->getTableTemplate() );
+ macroCmd->addCommand( ttCmd );
+ canvas->setTableTemplateName( tableTemplateSelector->getTableTemplate()->name() );
+ }
+ if ( macroCmd )
+ {
+ macroCmd->execute();
+ doc->addCommand( macroCmd );
+ }
+ }
+ }
+ KDialogBase::slotOk();
+}
+
+void KWTableDia::rowsChanged( int _rows )
+{
+ preview->setRows( _rows );
+}
+
+void KWTableDia::colsChanged( int _cols )
+{
+ preview->setCols( _cols );
+}
+
+void KWTableDia::slotSetReapply( bool _reapply )
+{
+ if ( cbReapplyTemplate1->isChecked()!=_reapply ) cbReapplyTemplate1->setChecked( _reapply );
+ if ( cbReapplyTemplate2->isChecked()!=_reapply ) cbReapplyTemplate2->setChecked( _reapply );
+}
+
+void KWTableDia::slotInlineTable( bool state)
+{
+#ifdef ALLOW_NON_INLINE_TABLES
+ if ( m_useMode==NEW )
+ {
+ lWid->setEnabled( !state );
+ lHei->setEnabled( !state );
+ cHei->setEnabled( !state );
+ cWid->setEnabled( !state );
+ }
+#else
+ Q_UNUSED( state );
+#endif
+}
diff --git a/kword/KWTableDia.h b/kword/KWTableDia.h
new file mode 100644
index 00000000..60f58b5c
--- /dev/null
+++ b/kword/KWTableDia.h
@@ -0,0 +1,113 @@
+/* This file is part of the KDE project
+ Copyright (C) 1998, 1999 Reginald Stadlbauer <reggie@kde.org>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+*/
+
+#ifndef tabledia_h
+#define tabledia_h
+
+#include <kdialogbase.h>
+#include <qptrlist.h>
+
+#include "defs.h"
+#include <KoBorder.h>
+
+class KWCanvas;
+class KWDocument;
+class KWTableTemplateSelector;
+
+class QGridLayout;
+class QLabel;
+class QListBox;
+class QWidget;
+class QCheckBox;
+class QButtonGroup;
+class QComboBox;
+class QSpinBox;
+
+/******************************************************************/
+/* Class: KWTablePreview */
+/******************************************************************/
+
+class KWTablePreview : public QWidget
+{
+ Q_OBJECT
+
+public:
+ KWTablePreview( QWidget *_parent, int _rows, int _cols )
+ : QWidget( _parent ), rows( _rows ), cols( _cols ) {}
+
+ void setRows( int _rows ) { rows = _rows; repaint( true ); }
+ void setCols( int _cols ) { cols = _cols; repaint( true ); }
+
+protected:
+ void paintEvent( QPaintEvent *e );
+
+ int rows, cols;
+
+};
+
+/******************************************************************/
+/* Class: KWTableDia */
+/******************************************************************/
+
+class KWTableDia : public KDialogBase
+{
+ Q_OBJECT
+
+public:
+ typedef int CellSize; // in fact KWTableFrameSet::CellSize, which is an enum
+ enum UseMode{ NEW, EDIT };
+ KWTableDia( QWidget *parent, const char *name, UseMode _useMode, KWCanvas *_canvas,
+ KWDocument *_doc, int rows, int cols, CellSize wid, CellSize hei, bool floating,
+ const QString & _templateName, int format);
+
+protected:
+ void setupTab1( int rows, int cols, CellSize wid, CellSize hei, bool floating );
+ void setupTab2( const QString &_templateName, int format);
+
+ QWidget *tab1;
+ QLabel *lRows, *lCols;
+#ifdef ALLOW_NON_INLINE_TABLES
+ QLabel *lWid, *lHei;
+ QComboBox *cHei, *cWid;
+ QCheckBox *cbIsFloating;
+#endif
+ QSpinBox *nRows, *nCols;
+ KWTablePreview *preview;
+ QCheckBox *cbReapplyTemplate1, *cbReapplyTemplate2;
+
+ QGridLayout *grid;
+ KWTableTemplateSelector *tableTemplateSelector;
+
+ UseMode m_useMode;
+ KWCanvas *canvas;
+ KWDocument *doc;
+
+ int oldRowCount, oldColCount;
+ QString oldTemplateName;
+protected slots:
+ void rowsChanged( int );
+ void colsChanged( int );
+ void slotSetReapply( bool );
+ virtual void slotOk();
+ void slotInlineTable( bool );
+};
+
+#endif
+
+
diff --git a/kword/KWTableFrameSet.cpp b/kword/KWTableFrameSet.cpp
new file mode 100644
index 00000000..983c9e07
--- /dev/null
+++ b/kword/KWTableFrameSet.cpp
@@ -0,0 +1,2943 @@
+/*
+ Copyright (C) 2001, S.R.Haque (srhaque@iee.org).
+ This file is part of the KDE project
+ Copyright (C) 2005 Thomas Zander <zander@kde.org>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+
+DESCRIPTION
+
+ This file implements KWord tables.
+*/
+
+// ### TODO : multi page tables
+
+#include "KWTableFrameSet.h"
+#include "KWDocument.h"
+#include "KWAnchor.h"
+#include "KWCanvas.h"
+#include "KWCommand.h"
+#include "KWViewMode.h"
+#include "KWView.h"
+#include "KWordFrameSetIface.h"
+#include "KWordTableFrameSetIface.h"
+#include "KWFrameList.h"
+#include "KWPageManager.h"
+#include "KWPage.h"
+#include "KWOasisSaver.h"
+
+#include <KoOasisContext.h>
+#include <KoXmlWriter.h>
+#include <KoDom.h>
+#include <KoXmlNS.h>
+#include <KoTextObject.h> // for customItemChar !
+#include <KoTextParag.h>
+
+#include <kmessagebox.h>
+#include <kdebug.h>
+#include <klocale.h>
+#include <dcopobject.h>
+#include <qapplication.h>
+#include <qpopupmenu.h>
+#include <qclipboard.h>
+
+
+KWTableFrameSet::KWTableFrameSet( KWDocument *doc, const QString & name ) :
+ KWFrameSet( doc )
+{
+ m_rows = m_cols = m_nr_cells = 0;
+ m_name = QString::null;
+ m_active = true;
+ m_frames.setAutoDelete(false);
+ if ( name.isEmpty() )
+ m_name = doc->generateFramesetName( i18n( "Table %1" ) );
+ else
+ m_name = name;
+}
+
+KWTableFrameSet::~KWTableFrameSet()
+{
+ m_doc = 0L;
+}
+
+KWordFrameSetIface* KWTableFrameSet::dcopObject()
+{
+ if ( !m_dcop )
+ m_dcop = new KWordTableFrameSetIface( this );
+
+ return m_dcop;
+}
+
+
+KWFrameSetEdit * KWTableFrameSet::createFrameSetEdit( KWCanvas * canvas )
+{
+ return new KWTableFrameSetEdit( this, canvas );
+}
+
+void KWTableFrameSet::updateFrames( int flags )
+{
+ for(TableIter c(this); c; ++c)
+ c.current()->updateFrames( flags );
+ if ( isFloating() ) {
+ KWAnchor * anchor = findAnchor( 0 );
+ if ( anchor )
+ anchor->resize();
+ }
+
+ KWFrameSet::updateFrames( flags );
+}
+
+void KWTableFrameSet::moveFloatingFrame( int /*frameNum TODO */, const KoPoint &position )
+{
+ // TODO multi-page case
+
+ double dx = position.x() - m_colPositions[0];
+ double dy = position.y() - m_rowPositions[0];
+
+ KWTableFrameSet::Cell *daCell = cell(0,0);
+ Q_ASSERT(daCell);
+ if (! daCell) return; //hack to work around https://bugs.kde.org/show_bug.cgi?id=67216
+ int oldPageNumber = daCell->frame(0)->pageNumber();
+ // TODO multi-page case
+
+ moveBy( dx, dy );
+
+ if ( dx || dy ) {
+ updateFrames();
+ cell(0,0)->frame(0)->frameStack()->updateAfterMove( oldPageNumber );
+ }
+}
+
+KoSize KWTableFrameSet::floatingFrameSize( int /*frameNum*/ )
+{
+ return boundingRect().size();
+}
+
+KCommand * KWTableFrameSet::anchoredObjectCreateCommand( int /*frameNum*/ )
+{
+ return new KWCreateTableCommand( i18n("Create Table"), this );
+}
+
+KCommand * KWTableFrameSet::anchoredObjectDeleteCommand( int /*frameNum*/ )
+{
+ return new KWDeleteTableCommand( i18n("Delete Table"), this );
+}
+
+KWAnchor * KWTableFrameSet::createAnchor( KoTextDocument *txt, int frameNum )
+{
+ //kdDebug(32004) << "KWTableFrameSet::createAnchor" << endl;
+ return new KWAnchor( txt, this, frameNum );
+}
+
+void KWTableFrameSet::createAnchors( KoTextParag * parag, int index, bool placeHolderExists /*= false */ /*only used when loading*/,
+ bool repaint )
+{
+ //kdDebug(32004) << "KWTableFrameSet::createAnchors" << endl;
+ // TODO make one rect per page, and create one anchor per page
+ // Anchor this frame, after the previous one
+ KWAnchor * anchor = createAnchor( m_anchorTextFs->textDocument(), 0 );
+ if ( !placeHolderExists )
+ parag->insert( index, KoTextObject::customItemChar() );
+ parag->setCustomItem( index, anchor, 0 );
+ kdDebug(32004) << "KWTableFrameSet::createAnchors setting anchor" << endl;
+ parag->setChanged( true );
+ if ( repaint )
+ emit repaintChanged( m_anchorTextFs );
+}
+
+void KWTableFrameSet::deleteAnchors()
+{
+ KWAnchor * anchor = findAnchor( 0 );
+ kdDebug(32004) << "KWTableFrameSet::deleteAnchors anchor=" << anchor << endl;
+ deleteAnchor( anchor );
+}
+
+
+void KWTableFrameSet::addCell( Cell* daCell ) // called add but also used to 'update'
+{
+ m_rows = kMax( daCell->rowAfter(), m_rows );
+ m_cols = kMax( daCell->columnAfter(), m_cols );
+
+ if ( m_rowArray.size() < daCell->rowAfter() )
+ m_rowArray.resize( daCell->rowAfter() );
+ for ( uint row = daCell->firstRow() ;row < daCell->rowAfter(); ++row )
+ {
+ if ( !m_rowArray[ row ] )
+ m_rowArray.insert( row, new Row );
+ m_rowArray[ row ]->addCell( daCell );
+ }
+}
+
+void KWTableFrameSet::removeCell( Cell* daCell )
+{
+ for ( uint row = daCell->firstRow() ; row < daCell->rowAfter(); ++row )
+ m_rowArray[ row ]->removeCell( daCell );
+}
+
+void KWTableFrameSet::insertRowVector(uint index, Row *r)
+{
+ if(m_rowArray.size() < m_rowArray.count() + 1)
+ m_rowArray.resize(m_rowArray.count() + 1);
+
+ for(uint i = m_rowArray.count(); i > index; i--)
+ m_rowArray.insert(i, m_rowArray[i-1]);
+
+ m_rowArray.insert(index, r);
+}
+
+/*
+ * Inserts a new (empty) element into each row vector.
+ * Elements in a row vector after index are moved back.
+ */
+void KWTableFrameSet::insertEmptyColumn(uint index)
+{
+ for(uint i = 0; i < m_rowArray.count(); ++i) {
+ Row *r = m_rowArray[i];
+ if(r->m_cellArray.size() < m_cols + 1)
+ r->m_cellArray.resize(m_cols + 1);
+ for(int j = m_cols - 1; j >= (int)index; --j)
+ r->m_cellArray.insert(j + 1, r->m_cellArray[j]);
+ r->m_cellArray.insert(index, 0);
+ }
+}
+
+KWTableFrameSet::Row*
+KWTableFrameSet::removeRowVector(uint index)
+{
+ Q_ASSERT(index < m_rowArray.count() );
+ Row *ret = m_rowArray.at(index);
+ Row *r;
+ for(uint i = index; i < m_rowArray.size() - 1; ++i){
+ r = m_rowArray.at(i+1);
+ m_rowArray.remove(i+1);
+ m_rowArray.insert(i,r);
+ }
+ return ret;
+}
+
+
+KoRect KWTableFrameSet::boundingRect() {
+ KoRect outerRect(m_colPositions[0], // left
+ m_rowPositions[0], // top
+ m_colPositions.last()-m_colPositions[0], // width
+ m_rowPositions.last()-m_rowPositions[0]);// height
+
+ // Add 1 'pixel' (at current zoom level) like KWFrame::outerKoRect(),
+ // to avoid that the bottom line disappears due to rounding problems
+ // (i.e. that it doesn't fit in the calculated paragraph height in pixels,
+ // which depends on the paragraph's Y position)
+ // Better have one pixel too much (caret looks too big by one pixel)
+ // than one missing (bottom line of cell not painted)
+ outerRect.rRight() += m_doc->zoomItX( 1 ) / m_doc->zoomedResolutionX();
+ outerRect.rBottom() += m_doc->zoomItY( 1 ) / m_doc->zoomedResolutionY();
+
+ return outerRect;
+
+}
+
+double KWTableFrameSet::topWithoutBorder()
+{
+ double top = 0.0;
+ for (uint i = 0; i < getColumns(); i++)
+ {
+ KWTableFrameSet::Cell *daCell = cell( 0, i );
+ top = kMax( top, m_rowPositions[0] + daCell->topBorder() );
+ }
+ return top;
+}
+
+
+double KWTableFrameSet::leftWithoutBorder()
+{
+ double left = 0.0;
+ for (uint i=0; i < getRows(); i++)
+ {
+ KWTableFrameSet::Cell *daCell = cell( i, 0 );
+ left = kMax( left, m_colPositions[0] + daCell->leftBorder() );
+ }
+ return left;
+}
+
+/* returns the cell that occupies row, col. */
+KWTableFrameSet::Cell *KWTableFrameSet::cell( unsigned int row, unsigned int col ) const
+{
+ if ( row < m_rowArray.size() && col < m_rowArray[row]->size() ) {
+ Cell* cell = (*m_rowArray[row])[col];
+ if ( cell )
+ return cell;
+ }
+// kdWarning() << name() << " cell " << row << "," << col << " => returning 0!" << kdBacktrace( 3 ) << endl;
+//#ifndef NDEBUG
+// validate();
+// printArrayDebug();
+//#endif
+ return 0L;
+}
+
+KWTableFrameSet::Cell *KWTableFrameSet::cellByPos( double x, double y ) const
+{
+ KWFrame *f = frameAtPos(x,y);
+ if(f) return static_cast<KWTableFrameSet::Cell *> (f->frameSet());
+ return 0L;
+}
+
+void KWTableFrameSet::recalcCols(unsigned int col,unsigned int row) {
+ if(col >= getColumns())
+ col = getColumns()-1;
+ if(row >= getRows())
+ row = getRows()-1;
+ Cell *activeCell = cell(row,col);
+ Q_ASSERT( activeCell );
+ if ( !activeCell )
+ return;
+ double difference = 0;
+
+ if(activeCell->frame(0)->left() - activeCell->leftBorder() != m_colPositions[activeCell->firstColumn()]) {
+ // left border moved.
+ col = activeCell->firstRow();
+ difference = 0-(activeCell->frame(0)->left() - activeCell->leftBorder() - m_colPositions[activeCell->firstColumn()]);
+ }
+
+ if(activeCell->frame(0)->right() - activeCell->rightBorder() !=
+ m_colPositions[activeCell->lastColumn()]) { // right border moved
+
+ col = activeCell->columnAfter();
+ double difference2 = activeCell->frame(0)->right() + activeCell->rightBorder() - m_colPositions[activeCell->columnAfter()];
+
+ double moved=difference2+difference;
+ if(moved > -0.01 && moved < 0.01) { // we were simply moved.
+ col=0;
+ difference = difference2;
+ } else if(difference2!=0)
+ difference = difference2;
+ }
+
+ m_redrawFromCol=getColumns(); // possible reposition col starting with this one, done in recalcRows
+ if(difference!=0) {
+ double last=col==0?0:m_colPositions[col-1];
+ for(unsigned int i=col; i < m_colPositions.count(); i++) {
+ double &colPos = m_colPositions[i];
+ colPos = colPos + difference;
+ if(colPos-last < s_minFrameWidth) { // Never make it smaller then allowed!
+ difference += s_minFrameWidth - colPos;
+ colPos = s_minFrameWidth + last;
+ }
+ last=colPos;
+ }
+ m_redrawFromCol=col;
+ if(col>0) m_redrawFromCol--;
+ //if(activeCell) activeCell->frame(0)->setMinimumFrameHeight(0);
+ }
+ updateFrames();
+ //kdDebug(32004) << "end KWTableFrameSet::recalcCols" << endl;
+}
+
+
+// Step through the whole table and recalculate the position and size
+// of each cell.
+
+void KWTableFrameSet::recalcRows(unsigned int col, unsigned int row) {
+ kdDebug(32004) << name() << " KWTableFrameSet::recalcRows ("<< col <<"," << row << ")" << endl;
+ //for(unsigned int i=0; i < m_rowPositions.count() ; i++) kdDebug(32004) << "row: " << i << " = " << m_rowPositions[i] << endl;
+
+ Cell *activeCell = cell(row,col);
+ Q_ASSERT( activeCell );
+ if ( !activeCell ) // #122807
+ return;
+ double difference = 0;
+
+ if(activeCell->frame(0)->height() != activeCell->frame(0)->minimumFrameHeight() &&
+ activeCell->type() == FT_TEXT) {
+ // when the amount of text changed and the frame has to be rescaled we are also called.
+ // lets check the minimum size for all the cells in this row.
+
+ // Take a square of table cells which depend on each others height. It is always the full
+ // width of the table and the height is determined by joined cells, the minimum is one row.
+ double minHeightOtherCols=0; // The minimum height which the whole square of table cells can take
+ double minHeightActiveRow=0; // The minimum height our cell can get because of cells in his row
+ double minHeightMyCol=0; // The minimum height our column can get in the whole square
+ unsigned int rowSpan = activeCell->rowSpan();
+ unsigned int startRow = activeCell->firstRow();
+ for (uint colCount = 0; colCount < getColumns(); ++colCount )
+ {
+ // for each column
+ unsigned int rowCount=startRow;
+ double thisColHeight=0; // the total height of this column
+ double thisColActiveRow=0; // the total height of all cells in this col, completely in the
+ // row of the activeCell
+ do { // for each row (under startRow)
+ Cell *thisCell=cell(rowCount,colCount);
+ if ( !thisCell )
+ break; // ###
+ if(thisCell->firstRow() < startRow) { // above -> set startRow and restart
+ rowSpan += startRow - thisCell->firstRow();
+ startRow = thisCell->firstRow();
+ break;
+ }
+ if(thisCell->rowAfter() > startRow + rowSpan) {
+ rowSpan = thisCell->rowAfter() - startRow;
+ break;
+ }
+
+ thisColHeight+=thisCell->frame(0)->minimumFrameHeight();
+ thisColHeight+=thisCell->topBorder();
+ thisColHeight+=thisCell->bottomBorder();
+
+ if(thisCell->firstRow() >= activeCell->firstRow() && thisCell->rowAfter() <= activeCell->rowAfter())
+ thisColActiveRow+=thisCell->frame(0)->minimumFrameHeight();
+
+ rowCount += thisCell->rowSpan();
+ } while (rowCount < rowSpan+startRow);
+
+ if(colCount >= activeCell->firstColumn() &&
+ colCount < activeCell->columnAfter() )
+ minHeightMyCol = thisColHeight;
+ else {
+ minHeightOtherCols = kMax(minHeightOtherCols, thisColHeight);
+ minHeightActiveRow = kMax(minHeightActiveRow, thisColActiveRow);
+ }
+ } // for each column
+
+ bool bottomRow = (startRow+rowSpan == activeCell->rowAfter());
+ if(!bottomRow) {
+ Cell *bottomCell=cell(startRow+rowSpan-1, activeCell->firstColumn());
+ bottomCell->frame(0)->setHeight(bottomCell->frame(0)->minimumFrameHeight() +
+ minHeightOtherCols - minHeightMyCol);
+ // ### RECURSE ###
+ recalcRows(bottomCell->firstColumn(), bottomCell->firstRow());
+ }
+ if(activeCell->frame(0)->minimumFrameHeight() > activeCell->frame(0)->height()) { // wants to grow
+ activeCell->frame(0)->setHeight(activeCell->frame(0)->minimumFrameHeight());
+ //kdDebug(32004) << activeCell->name() << " grew to its minheight: " << activeCell->frame(0)->minimumFrameHeight() << endl;
+ } else { // wants to shrink
+ double newHeight=kMax(activeCell->frame(0)->minimumFrameHeight(),minHeightActiveRow);
+ if(bottomRow) // I'm a strech cell
+ newHeight=kMax(newHeight, minHeightOtherCols - (minHeightMyCol - activeCell->frame(0)->minimumFrameHeight()));
+ activeCell->frame(0)->setHeight(newHeight);
+ //kdDebug(32004) << activeCell->name() << " shrunk to: " << newHeight << endl;
+ }
+ }
+
+ if(activeCell->frame(0)->top() - activeCell->topBorder() != getPositionOfRow(activeCell->firstRow())) {
+ // top moved.
+ row = activeCell->firstRow();
+ difference = 0 - (activeCell->frame(0)->top() - activeCell->topBorder() - getPositionOfRow(row));
+ }
+
+
+ if(activeCell->frame(0)->bottom() + activeCell->bottomBorder() !=
+ getPositionOfRow(activeCell->rowAfter())) { // bottom moved
+
+ row = activeCell->rowAfter();
+ double difference2 = activeCell->frame(0)->bottom() + activeCell->bottomBorder() - getPositionOfRow(row);
+ double moved=difference2+difference;
+ if(moved > -0.01 && moved < 0.01) { // we were simply moved.
+ row=0;
+ difference = difference2;
+ } else if( difference2!=0)
+ difference = difference2;
+ }
+
+ unsigned int fromRow = m_rows; // possible reposition rows starting with this one, default to no repositioning
+ unsigned int untilRow=0; // possible reposition rows ending with this one
+ if( QABS( difference ) > 1E-10 ) { // means "difference != 0.0"
+ QValueList<unsigned int>::iterator pageBound = m_pageBoundaries.begin();
+ QValueList<double>::iterator j = m_rowPositions.begin();
+ double last=0.0;
+ int lineNumber=-1;
+ while(j != m_rowPositions.end()) {
+ lineNumber++;
+ if(pageBound!=m_pageBoundaries.end()) {
+ if((int)*pageBound == lineNumber) { // next page
+ if(lineNumber >= (int)row) { // then delete line j
+ QValueList<double>::iterator nextJ = j;
+ ++nextJ;
+ difference -= *(nextJ)-*(j);
+ kdDebug(32004) << "Deleting line with old pos: " << *j << endl;
+ j=m_rowPositions.remove(j);
+ j--;
+ QValueList<unsigned int>::iterator tmp = pageBound;
+ ++pageBound;
+ m_pageBoundaries.remove(tmp);
+ j++;
+ continue;
+ }
+ ++pageBound;
+ lineNumber--;
+ }
+ }
+ if(lineNumber >= (int)row) { // below changed row
+ if(*(j)-last < s_minFrameHeight) // Never make it smaller then allowed!
+ difference += s_minFrameHeight - *(j) + last;
+ last=*(j);
+ kdDebug(32004) << "moving " << *(j) << " by " << difference << "; to " << (*j) + difference << endl;
+ (*j) += difference; // move line.
+ }
+ j++;
+ }
+ fromRow=row;
+ if(row>0) fromRow--;
+ } else {
+ row=0;
+ }
+#if 0
+{ QValueList<unsigned int>::iterator pb = m_pageBoundaries.begin();
+ unsigned int i=0;
+ double last=0;
+ do {
+ double cur=m_rowPositions[i];
+ if(pb!=m_pageBoundaries.end() && *(pb)==i) {
+ kdDebug(32004) << "line: " << i << ": " << cur << " *" << (last>cur?" (ALERT)":"") << endl;
+ ++pb;
+ } else
+ kdDebug(32004) << "line: " << i << ": " << cur << (last>cur?" (ALERT)":"") << endl;
+ last=cur;
+ i++;
+ } while( i<m_rowPositions.count());
+}
+#endif
+#if 0 // def SUPPORT_MULTI_PAGE_TABLES
+
+ //double pageHeight = m_doc->ptPaperHeight() - m_doc->ptBottomBorder() - m_doc->ptTopBorder();
+ unsigned int pageNumber=cell(0,0)->frame(0)->pageNumber() +1;
+ unsigned int lineNumber=1;
+ QValueList<unsigned int>::iterator pageBound = m_pageBoundaries.begin();
+ QValueList<double>::iterator j = m_rowPositions.begin();
+
+ double diff=0.0;
+ double pageBottom = pageNumber * m_doc->ptPaperHeight() - m_doc->ptBottomBorder();
+ // kdDebug(32004) << "pageBottom; " << pageBottom << endl;
+ while(++j!=m_rowPositions.end()) { // stuff for multipage tables.
+ if(pageBound!=m_pageBoundaries.end() && *pageBound == lineNumber ) {
+ if(*j > pageNumber * m_doc->ptPaperHeight() - m_doc->ptBottomBorder() ) { // next page marker exists, and is accurate...
+ pageNumber++;
+ pageBottom = pageNumber * m_doc->ptPaperHeight() - m_doc->ptBottomBorder();
+ // kdDebug(32004) << "pageBottom; " << pageBottom << endl;
+ untilRow=kMax(untilRow, *pageBound);
+ pageBound++;
+ }
+ }
+
+//kdDebug() << "checking; " << lineNumber << ", " << (*j) << endl;
+ if((*j) + diff > pageBottom) { // a row falls off the page.
+//kdDebug(32004) << "row falls off of page"<< endl;
+ untilRow = m_rows;
+ bool hugeRow = false;
+ unsigned int breakRow = lineNumber-1;
+ // find out of no cells are spanning multiple rows meaning we have to break higher.
+#if 0
+ // ### TODO: I did not get a chance do debug this yet! TZ.
+ for(int i=0; i < getColumns() ; i++) {
+ kdDebug() << "i: " << i<< endl;
+ Cell *c= cell(breakRow, i);
+ kdDebug() << "c: " << c->firstRow() << "," << c->m_col << " w: " << c->columnSpan() << ", h: " << c->rowSpan() << endl;
+ if(c->firstRow() < breakRow) {
+ breakRow = c->firstRow();
+ i=-1;
+ }
+ }
+ kdDebug() << "breakRow: " << breakRow<< endl;
+ fromRow=kMin(fromRow, breakRow);
+ if(breakRow < lineNumber+1) {
+ for(unsigned int i=lineNumber+1; i > breakRow;i--)
+ kdDebug() << "j--";
+ for(unsigned int i=lineNumber+1; i > breakRow;i--)
+ --j;
+ lineNumber=breakRow+1;
+ }
+
+ // find out if the next row (the new one on the page) does not contain cells higher then page.
+ for(unsigned int i=0; i < getColumns() ; i++) {
+ if(cell(breakRow+1,i) && cell(breakRow+1,i)->frame(0)->height() > pageHeight)
+ hugeRow=true;
+ }
+ //if((*pageBound) != breakRow) { // I think that this has to be that way
+ // voeg top in in rowPositions
+#endif
+
+ double topOfPage = m_doc->ptPaperHeight() * pageNumber + m_doc->ptTopBorder();
+
+ QValueList<double>::iterator tmp = m_rowPositions.at(breakRow);
+ diff += topOfPage - (*tmp); // diff between bottom of last row on page and top of new page
+//kdDebug() << "diff += " << topOfPage << " - " << (*tmp) << ". diff += " << topOfPage - (*tmp) <<" ="<< diff << endl;
+ lineNumber++;
+ m_rowPositions.insert(j, topOfPage);
+
+ // insert new pageBound. It points to last LINE on previous page
+ pageBound = m_pageBoundaries.insert(pageBound, breakRow);
+ //kdDebug(32004) << "inserting new pageBound: " << breakRow << " at " << m_rowPositions[breakRow] << endl;
+ pageBound++;
+ if(!hugeRow) {
+ // add header-rij toe. (en zet bool) TODO
+ //j++;
+ //lineNumber++;
+ // m_hasTmpHeaders = true;
+ }
+ pageNumber++;
+ pageBottom = pageNumber * m_doc->ptPaperHeight() - m_doc->ptBottomBorder();
+ //kdDebug(32004) << " pageBottom: " << pageBottom << " pageNumber=" << pageNumber << endl;
+ if((int)pageNumber > m_doc->numPages()) {
+ int num = m_doc->appendPage();
+ kdDebug(32004) << "Have appended page: " << num << " (one page mode!)" << endl;
+ m_doc->afterInsertPage( num );
+ }
+ }
+ //if(diff > 0) kdDebug(32004) << " adding " << diff << ", line " << lineNumber << " " << *(j) <<" -> " << *(j)+diff << endl;
+ if(diff > 0)
+ (*j) = (*j) + diff;
+ lineNumber++;
+
+#if 0 // def SUPPORT_MULTI_PAGE_TABLES
+ // Note: produces much ouput!
+ int i = 1; // DEBUG
+ for ( QValueList<double>::iterator itDebug = m_rowPositions.begin(); itDebug != m_rowPositions.end(); ++itDebug, ++i )
+ {
+ kdDebug(32004) << "m_rowPosition[" << i << "]= " << (*itDebug) << endl;
+ }
+#endif
+
+ }
+#endif
+#if 0
+{ QValueList<unsigned int>::iterator pb = m_pageBoundaries.begin();
+ unsigned int i=0;
+ double last=0;
+ do {
+ double cur=m_rowPositions[i];
+ if(pb!=m_pageBoundaries.end() && *(pb)==i) {
+ kdDebug(32004) << "line: " << i << ": " << cur << " *" << (last>cur?" (ALERT)":"") << endl;
+ ++pb;
+ } else
+ kdDebug(32004) << "line: " << i << ": " << cur << (last>cur?" (ALERT)":"") << endl;
+ last=cur;
+ i++;
+ } while( i<m_rowPositions.count());
+}
+#endif
+//for (unsigned int i=0; i < getRows(); kdDebug(32004)<<" pos of row["<<i<<"] = "<<getPositionOfRow(i)<<"/"<<getPositionOfRow(i,true)<<endl,i++);
+ //kdDebug () << "Repositioning from row : " << fromRow << " until: " << untilRow << endl;
+ //kdDebug () << "Repositioning from col > " << redrawFromCol << endl;
+ // do positioning.
+ //Cell *cell;
+ //bool setMinFrameSize= activeCell->frame(0)->isSelected();
+
+#if 0 // def SUPPORT_MULTI_PAGE_TABLES
+ for(TableIter cell(this); cell; ++cell) {
+ if((cell->rowAfter() > fromRow && cell->firstRow() < untilRow) || cell->columnAfter() > m_redrawFromCol)
+ position(cell, (cell==activeCell && cell->frame(0)->isSelected()));
+ }
+ m_redrawFromCol = getColumns();
+
+ // check if any rowPosition entries are unused
+
+ // first create a hash of all row entries
+ QMap<unsigned int,int> rows; // rownr, count
+ unsigned int top=m_rowPositions.count() - m_pageBoundaries.count()-1;
+ for(unsigned int i=0; i < top; rows[i++]=0);
+
+ // fill hash with data
+ for(TableIter i(this); i; ++i) {
+ rows[i->firstRow()] += 1;
+ }
+ // check if some entries have stayed unused.
+ unsigned int counter=top;
+ int adjustment=m_pageBoundaries.count()-1;
+
+ do {
+ counter--;
+ if(adjustment >= 0 && counter == m_pageBoundaries[adjustment])
+ adjustment--;
+ if(rows[counter]==0) {
+ kdDebug() << k_funcinfo << "no rows at counter=" << counter << " -> erasing" << endl;
+ m_rows--;
+ m_rowPositions.erase(m_rowPositions.at(counter+(adjustment>0?adjustment:0)));
+ for (TableIter cell(this); cell; ++cell) {
+ if(cell->firstRow() < counter && cell->rowAfter() > counter)
+ cell->setRowSpan(cell->rowSpan()-1);
+ if(cell->firstRow() > counter)
+ cell->setFirstRow(cell->firstRow()-1);
+ }
+
+ if(adjustment >= -1) {
+ pageBound = m_pageBoundaries.at(adjustment+1);
+ while(pageBound!=m_pageBoundaries.end()) {
+ (*pageBound)= (*pageBound)-1;
+ pageBound++;
+ }
+ }
+ }
+ } while(counter!=0);
+#endif
+
+
+ m_redrawFromCol = 0;
+ for (TableIter cell(this); cell; ++cell) {
+ if((cell->rowAfter() > fromRow && cell->firstRow() < untilRow)
+ || cell->columnAfter() > m_redrawFromCol)
+ position(cell);
+ }
+ m_redrawFromCol = getColumns();
+ kdDebug(32004) << name() << " KWTableFrameSet::recalcRows done" << endl;
+ updateFrames();
+}
+
+int KWTableFrameSet::columnEdgeAt( double x ) const
+{
+ // We compare x with the middle of columns (left+right/2),
+ // to find which column x is closest to.
+ // m_colPositions is sorted, so we can remember the last column we looked at.
+ double lastMiddlePos = 0;
+ for ( uint i = 0; i < m_colPositions.count() - 1; i++ ) {
+ double middlePos = ( m_colPositions[i] + m_colPositions[i+1] ) / 2;
+ Q_ASSERT( lastMiddlePos < middlePos );
+ if ( x > lastMiddlePos && x <= middlePos )
+ return i;
+ lastMiddlePos = middlePos;
+ }
+ return m_colPositions.count() - 1;
+}
+
+int KWTableFrameSet::rowEdgeAt( double y ) const
+{
+ double lastMiddlePos = 0;
+ for ( uint i = 0; i < m_rowPositions.count() - 1; i++ ) {
+ double middlePos = ( m_rowPositions[i] + m_rowPositions[i+1] ) / 2;
+ Q_ASSERT( lastMiddlePos < middlePos );
+ if ( y > lastMiddlePos && y <= middlePos )
+ return i;
+ lastMiddlePos = middlePos;
+ }
+ return m_rowPositions.count() - 1;
+}
+
+double KWTableFrameSet::columnSize( unsigned int col )
+{
+ return m_colPositions[ col ];
+}
+
+double KWTableFrameSet::rowSize( unsigned int row )
+{
+ return m_rowPositions[ row ];
+}
+
+void KWTableFrameSet::resizeColumn( unsigned int col, double x )
+{
+ kdDebug() << k_funcinfo << col << "," << x << endl;
+ if ((col != 0) && (x - m_colPositions[ col-1 ] < s_minFrameWidth))
+ m_colPositions[ col ] = m_colPositions[ col-1 ] + s_minFrameWidth;
+ else
+ if ((col != getColumns()) && (m_colPositions[ col + 1 ] - x < s_minFrameWidth))
+ m_colPositions[col] = m_colPositions[ col + 1 ] - s_minFrameWidth;
+ else
+ m_colPositions[ col ] = x;
+
+ // move all cells right of 'col'
+ for (TableIter cell(this); cell; ++cell) {
+ if ( cell->columnAfter() >= col ) {
+ position(cell);
+ }
+ }
+ recalcCols( col-1, 0 );
+}
+
+void KWTableFrameSet::resizeRow( unsigned int row, double y )
+{
+ kdDebug() << k_funcinfo << row << "," << y << endl;
+ double difference = m_rowPositions[row];
+ if ((row != 0) && (y - m_rowPositions[ row-1 ] < s_minFrameHeight))
+ m_rowPositions[ row ] = m_rowPositions[ row-1 ] + s_minFrameHeight;
+ else
+ if ((row != getRows()) && (m_rowPositions[ row + 1 ] - y < s_minFrameHeight))
+ m_rowPositions[row] = m_rowPositions[ row + 1 ] - s_minFrameHeight;
+ else
+ m_rowPositions[ row ] = y;
+ difference = m_rowPositions[row] - difference;
+
+ //move all rows under 'row'
+ if (row != 0)
+ for (unsigned int i=row+1; i<= getRows(); i++)
+ m_rowPositions[i] = m_rowPositions[i] + difference;
+
+ // move all cells under 'row'
+ for (TableIter cell(this); cell; ++cell) {
+ if ( cell->rowAfter() >= row ) {
+ position(cell);
+ }
+ }
+ recalcRows( 0, row-1 );
+}
+
+void KWTableFrameSet::resizeWidth( double width ) {
+ Q_ASSERT(width != 0);
+ Q_ASSERT(boundingRect().width() != 0);
+ kdDebug() << "bounding width before resize " << boundingRect().width() << endl;
+ double growth = width / boundingRect().width();
+
+ // since we move all the columns, we also move the 1st one,
+ // depending where it is on the page.
+ // just compensate by substracting that offset.
+ double moveOffset = m_colPositions[0] * growth - m_colPositions[0];
+
+ for (uint i=0; i<m_colPositions.count(); i++) {
+ m_colPositions[i] = m_colPositions[i] * growth - moveOffset;
+ }
+ finalize();
+ kdDebug() << "bounding width after resize" << boundingRect().width() << endl;
+ Q_ASSERT(boundingRect().width() - width < 0.01);
+}
+
+void KWTableFrameSet::setBoundingRect( KoRect rect, CellSize widthMode, CellSize heightMode ) {
+ // Column positions..
+ m_colPositions.clear();
+ unsigned int cols=0;
+ for (TableIter c(this); c; ++c)
+ cols = kMax(cols, c.current()->columnAfter());
+ double colWidth = rect.width() / cols;
+ if ( widthMode == TblAuto ) {
+ KWPage *page = pageManager()->page(rect);
+ rect.setLeft( page->leftMargin() );
+ colWidth = (page->width() - page->leftMargin() - page->rightMargin()) / cols;
+ }
+
+ for(unsigned int i=0; i <= cols;i++) {
+ m_colPositions.append(rect.x() + colWidth * i);
+ }
+
+ // Row positions..
+ m_rowPositions.clear();
+ m_pageBoundaries.clear();
+ double rowHeight = 0;
+ if( heightMode != TblAuto )
+ rowHeight = rect.height() / m_rows;
+ rowHeight=kMax(rowHeight, 22.0); // m_doc->getDefaultParagLayout()->getFormat().ptFontSize()) // TODO use table style font-size
+
+ for(unsigned int i=0; i <= m_rows;i++) {
+ m_rowPositions.append(rect.y() + rowHeight * i);
+ }
+
+ double oneMm = MM_TO_POINT( 1.0 );
+ for (TableIter cell(this); cell; ++cell) {
+ KWFrame *frame = cell->frame(0);
+ frame->setPaddingLeft( oneMm );
+ frame->setPaddingRight( oneMm );
+ frame->setPaddingTop( oneMm );
+ frame->setPaddingBottom( oneMm );
+ frame->setNewFrameBehavior( KWFrame::NoFollowup );
+ position(cell, true);
+ }
+}
+
+void KWTableFrameSet::position( Cell *theCell, bool setMinFrameHeight ) {
+ if(!theCell->frame(0)) { // sanity check.
+ kdDebug(32004) << "errorous table cell!! row:" << theCell->firstRow()
+ << ", col: " << theCell->firstColumn() << endl;
+ return;
+ }
+ double x = *m_colPositions.at(theCell->firstColumn());
+ double y = getPositionOfRow(theCell->firstRow());
+ double width = (*m_colPositions.at(theCell->columnAfter())) - x;
+ double height = getPositionOfRow(theCell->lastRow(), true) - y;
+
+#if 0
+ if(theCell->m_col==0) {
+ kdDebug(32004) << "row " << theCell->firstRow() << " has top: "
+ << y << ", and bottom: " << y + height << endl;
+ }
+#endif
+
+ // Now take the border sizes and make the cell smaller so it still fits inside the grid.
+ KWFrame *theFrame = theCell->frame(0);
+ x+=theCell->leftBorder();
+ width-=theCell->leftBorder();
+ width-=theCell->rightBorder();
+ y+=theCell->topBorder();
+ height-=theCell->topBorder();
+ height-=theCell->bottomBorder();
+
+ theFrame->setRect( x,y,width,height);
+ if( setMinFrameHeight )
+ theFrame->setMinimumFrameHeight(height);
+
+ if(!theCell->isVisible())
+ theCell->setVisible(true);
+}
+
+double KWTableFrameSet::getPositionOfRow( unsigned int row, bool bottom ) {
+ unsigned int adjustment=0;
+ QValueList<unsigned int>::iterator pageBound = m_pageBoundaries.begin();
+ while(pageBound != m_pageBoundaries.end() && (*pageBound) <= row + adjustment) {
+ adjustment++;
+ pageBound++;
+ }
+ if(m_rowPositions.count() < row+adjustment+(bottom?1:0)) // Requested row does not exist.
+ return 0;
+ return m_rowPositions[row+adjustment+(bottom?1:0)];
+}
+
+void KWTableFrameSet::moveBy( double dx, double dy ) {
+ bool redraw=false;
+ kdDebug(32004) << "KWTableFrameSet(" << name() << ")::moveBy(" << dx<<","<<dy<<")\n";
+ //for(unsigned int i=0; i < m_rowPositions.count() ; kdDebug(32004) << "row " << i << ": " << m_rowPositions[i++] << endl);
+ if(!(dy > -0.001 && dy < 0.001)) {
+ redraw=true;
+ QValueList<double>::iterator row = m_rowPositions.begin();
+ while(row != m_rowPositions.end()) {
+ (*row)= (*row)+dy;
+ row++;
+ }
+ }
+ if(!(dx > -0.001 && dx < 0.001)) {
+ redraw=true;
+ QValueList<double>::iterator col = m_colPositions.begin();
+ while(col != m_colPositions.end()) {
+ (*col)= (*col)+dx;
+ col++;
+ }
+ }
+
+ if(redraw) {
+ for(TableIter cell(this);cell;++cell)
+ position(cell);
+ }
+}
+
+/* Delete all cells that are completely in this row. */
+void KWTableFrameSet::deleteRow( unsigned int row, RemovedRow &rr, bool _recalc)
+{
+ Q_ASSERT(row < m_rowArray.size());
+ const unsigned int rowspan=1;
+
+ double height= getPositionOfRow(row+rowspan-1,true) - getPositionOfRow(row);
+ QValueList<double>::iterator tmp = m_rowPositions.at(row+rowspan);
+ tmp=m_rowPositions.erase(tmp);
+ while(tmp!=m_rowPositions.end()) {
+ (*tmp)= (*tmp)-height;
+ tmp++;
+ }
+
+ rr.m_index = row;
+ rr.m_rowHeight = height;
+ rr.m_row = m_rowArray[row];
+
+ // move/delete cells.
+ for ( TableIter cell(this); cell; ++cell ) {
+ if ( row >= cell->firstRow() && row < cell->rowAfter()) { // cell is indeed in row
+ if(cell->rowSpan() == 1) { // cell is wholly contained within row
+ m_frames.remove( cell->frame(0) );
+ } else { // make cell span rowspan less rows
+ cell->setRowSpan(cell->rowSpan()-rowspan);
+ position(cell);
+ }
+
+ } else if ( cell->firstRow() > row ) {
+ // move cell up
+ cell->setFirstRow( cell->firstRow() - rowspan );
+ position(cell);
+ }
+ }
+
+ removeRowVector(row);
+ m_rows -= rowspan;
+ m_rowArray.resize( m_rows );
+ validate();
+
+ if ( _recalc )
+ recalcRows( 0, row-1 );
+}
+
+void KWTableFrameSet::reInsertRow(RemovedRow &rr)
+{
+ uint row = rr.index();
+ Row *r = rr.row();
+ uint rlen = r->count();
+
+ // adjust cell positions & sizes
+ for(MarkedIterator cell(this); cell; ++cell) {
+
+ if ( cell->firstRow() < row && cell->lastRow() >= row ){ // cell is indeed in row
+ cell->setRowSpan(cell->rowSpan() + 1);
+ }
+ else if(r->m_cellArray[cell->firstColumn()] == cell.current()) {
+ cell->setRowSpan(cell->rowSpan() + 1);
+ }
+ else if ( cell->firstRow() >= row ) {
+ // move cell down
+ cell->setFirstRow( cell->firstRow() + 1);
+ }
+ }
+
+ // put back m_frames that were removed
+ for(uint i = 0; i < rlen; i++){
+ if( m_frames.findRef((*r)[i]->frame(0)) == -1 )
+ m_frames.append( (*r)[i]->frame(0) );
+ }
+
+ // adjust row positions (ignores page boundaries!)a
+ if(row == m_rows) { //reinserting at bottom of table
+ double d = m_rowPositions.last() + rr.height();
+ m_rowPositions.append(d);
+ }
+ else {
+ QValueList<double>::iterator top = m_rowPositions.at(row);
+ QValueList<double>::iterator i = m_rowPositions.at(row+1);
+ i = m_rowPositions.insert(i, *top + rr.height());
+ i++;
+ for(; i != m_rowPositions.end(); ++i) {
+ *i = *i+ rr.height();
+ }
+ }
+
+ // reinsert row into array
+ m_rows++;
+ insertRowVector(rr.index(), rr.takeRow());
+
+ // don't actually have to visit all the cells, this could be optimised
+ for(TableIter i(this); i ; ++i)
+ position(i.current());
+
+ validate();
+}
+
+void KWTableFrameSet::insertNewRow( uint idx, bool recalc, bool _removeable)
+{
+
+ (void) _removeable; // unused parameter
+ unsigned int copyFromRow = idx==0?0:idx-1;
+ if(idx==0)
+ copyFromRow=1;
+ Row *copyRow = m_rowArray[copyFromRow];
+
+ uint new_rows = m_rows + 1;
+ // What height to use for the new row
+ double height = getPositionOfRow(copyFromRow,true) - getPositionOfRow(copyFromRow);
+
+ // Calculate offset in QValueList because of page breaks.
+ unsigned int adjustment=0;
+ unsigned int untilRow=m_rows;
+ QValueList<unsigned int>::iterator pageBound = m_pageBoundaries.begin();
+ while(pageBound != m_pageBoundaries.end() && (*pageBound) <= idx) {
+ // Find out how many pages we already had.
+ adjustment++;
+ pageBound++;
+ }
+
+ // Move all rows down from newRow to bottom of page
+ QValueList<double>::iterator tmp = m_rowPositions.at(idx);
+ double newPos = *tmp + height;
+ tmp++;
+ m_rowPositions.insert(tmp, newPos);
+ for(unsigned int i=idx+adjustment+2; i < m_rowPositions.count(); i++) {
+ double &rowPos = m_rowPositions[i];
+ kdDebug(32004) << "adjusting " << rowPos << " -> " << rowPos + height << endl;
+ rowPos = rowPos + height;
+ if(*pageBound == i) {
+ untilRow= *pageBound;
+ break; // stop at pageBreak.
+ }
+ }
+
+ for ( MarkedIterator cells(this); cells; ++cells) {
+ if ( cells->firstRow() >= idx ) { // move all cells beneath the new row.
+ cells->setFirstRow(cells->firstRow()+1);
+ }
+ }
+
+ insertRowVector(idx, new Row);
+
+ unsigned int i = 0;
+ while(i < getColumns()) {
+
+ if(idx != 0 && (idx != m_rows)) {
+ Cell *c = cell(idx - 1, i);
+ if( c == cell(idx + 1, i) ) {
+ m_rowArray[idx]->addCell(c);
+ c->setRowSpan(c->rowSpan() + 1);
+ i += c->columnSpan();
+ continue; // don't need to make a new cell
+ }
+ }
+
+ KWFrame *theFrame = new KWFrame(copyRow->m_cellArray[i]->frame(0));
+ Cell *newCell=new Cell( this, idx, i, QString::null );
+ newCell->setColumnSpan( cell(copyFromRow,i)->columnSpan() );
+ addCell(newCell);
+ newCell->addFrame( theFrame, false );
+ position(newCell);
+ i += newCell->columnSpan();
+ }
+
+ // Position all changed cells.
+
+ m_rows = new_rows;
+ validate();
+ if ( recalc )
+ finalize();
+}
+
+void KWTableFrameSet::deleteColumn(uint col, RemovedColumn &rc)
+{
+ // keep these values in case we have to put it back
+ if(!rc.m_initialized) {
+ rc.m_index = col;
+ rc.m_width = m_colPositions[col+1] - m_colPositions[col];
+ }
+
+ // move the colomn positions
+ QValueList<double>::iterator tmp = m_colPositions.at(col+1);
+ tmp = m_colPositions.erase(tmp);
+ while(tmp != m_colPositions.end()) {
+ (*tmp) = (*tmp) - rc.m_width;
+ tmp++;
+ }
+
+ // remove cells that are wholy in this column,
+ // otherwise reduce rowspan. pointers to all cells
+ // are kept in the RemovedColumn
+ CheckedIter iter(this);
+ for(uint i = 0; i < m_rows; ++i) {
+ Cell *daCell = cell(i, col);
+
+ if(!rc.m_initialized) {
+ rc.m_column.append(daCell);
+ rc.m_removed.append(daCell->columnSpan() == 1);
+ }
+
+ if(daCell->columnSpan() == 1) { // lets remove it
+ if(daCell->firstRow() == i) {
+ m_frames.remove( daCell->frame(0) );
+ m_nr_cells--;
+ }
+ m_rowArray[i]->m_cellArray.insert(col, 0);
+ }
+ else { // make cell span 1 less column
+ if(daCell->firstRow() == i) {
+ daCell->setColumnSpan( daCell->columnSpan() - 1 );
+ position(daCell);
+ }
+ }
+ }
+
+ // adjust cells in a later column
+ for(; iter; ++iter) {
+ if (iter->firstColumn() > col ) {
+ iter->setFirstColumn( iter->firstColumn() - 1);
+ position(iter.current());
+ }
+ }
+
+ // move pointers in 2d array back one column to occupy
+ // removed column
+ for(uint i = 0; i < m_rows; i++) {
+ for(uint j = col + 1; j < m_cols; j++)
+ m_rowArray[i]->m_cellArray.insert(j-1, m_rowArray[i]->m_cellArray[j]);
+ }
+ m_cols--;
+ rc.m_initialized = true;
+
+ validate();
+ recalcCols( col, 0 );
+ recalcRows( col, 0 );
+}
+
+void KWTableFrameSet::reInsertColumn(RemovedColumn &rc)
+{
+ QValueList<double>::iterator tmp = m_colPositions.at(rc.m_index);
+
+ tmp = m_colPositions.insert(tmp, *tmp);
+ tmp++;
+ while(tmp != m_colPositions.end()) {
+ (*tmp) = (*tmp) + rc.m_width;
+ tmp++;
+ }
+
+ // if a cell starts after the column we are inserting, it
+ // must be moved to the right, except if it is going to
+ // occury the reinserted column also.
+ for ( MarkedIterator cells(this); cells ; ++cells ) {
+ if ( cells->firstColumn() >= rc.m_index &&
+ (rc.m_column.at(cells->firstRow()) != cells.current())) {
+
+ cells->setFirstColumn(cells->firstColumn() + 1);
+ }
+ }
+ insertEmptyColumn(rc.m_index);
+ m_cols++;
+
+ for(uint i = 0; i < m_rows; ++i) {
+ bool removed = rc.m_removed[i];
+ Cell *daCell = rc.m_column.at(i);
+ if(i == daCell->firstRow()) {
+ if(removed) {
+ daCell->setColumnSpan(1);
+ m_frames.append(daCell->frame(0));
+ m_nr_cells++;
+ }
+ else {
+ daCell->setColumnSpan(daCell->columnSpan() + 1);
+ }
+ addCell(daCell);
+ }
+ }
+
+ validate();
+ finalize();
+}
+
+void KWTableFrameSet::insertNewColumn( uint idx, double width)
+{
+ QValueList<double>::iterator tmp = m_colPositions.at(idx);
+
+ tmp = m_colPositions.insert(tmp, *tmp);
+ tmp++;
+ while(tmp!=m_colPositions.end()) {
+ (*tmp)= (*tmp)+width;
+ tmp++;
+ }
+
+ for ( MarkedIterator cells(this); cells ; ++cells ) {
+ if ( cells->firstColumn() >= idx) { // move all cells right of the new col.
+ cells->setFirstColumn(cells->firstColumn() + 1);
+ }
+ }
+ insertEmptyColumn(idx);
+ m_cols++;
+ uint copyCol = (idx == 0) ? 1 : idx - 1 ;
+
+ // make the new cells
+ // note that the loop counter is mucked with in the loop!
+ for( unsigned int i = 0; i < getRows(); i++ ) {
+
+ // can't break a cell in half, so if there is the same cell
+ // on both sides of inserted column, it occupies the new
+ // column as well
+ if(idx != 0 && (idx != m_cols -1)) {
+ Cell *c = cell(i, idx - 1);
+ if( c == cell(i, idx + 1) ) {
+// m_rowArray[i]->m_cellArray.insert(idx, c);
+ c->setColumnSpan(c->columnSpan() + 1);
+ addCell(c);
+ i += c->rowSpan() - 1;
+ continue; // don't need to make a new cell
+ }
+ }
+
+ Cell *newCell = new Cell( this, i, idx, QString::null );
+ KWFrame *theFrame = new KWFrame(cell(i, copyCol)->frame(0));
+ newCell->addFrame( theFrame, false );
+ position(newCell);
+ m_nr_cells++;
+ }
+ validate();
+ finalize();
+}
+
+void KWTableFrameSet::ungroup()
+{
+// m_cells.setAutoDelete( false );
+// m_cells.clear();
+ m_nr_cells = 0;
+
+ m_active = false;
+}
+
+void KWTableFrameSet::group()
+{
+// m_cells.setAutoDelete( true );
+// m_cells.clear();
+
+ m_nr_cells = 0;
+ m_active = true;
+}
+
+KCommand *KWTableFrameSet::joinCells(unsigned int colBegin,unsigned int rowBegin, unsigned int colEnd,unsigned int rowEnd) {
+ Cell *firstCell = cell(rowBegin, colBegin);
+ // if just one cell selected for joining; exit.
+ if(rowBegin == rowEnd && colBegin == colEnd || cell(rowBegin,colBegin) == cell(rowEnd,colEnd))
+ return 0L;
+ QPtrList<KWFrameSet> listFrameSet;
+ QPtrList<KWFrame> listCopyFrame;
+
+ // do the actual merge.
+ for(unsigned int i=colBegin; i<=colEnd;i++) {
+ for(unsigned int j=rowBegin; j<=rowEnd;j++) {
+ Cell *daCell = cell(j,i);
+ if(daCell && daCell!=firstCell) {
+ listFrameSet.append(daCell);
+ KWFrame* frame = daCell->frame(0);
+ Q_ASSERT(frame);
+ if(! frame) continue; // see bug #132642
+ listCopyFrame.append(frame->getCopy());
+ daCell->deleteFrame(frame);
+ }
+ }
+ }
+
+ Q_ASSERT(firstCell);
+ // update firstcell properties to reflect the merge
+ firstCell->setColumnSpan(colEnd-colBegin+1);
+ firstCell->setRowSpan(rowEnd-rowBegin+1);
+ addCell(firstCell);
+ position(firstCell);
+ validate();
+
+ m_doc->updateAllFrames(); // TODO: only fs->updateFrames() & m_doc->updateFramesOnTopOrBelow(pageNum)
+ m_doc->repaintAllViews();
+ return new KWJoinCellCommand( i18n("Join Cells"), this,colBegin,rowBegin, colEnd,rowEnd,listFrameSet,listCopyFrame);
+}
+
+KCommand *KWTableFrameSet::splitCell(unsigned int intoRows, unsigned int intoCols, unsigned int col, unsigned int row, QPtrList<KWFrameSet> listFrameSet, QPtrList<KWFrame>listFrame) {
+ if(intoRows < 1 || intoCols < 1)
+ return 0L;
+
+ kdDebug(32004) << "KWTableFrameSet::splitCell" << endl;
+ Cell *daCell=cell(row,col);
+ int rowsDiff = intoRows - daCell->rowSpan();
+ int colsDiff = ((int) intoCols) - daCell->columnSpan();
+
+ if(rowsDiff >0) {
+ unsigned int adjustment=0;
+ QValueList<unsigned int>::iterator pageBound = m_pageBoundaries.begin();
+ while(pageBound != m_pageBoundaries.end() && (*pageBound) <= row) {
+ adjustment++;
+ pageBound++;
+ }
+ double height = (m_rowPositions[row+adjustment+1] - m_rowPositions[row+adjustment])/intoRows;
+
+ QValueList<double>::iterator iRow = m_rowPositions.at(adjustment+row);
+ for (int i=0; i < rowsDiff; i++) {
+ double newPos = *iRow + height;
+ iRow++;
+ iRow=m_rowPositions.insert(iRow, newPos);
+ }
+
+ // insert more rows into m_rowArray
+ for(int i = 0; i < rowsDiff; ++i) {
+ insertRowVector(row+i+1, new Row);
+ m_rows++;
+ }
+
+ // m_rows += rowsDiff;
+ //for(unsigned int i=0; i < m_rowPositions.count() ; ++i)
+ // kdDebug(32004) << "row " << i << ": " << m_rowPositions[i] << endl);
+ }
+ if(colsDiff >0) {
+ double width = (m_colPositions[col+1] - m_colPositions[col])/intoCols;
+
+ QValueList<double>::iterator iCol = m_colPositions.at(col);
+ for (int i=0; i < colsDiff; i++) {
+ double newPos = *iCol + width;
+ iCol++;
+ iCol=m_colPositions.insert(iCol, newPos);
+ }
+
+ for(int i = 0; i < colsDiff; i++) {
+ insertEmptyColumn(col+i+1);
+ m_cols++;
+ }
+ //for(unsigned int i=0; i < m_colPositions.count(); ++i)
+ // kdDebug(32004) << "col " << i << ": " << m_colPositions[i] << endl);
+ //m_cols += colsDiff;
+ }
+
+ // adjust cellspan and rowspan on other cells.
+ for (CheckedIter i(this); i ; ++i) {
+ if(daCell == i) continue;
+
+ if(rowsDiff>0) {
+ if(row >= i->firstRow()&& row < i->firstRow()+ i->rowSpan())
+ i->setRowSpan(i->rowSpan() + rowsDiff);
+ if(i->firstRow() > row) {
+ i->setFirstRow(i->firstRow() + rowsDiff);
+ // theCell->frame(0)->setTop(theCell->frame(0)->top()+extraHeight);
+ }
+ }
+ if(colsDiff>0) {
+ if(col >= i->firstColumn() && col < i->columnAfter())
+ i->setColumnSpan(i->columnSpan() + colsDiff);
+ if(i->firstColumn() > col)
+ i->setFirstColumn(i->firstColumn() + colsDiff);
+ }
+ /*if(extraHeight != 0 && theCell->firstRow()== row) {
+ theCell->frame(0)->setHeight(theCell->frame(0)->height()+extraHeight);
+ } */
+ if ( rowsDiff > 0 || colsDiff > 0 ) // something changed?
+ addCell( i ); // update arrays
+ }
+
+ int i=0;
+ KWFrame *firstFrame = daCell->frame(0);
+ // create new cells
+ for (unsigned int y = 0; y < intoRows; y++) {
+ for (unsigned int x = 0; x < intoCols; x++){
+ if(x==0 && y==0)
+ continue; // the orig cell takes this spot.
+
+ Cell *lastFrameSet=0L;
+
+ if(listFrameSet.isEmpty())
+ lastFrameSet = new Cell( this, y + row, x + col );
+ else
+ lastFrameSet = static_cast<KWTableFrameSet::Cell*> (listFrameSet.at(i));
+ lastFrameSet->setGroupManager(this);
+
+ KWFrame *theFrame=0L;
+ if(listFrame.isEmpty())
+ {
+ theFrame=firstFrame->getCopy();
+ theFrame->setRunAround( KWFrame::RA_NO );
+ theFrame->setFrameBehavior(KWFrame::AutoExtendFrame);
+ theFrame->setNewFrameBehavior(KWFrame::NoFollowup);
+ lastFrameSet->addFrame( theFrame,false );
+ }
+ else
+ lastFrameSet->addFrame( listFrame.at(i)->getCopy(),false );
+ i++;
+
+ // if the orig cell spans more rows/cols than it is split into, make first col/row wider.
+ if(rowsDiff <0 && y==0)
+ lastFrameSet->setRowSpan(lastFrameSet->rowSpan() - rowsDiff);
+ if(colsDiff <0 && x==0)
+ lastFrameSet->setColumnSpan(lastFrameSet->columnSpan() - colsDiff);
+
+ addCell( lastFrameSet );
+ position(lastFrameSet);
+ }
+ }
+
+ // set new row and col-span. Use intermediate ints otherwise we get strange results as the
+ // intermediate result could be negative (which goes wrong with unsigned ints)
+ int r = (daCell->rowSpan() +1) - intoRows;
+ if(r < 1) r=1;
+ daCell->setRowSpan(r);
+
+ int c = (daCell->columnSpan() + 1) - intoCols;
+ if(c < 1) c=1;
+ daCell->setColumnSpan(c);
+
+ position(daCell);
+ addCell(daCell);
+ validate();
+
+ finalize();
+
+ return new KWSplitCellCommand(i18n("Split Cells"),this,col,row,intoCols, intoRows);
+}
+
+void KWTableFrameSet::viewFormatting( QPainter &/*painter*/, int )
+{
+}
+
+void KWTableFrameSet::validate()
+{
+ for(CheckedIter cells(this); cells; ++cells) {
+ if(cells->columnSpan() == 0 || cells->rowSpan() == 0) {
+ kdDebug(32004) << " KWTableFrameSet::validate(): zero dimension" << endl;
+ kdDebug(32004) << cells->firstRow() << " " << cells->firstColumn() << " " << cells->rowSpan()
+ << " " << cells->columnSpan() << endl;
+ }
+
+ for(uint i = cells->firstRow(); i < cells->rowAfter(); ++i) {
+
+ for(uint j = cells->firstColumn(); j < cells->columnAfter(); ++j) {
+ if( cell(i,j) != cells.current() ) {
+
+ QString str = QString("| 0x%1 ").arg( (unsigned long)cells.current(), 0, 16 );
+ kdDebug(32004) << " KWTableFrameSet::validate() failed " << endl;
+ kdDebug(32004) << "at row: "<< i << " col: "<< j << " cell: "<< str << endl;
+ kdDebug(32004) << cells->firstRow() << " " << cells->firstColumn() << " " << cells->rowSpan()
+ << " " << cells->columnSpan() << endl;
+ //printArrayDebug();
+ }
+ }
+ }
+ }
+}
+
+void KWTableFrameSet::createEmptyRegion( const QRect & crect, QRegion & emptyRegion, KWViewMode *viewMode )
+{
+ // Avoid iterating over all cells if we are out of view
+ if ( !viewMode->normalToView( m_doc->zoomRect( boundingRect() ) ).intersects( crect ) )
+ return;
+
+ QRect outerRect( viewMode->normalToView( m_doc->zoomRect( boundingRect() )));
+ outerRect &= crect;
+ if ( !outerRect.isEmpty() )
+ emptyRegion = emptyRegion.subtract( outerRect );
+
+ QPtrListIterator<KWFrame> frameIt = frameIterator();
+ for ( ; frameIt.current(); ++frameIt )
+ {
+ QRect outerRect( viewMode->normalToView( frameIt.current()->outerRect(viewMode) ) );
+ //kdDebug(32004) << "KWTableFrameSet::createEmptyRegion outerRect=" << DEBUGRECT( outerRect )
+ // << " crect=" << DEBUGRECT( crect ) << endl;
+ outerRect &= crect;
+ if ( !outerRect.isEmpty() )
+ emptyRegion = emptyRegion.subtract( outerRect );
+ }
+}
+
+void KWTableFrameSet::drawBorders( QPainter& painter, const QRect &crect, KWViewMode *viewMode ) {
+
+ /* Draw the borders on top of the lines stores in the m_rowPositions and m_colPositions arrays.
+ * check the relevant cells for borders and thus line thickness.
+ * We move the outer lines (on row==0 and col==0 plus on col=getColumns() etc) a bit so they will stay
+ * inside the boundary of the table!
+ */
+ painter.save();
+ QPen previewLinePen( QApplication::palette().color( QPalette::Active, QColorGroup::Mid ) );
+ QColor defaultBorderColor = KoTextFormat::defaultTextColor( &painter );
+ const int minborder = 1;
+ bool drawPreviewLines = viewMode && viewMode->drawFrameBorders();
+
+ // *** draw horizontal lines *** //
+ unsigned int row=0;
+ QValueList<unsigned int>::iterator pageBound = m_pageBoundaries.begin();
+ for (unsigned int i=0 ; i < m_rowPositions.count() ; i++) {
+ //kdDebug(32004) << "Horizontal line code. i: " << i << endl;
+ bool bottom=false;
+ if( (pageBound!=m_pageBoundaries.end() && (*pageBound) == row)
+ || i == m_rowPositions.count()-1)
+ bottom=true; // at end of page or end of table draw bottom border of cell.
+
+ const KoBorder *border=0;
+ double startPos =0;
+ for(unsigned int col=0; col <= getColumns();) {
+ //kdDebug(32004) << "bottom=" << bottom << " row=" << row << " col=" << col << endl;
+ Cell *daCell = col < getColumns() ? cell(bottom?row-1:row, col) : 0;
+ //if(daCell) kdDebug(32004) << "cell (" << daCell->firstRow()<< "," << daCell->firstColumn() << ")" << endl;
+ //else kdDebug(32004) << "cell: " << daCell << endl;
+
+ if(daCell && daCell->firstRow() != (bottom?row-1:row))
+ daCell=0;
+
+ if(startPos!=0 && (!daCell || col == getColumns() || (
+ bottom && daCell->frame(0)->bottomBorder()!=*border ||
+ !bottom && daCell->frame(0)->topBorder()!=*border
+ ))) {
+ if(border->width() > 0 || drawPreviewLines) {
+ double y = m_rowPositions[i];
+ if(row==0)
+ y+=border->width() / 2; // move slightly down.
+ else if (row == getRows())
+ y-=border->width() / 2; // move slightly up.
+ int ypix = m_doc->zoomItY(y);
+ double offset=0.0;
+ if(border->width() > 0 && col!=getColumns()) { // offset border when not at right most cell.
+ if(daCell) offset=daCell->leftBorder();
+ if ( row > 0 ) {
+ Cell *c = cell(row-1, col);
+ if(c) offset=kMax(offset, c->leftBorder());
+ }
+ }
+ double x = m_colPositions[col] + offset;
+ QPoint topLeft = viewMode->normalToView(QPoint(m_doc->zoomItX(startPos), ypix));
+ QPoint bottomRight = viewMode->normalToView(QPoint(m_doc->zoomItX(x), ypix));
+ QRect line = QRect(topLeft, bottomRight);
+ if(crect.intersects( line )) {
+ //if(border->width() <= 0) kdDebug(32004) << "preview line" << endl;
+ if(border->width() <= 0)
+ painter.setPen( previewLinePen );
+ else {
+ int borderWidth = KoBorder::zoomWidthY( border->width(), m_doc, minborder );
+ painter.setPen( KoBorder::borderPen( *border, borderWidth, defaultBorderColor ) );
+ }
+ //kdDebug(32004) << "Paint: painter.drawHorizontalLine(" << line.left() << "," << line.top() << "," << line.right() << "," << line.bottom() << ")\n";
+ painter.drawLine( line.left(), line.top(), line.right(), line.bottom());
+ }
+ }
+ // reset startPos
+ startPos = 0;
+ }
+ if(daCell && startPos==0) {
+ if(bottom)
+ border=&(daCell->frame(0)->bottomBorder());
+ else
+ border=&(daCell->frame(0)->topBorder());
+
+ if(col==0) // left most cell
+ startPos = m_colPositions[col];
+ else {
+ double offset=0.0;
+ if(border->width() > 0) { // move line to the left a bit to compensate for the left border
+ if(daCell) offset=daCell->leftBorder();
+ if ( row > 0 ) {
+ Cell *c = cell(row-1, col);
+ if(c) offset=kMax(offset, c->leftBorder());
+ }
+ }
+ startPos = m_colPositions[col] - offset;
+ }
+ }
+ col += daCell ? daCell->columnSpan() : 1;
+ }
+ if(pageBound!=m_pageBoundaries.end() && (*pageBound) == row)
+ pageBound++;
+ else
+ row++;
+ }
+
+ // *** draw vertical lines *** //
+ for (unsigned int col=0 ; col < m_colPositions.count(); col++) {
+ //kdDebug(32004) << "Vertical line code. col: " << col << endl;
+ bool right = false;
+ if(col == m_colPositions.count()-1)
+ right = true; // draw right border of cell.
+ int cellColumn = right?col-1:col; // the column we'll be looking for in the loop below
+ Q_ASSERT( cellColumn >= 0 );
+
+ const KoBorder *border = 0;
+ int startRow = -1;
+ for(unsigned int row=0; row <= getRows();) {
+ //kdDebug(32004) << "row=" << row << " cellColumn=" << cellColumn << endl;
+ Cell *daCell = row < getRows() ? cell(row, cellColumn) : 0;
+
+ //kdDebug(32004) << "Drawing vert. Line for cell row: " << row << " col: " << cellColumn << endl;
+ if(daCell && daCell->firstColumn() != (uint)cellColumn)
+ daCell=0;
+
+#if 0
+ kdDebug() << "Condition: startRow:" << (startRow!=-1) << endl;
+ if ( startRow != -1 ) {
+ Q_ASSERT( border );
+ kdDebug() << "Other conditions: cell:" << !daCell << endl;
+ kdDebug() << " or last row:" << ( row == ( int )getRows() ) << endl;
+ if ( daCell )
+ kdDebug() << "Different border:" <<
+ ( ( right && daCell->frame(0)->rightBorder() != *border) ||
+ ( !right && daCell->frame(0)->leftBorder() != *border) )
+ << endl;
+ }
+#endif
+
+ // be sure that the right border of the table is drawn even for joined cells
+ if ( !daCell && startRow == -1 && cellColumn == ((int)m_colPositions.count()-2 ) && right )
+ {
+ // find the joined cell
+ int col = cellColumn;
+ while ( !daCell && col>0 )
+ {
+ col--;
+ daCell = cell(row, col);
+ }
+ if ( daCell && daCell->isJoinedCell() && ( (int)daCell->columnSpan() + col -1 ) == cellColumn )
+ {
+ border = &(daCell->frame(0)->rightBorder());
+ startRow = row;
+ }
+ else
+ daCell = 0;
+ }
+
+ // Draw when something changed (different kind of border) or we're at the end
+ // This code could be rewritten in a more QRT-like way
+ // (iterate and compare with next, instead of the startRow/cell/border hack...)
+ if(startRow != -1 &&
+ (!daCell || row == getRows() ||
+ ( right && daCell->frame(0)->rightBorder() != *border) ||
+ ( !right && daCell->frame(0)->leftBorder() != *border) )
+ ) {
+ if(border->width() > 0 || drawPreviewLines) {
+ double x = m_colPositions[col];
+ if(col==0) {
+ x+=border->width() / 2;
+ } else if(col==getColumns()) {
+ x-=border->width() / 2;
+ }
+ int xpix = m_doc->zoomItX(x);
+ QValueList<unsigned int>::iterator pageBound = m_pageBoundaries.begin();
+ unsigned int topRow=startRow;
+ //kdDebug(32004) << "Drawing from topRow=" << topRow << endl;
+ do { // draw minimum of one line per page.
+ while( pageBound != m_pageBoundaries.end() && *(pageBound) < topRow )
+ pageBound++;
+
+ unsigned int bottomRow;
+ if(pageBound == m_pageBoundaries.end())
+ bottomRow = m_rowPositions.count()-1;
+ else
+ bottomRow = *(pageBound++);
+
+ //kdDebug(32004) << "from: " << topRow << " to: " << kMin((uint)row, bottomRow) << endl;
+ //kdDebug(32004) << "from: " << m_rowPositions[topRow] << " to: " << m_rowPositions[kMin((uint)row, bottomRow)] << endl;
+ double offset=0.0;
+ if(border->width() > 0) {
+ //kdDebug(32004) << "looking at topRow=" << topRow << " col=" << col << endl;
+ Cell *c=cell(topRow,col);
+ if(c) offset=c->topBorder();
+ if ( col > 0 ) {
+ c=cell(topRow,col-1);
+ if(c) offset=kMax(offset,c->topBorder());
+ }
+ if(topRow==0) offset=0.0;
+ }
+ double top=m_rowPositions[topRow]-offset;
+
+ unsigned int toRow=kMin((uint)row,bottomRow);
+ offset=0.0;
+ if(border->width() > 0 && toRow!=bottomRow) {
+ if(daCell) offset=daCell->topBorder();
+ Cell *c=cell(toRow,col-1);
+ if(c) offset=kMax(offset,c->topBorder());
+ }
+ double bottom=m_rowPositions[toRow] + offset;
+
+ QPoint topLeft = viewMode->normalToView(QPoint(xpix, m_doc->zoomItY(top)));
+ QPoint bottomRight = viewMode->normalToView(QPoint(xpix, m_doc->zoomItY(bottom)));
+ QRect line = QRect(topLeft, bottomRight);
+ if(crect.intersects( line )) {
+ if(border->width() <= 0)
+ painter.setPen( previewLinePen );
+ else {
+ int borderWidth = KoBorder::zoomWidthX( border->width(), m_doc, minborder );
+ painter.setPen(KoBorder::borderPen( *border, borderWidth, defaultBorderColor ));
+ }
+ //kdDebug(32004) << "drawBorders(): painter.drawVerticalLine(" << line.left() << "," << line.top() << "," << line.right() << "," << line.bottom() << ")\n";
+ painter.drawLine( line.left(), line.top(), line.right(), line.bottom());
+ }
+
+ topRow=bottomRow+1;
+ } while(topRow < (uint)row && topRow != m_rowPositions.count());
+ } // end "if border to be drawn"
+
+ // reset startRow
+ startRow = -1;
+ }
+
+ if(daCell && startRow == -1) {
+ startRow = row;
+ if(right)
+ border = &(daCell->frame(0)->rightBorder());
+ else
+ border = &(daCell->frame(0)->leftBorder());
+ //kdDebug(32004) << "startRow set to " << row << endl;
+ }
+ row += daCell ? daCell->rowSpan() : 1;
+ //kdDebug(32004) << "End of loop, row=" << row << endl;
+ }
+ }
+
+#if 0
+ if(drawPreviewLines) {
+ QPen minsizeLinePen( red );
+ painter.setPen( minsizeLinePen );
+ for ( unsigned int i = 0; i < m_cells.count(); i++ ) {
+ Cell *daCell = m_cells.at( i );
+ double y = daCell->frame(0)->top() + daCell->frame(0)->minimumFrameHeight() + 1.5;
+ if(y >= daCell->frame(0)->bottom()) continue;
+ int ypix=m_doc->zoomItY(y);
+ QPoint topLeft = viewMode->normalToView(QPoint(m_doc->zoomItX(daCell->frame(0)->left()), ypix));
+ QPoint bottomRight = viewMode->normalToView(QPoint(m_doc->zoomItX(daCell->frame(0)->right()), ypix));
+ QRect line = QRect(topLeft, bottomRight);
+ if(crect.intersects( line )) {
+ painter.drawLine( line.left(), line.top(), line.right(), line.bottom());
+ }
+ }
+ }
+#endif
+
+ painter.restore();
+}
+
+void KWTableFrameSet::drawContents( QPainter * painter, const QRect & crect,
+ const QColorGroup & cg, bool onlyChanged, bool resetChanged,
+ KWFrameSetEdit * edit, KWViewMode * viewMode,
+ KWFrameViewManager *fvm )
+{
+ for (TableIter cells(this) ; cells ; ++cells)
+ {
+ if (edit)
+ {
+ KWTableFrameSetEdit * tableEdit = static_cast<KWTableFrameSetEdit *>(edit);
+ if ( tableEdit->currentCell() && ((Cell*) cells) == tableEdit->currentCell()->frameSet() )
+ {
+ cells->drawContents( painter, crect, cg, onlyChanged, resetChanged, tableEdit->currentCell(), viewMode, fvm );
+ continue;
+ }
+ }
+ cells->drawContents( painter, crect, cg, onlyChanged, resetChanged, 0L, viewMode, fvm );
+ }
+ drawBorders( *painter, crect, viewMode );
+ //kdDebug(32004) << "drawContents()" << endl;
+}
+
+// Called by KWAnchor for inline tables
+// TODO: for non-inline ones we need a text-box around us...
+// Well, even for inline-as-char ones.... Currently being debated with OASIS.
+void KWTableFrameSet::saveOasis( KoXmlWriter& writer, KoSavingContext& context, bool ) const
+{
+ writer.startElement( "table:table" );
+ writer.addAttribute( "table:name", name() );
+ KoGenStyle tableStyle( KWDocument::STYLE_TABLE, "table" );
+ tableStyle.addProperty( "table:align", "margins" );
+ tableStyle.addPropertyPt( "style:width", m_colPositions.last()-m_colPositions[0] );
+ const QString tableStyleName = context.mainStyles().lookup( tableStyle, "table" );
+ writer.addAttribute( "table:style-name", tableStyleName );
+
+ // ### to minimize the XML, we could use table:number-columns-repeated here
+ // when a number of consecutive columns have the exact same style.
+ for ( uint colNr = 0; colNr < getColumns(); ++colNr )
+ {
+ writer.startElement( "table:table-column" );
+ KoGenStyle columnStyle( KWDocument::STYLE_TABLE_COLUMN, "table-column" );
+ columnStyle.addPropertyPt( "style:column-width", m_colPositions[colNr+1] - m_colPositions[colNr] );
+ const QString colStyleName = context.mainStyles().lookup( columnStyle, "col" );
+ writer.addAttribute( "table:style-name", colStyleName );
+ writer.endElement(); // table:table-column
+ }
+
+ // TODO table-header-rows once supported
+
+ for ( uint row = 0; row < getRows(); ++row )
+ {
+ writer.startElement( "table:table-row" );
+
+ KoGenStyle rowStyle( KWDocument::STYLE_TABLE_ROW, "table-row" );
+ rowStyle.addPropertyPt( "table:row-height", m_rowPositions[row+1] - m_rowPositions[row] );
+ // TODO is min-row-height or use-optimal-row-height necessary?
+ const QString rowStyleName = context.mainStyles().lookup( rowStyle, "row" );
+ writer.addAttribute( "table:style-name", rowStyleName );
+
+ for ( uint col = 0; col < getColumns(); ++col )
+ {
+ Cell* daCell = cell(row, col);
+ Q_ASSERT( daCell );
+ if ( !daCell )
+ continue;
+
+ if ( daCell->isFirstGridPosnFast( row, col ) )
+ {
+ writer.startElement( "table:table-cell" );
+
+ // Style: background, border, padding.
+ KoGenStyle cellStyle( KWDocument::STYLE_TABLE_CELL_AUTO, "table-cell" );
+ daCell->frame( 0 )->saveBorderProperties( cellStyle );
+ const QString colStyleName = context.mainStyles().lookup( cellStyle, "cell" );
+ writer.addAttribute( "table:style-name", colStyleName );
+
+ // Attributes
+ if ( daCell->columnSpan() > 1 )
+ writer.addAttribute( "table:number-columns-spanned", daCell->columnSpan() );
+ if ( daCell->rowSpan() > 1 )
+ writer.addAttribute( "table:number-row-spanned", daCell->rowSpan() );
+
+ // Content
+ daCell->saveOasisContent( writer, context );
+
+ writer.endElement(); // table:table-cell
+ }
+ else
+ {
+ // Empty element for the covered cell
+ writer.startElement( "table:covered-table-cell" );
+ writer.endElement();
+ }
+ }
+ writer.endElement(); // table:table-row
+ }
+
+ writer.endElement(); // table:table
+}
+
+void KWTableFrameSet::loadOasis( const QDomElement& tableTag, KoOasisContext& context )
+{
+ // Left position of each column. The last one defined is the right position of the last cell/column.
+ QMemArray<double> columnLefts(4);
+ uint maxColumns = columnLefts.size() - 1;
+
+ uint col = 0;
+ columnLefts[0] = 0.0; // Initialize left of first cell
+ QDomElement elem;
+ forEachElement( elem, tableTag )
+ {
+ if ( elem.localName() == "table-column" && elem.namespaceURI() == KoXmlNS::table )
+ {
+ uint repeat = elem.attributeNS( KoXmlNS::table, "number-columns-repeated", "1").toUInt(); // Default 1 time
+ if (!repeat)
+ repeat=1; // At least one column defined!
+ KoStyleStack& styleStack = context.styleStack();
+ styleStack.setTypeProperties( "table-column" );
+ styleStack.save();
+ context.fillStyleStack( elem, KoXmlNS::table, "style-name", "table-column" );
+
+ QString strWidth = styleStack.attributeNS( KoXmlNS::style, "column-width" );
+ double width = KoUnit::parseValue( strWidth );
+
+ if ( width < 1.0 ) // Something is wrong with the width
+ {
+ kdWarning(32004) << "Table column width ridiculous, assuming 1 inch!" << endl;
+ width = 72.0;
+ }
+ else
+ kdDebug(32004) << "- style width " << width << endl;
+
+ for ( uint j = 0; j < repeat; ++j )
+ {
+ ++col;
+ if ( col >= maxColumns )
+ {
+ // We need more columns
+ maxColumns += 4;
+ columnLefts.resize( maxColumns+1, QGArray::SpeedOptim );
+ }
+ columnLefts[col] = width + columnLefts[col-1];
+ kdDebug(32004) << "Cell column " << col-1 << " left " << columnLefts[col-1] << " right " << columnLefts[col] << endl;
+ }
+ styleStack.restore();
+ }
+ }
+
+ uint row = 0;
+ uint column = 0;
+ parseInsideOfTable( tableTag, context, columnLefts, row, column, 0 );
+}
+
+void KWTableFrameSet::parseInsideOfTable( const QDomElement& parent, KoOasisContext& context,
+ const QMemArray<double> & columnLefts, uint& row, uint& column,
+ double currentRowHeight )
+{
+ kdDebug(32004) << "parseInsideOfTable" << endl;
+ KoStyleStack& styleStack = context.styleStack();
+
+ QDomElement e;
+ forEachElement( e, parent )
+ {
+ const QString localName = e.localName();
+ const QString ns = e.namespaceURI();
+ if ( ns != KoXmlNS::table ) {
+ kdWarning(32004) << "Skipping element " << e.tagName() << " (in parseInsideOfTable)" << endl;
+ continue;
+ }
+
+ styleStack.save();
+ if ( localName == "table-cell" )
+ {
+ loadOasisCell( e, context, columnLefts, row, column, currentRowHeight );
+ ++column;
+ }
+ else if ( localName == "covered-table-cell" )
+ {
+ ++column;
+ }
+ else if ( localName == "table-row" )
+ {
+ context.fillStyleStack( e, KoXmlNS::table, "style-name", "table-row" );
+ context.styleStack().setTypeProperties( "table-row" );
+
+ // Load row height in case it was set - note that it might not be set (e.g. OOo)
+ double rowHeight = styleStack.attributeNS( KoXmlNS::table, "row-height" ).toDouble();
+ column = 0;
+ parseInsideOfTable( e, context, columnLefts, row, column, rowHeight );
+ ++row;
+ }
+ else if ( localName == "table-header-rows" ) // ###TODO
+ {
+ // TODO: do we need to fillStyleStack?
+ parseInsideOfTable( e, context, columnLefts, row, column, currentRowHeight );
+ }
+ else if ( localName == "table-column" )
+ {
+ // Already treated in loadOasis, we do not need to do anything here!
+ }
+ // TODO sub-table [ add to stack and expand at end of table loading ]
+ else
+ {
+ kdWarning(32004) << "Skipping element " << localName << " (in parseInsideOfTable)" << endl;
+ }
+
+ styleStack.restore();
+ }
+}
+
+void KWTableFrameSet::loadOasisCell( const QDomElement& element, KoOasisContext& context,
+ const QMemArray<double> & columnLefts, uint row, uint column,
+ double currentRowHeight )
+{
+ //kdDebug(32004) << k_funcinfo << element.localName() << " " << row << "," << column << endl;
+
+ KoStyleStack& styleStack = context.styleStack();
+ uint rowSpan = element.attributeNS( KoXmlNS::table, "number-rows-spanned", QString::null ).toUInt();
+ if ( rowSpan == 0 )
+ rowSpan = 1;
+ uint colSpan = element.attributeNS( KoXmlNS::table, "number-columns-spanned", QString::null ).toUInt();
+ if ( colSpan == 0 )
+ colSpan = 1;
+
+ // m_rowPositions / m_colPositions could be QMemArrays, or QValueVectors...
+ while(m_rowPositions.count() <= row + rowSpan + m_pageBoundaries.count()) {
+ m_rowPositions.append(0);
+ }
+ while(m_colPositions.count() <= column + colSpan) {
+ m_colPositions.append(0);
+ }
+
+ Cell *daCell = new Cell( this, row, column, QString::null /*unused*/ );
+
+ daCell->setRowSpan( rowSpan );
+ daCell->setColumnSpan( colSpan );
+ addCell( daCell ); // rowSpan/colSpan have changed -> update array
+
+ double width = columnLefts[ QMIN( column+colSpan, columnLefts.size()-1 ) ] - columnLefts[column];
+ double height = currentRowHeight > 0 ? currentRowHeight : 20;
+ KWFrame* frame = new KWFrame( daCell, columnLefts[column], 0, width, height );
+ if ( currentRowHeight > 0 )
+ frame->setMinimumFrameHeight( height ); // ensure that text formatting won't resize it down
+ frame->setRunAround( KWFrame::RA_NO );
+ frame->setFrameBehavior( KWFrame::AutoExtendFrame );
+ frame->setNewFrameBehavior( KWFrame::NoFollowup );
+ daCell->addFrame( frame, false );
+
+ context.fillStyleStack( element, KoXmlNS::table, "style-name", "table-cell" );
+ styleStack.setTypeProperties( "table-cell" );
+
+ daCell->frame( 0 )->loadBorderProperties( styleStack );
+
+ daCell->loadOasisContent( element, context );
+ afterLoadingCell( daCell );
+}
+
+// Old XML
+QDomElement KWTableFrameSet::save( QDomElement &parentElem, bool saveFrames ) {
+ // When saving to a file, we don't have anything specific to the frameset to save.
+ // Save the cells only.
+ for (TableIter cells(this) ; cells ; ++cells)
+ cells->save(parentElem, saveFrames);
+ return QDomElement(); // No englobing element for tables...
+}
+
+// Old XML
+QDomElement KWTableFrameSet::toXML( QDomElement &parentElem, bool saveFrames )
+{
+ QDomElement framesetElem = parentElem.ownerDocument().createElement( "FRAMESET" );
+ parentElem.appendChild( framesetElem );
+ KWFrameSet::saveCommon( framesetElem, false ); // Save the frameset attributes
+ // Save the cells
+ save( framesetElem, saveFrames );
+ return framesetElem;
+}
+
+// Old XML
+void KWTableFrameSet::fromXML( QDomElement &framesetElem, bool loadFrames, bool useNames )
+{
+ KWFrameSet::load( framesetElem, false ); // Load the frameset attributes
+ // Load the cells
+ QDomElement cellElem = framesetElem.firstChild().toElement();
+ for ( ; !cellElem.isNull() ; cellElem = cellElem.nextSibling().toElement() )
+ {
+ if ( cellElem.tagName() == "FRAMESET" )
+ loadCell( cellElem, loadFrames, useNames );
+ }
+}
+
+// Old XML
+KWTableFrameSet::Cell* KWTableFrameSet::loadCell( QDomElement &framesetElem, bool loadFrames, bool useNames )
+{
+ int _row = KWDocument::getAttribute( framesetElem, "row", 0 );
+ if(_row <0) _row =0;
+ unsigned int row=_row;
+ int _col = KWDocument::getAttribute( framesetElem, "col", 0 );
+ if(_col <0) _col =0;
+ int _rows = KWDocument::getAttribute( framesetElem, "rows", 1 );
+ if(_rows <0) _rows = 1;
+ int _cols = KWDocument::getAttribute( framesetElem, "cols", 1 );
+ if(_cols <0) _cols = 1;
+
+ // m_rowPositions / m_colPositions could be QMemArrays, or QValueVectors...
+ while(m_rowPositions.count() <= static_cast<unsigned int>(row + _rows + m_pageBoundaries.count())) {
+ m_rowPositions.append(0);
+ }
+ while(m_colPositions.count() <= static_cast<unsigned int>(_col + _cols)) {
+ m_colPositions.append(0);
+ }
+
+ Cell *daCell = new Cell( this, row, _col, QString::null /*unused*/ );
+ QString autoName = daCell->name();
+ //kdDebug(32004) << "KWTableFrameSet::loadCell autoName=" << autoName << endl;
+ daCell->load( framesetElem, loadFrames );
+ daCell->setRowSpan(_rows);
+ daCell->setColumnSpan(_cols);
+ addCell( daCell ); // rowSpan/colSpan have changed -> update array
+ afterLoadingCell( daCell );
+ if ( !useNames )
+ daCell->setName( autoName );
+ return daCell;
+}
+
+// Shared between old xml and oasis
+void KWTableFrameSet::afterLoadingCell( Cell* daCell )
+{
+ uint row = daCell->firstRow();
+ uint col = daCell->firstColumn();
+ uint rowSpan = daCell->rowSpan();
+ uint colSpan = daCell->columnSpan();
+ if(m_pageBoundaries.count() > 0) {
+ unsigned int adjustment=0;
+ QValueList<unsigned int>::iterator pageBound = m_pageBoundaries.begin();
+ while(pageBound != m_pageBoundaries.end() && (*pageBound) <= row + adjustment) {
+ adjustment++;
+ pageBound++;
+ }
+ row+=adjustment;
+ }
+
+ kdDebug(32004) << "loading cell (" << row << "," << col << ")\n";
+ if(daCell->frame(0)) {
+ daCell->frame(0)->setMinimumFrameHeight(daCell->frame(0)->height()); // TODO run the formatter over the text here
+ QValueList<double>::iterator tmp = m_colPositions.at(col);
+ if(*tmp == 0) (*tmp) = daCell->frame(0)->left();
+ else (*tmp) = (daCell->frame(0)->left() + *tmp) / 2;
+
+ tmp = m_colPositions.at(col+colSpan);
+ if(*tmp == 0) (*tmp) = daCell->frame(0)->right();
+ else (*tmp) = (daCell->frame(0)->right() + *tmp) / 2;
+
+ tmp = m_rowPositions.at(row);
+ if(*tmp == 0)
+ (*tmp) = daCell->frame(0)->top();
+ else {
+ if (static_cast<int>(*tmp/m_doc->pageLayout().ptHeight) < static_cast<int>(daCell->frame(0)->top()/m_doc->pageLayout().ptHeight)) {
+ kdDebug(32004) << "This cell is on a new page" << endl;
+ QValueList<unsigned int>::iterator pageBound = m_pageBoundaries.begin();
+ while(pageBound != m_pageBoundaries.end() && (*pageBound) < row) ++pageBound;
+ if(*pageBound!=row) {
+ m_pageBoundaries.insert(pageBound,row++);
+ ++tmp;
+ m_rowPositions.insert(tmp,daCell->frame(0)->top());
+ }
+ } else
+ (*tmp) = (daCell->frame(0)->top() + *tmp) / 2;
+ }
+
+ tmp = m_rowPositions.at( row + rowSpan );
+ if(*tmp == 0)
+ (*tmp) = daCell->frame(0)->bottom();
+ else { // untested...
+ if (static_cast<int>(*tmp/m_doc->pageLayout().ptHeight) > static_cast<int>(daCell->frame(0)->top()/m_doc->pageLayout().ptHeight)) {
+ kdDebug(32004) << "next cell is on a new page" << endl;
+ QValueList<unsigned int>::iterator pageBound = m_pageBoundaries.begin();
+ while(pageBound != m_pageBoundaries.end() && (*pageBound) < row) ++pageBound;
+ if(*pageBound!=row) {
+ m_pageBoundaries.insert(pageBound,row++);
+ m_rowPositions.insert(tmp,daCell->frame(0)->bottom());
+ }
+ } else
+ (*tmp) = (daCell->frame(0)->bottom() + *tmp) / 2;
+ }
+ }
+
+ if ( m_rowPositions.count() != m_rows + 1 ) {
+ kdDebug() << name() << " loadCell: m_rowPositions=" << m_rowPositions.count() << " m_rows= " << m_rows << endl;
+ }
+}
+
+int KWTableFrameSet::paragraphs()
+{
+ int paragraphs = 0;
+ for (TableIter cells(this) ; cells ; ++cells)
+ paragraphs += cells->paragraphs();
+ return paragraphs;
+}
+
+int KWTableFrameSet::paragraphsSelected()
+{
+ int paragraphs = 0;
+ for (TableIter cells(this) ; cells ; ++cells)
+ paragraphs += cells->paragraphsSelected();
+ return paragraphs;
+}
+
+bool KWTableFrameSet::statistics( QProgressDialog *progress, ulong & charsWithSpace, ulong & charsWithoutSpace, ulong & words,
+ ulong & sentences, ulong & syllables, ulong & lines, bool selected )
+{
+ for (TableIter cells(this) ; cells ; ++cells)
+ if( ! cells->statistics( progress, charsWithSpace, charsWithoutSpace, words, sentences, syllables, lines, selected ) )
+ {
+ return false;
+ }
+ return true;
+}
+
+void KWTableFrameSet::finalize( ) {
+ kdDebug(32004) << "KWTableFrameSet::finalize" << endl;
+
+ for (TableIter cells(this) ; cells ; ++cells)
+ {
+ position( cells );
+ cells->finalize();
+ }
+
+ recalcCols(0, 0);
+ recalcRows(0, 0);
+ KWFrameSet::finalize();
+}
+
+void KWTableFrameSet::layout()
+{
+ for (TableIter cells(this) ; cells ; ++cells)
+ cells->layout();
+}
+
+void KWTableFrameSet::invalidate()
+{
+ for (TableIter cells(this) ; cells ; ++cells)
+ cells->invalidate();
+}
+
+void KWTableFrameSet::setVisible( bool v )
+{
+ for (TableIter cells(this) ; cells ; ++cells)
+ cells->setVisible( v );
+
+ KWFrameSet::setVisible( v );
+}
+
+bool KWTableFrameSet::canRemovePage( int num ) {
+ /* This one is a lot simpler then the one it overrides, we simply don't have
+ to check if the frame contains something, the simple existence of a frame
+ is enough
+ */
+ QPtrListIterator<KWFrame> frameIt( frameIterator() );
+ for ( ; frameIt.current(); ++frameIt ) {
+ if ( frameIt.current()->pageNumber() == num ) {
+ return false;
+ }
+ }
+ return true;
+}
+
+void KWTableFrameSet::addTextFrameSets( QPtrList<KWTextFrameSet> & lst, bool onlyReadWrite )
+{
+ for (TableIter cells(this) ; cells ; ++cells)
+ if (!cells->textObject()->protectContent() || onlyReadWrite )
+ lst.append(cells);
+}
+
+KWTextFrameSet* KWTableFrameSet::nextTextObject( KWFrameSet *obj )
+{
+ bool found = false;
+ KWTableFrameSet::Cell *tmp = dynamic_cast<KWTableFrameSet::Cell *>(obj);
+
+ // make sure we have this cell
+ if ( tmp ) {
+ for(TableIter i(this); i; ++i) {
+ if(i.current() == tmp) {
+ found = true;
+ break;
+ }
+ }
+ }
+
+ TableIter iter(this);
+ if(found)
+ iter.goToCell(tmp);
+
+ for(; iter; ++iter) {
+ KWTextFrameSet *newFrm = iter->nextTextObject( obj );
+ if(newFrm && newFrm->textObject()->needSpellCheck())
+ return newFrm;
+ }
+
+ return 0L;
+}
+
+void KWTableFrameSet::setZOrder()
+{
+ for( TableIter cells(this) ; cells ; ++cells ) {
+ cells->setZOrder();
+ }
+
+}
+
+// TODO provide toPlainText() (reimplemented from KWFrameSet)
+
+QByteArray KWTableFrameSet::convertTableToText() // should be const, but TableIter doesn't allow it
+{
+ KWOasisSaver oasisSaver( m_doc );
+ for (TableIter cells(this); cells; ++cells)
+ {
+ cells->textObject()->saveOasisContent( oasisSaver.bodyWriter(), oasisSaver.savingContext() );
+ }
+ if ( !oasisSaver.finish() )
+ return QByteArray();
+ return oasisSaver.data();
+}
+
+#ifndef NDEBUG
+void KWTableFrameSet::printDebug( KWFrame * theFrame )
+{
+ KWTableFrameSet::Cell *daCell = dynamic_cast<KWTableFrameSet::Cell *>( theFrame->frameSet() );
+ Q_ASSERT( daCell );
+ if ( daCell ) {
+ kdDebug(32004) << " | |- row :" << daCell->firstRow() << endl;
+ kdDebug(32004) << " | |- col :" << daCell->firstColumn() << endl;
+ kdDebug(32004) << " | |- rows:" << daCell->rowSpan() << endl;
+ kdDebug(32004) << " | +- cols:" << daCell->columnSpan() << endl;
+ }
+}
+
+void KWTableFrameSet::printArrayDebug() {
+ kdDebug(32004) << " | Row/Cell arrays" << endl;
+ Q_ASSERT( m_rows == m_rowArray.size() );
+ for ( unsigned int row = 0; row < m_rows; ++row ) {
+ QString str = QString( " | Row %1: " ).arg( row );
+ for ( unsigned int col = 0; col < getColumns(); ++col )
+ str += QString("| 0x%1 ").arg( (unsigned long)(*m_rowArray[row])[col], 0, 16 );
+ kdDebug(32004) << str<< " |" << endl;
+ }
+}
+
+void KWTableFrameSet::printDebug() {
+ kdDebug(32004) << " | Table size (" << m_rows << "x" << getColumns() << ")" << endl;
+ kdDebug(32004) << " | col " << 0 << ": " << m_colPositions[0] << endl;
+ for(unsigned int i=1;i<m_colPositions.count(); ++i)
+ kdDebug(32004) << " | | " << i << ": " << m_colPositions[i] << endl;
+ kdDebug(32004) << " | row " << 0 << ": " << m_rowPositions[0] << endl;
+ for(unsigned int i=1;i<m_rowPositions.count(); ++i)
+ kdDebug(32004) << " | | " << i << ": " << m_rowPositions[i] << endl;
+
+ printArrayDebug();
+ KWFrameSet::printDebug();
+}
+
+#endif
+
+// ===
+
+KWTableFrameSet::Cell::Cell( KWTableFrameSet *table, unsigned int row, unsigned int col, const QString &/*name*/ ) :
+ KWTextFrameSet( table->m_doc,
+ // Generate frameset name from table_name+row+col
+ i18n("Hello dear translator :), 1 is the table name, 2 and 3 are row and column", "%1 Cell %2,%3")
+ .arg( table->name() ).arg(row).arg(col) )
+{
+ m_row = row;
+ m_col = col;
+ m_rows = 1;
+ m_cols = 1;
+ m_isJoinedCell = false;
+ setGroupManager( table );
+ table->addCell( this );
+}
+
+KWTableFrameSet::Cell::Cell( KWTableFrameSet *table, const Cell &original ) :
+ KWTextFrameSet( table->m_doc, original.m_name+'_' )
+{
+ m_row = original.m_row;
+ m_col = original.m_col;
+ m_rows = original.m_rows;
+ m_cols = original.m_cols;
+ m_isJoinedCell = original.m_isJoinedCell;
+ setGroupManager( table );
+ table->addCell( this );
+}
+
+KWTableFrameSet::Cell::~Cell()
+{
+}
+
+bool KWTableFrameSet::Cell::isAboveOrLeftOf( unsigned row, unsigned col ) const
+{
+ return ( m_row < row ) || ( ( m_row == row ) && ( m_col < col ) );
+}
+
+bool KWTableFrameSet::Cell::containsCell( unsigned row, unsigned col ) const
+{
+ return ( m_row <= row &&
+ m_col <= col &&
+ rowAfter() > row &&
+ columnAfter() > col );
+}
+
+void KWTableFrameSet::Cell::addFrame(KWFrame *_frame, bool recalc) {
+ if(groupmanager())
+ groupmanager()->addFrame(_frame, recalc);
+ KWTextFrameSet::addFrame(_frame, recalc);
+}
+
+void KWTableFrameSet::Cell::frameDeleted( KWFrame* frm, bool recalc )
+{
+ if(groupmanager())
+ groupmanager()->deleteFrame( frm, false, recalc );
+}
+
+double KWTableFrameSet::Cell::leftBorder() {
+ double b = frame(0)->leftBorder().width();
+ if(b==0.0)
+ return 0.0;
+ if(m_col==0) // left most cell
+ return b;
+ return (b / 2);
+}
+
+double KWTableFrameSet::Cell::rightBorder() {
+ double b=frame(0)->rightBorder().width();
+ if(b==0.0)
+ return 0.0;
+ if(m_col+m_cols==m_groupmanager->getColumns()) // right most cell
+ return b;
+ return (b / 2);
+}
+
+double KWTableFrameSet::Cell::topBorder() {
+ double b = frame(0)->topBorder().width();
+ if(b==0.0)
+ return 0.0;
+ if(m_row==0) // top most cell
+ return b;
+ return (b / 2);
+}
+
+double KWTableFrameSet::Cell::bottomBorder() {
+ double b = frame(0)->bottomBorder().width();
+ if(b==0.0)
+ return 0.0;
+ if(rowAfter() == m_groupmanager->m_rows) // bottom most cell
+ return b;
+ return (b / 2);
+}
+
+void KWTableFrameSet::Cell::setLeftBorder(KoBorder newBorder) {
+ KWFrame *f = frame(0);
+ double diff = f->leftBorder().width() - newBorder.width();
+ f->setLeftBorder(newBorder);
+
+ if((diff > 0.01 || diff < -0.01) && m_col!=0) {
+ diff = diff / 2; // if not outer edge only use halve
+ m_groupmanager->cell(m_row, m_col-1)->setRightBorder(newBorder);
+ }
+ f->setLeft(f->left() - diff);
+}
+
+void KWTableFrameSet::Cell::setRightBorder(KoBorder newBorder) {
+ KWFrame *f = frame(0);
+ double diff = f->rightBorder().width() - newBorder.width();
+ f->setRightBorder(newBorder);
+
+ if((diff > 0.01 || diff < -0.01) && m_col+m_cols!=m_groupmanager->getColumns()) {
+ diff = diff / 2; // if not outer edge only use halve
+ m_groupmanager->cell(m_row, m_col+1)->setLeftBorder(newBorder);
+ }
+ f->setRight(f->right() + diff);
+}
+
+void KWTableFrameSet::Cell::setTopBorder(KoBorder newBorder) {
+ KWFrame *f = frame(0);
+ double diff = f->topBorder().width() - newBorder.width();
+ f->setTopBorder(newBorder);
+
+ if((diff > 0.01 || diff < -0.01) && m_row!=0) {
+ diff = diff / 2; // if not outer edge only use halve
+ m_groupmanager->cell(m_row-1, m_col)->setBottomBorder(newBorder);
+ }
+ f->setTop(f->top() - diff);
+}
+
+void KWTableFrameSet::Cell::setBottomBorder(KoBorder newBorder) {
+ KWFrame *f = frame(0);
+ double diff = f->bottomBorder().width() - newBorder.width();
+ f->setBottomBorder(newBorder);
+
+ if((diff > 0.01 || diff < -0.01) && rowAfter() != m_groupmanager->m_rows) {
+ diff = diff / 2; // if not outer edge only use halve
+ m_groupmanager->cell(m_row+1, m_col)->setTopBorder(newBorder);
+ }
+ f->setBottom(f->bottom() + diff);
+}
+
+void KWTableFrameSet::Cell::setZOrder()
+{
+ QPtrListIterator<KWFrame> frameIt = frameIterator();
+ for ( ; frameIt.current(); ++frameIt )
+ {
+ (*frameIt)->setZOrder( kWordDocument()->maxZOrder( (*frameIt)->pageNumber() ) + 1 );
+ }
+}
+
+void KWTableFrameSet::Cell::drawContents( QPainter * painter, const QRect & crect,
+ const QColorGroup & cg, bool onlyChanged, bool resetChanged,
+ KWFrameSetEdit * edit, KWViewMode * viewMode, KWFrameViewManager *fvm )
+{
+ bool printing = painter->device()->devType() == QInternal::Printer;
+ bool drawPreviewLines = viewMode && viewMode->drawFrameBorders();
+ QRect cellRect = crect;
+ if(!printing && drawPreviewLines) {
+ // Make sure the clipping is changed so the preview lines (frame borders) are not overwritten.
+ QRect zoomedRect( m_doc->zoomRect(*frame(0)) );
+ QRect innerFrameRect( viewMode->normalToView( zoomedRect ) );
+ innerFrameRect.addCoords(1, 1, -1, -1); // move and shrink
+ cellRect = innerFrameRect.intersect(crect);
+ }
+ KWTextFrameSet::drawContents(painter, cellRect, cg, onlyChanged, resetChanged, edit, viewMode, fvm);
+}
+
+KWTableFrameSetEdit::~KWTableFrameSetEdit()
+{
+ if ( m_currentCell )
+ m_currentCell->terminate();
+ delete m_currentCell;
+}
+
+void KWTableFrameSetEdit::mousePressEvent( QMouseEvent * e, const QPoint & nPoint, const KoPoint & dPoint )
+{
+ setCurrentCell( dPoint );
+ if ( m_currentCell )
+ m_currentCell->mousePressEvent( e, nPoint, dPoint );
+}
+
+void KWTableFrameSetEdit::setCurrentCell( const KoPoint & dPoint )
+{
+ KWFrameSet *fs = tableFrameSet()->cellByPos( dPoint.x(), dPoint.y() );
+ KWTextFrameSet *textframeSet = dynamic_cast<KWTextFrameSet *>(fs);
+
+ if ( textframeSet&& textframeSet->protectContent() && !tableFrameSet()->kWordDocument()->cursorInProtectedArea())
+ return;
+
+ if ( fs && ( !m_currentCell || fs != m_currentCell->frameSet() ) )
+ setCurrentCell( fs );
+}
+
+void KWTableFrameSetEdit::setCurrentCell( KWFrameSet * fs, bool eraseSelection )
+{
+ bool oldProtectContent = false;
+ KWTextFrameSet *textframeSet=0L;
+ if ( m_currentCell )
+ textframeSet = dynamic_cast<KWTextFrameSet *>(m_currentCell->frameSet());
+ if ( textframeSet )
+ oldProtectContent = textframeSet->protectContent();
+
+ if ( m_currentCell )
+ {
+ m_currentCell->terminate(eraseSelection);
+ delete m_currentCell;
+ }
+ m_currentCell = fs->createFrameSetEdit( m_canvas );
+ textframeSet = dynamic_cast<KWTextFrameSet *>(m_currentCell->frameSet());
+ if ( textframeSet )
+ {
+ if ( oldProtectContent != textframeSet->protectContent())
+ {
+ m_canvas->kWordDocument()->updateTextFrameSetEdit();
+ }
+ }
+
+
+ m_currentFrame = fs->frame( 0 );
+ KWTextFrameSetEdit *textframeSetEdit = dynamic_cast<KWTextFrameSetEdit *>(m_currentCell);
+ if ( textframeSetEdit )
+ {
+ textframeSetEdit->ensureCursorVisible();
+ //refresh koruler
+ m_canvas->gui()->getView()->slotUpdateRuler();
+ }
+}
+
+KWFrameSetEdit* KWTableFrameSetEdit::currentTextEdit()
+{
+ return m_currentCell;
+}
+
+
+void KWTableFrameSetEdit::keyPressEvent( QKeyEvent * e )
+{
+ // This method handles the up/left/down/right navigation keys in tables
+ if ( !m_currentCell )
+ return;
+ KWTableFrameSet::Cell *cell = static_cast<KWTableFrameSet::Cell *>(m_currentCell->frameSet());
+ KWTextFrameSet *textframeSet = dynamic_cast<KWTextFrameSet *>(m_currentCell->frameSet());
+ bool moveToOtherCell = true;
+ if(textframeSet)
+ {
+ // don't move to an adjacent cell when we are selecting text
+ KoTextDocument * textdoc = textframeSet->textDocument();
+ if(textdoc->hasSelection( KoTextDocument::Standard ))
+ moveToOtherCell=false;
+ }
+ KWTableFrameSet::Cell *fs = 0L;
+
+ bool tab=false; // No tab key pressed
+ if(moveToOtherCell)
+ {
+ switch( e->key() ) {
+ case QKeyEvent::Qt::Key_Up:
+ {
+ if(!(static_cast<KWTextFrameSetEdit *>(m_currentCell))->cursor()->parag()->prev())
+ {
+ KWTableFrameSet* tableFrame=tableFrameSet();
+ int row = cell->firstRow() - 1;
+ int col = cell->firstColumn();
+ if (row < 0) { // Wrap at top of table
+ col--; // Goes to column on the left
+ row = tableFrame->getRows() - 1;
+ }
+ if (col < 0) { // It was the first column
+ // Maybe exit the table instead?
+ col = tableFrame->getColumns() - 1;
+ row = tableFrame->getRows() - 1;
+ }
+ fs=tableFrame->cell(row,col);
+ // Not needed. cell gives us the right one already
+ //if (fs && fs->firstRow() != static_cast<unsigned int>(row)) { // Merged cell
+ // fs=tableFrame->cell( row - fs->rowSpan() + 1, col );
+ //}
+ }
+ }
+ break;
+ case QKeyEvent::Qt::Key_Down:
+ {
+ if(!(static_cast<KWTextFrameSetEdit *>(m_currentCell))->cursor()->parag()->next())
+ {
+ KWTableFrameSet* tableFrame=tableFrameSet();
+ unsigned int row = cell->rowAfter();
+ unsigned int col = cell->firstColumn();
+ if(row >= tableFrame->getRows()) { // Wrap at bottom of table
+ row=0;
+ col++; // Go to next column
+ }
+ if(col >= tableFrame->getColumns()) { // It was the last one
+ // Maybe exit the table instead?
+ col=0;
+ row=0;
+ }
+ fs=tableFrame->cell(row,col);
+ Q_ASSERT( fs );
+ Q_ASSERT( fs->firstRow() == row ); // We can't end up in the middle of a merged cell here.
+ }
+ }
+ break;
+ case QKeyEvent::Qt::Key_Backtab:
+ tab=true;
+ if (e->state() & QKeyEvent::ControlButton)
+ break; // Break if tab was pressed with Control (in *any* key combination)
+ // Do not break
+ case QKeyEvent::Qt::Key_Left:
+ {
+ KoTextCursor *cur = (static_cast<KWTextFrameSetEdit *>(m_currentCell))->cursor();
+ if ( tab || (!cur->parag()->prev()&&cur->index()==0) )
+ {
+ KWTableFrameSet* tableFrame=tableFrameSet();
+ int row=cell->firstRow();
+ int col=cell->firstColumn() - 1;
+ if(col < 0) { // Wrap at first column
+ col = (int)tableFrame->getColumns()-1;
+ row--; // Go up
+ }
+ if(row < 0) { // It was the first row
+ // Maybe exit the table instead?
+ col = (int)tableFrame->getColumns()-1;
+ row = (int)tableFrame->getRows()-1;
+ }
+ fs=tableFrame->cell(row,col);
+ // Not needed. cell gives us the right one already
+ //if(fs && (int)fs->m_col != col) { // Merged cell
+ // fs=tableFrame->cell( row, col - fs->columnSpan() + 1 );
+ //}
+ }
+ }
+ break;
+ case QKeyEvent::Qt::Key_Tab:
+ tab=true;
+ if (e->state() & QKeyEvent::ControlButton)
+ break; // Break if tab was pressed with Control (in *any* key combination)
+ // Do not break
+ case QKeyEvent::Qt::Key_Right:
+ {
+ KoTextCursor *cur = (static_cast<KWTextFrameSetEdit *>(m_currentCell))->cursor();
+ if( tab || (!cur->parag()->next()&&cur->index()==cur->parag()->string()->length()-1) )
+ {
+ KWTableFrameSet* tableFrame=tableFrameSet();
+ unsigned int row = cell->firstRow();
+ unsigned int col = cell->columnAfter();
+ if(col >= tableFrame->getColumns()) { // Wrap after last column
+ col = 0;
+ row++; // Go down one row
+ }
+ if(row >= tableFrame->getRows()) { // It was the last row
+ // Maybe exit the table instead?
+ col = 0;
+ row = 0;
+ }
+ fs=tableFrame->cell(row,col);
+ Q_ASSERT( fs );
+ Q_ASSERT( fs->firstRow() == row ); // We can't end up in the middle of a merged cell here.
+ }
+ }
+ break;
+ }
+ }
+ if ( fs )
+ {
+ //don't switch to a protected cell protected when cursor in protected areas was disabled.
+ if ( fs->textObject()->protectContent() && !tableFrameSet()->kWordDocument()->cursorInProtectedArea())
+ return;
+ setCurrentCell( fs );
+ }
+ else if ( textframeSet )
+ {
+ if ( !textframeSet->textObject()->protectContent() )
+ {
+ if (tab && (e->state() & QKeyEvent::ControlButton) )
+ {
+ QKeyEvent event(QEvent::KeyPress, QKeyEvent::Qt::Key_Tab, 9, 0, QChar(9));
+ m_currentCell->keyPressEvent( &event );
+ }
+ else
+ m_currentCell->keyPressEvent( e );
+ }
+ else if(e->text().length() > 0)
+ KMessageBox::information(0L, i18n("Read-only content cannot be changed. No modifications will be accepted."));
+ }
+}
+
+void KWTableFrameSetEdit::keyReleaseEvent( QKeyEvent * e )
+{
+ if ( m_currentCell )
+ m_currentCell->keyReleaseEvent( e );
+}
+
+void KWTableFrameSetEdit::imStartEvent( QIMEvent* e )
+{
+ if ( m_currentCell )
+ m_currentCell->imStartEvent( e );
+}
+
+void KWTableFrameSetEdit::imComposeEvent( QIMEvent* e )
+{
+ if ( m_currentCell )
+ m_currentCell->imComposeEvent( e );
+}
+
+void KWTableFrameSetEdit::imEndEvent( QIMEvent* e )
+{
+ if ( m_currentCell )
+ m_currentCell->imEndEvent( e );
+}
+
+void KWTableFrameSetEdit::dragMoveEvent( QDragMoveEvent * e, const QPoint &n, const KoPoint &d )
+{
+ kdDebug(32004)<<"m_currentCell :"<<m_currentCell<<endl;
+ if ( m_currentCell )
+ {
+ KWFrameSet *fs = tableFrameSet()->cellByPos( d.x(), d.y() );
+ kdDebug(32004)<<"fs :"<<fs <<endl;
+ if(fs && fs != m_currentCell->frameSet())
+ setCurrentCell(fs, false);
+ if(m_currentCell)
+ m_currentCell->dragMoveEvent( e, n, d );
+ }
+ else
+ {
+ setCurrentCell( d );
+ kdDebug(32004)<<"after m_currentCell :"<<m_currentCell<<endl;
+ if(m_currentCell)
+ m_currentCell->dragMoveEvent( e, n, d );
+ }
+}
+
+void KWTableFrameSet::Row::addCell( Cell *cell )
+{
+ if ( m_cellArray.size() < cell->columnAfter())
+ m_cellArray.resize( cell->columnAfter() );
+ for ( uint col = cell->firstColumn() ; col < cell->columnAfter(); ++col )
+ m_cellArray.insert( col, cell );
+}
+
+void KWTableFrameSet::Row::removeCell( Cell* cell )
+{
+ for ( uint col = cell->firstColumn() ; col < cell->columnAfter(); ++col )
+ m_cellArray.remove( col );
+}
+
+template<>
+KWTableFrameSet::Cell*
+KWTableFrameSet::TableIterator<KWTableFrameSet::VISIT_CELL>::operator++()
+{
+ if(!m_cell) return 0;
+
+ Cell *ret = m_cell;
+
+ do{
+ // check for end of row first
+ if(m_table->cell(m_row,m_col)->lastColumn() >= m_limit[RIGHT] ) {
+ // now check for end of column
+ if (m_row >= m_limit[LOW]){
+ // at end of traversal
+ m_cell = 0;
+ break;
+ }
+ else {
+ // goto first grid position in next row
+ m_row += 1;
+ m_col = m_limit[LEFT];
+ }
+ }
+ else {
+ // goto next cell in row
+ m_col = m_table->cell(m_row, m_col)->columnAfter();
+ }
+
+ m_cell = m_table->cell(m_row,m_col);
+ } while( m_cell && !m_cell->isFirstGridPosnFast(m_row,m_col) );
+
+ return ret;
+}
+
+template<>
+KWTableFrameSet::Cell*
+KWTableFrameSet::TableIterator<KWTableFrameSet::VISIT_GRID>::operator++()
+{
+ if(!m_cell) return 0;
+
+ Cell *ret = m_cell;
+ // check for end of row
+ if(m_col == m_limit[RIGHT]) {
+ if(m_row == m_limit[LOW]) { // end of traversal
+ m_row = 0;
+ m_col = 0;
+ m_cell = 0;
+ }
+ else { // go to next row
+ m_row += 1;
+ m_col = m_limit[LEFT];
+ m_cell = m_table->cell(m_row, m_col);
+ }
+ }
+ else { // move to next cell in row
+ m_col += 1;
+ m_cell = m_table->cell(m_row, m_col);
+ }
+
+ return ret;
+}
+
+KWTableFrameSet::MarkedIterator::MarkedIterator(KWTableFrameSet *table) :
+ GridIter(table)
+{
+ // clear all the cell marks
+ for(GridIter cell(table); cell; ++cell)
+ cell->clearMark();
+
+ if ( current() ) {
+// kdDebug() << "MarkedIterator: visit: "
+// << QString("| 0x%1 ").arg((unsigned long)current(), 0, 16) << endl;
+ current()->setMark();
+ }
+}
+
+KWTableFrameSet::Cell *
+KWTableFrameSet::MarkedIterator::operator++()
+{
+ Cell *ret = GridIter::operator++();
+
+ while ( current() && current()->marked() ) {
+ GridIter::operator++();
+ }
+ if ( current() ) {
+// kdDebug() << "MarkedIterator: visit: "
+// << QString("| 0x%1 ").arg((unsigned long)current(), 0, 16) << endl;
+ current()->setMark();
+ }
+ return ret;
+}
+
+template<>
+KWTableFrameSet::TableIterator<KWTableFrameSet::CHECKED>::TableIterator(KWTableFrameSet *table):
+ m_table(table)
+{
+ Q_ASSERT(m_table);
+ set_limits(0, (int)m_table->getColumns() - 1, 0, (int)m_table->getRows() - 1);
+
+ Cell *c = 0;
+ for(uint i = m_limit[HIGH]; i <= m_limit[LOW]; ++i)
+ for(uint j = m_limit[LEFT]; j <= m_limit[RIGHT]; ++j) {
+
+ c = m_table->cell(i,j);
+ if(c) c->clearMark();
+ }
+ toFirstCell();
+}
+
+template<>
+KWTableFrameSet::Cell*
+KWTableFrameSet::TableIterator<KWTableFrameSet::CHECKED>::operator++ ()
+{
+
+ Cell *ret = m_cell;
+ if(!ret) return 0;
+
+ ret->setMark();
+ m_cell = 0;
+ uint i = m_row; uint j = m_col;
+
+ for(; i <= m_limit[LOW]; ++i) {
+
+ for(j = 0; j <= m_limit[RIGHT]; ++j) {
+ m_cell = m_table->cell(i,j);
+ if( m_cell && !m_cell->marked() ){
+ m_row = i; m_col = j;
+ goto out;
+ }
+ else if(i == m_limit[LOW] && j == m_limit[RIGHT]){
+ m_cell = 0;
+ goto out;
+ }
+ }
+ }
+
+ out:
+ return ret;
+}
+
+template<>
+KWTableFrameSet::Cell*
+KWTableFrameSet::TableIterator<KWTableFrameSet::CHECKED>::toFirstCell ()
+{
+ m_cell = 0;
+ for(uint i = m_limit[HIGH]; i <= m_limit[LOW]; ++i)
+ for(uint j = m_limit[LEFT]; j <= m_limit[RIGHT]; ++j) {
+ m_cell = m_table->cell(i,j);
+ if(m_cell) {
+ m_row = i; m_col = j;
+ goto out;
+ }
+ }
+
+ out:
+ return m_cell;
+}
+
+RemovedRow::RemovedRow() :
+ m_row(0), m_index(0), m_rowHeight(0.0)
+{
+
+}
+
+RemovedRow::~RemovedRow()
+{
+ // free cells as well ???
+ delete m_row;
+}
+
+KWTableFrameSet::Row *RemovedRow::takeRow()
+{
+ Q_ASSERT(m_row);
+ KWTableFrameSet::Row *ret = m_row;
+ m_row = 0;
+ return ret;
+}
+
+RemovedColumn::RemovedColumn()
+ : m_column(), m_removed(), m_index(0), m_width(0), m_initialized(false){ }
+
+
+#include "KWTableFrameSet.moc"
diff --git a/kword/KWTableFrameSet.h b/kword/KWTableFrameSet.h
new file mode 100644
index 00000000..92a5a867
--- /dev/null
+++ b/kword/KWTableFrameSet.h
@@ -0,0 +1,747 @@
+#ifndef KWTABLEFRAMESET_H
+#define KWTABLEFRAMESET_H
+/*
+ Copyright (C) 2001, S.R.Haque (srhaque@iee.org).
+ This file is part of the KDE project
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+
+DESCRIPTION
+
+ This file defines KWord tables. A table is a KWFrameSet, thus allowing its
+ internal structure to be invisible to the rest of kword. This is useful
+ since the internal structure of a table is itself a series of KWFrameSets
+ (one for each cell).
+*/
+
+#include "KWFrame.h"
+#include "KWTextFrameSet.h"
+
+#include <qptrlist.h>
+#include <qvaluevector.h>
+#include <qobject.h>
+#include <qstring.h>
+#include <KoRichText.h>
+
+class KWDocument;
+class KWTableFrameSetEdit;
+class QPainter;
+class KWAnchor;
+class KWordFrameSetIface;
+class KWFrameViewManager;
+
+class RemovedRow;
+class RemovedColumn;
+
+/**
+ * @brief This class implements tables by acting as the manager for
+ * the frame(set)s which make up the table cells.
+ *
+ * We have a cell structure which contains one frameset, because
+ * of the nature of the table this frameset will always hold
+ * exactly one frame. Therefore the terms cell, frameSet and frame
+ * can be used to describe the same thing: one table-cell
+ */
+class KWTableFrameSet : public KWFrameSet
+{
+ Q_OBJECT
+public:
+
+ /**
+ * Table cell
+ * @note A cell can be any type of FrameSet, but for now, we only support text!
+ */
+ class Cell : public KWTextFrameSet
+ {
+ unsigned int m_row, m_col;
+ unsigned int m_rows, m_cols;
+
+ bool m_isJoinedCell;
+ bool m_marker;
+ void calcIfJoinedCell() {
+ m_isJoinedCell = ( (m_rows > 1) || (m_cols > 1) );
+ }
+
+ public:
+ /// constructor
+ Cell( KWTableFrameSet *table, unsigned int row, unsigned int col, const QString & name = QString::null );
+ Cell( KWTableFrameSet *table, const Cell &original );
+ // destructor
+ virtual ~Cell();
+
+ uint firstRow() const { return m_row; }
+ uint firstColumn() const { return m_col; }
+ uint rowSpan() const { return m_rows; }
+ uint columnSpan() const { return m_cols; }
+
+ uint lastRow() const { return m_row + m_rows - 1; }
+ uint lastColumn() const { return m_col + m_cols - 1; }
+ uint rowAfter() const { return m_row + m_rows; }
+ uint columnAfter() const { return m_col + m_cols; }
+
+ void setFirstRow(uint row) { m_row = row; }
+ void setFirstColumn(uint col) { m_col = col; }
+ void setRowSpan(uint rows) {
+ m_rows = rows;
+ calcIfJoinedCell();
+ }
+ void setColumnSpan(uint cols) {
+ m_cols = cols;
+ calcIfJoinedCell();
+ }
+
+ bool isFirstGridPosn(uint row, uint col) const {
+ return (row == m_row) && (col == m_col);
+ }
+
+ bool isFirstGridPosnFast(uint row, uint col) const {
+ if(!m_isJoinedCell) return true;
+ return (row == m_row) && (col == m_col);
+ }
+ virtual void addFrame(KWFrame *_frame, bool recalc = true);
+ /// Called by deleteFrame when it really deletes a frame (remove=true), to remove it from the table too
+ virtual void frameDeleted( KWFrame* frm, bool recalc );
+
+ bool isAboveOrLeftOf( unsigned row, unsigned column ) const;
+ bool containsCell( unsigned row, unsigned column ) const;
+
+ double leftBorder();
+ double rightBorder();
+ double topBorder();
+ double bottomBorder();
+
+ void setLeftBorder(KoBorder newBorder);
+ void setRightBorder(KoBorder newBorder);
+ void setTopBorder(KoBorder newBorder);
+ void setBottomBorder(KoBorder newBorder);
+ /**
+ * set zorder for all frames in this cell
+ */
+ void setZOrder();
+ bool isJoinedCell() const { return m_isJoinedCell; }
+ void clearMark() { m_marker = false; }
+ void setMark() { m_marker = true; }
+ bool marked() const { return m_marker; }
+
+ /** Overloaded to not clear any preview borders. */
+ void drawContents( QPainter *painter, const QRect & crect,
+ const QColorGroup & cg, bool onlyChanged, bool resetChanged,
+ KWFrameSetEdit * edit, KWViewMode * viewMode,
+ KWFrameViewManager *frameViewManager );
+
+ };
+ friend class Cell;
+
+ /// Represents a row, for direct access to cells with m_rowArray[row][column]
+ class Row {
+ public:
+ Cell* operator[] ( uint i ) const { return i < size() ? m_cellArray[i] : 0; }
+ uint size() const { return m_cellArray.size(); }
+ uint count() const { return m_cellArray.count(); }
+
+ void addCell( Cell *cell );
+ void removeCell( Cell* cell );
+
+ /**
+ * @brief Array of cells in the row.
+ *
+ * If a cell has m_cols = N, N values in this array point to the same cell.
+ * (Same thing is a cell from a row above has m_rows > 1)
+ */
+ QPtrVector< Cell > m_cellArray;
+
+ };
+
+ /** The three different types of TableIterators */
+ enum VisitType {
+ /**
+ * This iterator visits each grid position once, ie every
+ * location in the m_rowArray rows. When some cells are joined, this
+ * iterator will visit those cells more than once.
+ */
+ VISIT_GRID = 1,
+
+ /**
+ * This iterator visits each cell in the table once, whether
+ * or not some of the cells are joined. If you want to visit all the cells
+ * fast and perform some read-only operation, this is the one to use.
+ */
+ VISIT_CELL = 2,
+ /**
+ * Like VISIT_CELL it also visits each cell once, but has some other benefits. Slower.
+ */
+ CHECKED = 3
+ };
+
+ /**
+ All the TableIterator templates are the same, except for the pre-increment
+ operator (operator++). There is a specialised version of this
+ operator method for each iterator type:
+
+ VISIT_GRID: This iterator visits each grid position once, ie every
+ location in the m_rowArray rows. When some cells are joined, this
+ iterator will visit those cells more than once.
+
+ VISIT_CELL: This iterator visits each cell in the table once, whether
+ or not some of the cells are joined. If you want to visit all the cells
+ fast and perform some read-only operation, this is the one to use.
+
+ CHECKED: Also visits each cell once, but has some other benefits. Slower.
+
+ Note that all the iterators have restrictions on the state that the
+ table data structures are in before and while they are being used.
+ This includes m_rowArray, the Rows and Cells but not m_colPositions and
+ m_rowPositions, as they are not used during the traversal.
+ The conditions include:
+ <UL>
+ <LI>( A ) All positions in m_rowArray must be occupied by a valid cell, ie must
+ not be null.</LI>
+ <LI>( B ) The Cell instance variables (m_row, m_rows, etc) must correctly
+ correspond to where the cells are in m_rowArray.</LI>
+ <LI>( C ) The m_rows and m_cols instance variables of the table are also correct.</LI>
+ </UL>
+ Taken together, these conditions are pretty much equivalent to the
+ validate() function passing. These conditions may not hold in the middle
+ of a method when table data structures are being manipulated.
+
+ This table shows what conditions are necessary for each type of iterator:
+
+ <TABLE>
+ <TR><TD> </TD><TD>A</TD><TD>B</TD><TD>C</TD></TR>
+ <TR><TD>TableIterator\<VISIT_GRID\></TD><TD>x</TD><TD> </TD><TD>x</TD></TR>
+ <TR><TD>TableIterator\<VISIT_CELL\></TD><TD>x</TD><TD>x</TD><TD>x</TD></TR>
+ <TR><TD>TableIterator\<CHECKED\> </TD><TD> </TD><TD> </TD><TD>x</TD></TR>
+ <TR><TD>MarkedIterator </TD><TD>x</TD><TD> </TD><TD>x</TD></TR>
+ </TABLE>
+
+ The only iterator that can be used when there are null positions in the
+ table is the checked iterator.
+ Note that both the Checked and Marked Iterators traverse the table twice,
+ once to clear the m_marked members in the cells (done in constructor) and
+ then again to do the actual traversal. Because they use m_marked, only one
+ of these iterators can be used at once.
+
+ Don't use these classes directly in code, use the provided typedefs. That
+ makes it easy to do more crazy template stuff later on. :-) Templates
+ are used here rather than inheritance to avoid virtual call overhead.
+ */
+ template<int VisitStyle = VISIT_CELL>
+ class TableIterator {
+ public:
+ /**
+ * @param table The table to iterate over. The current item is set to the Cell
+ * at row 0, column 0
+ */
+ TableIterator (KWTableFrameSet *table);
+
+ Cell* toFirstCell ();
+ void goToCell(Cell*);
+
+ operator Cell* () const { return m_cell; }
+ Cell * current() const;
+ Cell * operator->() { return m_cell; }
+ Cell * operator++ ();
+
+ protected:
+ KWTableFrameSet *m_table;
+ void set_limits(uint left, uint right, uint high, uint low)
+ {
+ m_limit[LEFT] = left;
+ m_limit[RIGHT] = right;
+ m_limit[HIGH] = high;
+ m_limit[LOW] = low;
+ }
+ private:
+
+ Cell *m_cell;
+ uint m_row;
+ uint m_col;
+
+ enum Direction {LEFT, RIGHT, HIGH, LOW};
+ static const uint DIRECTION_SIZE = 4;
+ uint m_limit[DIRECTION_SIZE];
+ };
+
+ typedef TableIterator<VISIT_CELL> TableIter;
+ typedef TableIterator<VISIT_GRID> GridIter;
+ typedef TableIterator<CHECKED> CheckedIter;
+
+ /**
+ * This iterator does not look at the Cell instance variables
+ * during traversal, (except m_marker), so they can be safely
+ * changed during the traversal. However, to the user it does
+ * not visit every grid position, it visits each cell once.
+ * (in spite of the fact that it inherits from a grid-visiting
+ * iterator).
+ * Only one MarkedIterator can be used at once. See TableIterator
+ */
+ class MarkedIterator : public GridIter {
+ public:
+ MarkedIterator(KWTableFrameSet *table);
+ Cell *operator++(); // overridden from base but not virtual
+
+ };
+
+
+ /** The type of frameset. Use this to differentiate between different instantiations of
+ * the framesets. Each implementation will return a different frameType.
+ */
+ virtual FrameSetType type() const { return FT_TABLE; }
+
+ virtual KWordFrameSetIface* dcopObject();
+
+ virtual void addTextFrameSets( QPtrList<KWTextFrameSet> & lst, bool onlyReadWrite =false );
+
+ /// constructor
+ KWTableFrameSet( KWDocument *_doc, const QString & name );
+ /// destructor
+ virtual ~KWTableFrameSet();
+
+ virtual KWFrameSetEdit * createFrameSetEdit( KWCanvas * canvas );
+
+ /**
+ * @param emptyRegion The region is modified to subtract the areas painted, thus
+ * allowing the caller to determine which areas remain to be painted.
+ * @param crect the clip rect, outside which nothing is important
+ * @param viewMode the current view mode
+ */
+ virtual void createEmptyRegion( const QRect & crect, QRegion & emptyRegion, KWViewMode *viewMode );
+ void drawBorders( QPainter& painter, const QRect &crect, KWViewMode *viewMode );
+ virtual void drawContents( QPainter * painter, const QRect & crect,
+ const QColorGroup & cg, bool onlyChanged, bool resetChanged,
+ KWFrameSetEdit *edit, KWViewMode *viewMode,
+ KWFrameViewManager *frameViewManager );
+ /// Dummy since we reimplement drawContents
+ virtual void drawFrame(KWFrame *, QPainter *, const QRect &, const QRect&,
+ const QPoint&,
+ KWFrame *, const QColorGroup &, bool, bool,
+ KWFrameSetEdit *, KWViewMode *, bool ) {}
+
+ // Frameset management
+ Cell *cell( unsigned int row, unsigned int column ) const;
+ Cell *cellByPos( double x, double y ) const;
+
+ enum CellSize {
+ TblAuto = 0,
+ TblManual
+ };
+
+ /**
+ * Calculate the absolute size of the complete table.
+ * From the first cell to the last, including page breaks et.
+ * @return KoRect which outlines the whole of the table.
+ */
+ KoRect boundingRect();
+
+ /**
+ * Layout all cells to fit inside the rect, cells will however use a minimum size, so
+ * the table might end up bigger.
+ */
+ void setBoundingRect( KoRect rect, CellSize widthMode, CellSize heightMode );
+
+ /**
+ * Calculate the top postion of the cell(s) in the leftmost column
+ * @return double table leftmost position
+ */
+ double topWithoutBorder();
+
+ /**
+ * Calculate the top postion of the cell(s) in the top row
+ * @return double table top position
+ */
+ double leftWithoutBorder();
+
+ /**
+ * change the width of the table, keeping the proportions of the cells
+ * (if one is wider than the others, it is still wider after resize)
+ */
+ void resizeWidth( double width );
+
+ /** resize and position all cells */
+ void recalcCols(uint column, uint row);
+ void recalcRows(uint column, uint row);
+
+ /** move a column edge (i.e. col can be 0 to getCols()+1) */
+ void resizeColumn( unsigned int col, double x );
+ /** move a row edge (i.e. row can be 0 to getRows()+1) */
+ void resizeRow( unsigned int row, double y );
+
+ double columnSize( unsigned int col );
+ double rowSize( unsigned int col );
+
+ /** return the number of the column edge closest to x (between 0 and getCols()+1) */
+ int columnEdgeAt( double x ) const;
+ /** return the number of the row edge closest to x (between 0 and getRows()+1) */
+ int rowEdgeAt( double y ) const;
+
+ /** returns the number of rows */
+ unsigned int getRows() const { return m_rows; }
+ /** returns the number of columns */
+ unsigned int getColumns() const { return m_cols; }
+
+ /** returns the number of cells the table contains, this includes
+ * temporary headers. */
+ unsigned int getNumCells()const { return m_nr_cells; }
+
+
+ /** move the whole of the table, this is mainly for anchored frames. */
+ void moveBy( double dx, double dy );
+
+ /** insert a row of new cells, use the getCols() call to decide how many cells are created */
+ void insertNewRow( uint _idx, bool _recalc = true, bool _removeable = false );
+ /** insert a column of new cells use the getRows() call to decide how many cells are created */
+ void insertNewColumn( uint _idx, double width = KWTableFrameSet::m_sDefaultColWidth);
+
+ /** Remove all the cells in a certain row */
+ void deleteRow( uint _idx, RemovedRow &rr, bool _recalc = true);
+
+ /** remove all the cells in a certain column */
+ void deleteColumn( uint _idx, RemovedColumn &rc);
+
+ /** replace a row that was removed with deleteRow() */
+ void reInsertRow(RemovedRow &row);
+ /** replace a column that was removed with deleteColumn() */
+ void reInsertColumn(RemovedColumn &col);
+
+ /** release the constrains of the table and allow all frames to be
+ * edited apart from each other. (ps. there is no way back..) */
+ void ungroup();
+
+ void group();
+
+ bool isActive()const { return m_active; }
+
+ /** merge cells to one cell. Will loose all text not in top-left cell
+ * @param firstColumn the first column of the square of columns that will be used to merge
+ * @param firstRow the first row
+ * @param endColumn the last column that will end up in the merged cell
+ * @param endRow last row
+ */
+ KCommand *joinCells(unsigned int firstColumn,unsigned int firstRow, unsigned int endColumn,unsigned int endRow);
+ /**
+ * split one cell into a number of cells and return a command for undo purposes.
+ * @param intoRows the amount of rows the cell should be split into
+ * @param intoColumns the amount of columns the cell should be split into
+ * @param column the column of the cell to be split
+ * @param row the row of the cell to be split
+ * @param listFrameSet needed for undo reasons
+ * @param listFrame needed for undo reasons
+ */
+ KCommand * splitCell(unsigned int intoRows, unsigned int intoColumns, unsigned int column,
+ unsigned int row, QPtrList<KWFrameSet> listFrameSet=QPtrList<KWFrameSet>(),
+ QPtrList<KWFrame>listFrame=QPtrList<KWFrame>() );
+
+ /** display formatting information */
+ void viewFormatting( QPainter &painter, int zoom );
+ /** do a number of complex tests to test the validity of the table. Missing/duplicate cells
+ * and wrong values will be detected (and corrected) */
+ void validate();
+
+ /** override save so we save in table style.. */
+ virtual QDomElement save( QDomElement &parentElem, bool saveFrames = true );
+
+ virtual void saveOasis( KoXmlWriter&, KoSavingContext&, bool saveFrames ) const;
+ void loadOasis( const QDomElement& tag, KoOasisContext& context );
+ virtual bool canBeSavedAsInlineCharacter() const { return false; }
+
+ /** load one cell */
+ Cell* loadCell( QDomElement &frameElem, bool loadFrames = true, bool useNames = true );
+
+ /** from and to XML - used when copying and pasting a table */
+ virtual QDomElement toXML( QDomElement &parentElem, bool saveFrames = true );
+ virtual void fromXML( QDomElement &framesetElem, bool loadFrames = true, bool useNames = true );
+
+ /** Contribute to the document statistics */
+ virtual int paragraphs();
+ virtual int paragraphsSelected();
+ virtual bool statistics( QProgressDialog *progress, ulong & charsWithSpace, ulong & charsWithoutSpace, ulong & words,
+ ulong & sentences, ulong & syllables,ulong & lines, bool selected );
+
+ virtual void finalize();
+ virtual void invalidate();
+ virtual void layout();
+
+ virtual void updateFrames( int flags = 0xff );
+
+ /* Overloaded methods, look for docu in kwframe.h */
+ virtual void moveFloatingFrame( int frameNum, const KoPoint &position );
+ virtual KoSize floatingFrameSize( int frameNum = 0 );
+ virtual KCommand * anchoredObjectCreateCommand( int frameNum );
+ virtual KCommand * anchoredObjectDeleteCommand( int frameNum );
+ virtual KWAnchor * createAnchor( KoTextDocument *txt, int frameNum );
+
+ virtual void setVisible( bool v );
+ virtual bool canRemovePage( int num );
+
+ /** Add a cell to this table, the cell should already have info like row, col and should
+ * already have a frame.
+ */
+ void addCell( Cell *cell );
+
+ /** Remove a cell from this table (either to delete it, or to move it)
+ */
+ void removeCell( Cell* cell );
+
+ // The normal mechanism doesn't apply to tables; cells are protected individually
+ // (in terms of data; the GUI has an item for protecting all cells at once)
+ virtual void setProtectContent ( bool ) {}
+ virtual bool protectContent() const { return false; }
+
+ virtual KWTextFrameSet* nextTextObject( KWFrameSet * );
+ /**
+ * Sets zOrder for all cells in this table
+ */
+ void setZOrder();
+
+ QByteArray convertTableToText();
+
+#ifndef NDEBUG
+ virtual void printDebug( KWFrame * frame );
+ virtual void printDebug();
+ void printArrayDebug();
+#endif
+ static const uint m_sDefaultColWidth = 60;
+protected:
+ /* Overloaded methods, look for docu in kwframe.h */
+ /// \overload KWFrameSet::deleteAnchors
+ virtual void deleteAnchors();
+ /// \overload KWFrameSet::createAnchors
+ virtual void createAnchors( KoTextParag * parag, int index, bool placeHolderExists = false, bool repaint = true );
+
+private:
+ void addCellToArray( Cell* cell );
+ void afterLoadingCell( Cell* cell );
+ void parseInsideOfTable( const QDomElement& parent, KoOasisContext& context,
+ const QMemArray<double> & columnLefts, uint& row, uint& column,
+ double currentRowHeight );
+ void loadOasisCell( const QDomElement& element, KoOasisContext& context,
+ const QMemArray<double> & columnLefts, uint row, uint column,
+ double currentRowHeight );
+
+ /**
+ * @brief position an individual cell in the grid
+ *
+ * Adjusts the size of the cell frames.
+ * It computes the sizes based on:
+ * <ol>
+ * <li>The values in the m_colPositions and m_rowPositions arrays.
+ * <li>The width of the Cell borders.
+ * </ol>
+ */
+ void position(Cell *theCell, bool setMinFrameHeight=false);
+
+ /**
+ * @brief Returns the absolute top-position of the row in the grid
+ *
+ * Returns a double value from m_rowPositions. This is either the bottom
+ * or top position of the row of cells @p row. Note that you cannot index
+ * directly into m_rowPositions from a row value obtained from a cell,
+ * eg cell->firstRow(), because of the extra elements in m_rowPositions when
+ * the table spans multiple pages.
+ */
+ double getPositionOfRow(unsigned int row, bool bottom=false);
+
+ void insertEmptyColumn(uint index);
+ /**
+ * insert a row in m_rowArray at position index. rows after
+ * the inserted row are moved back.
+ */
+ void insertRowVector(uint index, Row *row);
+ /**
+ * remove the row from m_rowArray at position index.
+ * rows after are moved forward
+ * @return the removed row
+ */
+ Row* removeRowVector(uint index);
+
+private:
+ unsigned int m_rows, m_cols, m_nr_cells;
+ bool m_active;
+ QPtrVector< Row > m_rowArray;
+
+ /** The list of page boundaries.
+ * Each page the table spans has an entry in this list which points to the last _line_
+ * on a page.
+ * For a 1 page table there is no page break; and therefor for such tables this list is
+ * empty.
+ */
+ QValueList<unsigned int> m_pageBoundaries;
+ unsigned int m_redrawFromCol;
+ QValueList<double> m_rowPositions, m_colPositions;
+};
+
+
+// all three templates specialise operator++
+template<>
+KWTableFrameSet::Cell*
+KWTableFrameSet::TableIterator<KWTableFrameSet::VISIT_CELL>::operator++ ();
+
+template<>
+KWTableFrameSet::Cell*
+KWTableFrameSet::TableIterator<KWTableFrameSet::VISIT_GRID>::operator++ ();
+
+template<>
+KWTableFrameSet::Cell*
+KWTableFrameSet::TableIterator<KWTableFrameSet::CHECKED>::operator++ ();
+
+template<int VisitStyle>
+KWTableFrameSet::TableIterator<VisitStyle>::TableIterator(KWTableFrameSet *table) :
+ m_table(table)
+{
+ Q_ASSERT(m_table);
+ set_limits(0, m_table->getColumns() - 1, 0, m_table->getRows() - 1);
+ toFirstCell();
+}
+
+// CHECKED specialises the constructor
+template<>
+KWTableFrameSet::TableIterator<KWTableFrameSet::CHECKED>::TableIterator(KWTableFrameSet *table);
+
+
+template<int VisitStyle>
+KWTableFrameSet::Cell*
+KWTableFrameSet::TableIterator<VisitStyle>::toFirstCell (){
+ m_cell = m_table->cell(m_limit[HIGH], m_limit[LEFT]);
+ Q_ASSERT(m_cell);
+ if ( !m_cell )
+ return 0;
+ m_row = m_cell->firstRow();
+ m_col = m_cell->firstColumn();
+ return m_cell;
+}
+
+template<int VisitStyle>
+void
+KWTableFrameSet::TableIterator<VisitStyle>::goToCell(KWTableFrameSet::Cell *cell)
+{
+ m_cell = cell;
+ Q_ASSERT( m_cell );
+ if ( m_cell )
+ {
+ m_row = m_cell->firstRow();
+ m_col = m_cell->firstColumn();
+ }
+}
+
+// CHECKED specialises to first cell
+template<>
+KWTableFrameSet::Cell*
+KWTableFrameSet::TableIterator<KWTableFrameSet::CHECKED>::toFirstCell ();
+
+
+template<int VisitStyle>
+KWTableFrameSet::Cell*
+KWTableFrameSet::TableIterator<VisitStyle>::current() const {
+ return m_cell;
+}
+
+/**
+ * RemovedRow and RemovedColumn implement the Memento design pattern
+ */
+class RemovedRow {
+
+ KWTableFrameSet::Row *m_row;
+ /// The row index that this row used to occupy
+ uint m_index;
+ double m_rowHeight;
+
+ uint index() const { return m_index; }
+ double height() const { return m_rowHeight; }
+ KWTableFrameSet::Row *takeRow();
+ KWTableFrameSet::Row *row() { return m_row; }
+
+ friend class KWTableFrameSet;
+public:
+ RemovedRow();
+ ~RemovedRow();
+};
+
+class RemovedColumn {
+
+ QPtrList<KWTableFrameSet::Cell> m_column;
+ QValueList<bool> m_removed;
+ uint m_index;
+ double m_width;
+ bool m_initialized;
+
+ friend class KWTableFrameSet;
+public:
+ RemovedColumn();
+};
+
+/**
+ * @brief The object created to edit this table
+ *
+ * In fact at a given moment,
+ * it edits one cell (frameset) of the table, the one in which the cursor is.
+ */
+class KWTableFrameSetEdit : public KWFrameSetEdit
+{
+public:
+ KWTableFrameSetEdit( KWTableFrameSet * fs, KWCanvas * canvas )
+ : KWFrameSetEdit( fs, canvas ), m_currentCell( 0L ) {}
+ virtual ~KWTableFrameSetEdit();
+
+ KWTableFrameSet * tableFrameSet() const {
+ return static_cast<KWTableFrameSet *>( m_fs );
+ }
+
+ virtual KWFrameSetEdit* currentTextEdit();
+
+ KWFrameSetEdit* currentCell() const { return m_currentCell; }
+
+ // Forward all events to the current cell
+ virtual void keyPressEvent( QKeyEvent * e );
+ virtual void keyReleaseEvent( QKeyEvent * e );
+ virtual void imStartEvent( QIMEvent* e );
+ virtual void imComposeEvent( QIMEvent* e );
+ virtual void imEndEvent( QIMEvent* e );
+ virtual void mousePressEvent( QMouseEvent * e, const QPoint &, const KoPoint & );
+ virtual void mouseMoveEvent( QMouseEvent * e, const QPoint & n, const KoPoint & d )
+ { if ( m_currentCell ) m_currentCell->mouseMoveEvent( e, n, d ); }
+ virtual void mouseReleaseEvent( QMouseEvent * e, const QPoint & n, const KoPoint & d )
+ { if ( m_currentCell ) m_currentCell->mouseReleaseEvent( e, n, d ); }
+ virtual void mouseDoubleClickEvent( QMouseEvent * e, const QPoint & n, const KoPoint & d )
+ { if ( m_currentCell ) m_currentCell->mouseDoubleClickEvent( e, n, d ); } // TODO check current cell
+
+ virtual void dragEnterEvent( QDragEnterEvent * e )
+ { if ( m_currentCell ) m_currentCell->dragEnterEvent( e ); }
+ virtual void dragMoveEvent( QDragMoveEvent * e, const QPoint &n, const KoPoint &d );
+ virtual void dragLeaveEvent( QDragLeaveEvent * e )
+ { if ( m_currentCell ) m_currentCell->dragLeaveEvent( e ); }
+ virtual void dropEvent( QDropEvent * e, const QPoint &n, const KoPoint &d, KWView* view )
+ { if ( m_currentCell ) m_currentCell->dropEvent( e, n, d, view ); } // TODO check current cell
+
+ virtual void focusInEvent() { if ( m_currentCell ) m_currentCell->focusInEvent(); }
+ virtual void focusOutEvent() { if ( m_currentCell ) m_currentCell->focusOutEvent(); }
+ virtual void copy() { if ( m_currentCell ) m_currentCell->copy(); }
+ virtual void cut() { if ( m_currentCell ) m_currentCell->cut(); }
+ virtual void paste() { if ( m_currentCell ) m_currentCell->paste(); }
+ /// \note should selectAll select all cells ? etc.
+ virtual void selectAll() { if ( m_currentCell ) m_currentCell->selectAll(); }
+
+ /// Set the cell which is currently being edited
+ void setCurrentCell( KWFrameSet * fs, bool eraseSelection=true );
+ /// Set the cell which is currently being edited
+ void setCurrentCell( const KoPoint & dPoint );
+
+ void showPopup( KWFrame* frame, KWView* view, const QPoint & _point );
+
+protected:
+ KWFrameSetEdit * m_currentCell;
+
+};
+#endif
diff --git a/kword/KWTableStyle.cpp b/kword/KWTableStyle.cpp
new file mode 100644
index 00000000..d8bb83a8
--- /dev/null
+++ b/kword/KWTableStyle.cpp
@@ -0,0 +1,219 @@
+/* This file is part of the KDE project
+ Copyright (C) 2002 Nash Hoogwater <nrhoogwater@wanadoo.nl>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; using
+ version 2 of the License.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+*/
+
+#include "KWTableStyle.h"
+#include "KWDocument.h"
+#include "KWFrame.h"
+
+#include <KoGenStyles.h>
+#include <KoOasisStyles.h>
+#include <KoOasisContext.h>
+#include <KoXmlNS.h>
+
+#include <kdebug.h>
+#include <klocale.h>
+#include <qdom.h>
+
+KWTableStyleCollection::KWTableStyleCollection()
+ : KoUserStyleCollection( QString::fromLatin1( "table" ) )
+{
+}
+
+void KWTableStyleCollection::saveOasis( KoGenStyles& mainStyles, KoSavingContext& savingContext ) const
+{
+ if ( !isDefault() ) {
+ for ( QValueList<KoUserStyle *>::const_iterator styleIt = m_styleList.begin(), styleEnd = m_styleList.end() ; styleIt != styleEnd ; ++styleIt )
+ {
+ KWTableStyle* style = static_cast<KWTableStyle *>( *styleIt );
+ style->saveOasis( mainStyles, savingContext );
+ }
+ }
+}
+
+int KWTableStyleCollection::loadOasisStyles( KoOasisContext& context, const KoStyleCollection& paragraphStyles, const KWFrameStyleCollection& frameStyles )
+{
+ QValueVector<QDomElement> userStyles = context.oasisStyles().userStyles();
+ bool defaultStyleDeleted = false;
+ int stylesLoaded = 0;
+ for (unsigned int item = 0; item < userStyles.count(); item++) {
+ QDomElement styleElem = userStyles[item];
+ Q_ASSERT( !styleElem.isNull() );
+
+ if ( styleElem.attributeNS( KoXmlNS::style, "family", QString::null ) != "table-cell" )
+ continue;
+
+ if ( !defaultStyleDeleted ) {
+ KWTableStyle *s = findStyle( defaultStyleName() );
+ //kdDebug() << "KWTableStyleCollection::loadOasisStyles looking for " << defaultStyleName() << ", to delete it. Found " << s << endl;
+ if(s) // delete the standard style.
+ removeStyle(s);
+ defaultStyleDeleted = true;
+ }
+
+ KWTableStyle *sty = new KWTableStyle( QString::null, 0, 0 );
+ // Load the style
+ sty->loadOasis( styleElem, context, paragraphStyles, frameStyles );
+ // Style created, now let's try to add it
+ sty = static_cast<KWTableStyle *>( addStyle( sty ) );
+
+ kdDebug() << " Loaded table cell style " << sty->name() << " - now " << count() << " styles" << endl;
+ ++stylesLoaded;
+ }
+ return stylesLoaded;
+}
+
+/******************************************************************/
+/* Class: KWTableStyle */
+/******************************************************************/
+
+KWTableStyle::KWTableStyle( const QString & name, KoParagStyle * _paragStyle, KWFrameStyle * _frameStyle )
+ : KoUserStyle( name )
+{
+ m_paragStyle = _paragStyle;
+ m_frameStyle = _frameStyle;
+}
+
+KWTableStyle::KWTableStyle( QDomElement & parentElem, KWDocument *_doc, int /*docVersion*/ )
+ : KoUserStyle( QString::null )
+{
+ QDomElement element = parentElem.namedItem( "NAME" ).toElement();
+ if ( ( !element.isNull() ) && ( element.hasAttribute("value") ) ) {
+ m_name = element.attribute( "value" );
+ m_displayName = i18n( "Style name", m_name.utf8() );
+ } else
+ kdWarning() << "No NAME tag in table style!" << endl;
+
+ element = parentElem.namedItem( "PFRAMESTYLE" ).toElement();
+ m_frameStyle = 0;
+ if ( ( !element.isNull() ) && ( element.hasAttribute("name") ) )
+ m_frameStyle = _doc->frameStyleCollection()->findStyleByDisplayName( element.attribute( "name" ) );
+
+ if ( !m_frameStyle ) {
+ if ( !_doc->frameStyleCollection()->isEmpty() )
+ m_frameStyle = _doc->frameStyleCollection()->frameStyleAt( 0 );
+ else { // Isn't possible ( I hope )
+ KWFrameStyle * standardFrameStyle = new KWFrameStyle( "Plain" );
+ standardFrameStyle->setBackgroundColor(QColor("white"));
+ standardFrameStyle->setTopBorder(KoBorder(QColor("black"),KoBorder::SOLID,0));
+ standardFrameStyle->setRightBorder(KoBorder(QColor("black"),KoBorder::SOLID,0));
+ standardFrameStyle->setLeftBorder(KoBorder(QColor("black"),KoBorder::SOLID,0));
+ standardFrameStyle->setBottomBorder(KoBorder(QColor("black"),KoBorder::SOLID,0));
+ _doc->frameStyleCollection()->addStyle( standardFrameStyle );
+ m_frameStyle = _doc->frameStyleCollection()->frameStyleAt( 0 );
+ }
+ }
+
+ element = parentElem.namedItem( "PSTYLE" ).toElement();
+ m_paragStyle = 0;
+ if ( ( !element.isNull() ) && ( element.hasAttribute("name") ) )
+ m_paragStyle = _doc->styleCollection()->findStyleByDisplayName( element.attribute( "name" ) );
+
+ if ( !m_paragStyle ) {
+ if ( _doc->styleCollection()->styleList().count()>0 )
+ m_paragStyle = _doc->styleCollection()->styleAt( 0 );
+ else { // Isn't possible ( I hope )
+ KoParagStyle * standardStyle = new KoParagStyle( "Standard" );
+ standardStyle->format().setFont( _doc->defaultFont() );
+ _doc->styleCollection()->addStyle( standardStyle );
+ m_paragStyle = _doc->styleCollection()->styleAt( 0 );
+ }
+ }
+}
+
+void KWTableStyle::operator=( const KWTableStyle &rhs )
+{
+ KoUserStyle::operator=( rhs );
+ m_paragStyle = rhs.paragraphStyle();
+ m_frameStyle = rhs.frameStyle();
+}
+
+void KWTableStyle::saveTableStyle( QDomElement & parentElem )
+{
+ QDomDocument doc = parentElem.ownerDocument();
+ QDomElement element = doc.createElement( "NAME" );
+ parentElem.appendChild( element );
+ element.setAttribute( "value", displayName() );
+
+ if (m_frameStyle)
+ {
+ element = doc.createElement( "PFRAMESTYLE" );
+ parentElem.appendChild( element );
+ element.setAttribute( "name", m_frameStyle->displayName() );
+ }
+ if (m_paragStyle)
+ {
+ element = doc.createElement( "PSTYLE" );
+ parentElem.appendChild( element );
+ element.setAttribute( "name", m_paragStyle->displayName() );
+ }
+
+}
+
+KWTableStyle *KWTableStyle::loadStyle( QDomElement & parentElem, KWDocument *_doc, int docVersion )
+{
+ return new KWTableStyle( parentElem, _doc, docVersion );
+}
+
+void KWTableStyle::saveOasis( KoGenStyles& mainStyles, KoSavingContext& /*savingContext*/ ) const
+{
+ KoGenStyle tableCellStyle( KWDocument::STYLE_TABLE_CELL_USER, "table-cell" );
+ tableCellStyle.addAttribute( "style:display-name", displayName() );
+ if ( m_frameStyle )
+ tableCellStyle.addProperty( "koffice:frame-style-name", m_frameStyle->name() );
+ if ( m_paragStyle )
+ tableCellStyle.addProperty( "koffice:paragraph-style-name", m_paragStyle->name() );
+
+ // try to preserve existing internal name, if it looks adequate (no spaces)
+ // ## TODO: check XML-Schemacs NCName conformity
+ const bool nameIsConform = !m_name.isEmpty() && m_name.find( ' ' ) == -1;
+ QString newName;
+ if ( nameIsConform )
+ newName = mainStyles.lookup( tableCellStyle, m_name, KoGenStyles::DontForceNumbering );
+ else
+ newName = mainStyles.lookup( tableCellStyle, "tc" );
+ const_cast<KWTableStyle*>( this )->m_name = newName;
+}
+
+void KWTableStyle::loadOasis( QDomElement & styleElem, KoOasisContext& context, const KoStyleCollection& paragraphStyles, const KWFrameStyleCollection& frameStyles )
+{
+ // Load name
+ m_name = styleElem.attributeNS( KoXmlNS::style, "name", QString::null );
+ m_displayName = styleElem.attributeNS( KoXmlNS::style, "display-name", QString::null );
+ if ( m_displayName.isEmpty() )
+ m_displayName = m_name;
+ kdDebug() << k_funcinfo << m_name << " " << m_displayName << endl;
+
+ KoStyleStack& styleStack = context.styleStack();
+ styleStack.setTypeProperties( "table-cell" );
+
+ styleStack.save();
+ context.addStyles( &styleElem, "table-cell" ); // Load all parents - only because we don't support inheritance.
+
+ const QString frameStyleName = styleStack.attributeNS( KoXmlNS::koffice, "frame-style-name" );
+ m_frameStyle = frameStyles.findStyle( frameStyleName );
+ if ( !m_frameStyle )
+ kdWarning(32001) << "Frame style " << frameStyleName << " not found!" << endl;
+
+ const QString paragraphStyleName = styleStack.attributeNS( KoXmlNS::koffice, "paragraph-style-name" );
+ m_paragStyle = paragraphStyles.findStyle( paragraphStyleName );
+ if ( !m_paragStyle )
+ kdWarning(32001) << "Paragraph style " << paragraphStyleName << " not found!" << endl;
+
+ styleStack.restore();
+}
diff --git a/kword/KWTableStyle.h b/kword/KWTableStyle.h
new file mode 100644
index 00000000..b63d8e0c
--- /dev/null
+++ b/kword/KWTableStyle.h
@@ -0,0 +1,131 @@
+/* This file is part of the KDE project
+ Copyright (C) 2002 Nash Hoogwater <nrhoogwater@wanadoo.nl>
+ Copyright (C) 2005 David Faure <faure@kde.org>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; using
+ version 2 of the License.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+*/
+
+#ifndef kwtablestyle_h
+#define kwtablestyle_h
+
+#include "KWFrameStyle.h"
+#include <KoParagStyle.h>
+
+#include <qdom.h>
+#include <qptrlist.h>
+#include <qbrush.h>
+
+class KWFrameStyleCollection;
+class KoStyleCollection;
+class KWTableStyle;
+class KWDocument;
+class KWFrame;
+
+/**
+ * Table style (can created/modified/deleted by the user)
+ * A table style is simply a paragraph style and a frame style,
+ * both of which are applied to a cell.
+ *
+ * This is used by KWTableTemplate to bundle together several styles
+ * in order to provide a full table template.
+ *
+ * This class could probably have been called KWTableCellStyle instead.
+ */
+class KWTableStyle : public KoUserStyle
+{
+public:
+ /** Create a blank framestyle (with default attributes) */
+ KWTableStyle( const QString & name, KoParagStyle * _style, KWFrameStyle * _frameStyle );
+
+ KWTableStyle( QDomElement & parentElem, KWDocument *_doc, int docVersion=2 );
+
+ /** Copy another framestyle */
+ KWTableStyle( const KWTableStyle & rhs ) : KoUserStyle( QString::null ) { *this = rhs; }
+
+ ~KWTableStyle() {}
+
+ void operator=( const KWTableStyle & );
+
+ // ATTRIBUTES
+ KoParagStyle* paragraphStyle() const { return m_paragStyle; }
+ void setParagraphStyle( KoParagStyle *paragStyle ) { m_paragStyle = paragStyle; }
+
+ KWFrameStyle* frameStyle() const { return m_frameStyle; }
+ void setFrameStyle( KWFrameStyle *frameStyle ) { m_frameStyle = frameStyle; }
+
+ /// save (old xml format)
+ void saveTableStyle( QDomElement & parentElem );
+ /// save (new oasis xml format)
+ void saveOasis( KoGenStyles& mainStyles, KoSavingContext& savingContext ) const;
+
+ /// load (old xml format)
+ static KWTableStyle *loadStyle( QDomElement & parentElem, KWDocument *_doc, int docVersion=2 );
+ /// load (new oasis xml format)
+ void loadOasis( QDomElement & styleElem, KoOasisContext& context, const KoStyleCollection& paragraphStyles, const KWFrameStyleCollection& frameStyles );
+
+private:
+ KoParagStyle *m_paragStyle;
+ KWFrameStyle *m_frameStyle;
+};
+
+/**
+ * Collection of user-defined table styles
+ */
+class KWTableStyleCollection : public KoUserStyleCollection
+{
+public:
+ KWTableStyleCollection();
+
+ static QString defaultStyleName() { return QString::fromLatin1( "Plain" ); }
+
+ /**
+ * Find style based on the untranslated name @p name.
+ * Overloaded for convenience
+ */
+ KWTableStyle* findStyle( const QString & name ) const {
+ return static_cast<KWTableStyle*>( KoUserStyleCollection::findStyle( name, defaultStyleName() ) );
+ }
+
+
+ /**
+ * Find style based on the display name @p name.
+ * This is only for the old XML loading.
+ * Overloaded for convenience
+ */
+ KWTableStyle* findStyleByDisplayName( const QString & name ) const {
+ return static_cast<KWTableStyle*>( KoUserStyleCollection::findStyleByDisplayName( name ) );
+ }
+
+ /**
+ * See KoUserStyleCollection::addStyle.
+ * Overloaded for convenience.
+ */
+ KWTableStyle* addStyle( KWTableStyle* sty ) {
+ return static_cast<KWTableStyle*>( KoUserStyleCollection::addStyle( sty ) );
+ }
+
+ /**
+ * Return style number @p i.
+ */
+ KWTableStyle* tableStyleAt( int i ) const {
+ return static_cast<KWTableStyle*>( m_styleList[i] );
+ }
+
+ void saveOasis( KoGenStyles& mainStyles, KoSavingContext& savingContext ) const;
+ int loadOasisStyles( KoOasisContext& context, const KoStyleCollection& paragraphStyles, const KWFrameStyleCollection& frameStyles );
+};
+
+#endif
diff --git a/kword/KWTableStyleManager.cpp b/kword/KWTableStyleManager.cpp
new file mode 100644
index 00000000..7a2a6494
--- /dev/null
+++ b/kword/KWTableStyleManager.cpp
@@ -0,0 +1,716 @@
+/* This file is part of the KDE project
+ Copyright (C) 2002 Nash Hoogwater <nrhoogwater@wanadoo.nl>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; using
+ version 2 of the License.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+*/
+
+#include "KWTableStyleManager.h"
+#include "KWTableStyleManager.moc"
+#include "KWImportStyleDia.h"
+
+#include "KWDocument.h"
+
+#include <KoParagCounter.h>
+#include <KoTextDocument.h>
+
+#include "KoParagStyle.h"
+#include "KWFrameStyleManager.h"
+#include "KWStyleManager.h"
+
+#include <klocale.h>
+#include <kiconloader.h>
+#include <kdebug.h>
+
+#include <qpushbutton.h>
+#include <qlabel.h>
+#include <qgroupbox.h>
+#include <qpainter.h>
+#include <qlineedit.h>
+#include <qlayout.h>
+#include <qcombobox.h>
+#include <qframe.h>
+
+
+/******************************************************************/
+/* Class: KWTableStylePreview */
+/******************************************************************/
+
+KWTableStylePreview::KWTableStylePreview( const QString& title, const QString& text, QWidget* parent, const char* name )
+ : QGroupBox( title, parent, name )
+{
+ m_zoomHandler = new KoTextZoomHandler;
+ QFont font = KoGlobal::defaultFont();
+ m_textdoc = new KoTextDocument( m_zoomHandler, new KoTextFormatCollection( font, QColor(),KGlobal::locale()->language(), false ) );
+ KoTextParag * parag = m_textdoc->firstParag();
+ parag->insert( 0, text );
+}
+
+KWTableStylePreview::~KWTableStylePreview()
+{
+ delete m_textdoc;
+ delete m_zoomHandler;
+}
+
+#undef ptToPx
+#define ptToPx qRound
+
+void KWTableStylePreview::drawContents( QPainter *p )
+{
+ p->save();
+ QRect r = contentsRect();
+
+ int wid = ( r.width() - 40 );
+ int hei = ( r.height() - 40 );
+
+
+ // 1: create document background = white
+
+ p->fillRect( QRect( 10, 20, r.width()-20, r.height() - 20 ), QColor("white") );
+
+ // 2: create borders (KWFrameStyle)
+
+ if (tableStyle->frameStyle()->topBorder().width()>0) {
+ p->setPen( KoBorder::borderPen(tableStyle->frameStyle()->topBorder(), ptToPx( tableStyle->frameStyle()->topBorder().width() ), black) ); // Top border
+ p->drawLine( 20 - int(tableStyle->frameStyle()->leftBorder().width()/2), 30,
+ 20 + wid + int(tableStyle->frameStyle()->rightBorder().width()/2), 30 );
+ }
+ if (tableStyle->frameStyle()->leftBorder().width()>0) {
+ p->setPen( KoBorder::borderPen(tableStyle->frameStyle()->leftBorder(), ptToPx( tableStyle->frameStyle()->leftBorder().width() ), black) ); // Left border
+ p->drawLine( 20, 30 - int(tableStyle->frameStyle()->topBorder().width()/2),
+ 20 , 30 + hei + int(tableStyle->frameStyle()->bottomBorder().width()/2) );
+ }
+ if (tableStyle->frameStyle()->bottomBorder().width()>0) {
+ p->setPen( KoBorder::borderPen(tableStyle->frameStyle()->bottomBorder(), ptToPx( tableStyle->frameStyle()->bottomBorder().width() ), black) ); // Bottom border
+ p->drawLine( 20 + wid + int(ceil(tableStyle->frameStyle()->rightBorder().width()/2)), 30 + hei,
+ 20 - int(tableStyle->frameStyle()->leftBorder().width()/2), 30 + hei );
+ }
+ if (tableStyle->frameStyle()->rightBorder().width()>0) {
+ p->setPen( KoBorder::borderPen(tableStyle->frameStyle()->rightBorder(), ptToPx( tableStyle->frameStyle()->rightBorder().width() ), black) ); // Right border
+ p->drawLine( 20 + wid, 30 - int(tableStyle->frameStyle()->topBorder().width()/2) ,
+ 20 + wid, 30 + hei + int(tableStyle->frameStyle()->bottomBorder().width()/2) );
+ }
+
+ // 3: create background whithin "frame"
+
+ QRect fr( QPoint(20 + int(ceil(tableStyle->frameStyle()->leftBorder().width()/2)), 30 + int(ceil(tableStyle->frameStyle()->topBorder().width()/2))),
+ QPoint(20 + wid - int(floor(tableStyle->frameStyle()->rightBorder().width()/2)+1), 30 + hei - int(floor(tableStyle->frameStyle()->bottomBorder().width()/2)+1)) );
+
+ p->fillRect( fr, tableStyle->frameStyle()->backgroundColor() );
+
+ // 4: create text (KoParagStyle)
+
+ KoTextParag * parag = m_textdoc->firstParag();
+ int widthLU = m_zoomHandler->pixelToLayoutUnitX( fr.width() - 2 ); // keep one pixel border horizontally
+ if ( m_textdoc->width() != widthLU )
+ {
+ // For centering to work, and to even get word wrapping when the thing is too big :)
+ m_textdoc->setWidth( widthLU );
+ parag->invalidate(0);
+ }
+
+ parag->format();
+ QRect textRect = parag->pixelRect( m_zoomHandler );
+
+ // Center vertically, but not horizontally, to keep the parag alignment working,
+ textRect.moveTopLeft( QPoint( fr.x(), fr.y() + ( fr.height() - textRect.height() ) / 2 ) );
+
+ p->setClipRect( textRect.intersect( fr ) );
+ p->translate( textRect.x(), textRect.y() );
+
+ QColorGroup cg = QApplication::palette().active();
+ cg.setBrush( QColorGroup::Base, tableStyle->frameStyle()->backgroundColor() );
+
+ m_textdoc->drawWYSIWYG( p, 1, 0, textRect.width() - 1, textRect.height(), cg, m_zoomHandler );
+
+ p->restore();
+}
+
+void KWTableStylePreview::setTableStyle( KWTableStyle *_tableStyle )
+{
+ tableStyle = _tableStyle;
+
+ KoTextParag * parag = m_textdoc->firstParag();
+ parag->applyStyle( tableStyle->paragraphStyle() );
+
+ repaint(true);
+}
+
+/******************************************************************/
+/* Class: KWTableStyleListItem */
+/******************************************************************/
+
+KWTableStyleListItem::~KWTableStyleListItem()
+{
+}
+
+void KWTableStyleListItem::switchStyle()
+{
+ delete m_changedTableStyle;
+
+ if ( m_origTableStyle )
+ m_changedTableStyle = new KWTableStyle( *m_origTableStyle );
+}
+
+void KWTableStyleListItem::deleteStyle( KWTableStyle *current )
+{
+ Q_ASSERT( m_changedTableStyle == current );
+ delete m_changedTableStyle;
+ m_changedTableStyle = 0L;
+}
+
+void KWTableStyleListItem::apply()
+{
+ *m_origTableStyle = *m_changedTableStyle;
+}
+
+/******************************************************************/
+/* Class: KWTableStyleManager */
+/******************************************************************/
+
+// Proof reader comment: stylist sounds like a hair dresser
+
+KWTableStyleManager::KWTableStyleManager( QWidget *_parent, KWDocument *_doc )
+ : KDialogBase( _parent, "Tablestylist", true,
+ i18n("Table Style Manager"),
+ KDialogBase::Ok | KDialogBase::Cancel | KDialogBase::Apply | KDialogBase::User1 )
+{
+ m_doc = _doc;
+
+ m_currentTableStyle = 0L;
+ noSignals=true;
+
+ m_tableStyles.setAutoDelete(false);
+
+ setupWidget(); // build the widget with the buttons and the list selector.
+
+ m_stylesList->setCurrentItem( 0 );
+ noSignals=false;
+ switchStyle();
+ setInitialSize( QSize( 450, 450 ) );
+ setButtonText( KDialogBase::User1, i18n("Import From File...") );
+ connect(this, SIGNAL(user1Clicked()), this, SLOT(importFromFile()));
+
+}
+
+KWTableStyleManager::~KWTableStyleManager()
+{
+ m_tableStyles.setAutoDelete( true );
+ m_tableStyles.clear();
+}
+
+void KWTableStyleManager::setupWidget()
+{
+ QFrame * frame1 = makeMainWidget();
+ QGridLayout *frame1Layout = new QGridLayout( frame1, 0, 0, // auto
+ 0, KDialog::spacingHint() );
+
+
+ KWTableStyleCollection* collection = m_doc->tableStyleCollection();
+ numTableStyles = collection->count();
+ m_stylesList = new QListBox( frame1, "stylesList" );
+ m_stylesList->insertStringList( collection->displayNameList() );
+ const QValueList<KoUserStyle*> styleList = collection->styleList();
+ Q_ASSERT( !styleList.isEmpty() );
+ for ( QValueList<KoUserStyle *>::const_iterator it = styleList.begin(), end = styleList.end();
+ it != end ; ++it )
+ {
+ KWTableStyle* style = static_cast<KWTableStyle *>( *it );
+ m_tableStyles.append( new KWTableStyleListItem(style,new KWTableStyle(*style) ) );
+ m_styleOrder << style->name();
+ }
+ Q_ASSERT( m_stylesList->count() == m_styleOrder.count() );
+ Q_ASSERT( m_styleOrder.count() == m_tableStyles.count() );
+
+ frame1Layout->addMultiCellWidget( m_stylesList, 0, 0, 0, 1 );
+
+
+ m_moveUpButton = new QPushButton( frame1, "moveUpButton" );
+ m_moveUpButton->setIconSet( SmallIconSet( "up" ) );
+ connect( m_moveUpButton, SIGNAL( clicked() ), this, SLOT( moveUpStyle() ) );
+ frame1Layout->addWidget( m_moveUpButton, 1, 1 );
+
+ m_moveDownButton = new QPushButton( frame1, "moveDownButton" );
+ m_moveDownButton->setIconSet( SmallIconSet( "down" ) );
+ connect( m_moveDownButton, SIGNAL( clicked() ), this, SLOT( moveDownStyle() ) );
+ frame1Layout->addWidget( m_moveDownButton, 1, 0 );
+
+
+ m_deleteButton = new QPushButton( frame1, "deleteButton" );
+ m_deleteButton->setText( i18n( "&Delete" ) );
+ connect( m_deleteButton, SIGNAL( clicked() ), this, SLOT( deleteStyle() ) );
+
+ frame1Layout->addWidget( m_deleteButton, 2, 1 );
+
+ m_newButton = new QPushButton( frame1, "newButton" );
+ m_newButton->setText( i18n( "New" ) );
+ connect( m_newButton, SIGNAL( clicked() ), this, SLOT( addStyle() ) );
+
+ frame1Layout->addWidget( m_newButton, 2, 0 );
+
+ main = new QWidget( frame1 );
+
+ setupMain();
+
+ frame1Layout->addMultiCellWidget( main, 0, 2, 2, 2 );
+
+ connect( m_stylesList, SIGNAL( selectionChanged() ), this, SLOT( switchStyle() ) );
+}
+
+void KWTableStyleManager::setupMain()
+{
+ QGridLayout *mainLayout = new QGridLayout( main );
+ mainLayout->setSpacing( KDialog::spacingHint() );
+
+ preview = new KWTableStylePreview( i18n("Preview"), i18n("Tablestyles preview"), main );
+ preview->resize(preview->sizeHint());
+
+ mainLayout->addMultiCellWidget( preview, 1, 1, 0, 1 );
+
+ m_nameString = new QLineEdit( main );
+ m_nameString->resize(m_nameString->sizeHint() );
+ connect( m_nameString, SIGNAL( textChanged( const QString &) ), this, SLOT( renameStyle(const QString &) ) );
+
+ mainLayout->addWidget( m_nameString, 0, 1 );
+
+ QLabel *nameLabel = new QLabel( main );
+ nameLabel->setText( i18n( "Name:" ) );
+ nameLabel->resize(nameLabel->sizeHint());
+ nameLabel->setAlignment( AlignRight | AlignVCenter );
+
+ mainLayout->addWidget( nameLabel, 0, 0 );
+
+ QGroupBox *adjustBox = new QGroupBox( 0, Qt::Vertical, i18n("Adjust"), main);
+ adjustBox->layout()->setSpacing(KDialog::spacingHint());
+ adjustBox->layout()->setMargin(KDialog::marginHint());
+ QGridLayout *adjustLayout = new QGridLayout( adjustBox->layout() );
+
+ QLabel *frameStyleLabel = new QLabel( adjustBox );
+ frameStyleLabel->setText( i18n( "Framestyle:" ) );
+ frameStyleLabel->setAlignment( AlignRight | AlignVCenter );
+
+ QLabel *styleLabel = new QLabel( adjustBox );
+ styleLabel->setText( i18n( "Textstyle:" ) );
+ styleLabel->setAlignment( AlignRight | AlignVCenter );
+
+ m_frameStyle = new QComboBox( adjustBox );
+ m_style = new QComboBox( adjustBox );
+ updateAllStyleCombos();
+
+ connect( m_frameStyle, SIGNAL( activated(int) ), this, SLOT( selectFrameStyle(int) ) );
+ connect( m_style, SIGNAL( activated(int) ), this, SLOT( selectStyle(int) ) );
+
+ m_changeFrameStyleButton = new QPushButton( adjustBox );
+ m_changeFrameStyleButton->setText( i18n( "Change..." ) );
+ connect( m_changeFrameStyleButton, SIGNAL( clicked() ), this, SLOT( changeFrameStyle() ) );
+
+ m_changeStyleButton = new QPushButton( adjustBox );
+ m_changeStyleButton->setText( i18n( "Change..." ) );
+ connect( m_changeStyleButton, SIGNAL( clicked() ), this, SLOT( changeStyle() ) );
+
+ adjustLayout->addWidget( frameStyleLabel, 0, 0 );
+ adjustLayout->addWidget( styleLabel, 1, 0 );
+
+ adjustLayout->addWidget( m_frameStyle, 0, 1 );
+ adjustLayout->addWidget( m_style, 1, 1 );
+
+ adjustLayout->addWidget( m_changeFrameStyleButton, 0, 2 );
+ adjustLayout->addWidget( m_changeStyleButton, 1, 2 );
+
+ adjustBox->setMaximumHeight(120);
+ mainLayout->addMultiCellWidget( adjustBox, 2, 2, 0, 1);
+}
+
+void KWTableStyleManager::switchStyle()
+{
+ kdDebug() << "KWTableStyleManager::switchStyle noSignals=" << noSignals << endl;
+ if(noSignals) return;
+ noSignals=true;
+
+ if(m_currentTableStyle !=0L)
+ save();
+
+ m_currentTableStyle = 0L;
+ int num = tableStyleIndex( m_stylesList->currentItem() );
+
+ kdDebug() << "KWTableStyleManager::switchStyle switching to " << num << endl;
+ if( m_tableStyles.at(num)->origTableStyle() == m_tableStyles.at(num)->changedTableStyle() )
+ m_tableStyles.at(num)->switchStyle();
+ else
+ m_currentTableStyle = m_tableStyles.at(num)->changedTableStyle();
+
+ updateGUI();
+
+ noSignals=false;
+}
+
+int KWTableStyleManager::tableStyleIndex( int pos )
+{
+ int p = 0;
+ for(unsigned int i=0; i < m_tableStyles.count(); i++) {
+ // Skip deleted styles, they're no in m_stylesList anymore
+ KWTableStyle * style = m_tableStyles.at(i)->changedTableStyle();
+ if ( !style ) continue;
+ if ( p == pos )
+ return i;
+ ++p;
+ }
+ kdWarning() << "KWTableStyleManager::tableStyleIndex no style found at pos " << pos << endl;
+
+#ifdef __GNUC_
+#warning implement undo/redo
+#endif
+
+ return 0;
+}
+
+void KWTableStyleManager::updateGUI()
+{
+ kdDebug() << "KWTableStyleManager::updateGUI m_currentTableStyle=" << m_currentTableStyle << " " << m_currentTableStyle->name() << endl;
+
+ // Update name
+ m_nameString->setText(m_currentTableStyle->displayName());
+ // Update style and framestyle
+ if ( m_doc->styleCollection()->findStyle( m_currentTableStyle->paragraphStyle()->name() ) )
+ m_style->setCurrentText(m_currentTableStyle->paragraphStyle()->displayName());
+ if ( m_doc->frameStyleCollection()->findStyle( m_currentTableStyle->frameStyle()->name() ) )
+ m_frameStyle->setCurrentText(m_currentTableStyle->frameStyle()->displayName());
+
+ // update delete button (can't delete first style);
+ m_deleteButton->setEnabled(m_stylesList->currentItem() != 0);
+
+ m_moveUpButton->setEnabled(m_stylesList->currentItem() != 0);
+ m_moveDownButton->setEnabled(m_stylesList->currentItem()!=(int)m_stylesList->count()-1);
+
+ updatePreview();
+}
+
+void KWTableStyleManager::updatePreview()
+{
+ preview->setTableStyle(m_currentTableStyle);
+}
+
+void KWTableStyleManager::save()
+{
+ m_currentTableStyle->setDisplayName( m_nameString->text() );
+}
+
+void KWTableStyleManager::addStyle()
+{
+ save();
+ KWTableStyleCollection* collection = m_doc->tableStyleCollection();
+
+ QString str = i18n( "New Tablestyle Template (%1)" ).arg(numTableStyles++);
+ if ( m_currentTableStyle )
+ {
+ m_currentTableStyle = new KWTableStyle( *m_currentTableStyle );
+ m_currentTableStyle->setDisplayName( str );
+ }
+ else
+ {
+ KWTableStyle* defaultTableStyle = collection->findStyle( collection->defaultStyleName() );
+ Q_ASSERT( defaultTableStyle ); // can't be 0 except if there are no styles at all
+
+ KWFrameStyle *defaultFrameStyle = defaultTableStyle->frameStyle();
+ KoParagStyle *defaultParagraphStyle = defaultTableStyle->paragraphStyle();
+
+ m_currentTableStyle = new KWTableStyle( str, defaultParagraphStyle, defaultFrameStyle );
+ }
+ m_currentTableStyle->setName( collection->generateUniqueName() );
+
+ noSignals=true;
+ m_tableStyles.append(new KWTableStyleListItem(0L,m_currentTableStyle));
+ m_stylesList->insertItem( str );
+ m_styleOrder << m_currentTableStyle->name();
+ m_stylesList->setCurrentItem( m_stylesList->count() - 1 );
+ noSignals=false;
+
+ updateGUI();
+}
+
+void KWTableStyleManager::importFromFile()
+{
+ QStringList lst;
+ for (unsigned int i = 0; i<m_stylesList->count();i++)
+ {
+ lst << m_stylesList->text(i );
+ }
+
+ KWImportFrameTableStyleDia dia( m_doc, lst, KWImportFrameTableStyleDia::TableStyle, this, 0 );
+ if ( dia.listOfTableStyleImported().count() > 0 && dia.exec() ) {
+ QPtrList<KWTableStyle> list = dia.listOfTableStyleImported();
+ addStyles( list);
+ }
+}
+
+void KWTableStyleManager::addStyles(const QPtrList<KWTableStyle> &listStyle )
+{
+ save();
+
+ QPtrListIterator<KWTableStyle> style( listStyle );
+ for ( ; style.current() ; ++style )
+ {
+ noSignals=true;
+ m_stylesList->insertItem( style.current()->displayName() );
+ m_styleOrder << style.current()->name();
+ m_tableStyles.append( new KWTableStyleListItem( 0L,new KWTableStyle(*style.current())) );
+ noSignals=false;
+
+ }
+
+ updateGUI();
+}
+
+
+void KWTableStyleManager::deleteStyle()
+{
+ Q_ASSERT( m_currentTableStyle );
+
+ unsigned int cur = tableStyleIndex( m_stylesList->currentItem() );
+ m_styleOrder.remove( m_currentTableStyle->name() );
+ if ( !m_tableStyles.at(cur)->origTableStyle() )
+ m_tableStyles.take( cur );
+ else {
+ m_tableStyles.at(cur)->deleteStyle( m_currentTableStyle );
+ m_currentTableStyle = 0L;
+ }
+
+ // Update GUI
+ m_stylesList->removeItem( m_stylesList->currentItem() );
+ numTableStyles--;
+ m_stylesList->setSelected( m_stylesList->currentItem(), true );
+}
+
+void KWTableStyleManager::moveUpStyle()
+{
+ Q_ASSERT( m_currentTableStyle );
+ if ( m_currentTableStyle )
+ save();
+
+ const QString currentStyleName = m_currentTableStyle->name();
+ const QString currentStyleDisplayName = m_stylesList->currentText();
+ int pos2 = m_styleOrder.findIndex( currentStyleName );
+ if ( pos2 != -1 )
+ {
+ m_styleOrder.remove( m_styleOrder.at(pos2) );
+ m_styleOrder.insert( m_styleOrder.at(pos2-1), currentStyleName );
+ }
+
+
+ int pos = m_stylesList->currentItem();
+ noSignals=true;
+ m_stylesList->changeItem( m_stylesList->text( pos-1 ), pos );
+
+ m_stylesList->changeItem( currentStyleDisplayName, pos-1 );
+
+ m_stylesList->setCurrentItem( m_stylesList->currentItem() );
+ noSignals=false;
+
+ updateGUI();
+}
+
+void KWTableStyleManager::moveDownStyle()
+{
+ Q_ASSERT( m_currentTableStyle );
+ if ( m_currentTableStyle )
+ save();
+
+ const QString currentStyleName = m_currentTableStyle->name();
+ const QString currentStyleDisplayName = m_stylesList->currentText();
+ int pos2 = m_styleOrder.findIndex( currentStyleName );
+ if ( pos2 != -1 )
+ {
+ m_styleOrder.remove( m_styleOrder.at(pos2) );
+ m_styleOrder.insert( m_styleOrder.at(pos2+1), currentStyleName );
+ }
+
+ int pos = m_stylesList->currentItem();
+ noSignals=true;
+ m_stylesList->changeItem( m_stylesList->text( pos+1 ), pos );
+ m_stylesList->changeItem( currentStyleDisplayName, pos+1 );
+ m_stylesList->setCurrentItem( m_stylesList->currentItem() );
+ noSignals=false;
+
+ updateGUI();
+}
+
+void KWTableStyleManager::slotOk() {
+ save();
+ apply();
+ KDialogBase::slotOk();
+}
+
+void KWTableStyleManager::slotApply() {
+ save();
+ apply();
+ KDialogBase::slotApply();
+}
+
+void KWTableStyleManager::apply() {
+ noSignals=true;
+ for (unsigned int i =0 ; i < m_tableStyles.count() ; i++) {
+ if(m_tableStyles.at(i)->origTableStyle() == 0) { // newly added style
+ kdDebug() << "adding new tablestyle" << m_tableStyles.at(i)->changedTableStyle()->name() << " (" << i << ")" << endl;
+ KWTableStyle *tmp = m_doc->tableStyleCollection()->addStyle( m_tableStyles.take(i)->changedTableStyle() );
+ m_tableStyles.insert(i, new KWTableStyleListItem(0, tmp) );
+ } else if(m_tableStyles.at(i)->changedTableStyle() == 0) { // deleted style
+ kdDebug() << "deleting orig tablestyle " << m_tableStyles.at(i)->origTableStyle()->name() << " (" << i << ")" << endl;
+
+ KWTableStyle *orig = m_tableStyles.at(i)->origTableStyle();
+ m_doc->tableStyleCollection()->removeStyle( orig );
+ } else {
+ kdDebug() << "update tablestyle " << m_tableStyles.at(i)->changedTableStyle()->name() << " (" << i << ")" << endl;
+
+ m_tableStyles.at(i)->apply();
+ }
+ }
+ m_doc->tableStyleCollection()->updateStyleListOrder( m_styleOrder );
+ m_doc->updateAllTableStyleLists();
+ m_doc->setModified( true );
+ noSignals=false;
+}
+
+void KWTableStyleManager::renameStyle(const QString &theText) {
+ if(noSignals) return;
+ noSignals=true;
+
+ int index = m_stylesList->currentItem();
+ kdDebug() << "KWTableStyleManager::renameStyle " << index << " to " << theText << endl;
+
+ // rename only in the GUI, not even in the underlying objects (save() does it).
+ m_stylesList->changeItem( theText, index );
+ //m_styleOrder[index]=theText; // not needed anymore, we use internal names
+ // Check how many styles with that name we have now
+ int synonyms = 0;
+ for ( unsigned int i = 0; i < m_stylesList->count(); i++ ) {
+ if ( m_stylesList->text( i ) == m_stylesList->currentText() )
+ ++synonyms;
+ }
+ Q_ASSERT( synonyms > 0 ); // should have found 'index' at least !
+ noSignals=false;
+ // Can't close the dialog if two styles have the same name
+ bool state=!theText.isEmpty() && (synonyms == 1);
+ enableButtonOK(state );
+ enableButtonApply(state);
+ enableButton( KDialogBase::User1, state );
+ m_deleteButton->setEnabled(state&&(m_stylesList->currentItem() != 0));
+ m_newButton->setEnabled(state);
+ m_stylesList->setEnabled( state );
+ if ( state )
+ {
+ m_moveUpButton->setEnabled(m_stylesList->currentItem() != 0);
+ m_moveDownButton->setEnabled(m_stylesList->currentItem()!=(int)m_stylesList->count()-1);
+ }
+ else
+ {
+ m_moveUpButton->setEnabled(false);
+ m_moveDownButton->setEnabled(false);
+ }
+
+}
+
+/** Show the frame-style-manager and apply changes to the current selected tablestyle.
+ */
+void KWTableStyleManager::changeFrameStyle()
+{
+// 0. Save name, otherwise it will be gone when you return
+ save();
+
+// 1. Execute frame style manager
+ KWFrameStyleManager frameStylist( this, m_doc, m_currentTableStyle->frameStyle()->name() );
+ frameStylist.exec();
+
+// 2. Apply changes
+ updateAllStyleCombos();
+ updateGUI();
+}
+
+/** Show the stylist and apply changes to the current selected tablestyle.
+ */
+void KWTableStyleManager::changeStyle()
+{
+// 0. Save name, otherwise it will be gone when you return
+ save();
+
+// 1. Execute stylist
+ KWStyleManager styleManager( this, m_doc->unit(), m_doc, *m_doc->styleCollection());
+ styleManager.exec();
+
+// 2. Apply changes
+ updateAllStyleCombos();
+ updateGUI();
+}
+
+void KWTableStyleManager::updateAllStyleCombos()
+{
+ unsigned int oldSindex = 0;
+ unsigned int oldFSindex = 0;
+ QString oldS = "";
+ QString oldFS = "";
+
+ if (m_style->currentItem()>=0) {
+ oldSindex = m_style->currentItem();
+ oldS = m_style->currentText();
+ }
+ if (m_frameStyle->currentItem()>=0) {
+ oldFSindex = m_frameStyle->currentItem();
+ oldFS = m_frameStyle->currentText();
+ }
+
+ // Let's check if there were deleted framestyles or styles.
+ // If that is the case than we search for the old name
+ // If it exists then we use that index, else we use
+ // the old index.
+ // Problems:
+ // - 1. Count is the same, but the user has delete the same number as he added
+ // - 2. Old name is not in new list, old index is wrong index in new list
+ if ( ( static_cast<unsigned int>(m_style->count())!=m_doc->styleCollection()->styleList().count() ) &&
+ ( m_style->listBox()->findItem( oldS ) ) ) {
+ oldSindex = m_style->listBox()->index( m_style->listBox()->findItem( oldS ) );
+ }
+ if ( ( m_frameStyle->count() != m_doc->frameStyleCollection()->count() ) &&
+ ( m_frameStyle->listBox()->findItem( oldFS ) ) ) {
+ oldFSindex = m_frameStyle->listBox()->index( m_frameStyle->listBox()->findItem( oldFS ) );
+ }
+
+ // Update the comboboxes
+
+ m_frameStyle->clear();
+ m_frameStyle->insertStringList( m_doc->frameStyleCollection()->displayNameList() );
+ m_frameStyle->setCurrentItem( oldFSindex );
+
+ m_style->clear();
+ m_style->insertStringList( m_doc->styleCollection()->displayNameList() );
+ m_style->setCurrentItem( oldSindex );
+}
+
+void KWTableStyleManager::selectFrameStyle(int index)
+{
+ kdDebug() << "KWTableStyleManager::selectFrameStyle index " << index << endl;
+
+ if ( (index>=0) && ( index < (int)m_doc->frameStyleCollection()->count() ) )
+ m_currentTableStyle->setFrameStyle( m_doc->frameStyleCollection()->frameStyleAt(index) );
+ save();
+ updateGUI();
+}
+
+void KWTableStyleManager::selectStyle(int index)
+{
+ kdDebug() << "KWTableStyleManager::selectStyle index " << index << endl;
+ if ( (index>=0) && ( index < (int)m_doc->styleCollection()->styleList().count() ) )
+ m_currentTableStyle->setParagraphStyle( m_doc->styleCollection()->styleAt(index) );
+ save();
+ updateGUI();
+}
diff --git a/kword/KWTableStyleManager.h b/kword/KWTableStyleManager.h
new file mode 100644
index 00000000..aaa61083
--- /dev/null
+++ b/kword/KWTableStyleManager.h
@@ -0,0 +1,156 @@
+/* This file is part of the KDE project
+ Copyright (C) 2002 Nash Hoogwater <nrhoogwater@wanadoo.nl>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; using
+ version 2 of the License.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+*/
+
+#ifndef kwtablestylemanager_h
+#define kwtablestylemanager_h
+
+#include "KWFrameStyle.h"
+#include "KWTableStyle.h"
+
+#include <kdialogbase.h>
+#include <qgroupbox.h>
+#include <qptrlist.h>
+
+
+class QGridLayout;
+class QLineEdit;
+class QListBox;
+class QPushButton;
+class QWidget;
+class QFrame;
+class QComboBox;
+
+class KWDocument;
+class KoParagStyle;
+
+class KoTextDocument;
+
+/******************************************************************/
+/* Class: KWTableStylePreview */
+/******************************************************************/
+
+class KWTableStylePreview : public QGroupBox
+{
+ Q_OBJECT
+
+public:
+ KWTableStylePreview(const QString &title, const QString &text, QWidget *parent, const char* name = 0);
+ virtual ~KWTableStylePreview();
+
+ void setTableStyle(KWTableStyle *_tableStyle);
+
+protected:
+ void drawContents( QPainter *p );
+
+ KWTableStyle *tableStyle;
+
+ KoTextDocument *m_textdoc;
+ KoTextZoomHandler *m_zoomHandler;
+};
+
+class KWTableStyleListItem
+{
+ public:
+ KWTableStyleListItem() {}
+ ~KWTableStyleListItem();
+ KWTableStyleListItem(KWTableStyle *orig, KWTableStyle *changed) {
+ m_origTableStyle = orig;
+ m_changedTableStyle = changed;
+ }
+
+ KWTableStyle *origTableStyle()const { return m_origTableStyle; }
+ KWTableStyle *changedTableStyle()const { return m_changedTableStyle; }
+ void setOrigTableStyle( KWTableStyle *_orig ) { m_origTableStyle = _orig; }
+ void setChangedTableStyle( KWTableStyle *_changed ) { m_changedTableStyle = _changed; }
+ void deleteOrigTableStyle() { delete m_changedTableStyle; }
+ void deleteChangedTableStyle() { delete m_changedTableStyle; }
+
+ void switchStyle();
+ void deleteStyle( KWTableStyle *current );
+ void apply();
+
+ protected:
+ KWTableStyle *m_origTableStyle;
+ KWTableStyle *m_changedTableStyle;
+};
+
+/******************************************************************/
+/* Class: KWTableStyleManager */
+/******************************************************************/
+class KWTableStyleManager : public KDialogBase
+{
+ Q_OBJECT
+
+public:
+ KWTableStyleManager( QWidget *_parent, KWDocument *_doc );
+ ~KWTableStyleManager();
+
+private:
+ void setupWidget();
+ void addGeneralTab();
+ void apply();
+ void updateGUI();
+ void updatePreview();
+ void save();
+ int tableStyleIndex( int pos );
+
+ void addStyles(const QPtrList<KWTableStyle> &listStyle );
+
+ QListBox *m_stylesList;
+ QLineEdit *m_nameString;
+ QPushButton *m_deleteButton;
+ QPushButton *m_newButton;
+ QPushButton *m_moveUpButton;
+ QPushButton *m_moveDownButton;
+ QComboBox *m_frameStyle;
+ QComboBox *m_style;
+ QPushButton *m_changeFrameStyleButton;
+ QPushButton *m_changeStyleButton;
+ QStringList m_styleOrder;
+ QGroupBox *previewBox;
+ KWTableStylePreview *preview;
+
+ QWidget *main;
+
+ KWTableStyle *m_currentTableStyle;
+ QPtrList<KWTableStyleListItem> m_tableStyles;
+ int numTableStyles;
+ bool noSignals;
+
+ KWDocument *m_doc;
+
+protected slots:
+ virtual void slotOk();
+ virtual void slotApply();
+ void updateAllStyleCombos();
+ void changeFrameStyle();
+ void changeStyle();
+ void selectFrameStyle(int);
+ void selectStyle(int);
+ void switchStyle();
+ void addStyle();
+ void deleteStyle();
+ void moveUpStyle();
+ void moveDownStyle();
+ void renameStyle(const QString &);
+ void setupMain();
+ void importFromFile();
+};
+
+#endif
diff --git a/kword/KWTableTemplate.cpp b/kword/KWTableTemplate.cpp
new file mode 100644
index 00000000..02bc428c
--- /dev/null
+++ b/kword/KWTableTemplate.cpp
@@ -0,0 +1,299 @@
+/* This file is part of the KDE project
+ Copyright (C) 2002 Nash Hoogwater <nrhoogwater@wanadoo.nl>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; using
+ version 2 of the License.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+*/
+
+#include "KWTableTemplate.h"
+
+#include "KWDocument.h"
+#include "KWFrameStyle.h"
+#include "KoParagStyle.h"
+
+#include <kdebug.h>
+#include <klocale.h>
+#include <qdom.h>
+
+
+/******************************************************************/
+/* Class: KWTableTemplateCollection */
+/******************************************************************/
+
+KWTableTemplateCollection::KWTableTemplateCollection()
+{
+ m_templateList.setAutoDelete( false );
+ m_deletedTemplates.setAutoDelete( true );
+ m_lastTemplate = 0L;
+}
+
+KWTableTemplateCollection::~KWTableTemplateCollection()
+{
+ //kdDebug() << "KWTableTemplateCollection::destructor" << endl;
+ clear();
+}
+
+void KWTableTemplateCollection::clear()
+{
+ m_templateList.setAutoDelete( true );
+ m_templateList.clear();
+ m_deletedTemplates.clear();
+ m_lastTemplate = 0;
+}
+
+KWTableTemplate* KWTableTemplateCollection::findTableTemplate( const QString & _name )
+{
+ // Caching, to speed things up
+ if ( m_lastTemplate && m_lastTemplate->name() == _name )
+ return m_lastTemplate;
+
+ QPtrListIterator<KWTableTemplate> templateIt( m_templateList );
+ for ( ; templateIt.current(); ++templateIt )
+ {
+ if ( templateIt.current()->name() == _name ) {
+ m_lastTemplate = templateIt.current();
+ return m_lastTemplate;
+ }
+ }
+
+// if(_name == "Plain") return m_styleList.at(0); // fallback..
+
+ return 0L;
+}
+
+
+KWTableTemplate* KWTableTemplateCollection::addTableTemplate( KWTableTemplate * tt )
+{
+ // First check for duplicates.
+ for ( KWTableTemplate* p = m_templateList.first(); p != 0L; p = m_templateList.next() )
+ {
+ if ( p->name() == tt->name() ) {
+ // Replace existing template
+ if ( tt != p )
+ {
+ *p = *tt;
+ delete tt;
+ }
+ return p;
+ }
+ }
+ m_templateList.append( tt );
+ return tt;
+}
+
+void KWTableTemplateCollection::removeTableTemplate ( KWTableTemplate *tt )
+{
+ if( m_templateList.removeRef( tt )) {
+ if ( m_lastTemplate == tt )
+ m_lastTemplate = 0L;
+ // Remember to delete this template when deleting the document
+ m_deletedTemplates.append( tt );
+ }
+}
+
+/******************************************************************/
+/* Class: KWTableTemplate */
+/******************************************************************/
+
+KWTableTemplate::KWTableTemplate( const QString & name, KWTableStyle * _firstRow, KWTableStyle * _firstCol,
+ KWTableStyle *_lastRow, KWTableStyle *_lastCol, KWTableStyle *_bodyCell,
+ KWTableStyle *_topLeftCorner, KWTableStyle *_topRightCorner,
+ KWTableStyle *_bottomLeftCorner, KWTableStyle *_bottomRightCorner )
+{
+ m_name = name;
+ m_firstRow = _firstRow;
+ m_firstCol = _firstCol;
+ m_lastRow = _lastRow;
+ m_lastCol = _lastCol;
+ m_bodyCell = _bodyCell;
+ m_topLeftCorner = _topLeftCorner;
+ m_topRightCorner = _topRightCorner;
+ m_bottomRightCorner = _bottomRightCorner;
+ m_bottomLeftCorner = _bottomLeftCorner;
+}
+
+KWTableTemplate::KWTableTemplate( QDomElement & parentElem, KWDocument *_doc, int /*docVersion*/ )
+{
+ m_topRightCorner = 0L;
+ m_topLeftCorner = 0L;
+ m_bottomRightCorner = 0L;
+ m_bottomLeftCorner = 0L;
+
+ QDomElement element = parentElem.namedItem( "NAME" ).toElement();
+ if ( ( !element.isNull() ) && ( element.hasAttribute("value") ) )
+ m_name = element.attribute( "value" );
+
+ element = parentElem.namedItem( "BODYCELL" ).toElement();
+ if ( ( !element.isNull() ) && ( element.hasAttribute("name") )
+ && ( _doc->tableStyleCollection()->findStyle( element.attribute( "name" ) ) ) )
+ m_bodyCell = _doc->tableStyleCollection()->findStyle( element.attribute( "name" ) );
+ else {
+ KWTableStyle *ts = _doc->tableStyleCollection()->findStyle( "Plain" );
+ if (ts) {
+ setBodyCell( ts );
+ }
+ else {
+ ts = new KWTableStyle( "Plain", 0L, 0L );
+ KWFrameStyle *fs = _doc->frameStyleCollection()->findStyle( "Plain" );
+ KoParagStyle *s = _doc->styleCollection()->findStyle( "Standard" );
+ if ( fs )
+ ts->setFrameStyle( fs );
+ else {
+ KWFrameStyle * standardFrameStyle = new KWFrameStyle( "Plain" );
+ standardFrameStyle->setBackgroundColor(QColor("white"));
+ standardFrameStyle->setTopBorder(KoBorder(QColor("black"),KoBorder::SOLID,0));
+ standardFrameStyle->setRightBorder(KoBorder(QColor("black"),KoBorder::SOLID,0));
+ standardFrameStyle->setLeftBorder(KoBorder(QColor("black"),KoBorder::SOLID,0));
+ standardFrameStyle->setBottomBorder(KoBorder(QColor("black"),KoBorder::SOLID,0));
+ _doc->frameStyleCollection()->addStyle( standardFrameStyle );
+ ts->setFrameStyle( fs );
+ }
+
+ if ( s )
+ ts->setParagraphStyle( s );
+ else {
+ KoParagStyle * standardStyle = new KoParagStyle( "Standard" );
+ standardStyle->format().setFont( _doc->defaultFont() );
+ _doc->styleCollection()->addStyle( standardStyle );
+ ts->setParagraphStyle( s );
+ }
+ setBodyCell ( ts );
+ }
+ }
+ element = parentElem.namedItem( "FIRSTROW" ).toElement();
+ if ( ( !element.isNull() ) && ( element.hasAttribute("name") )
+ && ( _doc->tableStyleCollection()->findStyle( element.attribute( "name" ) ) ) )
+ {
+ m_firstRow = _doc->tableStyleCollection()->findStyle( element.attribute( "name" ) );
+
+ if ( element.hasAttribute("topleftcorner") )
+ m_topLeftCorner = m_firstRow;
+ if ( element.hasAttribute("toprightcorner") )
+ m_topRightCorner = m_firstRow;
+ }
+ else
+ m_firstRow = m_bodyCell;
+
+ element = parentElem.namedItem( "FIRSTCOL" ).toElement();
+ if ( ( !element.isNull() ) && ( element.hasAttribute("name") )
+ && ( _doc->tableStyleCollection()->findStyle( element.attribute( "name" ) ) ) )
+ {
+ m_firstCol = _doc->tableStyleCollection()->findStyle( element.attribute( "name" ) );
+
+ if ( element.hasAttribute("topleftcorner") )
+ m_topLeftCorner = m_firstCol;
+ if ( element.hasAttribute("bottomleftcorner") )
+ m_bottomLeftCorner = m_firstCol;
+ }
+ else
+ m_firstCol = m_bodyCell;
+
+ element = parentElem.namedItem( "LASTROW" ).toElement();
+ if ( ( !element.isNull() ) && ( element.hasAttribute("name") )
+ && ( _doc->tableStyleCollection()->findStyle( element.attribute( "name" ) ) ) )
+ {
+ m_lastRow = _doc->tableStyleCollection()->findStyle( element.attribute( "name" ) );
+
+ if ( ( !element.isNull() ) && ( element.hasAttribute("bottomrightcorner") ) )
+ m_bottomRightCorner = m_lastRow;
+ if ( ( !element.isNull() ) && ( element.hasAttribute("bottomleftcorner") ) )
+ m_bottomLeftCorner = m_lastRow;
+ }
+ else
+ m_lastRow = m_bodyCell;
+
+ element = parentElem.namedItem( "LASTCOL" ).toElement();
+ if ( ( !element.isNull() ) && ( element.hasAttribute("name") )
+ && ( _doc->tableStyleCollection()->findStyle( element.attribute( "name" ) ) ) )
+ {
+ m_lastCol = _doc->tableStyleCollection()->findStyle( element.attribute( "name" ) );
+
+ if ( element.hasAttribute("toprightcorner") )
+ m_topRightCorner = m_lastCol;
+ if ( element.hasAttribute("bottomrightcorner") )
+ m_bottomRightCorner = m_lastCol;
+ }
+ else
+ m_lastCol = m_bodyCell;
+
+ if (!m_topRightCorner) m_topRightCorner = m_bodyCell;
+ if (!m_topLeftCorner) m_topLeftCorner = m_bodyCell;
+ if (!m_bottomRightCorner) m_bottomRightCorner = m_bodyCell;
+ if (!m_bottomLeftCorner) m_bottomLeftCorner = m_bodyCell;
+}
+
+void KWTableTemplate::operator=( const KWTableTemplate &rhs )
+{
+ m_name = rhs.m_name;
+ m_firstRow = rhs.pFirstRow();
+ m_firstCol = rhs.pFirstCol();
+ m_lastRow = rhs.pLastRow();
+ m_lastCol = rhs.pLastCol();
+ m_bodyCell = rhs.pBodyCell();
+ m_topLeftCorner = rhs.pTopLeftCorner();
+ m_topRightCorner = rhs.pTopRightCorner();
+ m_bottomRightCorner = rhs.pBottomRightCorner();
+ m_bottomLeftCorner = rhs.pBottomLeftCorner();
+}
+
+QString KWTableTemplate::displayName() const
+{
+ return i18n( "Style name", name().utf8() );
+}
+
+// TODO
+void KWTableTemplate::saveTableTemplate( QDomElement & parentElem )
+{
+ QDomDocument doc = parentElem.ownerDocument();
+ QDomElement element = doc.createElement( "NAME" );
+ parentElem.appendChild( element );
+ element.setAttribute( "value", name() );
+
+ if (m_bodyCell)
+ {
+ element = doc.createElement( "BODYCELL" );
+ parentElem.appendChild( element );
+ element.setAttribute( "name", m_bodyCell->name() );
+ }
+ if (m_firstRow)
+ {
+ element = doc.createElement( "FIRSTROW" );
+ parentElem.appendChild( element );
+ element.setAttribute( "name", m_firstRow->name() );
+ }
+ if (m_firstCol)
+ {
+ element = doc.createElement( "FIRSTCOL" );
+ parentElem.appendChild( element );
+ element.setAttribute( "name", m_firstCol->name() );
+ }
+ if (m_lastRow)
+ {
+ element = doc.createElement( "LASTROW" );
+ parentElem.appendChild( element );
+ element.setAttribute( "name", m_lastRow->name() );
+ }
+ if (m_lastCol)
+ {
+ element = doc.createElement( "LASTCOL" );
+ parentElem.appendChild( element );
+ element.setAttribute( "name", m_lastCol->name() );
+ }
+}
+
+KWTableTemplate *KWTableTemplate::loadTemplate( QDomElement & parentElem, KWDocument *_doc, int docVersion )
+{
+ return new KWTableTemplate(parentElem, _doc, docVersion);
+}
diff --git a/kword/KWTableTemplate.h b/kword/KWTableTemplate.h
new file mode 100644
index 00000000..729f2820
--- /dev/null
+++ b/kword/KWTableTemplate.h
@@ -0,0 +1,145 @@
+/* This file is part of the KDE project
+ Copyright (C) 2002 Nash Hoogwater <nrhoogwater@wanadoo.nl>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; using
+ version 2 of the License.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+*/
+
+#ifndef kwtabletemplate_h
+#define kwtabletemplate_h
+
+#include "KWTableStyle.h"
+
+#include <qdom.h>
+#include <qptrlist.h>
+#include <qbrush.h>
+
+class KWTableTemplate;
+class KWDocument;
+
+/******************************************************************/
+/* Class: KWTableTemplateCollection */
+/******************************************************************/
+
+class KWTableTemplateCollection
+{
+public:
+ KWTableTemplateCollection();
+ ~KWTableTemplateCollection();
+ const QPtrList<KWTableTemplate> & tableTemplateList() const { return m_templateList; }
+ void clear();
+
+ KWTableTemplate* findTableTemplate( const QString & name );
+ /**
+ * Return style number @p i.
+ */
+ KWTableTemplate* tableTemplateAt( int i ) { return m_templateList.at(i); }
+
+ KWTableTemplate* addTableTemplate( KWTableTemplate *tt );
+
+ void removeTableTemplate ( KWTableTemplate *tt );
+
+private:
+ QPtrList<KWTableTemplate> m_templateList;
+ QPtrList<KWTableTemplate> m_deletedTemplates;
+ KWTableTemplate *m_lastTemplate;
+};
+
+/******************************************************************/
+/* Class: KWTableTemplate */
+/******************************************************************/
+
+class KWTableTemplate
+{
+public:
+ KWTableTemplate( const QString & name, KWTableStyle * _firstRow=0L, KWTableStyle * _firstCol=0L,
+ KWTableStyle *_lastRow=0L, KWTableStyle *_lastCol=0L, KWTableStyle *_bodyCell=0L,
+ KWTableStyle *_topLeftCorner=0L, KWTableStyle *_topRightCorner=0L,
+ KWTableStyle *_bottomLeftCorner=0L, KWTableStyle *_bottomRightCorner=0L );
+
+ KWTableTemplate( const KWTableTemplate & rhs ) { *this = rhs; }
+
+ KWTableTemplate( QDomElement & parentElem, KWDocument *_doc, int docVersion=2 );
+
+ ~KWTableTemplate() {}
+
+ void operator=( const KWTableTemplate & );
+
+ /** The internal name (untranslated if a standard style) */
+ QString name() const { return m_name; }
+ void setName( const QString & name ) { m_name = name; }
+ /** The translated name */
+ QString displayName() const;
+
+ // ATTRIBUTES
+ KWTableStyle firstRow() const { return *m_firstRow; }
+ KWTableStyle* pFirstRow() const { return m_firstRow; }
+ void setFirstRow( KWTableStyle *_tableStyle ) { m_firstRow = _tableStyle; }
+
+ KWTableStyle lastRow() const { return *m_lastRow; }
+ KWTableStyle* pLastRow() const { return m_lastRow; }
+ void setLastRow( KWTableStyle *_tableStyle ) { m_lastRow = _tableStyle; }
+
+ KWTableStyle firstCol() const { return *m_firstCol; }
+ KWTableStyle* pFirstCol() const { return m_firstCol; }
+ void setFirstCol( KWTableStyle *_tableStyle ) { m_firstCol = _tableStyle; }
+
+ KWTableStyle lastCol() const { return *m_lastCol; }
+ KWTableStyle* pLastCol() const { return m_lastCol; }
+ void setLastCol( KWTableStyle *_tableStyle ) { m_lastCol = _tableStyle; }
+
+ KWTableStyle bodyCell() const { return *m_bodyCell; }
+ KWTableStyle* pBodyCell() const { return m_bodyCell; }
+ void setBodyCell( KWTableStyle *_tableStyle ) { m_bodyCell = _tableStyle; }
+
+ KWTableStyle topLeftCorner() const { return *m_topLeftCorner; }
+ KWTableStyle* pTopLeftCorner() const { return m_topLeftCorner; }
+ void setTopLeftCorner( KWTableStyle *_tableStyle ) { m_topLeftCorner = _tableStyle; }
+
+ KWTableStyle topRightCorner() const { return *m_topRightCorner; }
+ KWTableStyle* pTopRightCorner() const { return m_topRightCorner; }
+ void setTopRightCorner( KWTableStyle *_tableStyle ) { m_topRightCorner = _tableStyle; }
+
+ KWTableStyle bottomRightCorner() const { return *m_bottomRightCorner; }
+ KWTableStyle* pBottomRightCorner() const { return m_bottomRightCorner; }
+ void setBottomRightCorner( KWTableStyle *_tableStyle ) { m_bottomRightCorner = _tableStyle; }
+
+ KWTableStyle bottomLeftCorner() const { return *m_bottomLeftCorner; }
+ KWTableStyle* pBottomLeftCorner() const { return m_bottomLeftCorner; }
+ void setBottomLeftCorner( KWTableStyle *_tableStyle ) { m_bottomLeftCorner = _tableStyle; }
+
+ // SAVING METHODS
+ void save( QDomElement parentElem, KoTextZoomHandler* zh );
+ void saveTableTemplate( QDomElement & parentElem );
+
+ // STATIC METHODS
+ static KWTableTemplate *loadTemplate( QDomElement & parentElem, KWDocument *_doc, int docVersion=2 );
+
+private:
+ QString m_name;
+ KWTableStyle *m_firstRow;
+ KWTableStyle *m_lastRow;
+ KWTableStyle *m_firstCol;
+ KWTableStyle *m_lastCol;
+ KWTableStyle *m_bodyCell;
+
+ KWTableStyle *m_topLeftCorner;
+ KWTableStyle *m_topRightCorner;
+ KWTableStyle *m_bottomRightCorner;
+ KWTableStyle *m_bottomLeftCorner;
+
+};
+
+#endif
diff --git a/kword/KWTableTemplateSelector.cpp b/kword/KWTableTemplateSelector.cpp
new file mode 100644
index 00000000..e80c5bba
--- /dev/null
+++ b/kword/KWTableTemplateSelector.cpp
@@ -0,0 +1,680 @@
+/* This file is part of the KDE project
+ Copyright (C) 2002 Nash Hoogwater <nrhoogwater@wanadoo.nl>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; using
+ version 2 of the License.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+*/
+
+#include "KWTableTemplateSelector.h"
+#include "KWTableTemplateSelector.moc"
+
+#include "KWTableTemplate.h"
+#include "KWTableFrameSet.h"
+#include "KWDocument.h"
+#include "KWTextDocument.h"
+
+#include <KoRect.h>
+
+#include <klocale.h>
+#include <kurl.h>
+#include <kio/netaccess.h>
+#include <kstandarddirs.h>
+#include <kdebug.h>
+
+#include <qlabel.h>
+#include <qbuttongroup.h>
+#include <qcheckbox.h>
+#include <qcombobox.h>
+#include <qfile.h>
+#include <qdom.h>
+#include <qrect.h>
+#include <qptrlist.h>
+#include <qlayout.h>
+
+#include <stdlib.h>
+#include <math.h>
+
+/******************************************************************/
+/* Class: KWTableTemplatePreview */
+/******************************************************************/
+
+KWTableTemplatePreview::KWTableTemplatePreview( const QString& title, KWTableStyle *_emptyStyle, QWidget* parent, const char* name )
+ : QGroupBox( title, parent, name )
+{
+ m_emptyStyle = _emptyStyle;
+ m_zoomHandler = new KoTextZoomHandler;
+ m_textdoc = new KWTextDocument( m_zoomHandler );
+ tableTemplate = 0L;
+ origTableTemplate = 0L;
+ m_disableRepaint = false;
+ fillContents();
+}
+
+KWTableTemplatePreview::~KWTableTemplatePreview()
+{
+
+ delete m_textdoc;
+ delete m_zoomHandler;
+
+// if (tableTemplate)
+// delete tableTemplate;
+
+}
+
+int KWTableTemplatePreview::bottomBorder(const int rows, const int cols, const int rowpos, const int colpos)
+{
+ if ( (rowpos<0) || (colpos<0) ) return 0;
+
+ if ( (rowpos==0) && (colpos==0) ) // TOP LEFT CORNER
+ return int( tableTemplate->pTopLeftCorner()->frameStyle()->bottomBorder().width() );
+ else
+ if ( (rowpos==0) && ( colpos==(cols-1) ) ) // TOP RIGHT CORNER
+ return int( tableTemplate->pTopRightCorner()->frameStyle()->bottomBorder().width() );
+ else
+ if ( ( rowpos==(rows-1) ) && (colpos==0) ) // BOTTOM LEFT CORNER
+ return int( tableTemplate->pBottomLeftCorner()->frameStyle()->bottomBorder().width() );
+ else
+ if ( ( rowpos==(rows-1) ) && ( colpos==(cols-1) ) ) // BOTTOM RIGHT CORNER
+ return int( tableTemplate->pBottomRightCorner()->frameStyle()->bottomBorder().width() );
+ else
+ if ( ( rowpos==0 ) && ( colpos>0 ) && ( colpos<(cols-1) ) ) // FIRST ROW
+ return int( tableTemplate->pFirstRow()->frameStyle()->bottomBorder().width() );
+ else
+ if ( ( colpos==0 ) && ( rowpos>0 ) && ( rowpos<(rows-1) ) ) // FIRST COL
+ return int( tableTemplate->pFirstCol()->frameStyle()->bottomBorder().width() );
+ else
+ if ( ( rowpos==(rows-1) ) && ( colpos>0 ) && ( colpos<(cols-1) ) ) // LAST ROW
+ return int( tableTemplate->pLastRow()->frameStyle()->bottomBorder().width() );
+ else
+ if ( ( colpos==(cols-1) ) && ( rowpos>0 ) && ( rowpos<(rows-1) ) ) // LAST COL
+ return int( tableTemplate->pLastCol()->frameStyle()->bottomBorder().width() );
+ else
+ if ( (rowpos>0) && (colpos>0) && (rowpos<(rows-1)) && (colpos<(cols-1)) ) // BODY
+ return int( tableTemplate->pBodyCell()->frameStyle()->bottomBorder().width() );
+
+ return 0;
+}
+
+int KWTableTemplatePreview::rightBorder(const int rows, const int cols, const int rowpos, const int colpos)
+{
+ if ( (rowpos<0) || (colpos<0) ) return 0;
+
+ if ( (rowpos==0) && (colpos==0) ) // TOP LEFT CORNER
+ return int( tableTemplate->pTopLeftCorner()->frameStyle()->rightBorder().width() );
+ else
+ if ( (rowpos==0) && ( colpos==(cols-1) ) ) // TOP RIGHT CORNER
+ return int( tableTemplate->pTopRightCorner()->frameStyle()->rightBorder().width() );
+ else
+ if ( ( rowpos==(rows-1) ) && (colpos==0) ) // BOTTOM LEFT CORNER
+ return int( tableTemplate->pBottomLeftCorner()->frameStyle()->rightBorder().width() );
+ else
+ if ( ( rowpos==(rows-1) ) && ( colpos==(cols-1) ) ) // BOTTOM RIGHT CORNER
+ return int( tableTemplate->pBottomRightCorner()->frameStyle()->rightBorder().width() );
+ else
+ if ( ( rowpos==0 ) && ( colpos>0 ) && ( colpos<(cols-1) ) ) // FIRST ROW
+ return int( tableTemplate->pFirstRow()->frameStyle()->rightBorder().width() );
+ else
+ if ( ( colpos==0 ) && ( rowpos>0 ) && ( rowpos<(rows-1) ) ) // FIRST COL
+ return int( tableTemplate->pFirstCol()->frameStyle()->rightBorder().width() );
+ else
+ if ( ( rowpos==(rows-1) ) && ( colpos>0 ) && ( colpos<(cols-1) ) ) // LAST ROW
+ return int( tableTemplate->pLastRow()->frameStyle()->rightBorder().width() );
+ else
+ if ( ( colpos==(cols-1) ) && ( rowpos>0 ) && ( rowpos<(rows-1) ) ) // LAST COL
+ return int( tableTemplate->pLastCol()->frameStyle()->rightBorder().width() );
+ else
+ if ( (rowpos>0) && (colpos>0) && (rowpos<(rows-1)) && (colpos<(cols-1)) ) // BODY
+ return int( tableTemplate->pBodyCell()->frameStyle()->rightBorder().width() );
+
+ return 0;
+}
+
+void KWTableTemplatePreview::drawCell( QPainter *p, const KWTableStyle *ts, const QRect globalRect,
+ const int rows, int cols, int rowpos, int colpos, const QString & txt)
+{
+ if (!ts) return;
+
+ QRect insRect;
+
+ p->resetXForm();
+ p->setClipping( false );
+
+ // 1. Calculate insRect
+ int wid = int( globalRect.width()/cols ); // inner width
+ int hei = int( globalRect.height()/rows ); // inner height
+
+ insRect.setX( colpos*wid + globalRect.x() );
+ insRect.setY( rowpos*hei + globalRect.y() );
+ insRect.setWidth( static_cast<int>(wid + ts->frameStyle()->rightBorder().width()) );
+ insRect.setHeight( static_cast<int>(hei + ts->frameStyle()->bottomBorder().width()) );
+
+ // 2. Set background
+ // caching
+ int rb = rightBorder(rows,cols,rowpos,colpos-1);
+ int bb = bottomBorder(rows,cols,rowpos-1,colpos);
+ int hbb = bottomBorder(rows,cols,rowpos,colpos-1);
+ int wrb = rightBorder(rows,cols,rowpos-1,colpos);
+
+ if (rb==0)
+ rb = rightBorder(rows,cols,rowpos-1,colpos-1);
+ if (bb==0)
+ bb = bottomBorder(rows,cols,rowpos-1,colpos-1);
+
+ p->fillRect( QRect( colpos*wid + globalRect.x() + ( (rb <= ts->frameStyle()->rightBorder().width()) ? int(ts->frameStyle()->rightBorder().width()) : rb ),
+ rowpos*hei + globalRect.y() + ( (bb <= ts->frameStyle()->topBorder().width()) ? int(ts->frameStyle()->topBorder().width()) : bb ),
+ wid + ( ( (wrb > ts->frameStyle()->rightBorder().width()) && ((rb > ts->frameStyle()->rightBorder().width()) || ((rb==0) && (ts->frameStyle()->rightBorder().width()==0) ) ) && ((wrb-rb)>0) ) ? wrb : 0 ),
+ hei + ( ( (hbb > ts->frameStyle()->bottomBorder().width()) && ((bb > ts->frameStyle()->topBorder().width()) || ((bb==0) && (ts->frameStyle()->topBorder().width()==0) ) ) && ((hbb-bb)>0) ) ? hbb : 0 )),
+ ts->frameStyle()->backgroundColor() );
+
+ // 2. set Style
+ KoTextParag * parag = m_textdoc->firstParag();
+
+ parag->remove( 0, parag->string()->length()-1 );
+ parag->insert( 0, txt );
+ parag->applyStyle( ts->paragraphStyle() );
+
+ int widthLU = m_zoomHandler->pixelToLayoutUnitX( wid - 2 ); // keep one pixel border horizontally
+ if ( m_textdoc->width() != widthLU )
+ {
+ // For centering to work, and to even get word wrapping when the thing is too big :)
+ m_textdoc->setWidth( widthLU );
+ parag->invalidate(0);
+ }
+ double x_add = ( (rb < ts->frameStyle()->rightBorder().width()) ?
+ ts->frameStyle()->rightBorder().width() : rb ) +1;
+ double y_add = ( (bb < ts->frameStyle()->topBorder().width()) ?
+ ts->frameStyle()->topBorder().width() : bb ) + 1;
+
+ QRect textRect = parag->pixelRect( m_zoomHandler );
+ textRect.moveTopLeft( QPoint( insRect.x() + static_cast<int>(x_add),
+ insRect.y() + static_cast<int>(y_add)) );
+
+
+ textRect.setWidth(wid-2);
+
+ p->setClipRect( textRect.intersect( globalRect ) );
+ p->translate( textRect.x(), textRect.y() );
+
+ QColorGroup cg = QApplication::palette().active();
+ cg.setBrush( QColorGroup::Base, ts->frameStyle()->backgroundColor() );
+
+ m_textdoc->drawWYSIWYG( p, 1, 0, textRect.width() - 1, textRect.height(), cg, m_zoomHandler );
+
+ // 4. Set borders
+ p->resetXForm();
+ p->setClipping( false );
+
+ QRect cell(globalRect.x(), globalRect.y(),
+ int( globalRect.width() + ts->frameStyle()->rightBorder().width() ),
+ int( globalRect.height() + ts->frameStyle()->bottomBorder().width() ));
+ p->setClipRect( insRect.intersect( cell ) );
+
+ p->translate( insRect.x(), insRect.y() );
+
+ if (ts->frameStyle()->topBorder().width()>0) {
+ p->setPen( KoBorder::borderPen(ts->frameStyle()->topBorder(),
+ int(ts->frameStyle()->topBorder().width()), black) ); // Top border
+
+ p->drawLine( 0, int( floor( ts->frameStyle()->topBorder().width()/2 ) ),
+ int(wid + ts->frameStyle()->rightBorder().width()), int( floor( ts->frameStyle()->topBorder().width()/2 ) ) );
+ }
+ if (ts->frameStyle()->leftBorder().width()>0) {
+ p->setPen( KoBorder::borderPen(ts->frameStyle()->leftBorder(),
+ int(ts->frameStyle()->leftBorder().width()), black) ); // Left border
+
+ p->drawLine( int( floor( ts->frameStyle()->leftBorder().width()/2 ) ), 0,
+ int( floor( ts->frameStyle()->leftBorder().width()/2 ) ), hei + int(ts->frameStyle()->bottomBorder().width()) );
+ }
+ if (ts->frameStyle()->bottomBorder().width()>0) {
+ p->setPen( KoBorder::borderPen(ts->frameStyle()->bottomBorder(),
+ int(ts->frameStyle()->bottomBorder().width()), black) ); // Bottom border
+
+ p->drawLine( 0, hei+int( floor( ts->frameStyle()->bottomBorder().width()/2 ) ),
+ int(wid + ts->frameStyle()->rightBorder().width()), hei + int( floor( ts->frameStyle()->bottomBorder().width()/2 ) ) );
+ }
+ if (ts->frameStyle()->rightBorder().width()>0) {
+ p->setPen( KoBorder::borderPen(ts->frameStyle()->rightBorder(),
+ int(ts->frameStyle()->rightBorder().width()), black) ); // Right border
+
+ p->drawLine( wid + int( floor( ts->frameStyle()->rightBorder().width()/2 ) ), 0,
+ wid + int( floor( ts->frameStyle()->rightBorder().width()/2 ) ), hei + int(ts->frameStyle()->bottomBorder().width()) );
+ }
+}
+
+
+void KWTableTemplatePreview::drawPreviewTable( QPainter *p, int rows, int cols, QRect globalRect )
+{
+ KWTableStyle *cell = 0L;
+ QString txt;
+
+ for ( int i = 0; i < rows; i++ )
+ {
+ for ( int j = 0; j < cols; j++ )
+ {
+ if ( (i==0) && (j==0) ) // TOP LEFT CORNER
+ cell = tableTemplate->pTopLeftCorner();
+ else
+ if ( (i==0) && ( j==(cols-1) ) ) // TOP RIGHT CORNER
+ cell = tableTemplate->pTopRightCorner();
+ else
+ if ( ( i==(rows-1) ) && (j==0) ) // BOTTOM LEFT CORNER
+ cell = tableTemplate->pBottomLeftCorner();
+ else
+ if ( ( i==(rows-1) ) && ( j==(cols-1) ) ) // BOTTOM RIGHT CORNER
+ cell = tableTemplate->pBottomRightCorner();
+ else
+ if ( ( i==0 ) && ( j>0 ) && ( j<(cols-1) ) ) // FIRST ROW
+ cell = tableTemplate->pFirstRow();
+ else
+ if ( ( j==0 ) && ( i>0 ) && ( i<(rows-1) ) ) // FIRST COL
+ cell = tableTemplate->pFirstCol();
+ else
+ if ( ( i==(rows-1) ) && ( j>0 ) && ( j<(cols-1) ) ) // LAST ROW
+ cell = tableTemplate->pLastRow();
+ else
+ if ( ( j==(cols-1) ) && ( i>0 ) && ( i<(rows-1) ) ) // LAST COL
+ cell = tableTemplate->pLastCol();
+ else
+ if ( (i>0) && (j>0) && (i<(rows-1)) && (j<(cols-1)) ) // BODY
+ cell = tableTemplate->pBodyCell();
+
+ if ( (i==0) && (j==0) ) // TOP LEFT CORNER
+ txt = m_contents[0][0];
+ else
+ if ( ( i==0 ) && ( j>0 ) )
+ txt = m_contents[i][j];
+ else
+ if ( ( j==0 ) && ( i>0 ) )
+ txt = m_contents[1][i];
+ else
+ txt = QString::number(i) + QString::number(j);
+
+ drawCell( p, cell, globalRect, rows, cols, i, j, txt );
+ }
+ }
+}
+
+void KWTableTemplatePreview::drawContents( QPainter *p )
+{
+ p->save();
+ QRect r = contentsRect();
+
+ // 1. Draw fake document white background
+ p->fillRect( QRect( 10, 20, r.width() - 20, r.height() - 20 ), QColor("white") );
+
+ // 2. Draw preview table
+ if (tableTemplate) {
+
+ QRect tableRect;
+ int x,y;
+
+ // x
+ if ( tableTemplate->pTopRightCorner()->frameStyle()->rightBorder().width() >
+ tableTemplate->pLastCol()->frameStyle()->rightBorder().width() )
+ x = int( tableTemplate->pTopRightCorner()->frameStyle()->rightBorder().width() );
+ else
+ x = int( tableTemplate->pLastCol()->frameStyle()->rightBorder().width() );
+ if ( tableTemplate->pBottomRightCorner()->frameStyle()->rightBorder().width() > x )
+ x = int( tableTemplate->pBottomRightCorner()->frameStyle()->rightBorder().width() );
+
+ // y
+ if ( tableTemplate->pBottomRightCorner()->frameStyle()->bottomBorder().width() >
+ tableTemplate->pLastRow()->frameStyle()->bottomBorder().width() )
+ y = int( tableTemplate->pBottomRightCorner()->frameStyle()->bottomBorder().width() );
+ else
+ y = int( tableTemplate->pLastRow()->frameStyle()->bottomBorder().width() );
+ if ( tableTemplate->pBottomLeftCorner()->frameStyle()->bottomBorder().width() > y )
+ y = int( tableTemplate->pBottomLeftCorner()->frameStyle()->leftBorder().width() );
+
+ tableRect.setX( 20 - int(x/2) );
+ tableRect.setY( 30 - int(y/2) );
+ tableRect.setWidth( r.width() - 40 );
+ tableRect.setHeight( r.height() - 40 );
+
+ drawPreviewTable( p, 5, 4, tableRect );
+ }
+
+ p->restore();
+}
+
+void KWTableTemplatePreview::setSpecialCells( KWTableTemplate *_tableTemplate )
+{
+ if (_tableTemplate->pFirstRow()==_tableTemplate->pBodyCell())
+ tableTemplate->setFirstRow( tableTemplate->pBodyCell() );
+ else
+ tableTemplate->setFirstRow( _tableTemplate->pFirstRow() );
+
+ if (_tableTemplate->pFirstCol()==_tableTemplate->pBodyCell())
+ tableTemplate->setFirstCol( tableTemplate->pBodyCell() );
+ else
+ tableTemplate->setFirstCol( _tableTemplate->pFirstCol() );
+
+ if (_tableTemplate->pLastRow()==_tableTemplate->pBodyCell())
+ tableTemplate->setLastRow( tableTemplate->pBodyCell() );
+ else
+ tableTemplate->setLastRow( _tableTemplate->pLastRow() );
+
+ if (_tableTemplate->pLastCol()==_tableTemplate->pBodyCell())
+ tableTemplate->setLastCol( tableTemplate->pBodyCell() );
+ else
+ tableTemplate->setLastCol( _tableTemplate->pLastCol() );
+
+ if (_tableTemplate->pTopLeftCorner()==_tableTemplate->pBodyCell())
+ tableTemplate->setTopLeftCorner( tableTemplate->pBodyCell() );
+ else
+ tableTemplate->setTopLeftCorner( _tableTemplate->pTopLeftCorner() );
+
+ if (_tableTemplate->pTopRightCorner()==_tableTemplate->pBodyCell())
+ tableTemplate->setTopRightCorner( tableTemplate->pBodyCell() );
+ else
+ tableTemplate->setTopRightCorner( _tableTemplate->pTopRightCorner() );
+
+ if (_tableTemplate->pBottomLeftCorner()==_tableTemplate->pBodyCell())
+ tableTemplate->setBottomLeftCorner( tableTemplate->pBodyCell() );
+ else
+ tableTemplate->setBottomLeftCorner( _tableTemplate->pBottomLeftCorner() );
+
+ if (_tableTemplate->pBottomRightCorner()==_tableTemplate->pBodyCell())
+ tableTemplate->setBottomRightCorner( tableTemplate->pBodyCell() );
+ else
+ tableTemplate->setBottomRightCorner( _tableTemplate->pBottomRightCorner() );
+}
+
+void KWTableTemplatePreview::setTableTemplate( KWTableTemplate *_tableTemplate )
+{
+ origTableTemplate = _tableTemplate;
+
+ delete tableTemplate;
+
+ tableTemplate = new KWTableTemplate(_tableTemplate->displayName());
+ tableTemplate->setBodyCell( _tableTemplate->pBodyCell() );
+
+ setSpecialCells(_tableTemplate);
+
+ repaint( true );
+}
+
+void KWTableTemplatePreview::fillContents()
+{
+ // First row
+ m_contents[0][0] = "A";
+ m_contents[0][1] = "B";
+ m_contents[0][2] = "C";
+ m_contents[0][3] = "D";
+ m_contents[0][4] = "E";
+ // First col
+ m_contents[1][0] = ""; // Is overwritten by m_contents[0][0]
+ m_contents[1][1] = "I";
+ m_contents[1][2] = "II";
+ m_contents[1][3] = "III";
+ m_contents[1][4] = "IV";
+
+}
+
+KWTableTemplate* KWTableTemplatePreview::getTableTemplate() const
+{
+ return tableTemplate;
+}
+
+void KWTableTemplatePreview::cbFirstRowChanged( bool enable )
+{
+ if ( enable && (origTableTemplate->pFirstRow()!=origTableTemplate->pBodyCell()) )
+ tableTemplate->setFirstRow( origTableTemplate->pFirstRow() );
+ else
+ tableTemplate->setFirstRow( tableTemplate->pBodyCell() );
+
+ if ( enable && ( origTableTemplate->pTopLeftCorner()==origTableTemplate->pFirstRow() ) )
+ tableTemplate->setTopLeftCorner( origTableTemplate->pTopLeftCorner() );
+ else
+ if ( (!enable) && ( origTableTemplate->pTopLeftCorner()==origTableTemplate->pFirstRow() ) )
+ tableTemplate->setTopLeftCorner( tableTemplate->pBodyCell() );
+
+ if ( enable && ( origTableTemplate->pTopRightCorner()==origTableTemplate->pFirstRow() ) )
+ tableTemplate->setTopRightCorner( origTableTemplate->pTopRightCorner() );
+ else
+ if ( (!enable) && ( origTableTemplate->pTopRightCorner()==origTableTemplate->pFirstRow() ) )
+ tableTemplate->setTopRightCorner( tableTemplate->pBodyCell() );
+ if ( !m_disableRepaint )
+ repaint( true );
+}
+
+void KWTableTemplatePreview::cbFirstColChanged( bool enable )
+{
+ if ( enable && (origTableTemplate->pFirstCol()!=origTableTemplate->pBodyCell()) )
+ tableTemplate->setFirstCol( origTableTemplate->pFirstCol() );
+ else
+ tableTemplate->setFirstCol( tableTemplate->pBodyCell() );
+
+ if ( enable && ( origTableTemplate->pTopLeftCorner()==origTableTemplate->pFirstCol() ) )
+ tableTemplate->setTopLeftCorner( origTableTemplate->pTopLeftCorner() );
+ else
+ if ( (!enable) && ( origTableTemplate->pTopLeftCorner()==origTableTemplate->pFirstCol() ) )
+ tableTemplate->setTopLeftCorner( tableTemplate->pBodyCell() );
+
+ if ( enable && ( origTableTemplate->pBottomLeftCorner()==origTableTemplate->pFirstCol() ) )
+ tableTemplate->setBottomLeftCorner( origTableTemplate->pBottomLeftCorner() );
+ else
+ if ( (!enable) && ( origTableTemplate->pBottomLeftCorner()==origTableTemplate->pFirstCol() ) )
+ tableTemplate->setBottomLeftCorner( tableTemplate->pBodyCell() );
+
+ if ( !m_disableRepaint )
+ repaint( true );
+}
+
+void KWTableTemplatePreview::cbLastRowChanged( bool enable )
+{
+ if ( enable && (origTableTemplate->pLastRow()!=origTableTemplate->pBodyCell()) )
+ tableTemplate->setLastRow( origTableTemplate->pLastRow() );
+ else
+ tableTemplate->setLastRow( tableTemplate->pBodyCell() );
+
+ if ( enable && ( origTableTemplate->pBottomRightCorner()==origTableTemplate->pLastRow() ) )
+ tableTemplate->setBottomRightCorner( origTableTemplate->pBottomRightCorner() );
+ else
+ if ( (!enable) && ( origTableTemplate->pBottomRightCorner()==origTableTemplate->pLastRow() ) )
+ tableTemplate->setBottomRightCorner( tableTemplate->pBodyCell() );
+
+ if ( enable && ( origTableTemplate->pBottomLeftCorner()==origTableTemplate->pLastRow() ) )
+ tableTemplate->setBottomLeftCorner( origTableTemplate->pBottomLeftCorner() );
+ else
+ if ( (!enable) && ( origTableTemplate->pBottomLeftCorner()==origTableTemplate->pLastRow() ) )
+ tableTemplate->setBottomLeftCorner( tableTemplate->pBodyCell() );
+
+ if ( !m_disableRepaint )
+ repaint( true );
+}
+
+void KWTableTemplatePreview::cbLastColChanged( bool enable )
+{
+ if ( enable && (origTableTemplate->pLastCol()!=origTableTemplate->pBodyCell()) )
+ tableTemplate->setLastCol( origTableTemplate->pLastCol() );
+ else
+ tableTemplate->setLastCol( tableTemplate->pBodyCell() );
+
+ if ( enable && ( origTableTemplate->pTopRightCorner()==origTableTemplate->pLastCol() ) )
+ tableTemplate->setTopRightCorner( origTableTemplate->pTopRightCorner() );
+ else
+ if ( (!enable) && ( origTableTemplate->pTopRightCorner()==origTableTemplate->pLastCol() ) )
+ tableTemplate->setTopRightCorner( tableTemplate->pBodyCell() );
+
+ if ( enable && ( origTableTemplate->pBottomRightCorner()==origTableTemplate->pLastCol() ) )
+ tableTemplate->setBottomRightCorner( origTableTemplate->pBottomRightCorner() );
+ else
+ if ( (!enable) && ( origTableTemplate->pBottomRightCorner()==origTableTemplate->pLastCol() ) )
+ tableTemplate->setBottomRightCorner( tableTemplate->pBodyCell() );
+
+ if ( !m_disableRepaint )
+ repaint( true );
+}
+
+void KWTableTemplatePreview::cbBodyChanged( bool enable )
+{
+ KWTableTemplate *oldTemplate = new KWTableTemplate( *tableTemplate );
+
+ if ( enable )
+ tableTemplate->setBodyCell( origTableTemplate->pBodyCell() );
+ else
+ tableTemplate->setBodyCell( m_emptyStyle );
+
+ setSpecialCells(oldTemplate);
+
+ delete oldTemplate;
+
+ if ( !m_disableRepaint )
+ repaint( true );
+
+}
+
+
+/******************************************************************/
+/* Class: KWTableTemplateSelector */
+/******************************************************************/
+
+KWTableTemplateSelector::KWTableTemplateSelector( KWDocument *_doc, QWidget *_parent, const QString & _tableTemplate, int _type,const char *_name)
+ : QWidget( _parent, _name )
+{
+ m_doc = _doc;
+
+ QGridLayout *grid = new QGridLayout( this, 3, 2, 0, KDialog::spacingHint() );
+
+ QWidget *innerHolder = new QWidget( this );
+ QGridLayout *innerGrid = new QGridLayout( innerHolder, 2, 1, 0, KDialog::spacingHint() );
+
+ lbTemplates = new QListBox( innerHolder );
+
+ QPtrListIterator<KWTableTemplate> it( m_doc->tableTemplateCollection()->tableTemplateList() );
+ for ( ; it.current() ; ++it )
+ {
+ lbTemplates->insertItem( it.current()->displayName() );
+ }
+
+ innerGrid->addWidget( lbTemplates, 0, 0 );
+
+ pbCustomize = new QPushButton( i18n( "&Customize" ), innerHolder );
+ pbCustomize->setEnabled(false);
+ pbCustomize->hide();
+ innerGrid->addWidget( pbCustomize, 1, 0 );
+
+ grid->addMultiCellWidget( innerHolder, 0, 2, 0, 0 );
+
+ preview = new KWTableTemplatePreview( i18n( "Preview" ), m_doc->tableStyleCollection()->findStyle("Plain"), this );
+ grid->addWidget( preview, 0, 1 );
+
+ bgCustomize = new QButtonGroup( 3, Horizontal, i18n( "Apply To" ), this );
+
+ cbFirstRow = new QCheckBox( i18n( "First row" ), bgCustomize );
+ cbLastRow = new QCheckBox( i18n( "Last row" ), bgCustomize );
+ cbBody = new QCheckBox( i18n( "Body" ), bgCustomize );
+ cbFirstCol = new QCheckBox( i18n( "First column" ), bgCustomize );
+ cbLastCol = new QCheckBox( i18n( "Last column" ), bgCustomize );
+
+ grid->addWidget( bgCustomize, 1, 1 );
+
+ grid->setRowStretch( 0, 1 );
+ grid->setRowStretch( 1, 0 );
+ grid->addColSpacing( 0, innerHolder->width() );
+ grid->setColStretch( 0, 0 );
+ grid->setColStretch( 1, 1 );
+ grid->activate();
+
+ connect( cbFirstRow, SIGNAL( toggled( bool ) ), preview, SLOT( cbFirstRowChanged( bool ) ) );
+ connect( cbFirstCol, SIGNAL( toggled( bool ) ), preview, SLOT( cbFirstColChanged( bool ) ) );
+ connect( cbLastRow, SIGNAL( toggled( bool ) ), preview, SLOT( cbLastRowChanged( bool ) ) );
+ connect( cbLastCol, SIGNAL( toggled( bool ) ), preview, SLOT( cbLastColChanged( bool ) ) );
+ connect( cbBody, SIGNAL( toggled( bool ) ), preview, SLOT( cbBodyChanged( bool ) ) );
+
+ connect( lbTemplates, SIGNAL( selectionChanged () ), this, SLOT( changeTableTemplate() ) );
+ QListBoxItem * item = lbTemplates->findItem( _tableTemplate );
+ int index = 0;
+ if ( item )
+ index = lbTemplates->index ( item );
+ if (m_doc->tableTemplateCollection()->tableTemplateList().count() > 0) {
+ preview->setTableTemplate( m_doc->tableTemplateCollection()->tableTemplateAt(index) );
+ selectedTableTemplate = 0L;
+ lbTemplates->setSelected( index, true );
+ }
+ initFormat( _type );
+}
+
+void KWTableTemplateSelector::changeTableTemplate()
+{
+ preview->setTableTemplate( m_doc->tableTemplateCollection()->tableTemplateAt( lbTemplates->currentItem() ) );
+ selectedTableTemplate = lbTemplates->currentItem();
+ initPreview();
+}
+
+KWTableTemplate* KWTableTemplateSelector::getTableTemplate() const
+{
+ return (selectedTableTemplate) ? preview->getTableTemplate() : 0L;
+}
+
+void KWTableTemplateSelector::initFormat( int format)
+{
+ if ( format & FirstRow)
+ cbFirstRow->setChecked( true );
+
+ if ( format & FirstColumn)
+ cbFirstCol->setChecked( true );
+
+ if ( format & LastRow)
+ cbLastRow->setChecked( true );
+
+ if ( format & LastCol)
+ cbLastCol->setChecked( true );
+
+ if ( format & Body)
+ cbBody->setChecked( true );
+ initPreview();
+}
+
+void KWTableTemplateSelector::initPreview()
+{
+ preview->disableRepaint(true);
+ preview->cbFirstRowChanged( cbFirstRow->isChecked() );
+ preview->cbFirstColChanged( cbFirstCol->isChecked( ) );
+ preview->cbLastRowChanged(cbLastRow->isChecked() );
+ preview->cbLastColChanged( cbLastCol->isChecked() );
+ preview->cbBodyChanged( cbBody->isChecked() );
+ preview->disableRepaint(false);
+ preview->repaint();
+}
+
+int KWTableTemplateSelector::getFormatType() const
+{
+ int type = 0;
+ if ( cbFirstRow->isChecked())
+ {
+ type = type | FirstRow;
+ }
+ if ( cbFirstCol->isChecked())
+ {
+ type = type |FirstColumn;
+
+ }
+ if ( cbLastRow->isChecked())
+ {
+ type = type | LastRow;
+
+ }
+ if ( cbLastCol->isChecked())
+ {
+ type = type | LastCol;
+ }
+ if ( cbBody->isChecked())
+ {
+ type = type | Body;
+ }
+ return type;
+}
diff --git a/kword/KWTableTemplateSelector.h b/kword/KWTableTemplateSelector.h
new file mode 100644
index 00000000..ada023bf
--- /dev/null
+++ b/kword/KWTableTemplateSelector.h
@@ -0,0 +1,126 @@
+/* This file is part of the KDE project
+ Copyright (C) 2002 Nash Hoogwater <nrhoogwater@wanadoo.nl>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; using
+ version 2 of the License.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+*/
+
+#ifndef kwtabletemplateselector_h
+#define kwtabletemplateselector_h
+
+#include <qwidget.h>
+#include <qgroupbox.h>
+#include <qptrlist.h>
+
+#include <qlabel.h>
+#include <qpushbutton.h>
+/*#include <qlayout.h>
+#include <qfont.h>
+#include <qbrush.h>
+*/
+
+class QListBox;
+class QCheckBox;
+class QButtonGroup;
+class QGroupBox;
+class QRect;
+
+class KWTableTemplate;
+class KWTableTemplateCollection;
+class KoRect;
+class KoTextZoomHandler;
+class KWTextDocument;
+class KWDocument;
+class KWTableFrameSet;
+class KWTableStyle;
+
+/******************************************************************/
+/* Class: KWTableTemplatePreview */
+/******************************************************************/
+
+class KWTableTemplatePreview : public QGroupBox
+{
+ Q_OBJECT
+
+public:
+ KWTableTemplatePreview( const QString& title, KWTableStyle *_emptyStyle, QWidget* parent, const char* name=0L );
+ ~KWTableTemplatePreview();
+ void setTableTemplate(KWTableTemplate *_tableTemplate);
+ KWTableTemplate *getTableTemplate()const ;
+ void disableRepaint(bool _b) { m_disableRepaint =_b;}
+public slots:
+ void cbFirstRowChanged( bool );
+ void cbFirstColChanged( bool );
+ void cbLastRowChanged( bool );
+ void cbLastColChanged( bool );
+ void cbBodyChanged( bool );
+
+protected:
+ int bottomBorder(const int rows, const int cols, const int rowpos, const int colpos);
+ int rightBorder(const int rows, const int cols, const int rowpos, const int colpos);
+ void drawCell( QPainter *p, const KWTableStyle *ts, const QRect globalRect,
+ const int rows, int cols, int rowpos, int colpos, const QString & txt);
+ void drawPreviewTable(QPainter *p, int rows, int cols, QRect globalRect);
+ void drawContents( QPainter *p );
+ void setSpecialCells(KWTableTemplate *);
+
+ KWTableStyle *m_emptyStyle;
+ KWTextDocument *m_textdoc;
+ KoTextZoomHandler *m_zoomHandler;
+ KWTableTemplate *tableTemplate;
+ KWTableTemplate *origTableTemplate;
+ //necessary when we init preview
+ bool m_disableRepaint;
+private:
+ QString m_contents[2][5];
+
+ void fillContents();
+};
+
+/******************************************************************/
+/* Class: KWTableTemplateSelector */
+/******************************************************************/
+
+class KWTableTemplateSelector : public QWidget
+{
+ Q_OBJECT
+
+public:
+ enum FormatType { FirstRow = 1 , FirstColumn = 2, LastRow = 4, LastCol =8, Body =16 };
+ KWTableTemplateSelector( KWDocument *_doc, QWidget * _parent, const QString & _tableTemplate, int _type = 31 , const char * _name = 0 );
+
+ KWTableTemplate *getTableTemplate()const ;
+ int getFormatType() const ;
+protected:
+ KWDocument *m_doc;
+
+ KWTableTemplatePreview *preview;
+ QLabel *lTemplates;
+ QListBox *lbTemplates;
+ QPushButton *pbCustomize;
+
+ QButtonGroup *bgCustomize;
+ QCheckBox *cbFirstRow, *cbFirstCol, *cbLastRow, *cbLastCol, *cbBody;
+
+ int selectedTableTemplate;
+ void initFormat( int format);
+ void initPreview();
+protected slots:
+ void changeTableTemplate();
+};
+
+#endif
+
+
diff --git a/kword/KWTextDocument.cpp b/kword/KWTextDocument.cpp
new file mode 100644
index 00000000..ddfb5304
--- /dev/null
+++ b/kword/KWTextDocument.cpp
@@ -0,0 +1,327 @@
+/* This file is part of the KDE project
+ Copyright (C) 2001-2005 David Faure <faure@kde.org>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+*/
+
+#include "KWCommand.h"
+#include "KWDocument.h"
+#include "KWTextDocument.h"
+#include "KWTextFrameSet.h"
+#include "KWTextParag.h"
+#include "KWLoadingInfo.h"
+#include "KWVariable.h"
+#include "KWAnchor.h"
+#include "KWOasisLoader.h"
+#include "KWTableFrameSet.h"
+
+#include <KoOasisContext.h>
+#include <KoXmlNS.h>
+#include <KoDom.h>
+
+#include <kdebug.h>
+#include <kglobalsettings.h>
+#include <klocale.h>
+
+KWTextDocument::KWTextDocument( KWTextFrameSet * textfs, KoTextFormatCollection *fc, KoTextFormatter *formatter )
+ : KoTextDocument( textfs->kWordDocument(), fc, formatter, false ), m_textfs( textfs )
+{
+ init();
+}
+
+KWTextDocument::KWTextDocument( KoTextZoomHandler * zoomHandler )
+ : KoTextDocument( zoomHandler, new KoTextFormatCollection( KGlobalSettings::generalFont() /*unused*/, QColor(), KGlobal::locale()->language(), false), 0L, false ),
+ m_textfs( 0 )
+{
+ init();
+}
+
+void KWTextDocument::init()
+{
+ // Create initial paragraph as a KWTextParag
+ clear( true );
+}
+
+KWTextDocument::~KWTextDocument()
+{
+}
+
+KoTextParag * KWTextDocument::createParag( KoTextDocument *d, KoTextParag *pr, KoTextParag *nx, bool updateIds )
+{
+ return new KWTextParag( static_cast<KoTextDocument *>(d), static_cast<KoTextParag *>(pr), static_cast<KoTextParag *>(nx), updateIds );
+}
+
+KoTextDocCommand *KWTextDocument::deleteTextCommand( KoTextDocument *textdoc, int id, int index, const QMemArray<KoTextStringChar> & str, const CustomItemsMap & customItemsMap, const QValueList<KoParagLayout> & oldParagLayouts )
+{
+ //kdDebug(32500)<<" KoTextDocument::deleteTextCommand************\n";
+ return new KWTextDeleteCommand( textdoc, id, index, str, customItemsMap, oldParagLayouts );
+}
+
+void KWTextDocument::loadOasisTOC( const QDomElement& tag, KoOasisContext& context, KoTextParag* & lastParagraph, KoStyleCollection * styleColl, KoTextParag* nextParagraph )
+{
+ // table-of-content OOo SPEC 7.5 p452
+ //fillStyleStack( tag, "text:style-name" ); that's the section style
+
+ //QDomElement tocSource = KoDom::namedItemNS( toc, KoXmlNS::text, "table-of-content-source" );
+ // TODO parse templates and generate "Contents ..." styles from it
+ //for ( QDomNode n(tocSource.firstChild()); !text.isNull(); text = text.nextSibling() )
+ //{
+ //}
+
+ QDomElement tocIndexBody = KoDom::namedItemNS( tag, KoXmlNS::text, "index-body" );
+ QDomElement t;
+ forEachElement( t, tocIndexBody )
+ {
+ context.styleStack().save();
+ const QString localName = t.localName();
+ QDomElement e;
+ bool isTextNS = tag.namespaceURI() == KoXmlNS::text;
+ if ( isTextNS && localName == "index-title" ) {
+ lastParagraph = loadOasisText( t, context, lastParagraph, styleColl, nextParagraph ); // recurse again
+ lastParagraph->setPartOfTableOfContents( true );
+ } else if ( isTextNS && localName == "p" ) {
+ context.fillStyleStack( t, KoXmlNS::text, "style-name", "paragraph" );
+ lastParagraph = createParag( this, lastParagraph, nextParagraph );
+ uint pos = 0;
+ lastParagraph->loadOasis( t, context, styleColl, pos );
+ lastParagraph->setPartOfTableOfContents( true );
+ } else
+ kdWarning() << "OASIS TOC loading: unknown tag " << t.tagName() << " found in index-body" << endl;
+ context.styleStack().restore();
+ }
+
+ m_textfs->kWordDocument()->setTocPresent( true );
+}
+
+bool KWTextDocument::loadOasisBodyTag( const QDomElement& tag, KoOasisContext& context,
+ KoTextParag* & lastParagraph, KoStyleCollection* styleColl,
+ KoTextParag* nextParagraph )
+{
+ const QString localName( tag.localName() );
+ // Non-inline frame (i.e. anchored to page)
+ if ( localName == "frame" && tag.namespaceURI() == KoXmlNS::draw )
+ {
+ KWDocument* doc = m_textfs->kWordDocument();
+ KWOasisLoader loader( doc );
+ KWFrame* frame = loader.loadFrame( tag, context, KoPoint() );
+ if ( frame )
+ return true;
+ }
+
+ // Anchored-to-paragraph table.
+ else if ( localName == "table" && tag.namespaceURI() == KoXmlNS::table )
+ {
+ KWDocument* doc = m_textfs->kWordDocument();
+ KWOasisLoader loader( doc );
+ KWTableFrameSet* table = loader.loadOasisTable( tag, context );
+ table->finalize();
+ // Create paragraph for this table
+ KoTextParag *parag = createParag( this, lastParagraph, nextParagraph );
+ if ( !lastParagraph ) // First parag
+ setFirstParag( parag );
+ lastParagraph = parag;
+ // Put inline table in that paragraph
+ parag->insert( 0, KoTextObject::customItemChar() );
+ table->setAnchorFrameset( m_textfs );
+ parag->setCustomItem( 0, table->createAnchor( m_textfs->textDocument(), 0 ), 0 );
+ return true;
+ }
+ else if ( localName == "table-of-content" && tag.namespaceURI() == KoXmlNS::text )
+ {
+ loadOasisTOC( tag, context, lastParagraph, styleColl, nextParagraph );
+ return true;
+ }
+
+ return false;
+}
+
+void KWTextDocument::appendBookmark( KoTextParag* parag, int pos, KoTextParag* endParag, int endPos, const QString& name )
+{
+ // The OASIS format is cool. No need to store the bookmarks until end of loading (e.g. KWLoadingInfo)
+ // We can "resolve" them right away.
+ m_textfs->kWordDocument()->insertBookmark( name, parag, endParag, pos, endPos );
+}
+
+void KWTextDocument::loadOasisFootnote( const QDomElement& tag, KoOasisContext& context,
+ KoTextCustomItem* & customItem )
+{
+ const QString frameName( tag.attributeNS( KoXmlNS::text, "id", QString::null) );
+ const QString localName( tag.localName() );
+ const QDomElement citationElem = tag.namedItem( localName + "-citation" ).toElement();
+
+ bool endnote = localName == "endnote" && tag.namespaceURI() == KoXmlNS::text;
+
+ QString label = citationElem.attributeNS( KoXmlNS::text, "label", QString::null );
+ bool autoNumbered = label.isEmpty();
+
+ KWFootNoteFrameSet *fs = m_textfs->insertFootNote(
+ endnote ? EndNote : FootNote,
+ autoNumbered ? KWFootNoteVariable::Auto : KWFootNoteVariable::Manual,
+ label );
+ customItem = fs->footNoteVariable();
+
+ fs->createInitialFrame( 0 ); // we don't know the page number...
+
+ // Parse contents into the frameset
+ const QDomElement bodyElem = KoDom::namedItemNS( tag, KoXmlNS::text, QCString( localName.latin1() ) + "-body" ).toElement();
+ fs->loadOasisContent( bodyElem, context );
+}
+
+bool KWTextDocument::loadSpanTag( const QDomElement& tag, KoOasisContext& context,
+ KoTextParag* parag, uint pos,
+ QString& textData, KoTextCustomItem* & customItem )
+{
+ const QString localName( tag.localName() );
+ const bool isTextNS = tag.namespaceURI() == KoXmlNS::text;
+ kdDebug(32500) << "KWTextDocument::loadSpanTag: " << localName << endl;
+
+ if ( isTextNS )
+ {
+ if ( localName == "a" )
+ {
+ QString href( tag.attributeNS( KoXmlNS::xlink, "href", QString::null) );
+ if ( href.startsWith("#") )
+ {
+ context.styleStack().save();
+ // We have a reference to a bookmark (### TODO)
+ // As we do not support it now, treat it as a <span> without formatting
+ parag->loadOasisSpan( tag, context, pos ); // recurse
+ context.styleStack().restore();
+ }
+ else
+ {
+ // The text is contained in a <span> inside the <a> element. In theory
+ // we could have multiple spans there, but OO ensures that there is always only one,
+ // splitting the hyperlink if necessary (at format changes).
+ // Note that we ignore the formatting of the span.
+ QDomElement spanElem = KoDom::namedItemNS( tag, KoXmlNS::text, "span" );
+ QString text;
+ if( spanElem.isNull() )
+ text = tag.text();
+ else {
+ // The save/restore of the stack is done by the caller (KoTextParag::loadOasisSpan)
+ // This allows to use the span's format for the variable.
+ //kdDebug(32500) << "filling stack with " << spanElem.attributeNS( KoXmlNS::text, "style-name", QString::null ) << endl;
+ context.fillStyleStack( spanElem, KoXmlNS::text, "style-name", "text" );
+ text = spanElem.text();
+ }
+ textData = KoTextObject::customItemChar(); // hyperlink placeholder
+ // unused tag.attributeNS( KoXmlNS::office, "name", QString::null )
+ KoVariableCollection& coll = context.variableCollection();
+ customItem = new KoLinkVariable( this, text, href,
+ coll.formatCollection()->format( "STRING" ),
+ &coll );
+ }
+ return true;
+ }
+ else if ( localName == "bookmark" )
+ {
+ appendBookmark( parag, pos, parag, pos, tag.attributeNS( KoXmlNS::text, "name", QString::null ) );
+ return true;
+ }
+ else if ( localName == "bookmark-start" ) {
+ KWLoadingInfo* loadingInfo = m_textfs->kWordDocument()->loadingInfo();
+ loadingInfo->m_bookmarkStarts.insert( tag.attributeNS( KoXmlNS::text, "name", QString::null ),
+ KWLoadingInfo::BookmarkStart( this, parag, pos ) );
+ return true;
+ }
+ else if ( localName == "bookmark-end" ) {
+ KWLoadingInfo* loadingInfo = m_textfs->kWordDocument()->loadingInfo();
+ QString bkName = tag.attributeNS( KoXmlNS::text, "name", QString::null );
+ KWLoadingInfo::BookmarkStartsMap::iterator it = loadingInfo->m_bookmarkStarts.find( bkName );
+ if ( it == loadingInfo->m_bookmarkStarts.end() ) { // bookmark end without start. This seems to happen..
+ // insert simple bookmark then
+ appendBookmark( parag, pos, parag, pos, tag.attributeNS( KoXmlNS::text, "name", QString::null ) );
+ } else {
+ if ( (*it).doc != this ) {
+ // Oh tell me this never happens...
+ kdWarning(32500) << "Cross-frameset bookmark! Not supported." << endl;
+ } else {
+ appendBookmark( (*it).parag, (*it).pos, parag, pos, it.key() );
+ }
+ loadingInfo->m_bookmarkStarts.remove( it );
+ }
+ return true;
+ }
+ else if ( localName == "footnote" || localName == "endnote" )
+ {
+ textData = KoTextObject::customItemChar(); // anchor placeholder
+ loadOasisFootnote( tag, context, customItem );
+ return true;
+ }
+ }
+ else // not in the "text" namespace
+ {
+ if ( tag.namespaceURI() == KoXmlNS::draw && localName == "frame" )
+ {
+ if ( tag.attributeNS( KoXmlNS::koffice, "is-wrapper-frame", QString::null )
+ == "true" )
+ {
+ QDomElement textbox = KoDom::namedItemNS( tag, KoXmlNS::draw, "text-box" );
+ if ( !textbox.isNull() )
+ {
+ int numberOfElements = 0;
+ QDomElement elem;
+ QDomElement firstElem;
+ forEachElement( elem, textbox )
+ {
+ ++numberOfElements;
+ firstElem = elem;
+ }
+ if ( numberOfElements == 1 ) // if someone added more stuff, keep the wrapper frame
+ {
+ kdDebug(32001) << "Wrapper frame removed, loading " << firstElem.tagName() << " directly" << endl;
+ // load the only child, e.g. table:table
+ return loadSpanTag( firstElem, context, parag, pos, textData, customItem );
+ }
+ }
+ return true;
+ }
+
+ KWDocument* doc = m_textfs->kWordDocument();
+ KWOasisLoader loader( doc );
+ KWFrame* frame = loader.loadFrame( tag, context, KoPoint() );
+ if ( frame )
+ {
+ KWFrameSet* fs = frame->frameSet();
+ // Hmm, if this is a continuation frame of a non-inline frameset,
+ // it's going to inline the whole frameset...
+ // ###### In fact this shows we should inline frames, not framesets, in KWord (!!!!) (big TODO)
+ // ## well, for tables it's the whole frameset.
+ textData = KoTextObject::customItemChar();
+ fs->setAnchorFrameset( m_textfs );
+ customItem = fs->createAnchor( m_textfs->textDocument(), 0 /*frame number; TODO somehow*/ );
+ }
+ return true;
+ }
+ // anchored-as-char table. Not supported by OASIS directly, but we end up
+ // calling this when removing the wrapper frame above.
+ else if ( tag.namespaceURI() == KoXmlNS::table && localName == "table" )
+ {
+ KWDocument* doc = m_textfs->kWordDocument();
+ KWOasisLoader loader( doc );
+ KWTableFrameSet* table = loader.loadOasisTable( tag, context );
+ table->finalize();
+ textData = KoTextObject::customItemChar();
+ table->setAnchorFrameset( m_textfs );
+ customItem = table->createAnchor( m_textfs->textDocument(), 0 /*frame number*/ );
+ return true;
+ }
+ }
+ return false;
+}
+
+#include "KWTextDocument.moc"
diff --git a/kword/KWTextDocument.h b/kword/KWTextDocument.h
new file mode 100644
index 00000000..c1a6bb84
--- /dev/null
+++ b/kword/KWTextDocument.h
@@ -0,0 +1,73 @@
+/* This file is part of the KDE project
+ Copyright (C) 2001-2005 David Faure <faure@kde.org>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+*/
+
+#ifndef kwtextdocument_h
+#define kwtextdocument_h
+
+#include "KoRichText.h"
+#include <KoTextDocument.h>
+
+class KWFrame;
+class KWTextFrameSet;
+class KoTextFormatCollection;
+class KoTextDocCommand;
+
+/**
+ * This is our KoTextDocument reimplementation, to create KWTextParag instead of KoTextParags,
+ * and to relate it to the text frameset it's in.
+ */
+class KWTextDocument : public KoTextDocument
+{
+ Q_OBJECT
+public:
+ /** A real text document inside a frameset */
+ KWTextDocument( KWTextFrameSet * textfs, KoTextFormatCollection *fc, KoTextFormatter *formatter = 0L );
+ /** A standalone text document, for a preview */
+ KWTextDocument( KoTextZoomHandler * zoomHandler );
+
+ ~KWTextDocument();
+
+ virtual KoTextParag * createParag( KoTextDocument *d, KoTextParag *pr = 0, KoTextParag *nx = 0, bool updateIds = TRUE );
+
+ /** Return the text frameset in which this document is.
+ * Note that this can be 0L (e.g. for paragraphs in the paragdia preview) */
+ KWTextFrameSet * textFrameSet() const { return m_textfs; }
+
+ virtual KoTextDocCommand *deleteTextCommand( KoTextDocument *textdoc, int id, int index, const QMemArray<KoTextStringChar> & str, const CustomItemsMap & customItemsMap, const QValueList<KoParagLayout> & oldParagLayouts );
+
+ /// Extensions to KoTextParag::loadOasisSpan
+ virtual bool loadSpanTag( const QDomElement& tag, KoOasisContext& context,
+ KoTextParag* parag, uint pos,
+ QString& textData, KoTextCustomItem* & customItem );
+ /// Extensions to KoTextDocument::loadOasisText
+ virtual bool loadOasisBodyTag( const QDomElement& tag, KoOasisContext& context,
+ KoTextParag* & lastParagraph, KoStyleCollection * styleColl,
+ KoTextParag* nextParagraph );
+protected:
+ void init();
+private:
+ void appendBookmark( KoTextParag* parag, int pos, KoTextParag* endParag, int endPos, const QString& name );
+ void loadOasisFootnote( const QDomElement& tag, KoOasisContext& context,
+ KoTextCustomItem* & customItem );
+ void loadOasisTOC( const QDomElement& tag, KoOasisContext& context, KoTextParag* & lastParagraph, KoStyleCollection* styleColl, KoTextParag* nextParagraph );
+
+ KWTextFrameSet * m_textfs;
+};
+
+#endif
diff --git a/kword/KWTextFrameSet.cpp b/kword/KWTextFrameSet.cpp
new file mode 100644
index 00000000..9652cd0c
--- /dev/null
+++ b/kword/KWTextFrameSet.cpp
@@ -0,0 +1,4154 @@
+/* This file is part of the KDE project
+ Copyright (C) 1998, 1999, 2000 Reginald Stadlbauer <reggie@kde.org>
+ Copyright (C) 2001-2006 David Faure <faure@kde.org>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+*/
+
+#include "KWTextFrameSet.h"
+#include "KWTableFrameSet.h"
+#include "KWDocument.h"
+#include "KWView.h"
+#include "KWViewMode.h"
+#include "KWCanvas.h"
+#include "KWAnchor.h"
+#include "KWCommand.h"
+#include "KWFormulaFrameSet.h"
+#include "KWBgSpellCheck.h"
+#include "KWordTextFrameSetIface.h"
+#include "KWordTextFrameSetEditIface.h"
+#include "KWordFootNoteFrameSetIface.h"
+#include "KWordFrameSetIface.h"
+#include "KWLoadingInfo.h"
+#include "KWInsertTOCCommand.h"
+#include "KWMailMergeDataBase.h"
+#include "KoTextBookmark.h"
+#include "KWVariable.h"
+#include "KWOasisSaver.h"
+#include "KWFrameList.h"
+#include "KWPageManager.h"
+#include "KWPage.h"
+
+#include <KoParagCounter.h>
+#include <KoCustomVariablesDia.h>
+#include <KoAutoFormat.h>
+#include <KoTextObject.h>
+#include <KoTextCommand.h>
+#include <KoTextFormatter.h>
+#include <KoChangeCaseDia.h>
+#include <KoXmlNS.h>
+#include <KoXmlWriter.h>
+#include <KoOasisContext.h>
+#include <KoStore.h>
+
+#include <klocale.h>
+#include <kaction.h>
+#include <kmessagebox.h>
+#include <kdebug.h>
+
+#include <qclipboard.h>
+#include <qdragobject.h>
+#include <qcursor.h>
+#include <qfile.h>
+#include <qprogressdialog.h>
+#include <qregexp.h>
+
+#include <assert.h>
+#include <qapplication.h>
+
+//#define DEBUG_MARGINS
+//#define DEBUG_FORMATVERTICALLY
+//#define DEBUG_FORMATS
+//#define DEBUG_FORMAT_MORE
+//#define DEBUG_VIEWAREA
+//#define DEBUG_CURSOR
+
+//#define DEBUG_DTI
+//#define DEBUG_ITD
+
+/**
+ * KWord's text formatter.
+ * It derives from KoTextFormatter and simply forwards formatVertically to KWTextFrameSet,
+ * since only KWTextFrameSet knows about page-breaking, overlapping frames etc.
+ */
+class KWTextFormatter : public KoTextFormatter
+{
+public:
+ KWTextFormatter( KWTextFrameSet *textfs ) : m_textfs( textfs ) {}
+ virtual ~KWTextFormatter() {}
+
+ virtual int formatVertically( KoTextDocument*, KoTextParag* parag )
+ {
+ return m_textfs->formatVertically( parag, parag->rect() );
+ }
+ virtual void postFormat( KoTextParag* parag )
+ {
+ m_textfs->fixParagWidth( static_cast<KWTextParag *>( parag ) );
+ }
+private:
+ KWTextFrameSet *m_textfs;
+};
+
+KWTextFrameSet::KWTextFrameSet( KWDocument *_doc, const QString & name )
+ : KWFrameSet( _doc )
+{
+ //kdDebug() << "KWTextFrameSet::KWTextFrameSet " << this << endl;
+ if ( name.isEmpty() )
+ m_name = _doc->generateFramesetName( i18n( "Text Frameset %1" ) );
+ else
+ m_name = name;
+
+ QObject::setName( m_name.utf8() ); // store name in the QObject, for DCOP users
+ init();
+}
+
+KWTextFrameSet::KWTextFrameSet( KWDocument* doc, const QDomElement& tag, KoOasisContext& /*context*/ )
+ : KWFrameSet( doc )
+{
+ m_name = tag.attributeNS( KoXmlNS::draw, "name", QString::null );
+ if ( doc->frameSetByName( m_name ) ) // already exists!
+ m_name = doc->generateFramesetName( m_name + " %1" );
+ init();
+ // Note that we don't call loadOasis here. The caller wants to do it,
+ // to get the frame it returns.
+}
+
+// protected constructor for testing purposes; does not do an init.
+KWTextFrameSet::KWTextFrameSet( const QString &name ) : KWFrameSet(0) {
+ m_name = name;
+
+ QObject::setName( m_name.utf8() ); // store name in the QObject, for DCOP users
+ m_currentViewMode = 0L;
+ m_currentDrawnFrame = 0L;
+ m_lastTextDocHeight = 0;
+ m_textobj = 0;
+}
+
+void KWTextFrameSet::init()
+{
+ m_currentViewMode = 0L;
+ m_currentDrawnFrame = 0L;
+ m_lastTextDocHeight = 0;
+ // Create the text document to set in the text object
+ KWTextDocument* textdoc = new KWTextDocument( this,
+ new KoTextFormatCollection( m_doc->defaultFont(), QColor(),
+ m_doc->globalLanguage(),
+ m_doc->globalHyphenation() ),
+ new KWTextFormatter( this ) );
+ textdoc->setFlow( this );
+ textdoc->setPageBreakEnabled( true ); // get verticalBreak to be called
+ if ( m_doc->tabStopValue() != -1 )
+ textdoc->setTabStops( m_doc->ptToLayoutUnitPixX( m_doc->tabStopValue() ));
+
+ m_textobj = new KoTextObject( textdoc, m_doc->styleCollection()->findStyle( "Standard" ),
+ this, (m_name+"-textobj").utf8() );
+ m_doc->backSpeller()->registerNewTextObject( m_textobj );
+ connect( m_textobj, SIGNAL( availableHeightNeeded() ),
+ SLOT( slotAvailableHeightNeeded() ) );
+ connect( m_textobj, SIGNAL( afterFormatting( int, KoTextParag*, bool* ) ),
+ SLOT( slotAfterFormatting( int, KoTextParag*, bool* ) ) );
+ //connect( m_textobj, SIGNAL( formattingFirstParag() ),
+ // SLOT( slotFormattingFirstParag() ) );
+ //connect( m_textobj, SIGNAL( chapterParagraphFormatted( KoTextParag * ) ),
+ // SLOT( slotChapterParagraphFormatted( KoTextParag * ) ) );
+ connect( m_textobj, SIGNAL( newCommand( KCommand * ) ),
+ SLOT( slotNewCommand( KCommand * ) ) );
+ connect( m_textobj, SIGNAL( repaintChanged( KoTextObject* ) ),
+ SLOT( slotRepaintChanged() ) );
+ connect( m_textobj, SIGNAL( paragraphDeleted( KoTextParag*) ),
+ SLOT( slotParagraphDeleted(KoTextParag*) ));
+
+ connect( m_textobj, SIGNAL( paragraphCreated( KoTextParag*) ),
+ SLOT( slotParagraphCreated(KoTextParag*) ));
+ connect( m_textobj, SIGNAL( paragraphModified( KoTextParag*, int, int, int) ),
+ SLOT( slotParagraphModified(KoTextParag*, int, int, int) ));
+}
+
+void KWTextFrameSet::slotParagraphModified(KoTextParag* _parag, int /*KoTextParag::ParagModifyType*/ _type, int start, int lenght)
+{
+ kWordDocument()->paragraphModified(_parag, _type, start, lenght);
+}
+
+void KWTextFrameSet::slotParagraphCreated(KoTextParag* /*_parag*/)
+{
+ //todo
+}
+
+void KWTextFrameSet::slotParagraphDeleted(KoTextParag*_parag)
+{
+ kWordDocument()->paragraphDeleted( _parag, this);
+}
+
+KWordFrameSetIface* KWTextFrameSet::dcopObject()
+{
+ if ( !m_dcop )
+ m_dcop = new KWordTextFrameSetIface( this );
+
+ return m_dcop;
+}
+
+KWFrameSetEdit * KWTextFrameSet::createFrameSetEdit( KWCanvas * canvas )
+{
+ return new KWTextFrameSetEdit( this, canvas );
+}
+
+KoTextDocument * KWTextFrameSet::textDocument() const
+{
+ return m_textobj->textDocument();
+}
+
+KWTextDocument * KWTextFrameSet::kwTextDocument() const
+{
+ return static_cast<KWTextDocument *>(m_textobj->textDocument());
+}
+
+void KWTextFrameSet::slotAvailableHeightNeeded()
+{
+ Q_ASSERT( isVisible() );
+ kdDebug() << "KWTextFrameSet::slotAvailableHeightNeeded " << name() << endl;
+ updateFrames( 0 ); // only do the available-height determination
+}
+
+KWFrame * KWTextFrameSet::documentToInternal( const KoPoint &dPoint, QPoint &iPoint ) const
+{
+#ifdef DEBUG_DTI
+ kdDebug() << "KWTextFrameSet::documentToInternal dPoint:" << dPoint.x() << "," << dPoint.y() << endl;
+#endif
+ if ( !m_doc->layoutViewMode()->hasFrames() ) { // text viewmode
+ iPoint = QPoint( m_doc->ptToLayoutUnitPixX( dPoint.x() ),
+ m_doc->ptToLayoutUnitPixY( dPoint.y() ) );
+ return m_frames.getFirst();
+ }
+ // Find the frame that contains dPoint. To go fast, we look them up by page number.
+ int pageNum = m_doc->pageManager()->pageNumber(dPoint);
+ QPtrListIterator<KWFrame> frameIt( framesInPage( pageNum ) );
+ for ( ; frameIt.current(); ++frameIt )
+ {
+ KWFrame *theFrame = frameIt.current();
+ if ( theFrame->contains( dPoint ) )
+ {
+ iPoint.setX( m_doc->ptToLayoutUnitPixX( dPoint.x() - theFrame->innerRect().x() ) );
+ iPoint.setY( m_doc->ptToLayoutUnitPixY( dPoint.y() - theFrame->innerRect().y() + theFrame->internalY() ) );
+#ifdef DEBUG_DTI
+ kdDebug() << "documentToInternal: returning " << iPoint.x() << "," << iPoint.y()
+ << " internalY=" << theFrame->internalY() << " because frame=" << theFrame
+ << " contains dPoint:" << dPoint.x() << "," << dPoint.y() << endl;
+#endif
+ return theFrame;
+ }
+#ifdef DEBUG_DTI
+ //else
+ // kdDebug() << "DTI: " << frameRect
+ // << " doesn't contain nPoint:" << nPoint.x() << "," << nPoint.y() << endl;
+#endif
+ }
+ // Not found. This means the mouse isn't over any frame, in the page pageNum.
+ iPoint = m_doc->ptToLayoutUnitPix( dPoint ); // bah
+ return 0;
+}
+
+KWFrame * KWTextFrameSet::documentToInternalMouseSelection( const KoPoint &dPoint, QPoint &iPoint, RelativePosition& relPos, KWViewMode *viewMode ) const
+{
+#ifdef DEBUG_DTI
+ kdDebug() << "KWTextFrameSet::documentToInternalMouseSelection dPoint:" << dPoint.x() << "," << dPoint.y() << endl;
+#endif
+ if ( !viewMode->hasFrames() ) { // text viewmode
+ relPos = InsideFrame;
+ iPoint = QPoint( m_doc->ptToLayoutUnitPixX( dPoint.x() ),
+ m_doc->ptToLayoutUnitPixY( dPoint.y() ) );
+ return m_frames.getFirst();
+ }
+
+ // Find the frame that contains dPoint. To go fast, we look them up by page number.
+ int pageNum = m_doc->pageManager()->pageNumber(dPoint);
+ QPtrListIterator<KWFrame> frameIt( framesInPage( pageNum ) );
+ for ( ; frameIt.current(); ++frameIt )
+ {
+ KWFrame *theFrame = frameIt.current();
+ if ( theFrame->contains( dPoint ) )
+ {
+ iPoint.setX( m_doc->ptToLayoutUnitPixX( dPoint.x() - theFrame->innerRect().x() ) );
+ iPoint.setY( m_doc->ptToLayoutUnitPixY( dPoint.y() - theFrame->innerRect().y() + theFrame->internalY() ) );
+#ifdef DEBUG_DTI
+ kdDebug() << "documentToInternal: returning InsideFrame " << iPoint.x() << "," << iPoint.y()
+ << " internalY=" << theFrame->internalY() << " because frame=" << theFrame
+ << " contains dPoint:" << dPoint.x() << "," << dPoint.y() << endl;
+#endif
+ relPos = InsideFrame;
+ return theFrame;
+ }
+ }
+ frameIt.toFirst();
+ for ( ; frameIt.current(); ++frameIt )
+ {
+ KWFrame *theFrame = frameIt.current();
+ KoRect openLeftRect( theFrame->innerRect() );
+ openLeftRect.setLeft( theFrame->paddingLeft() );
+#ifdef DEBUG_DTI
+ kdDebug() << "documentToInternal: openLeftRect=" << openLeftRect << endl;
+#endif
+ if ( openLeftRect.contains( dPoint ) )
+ {
+ // We are at the left of this frame (and not in any other frame of this frameset)
+ iPoint.setX( m_doc->ptToLayoutUnitPixX(theFrame->innerRect().left() ));
+ iPoint.setY( m_doc->ptToLayoutUnitPixY( dPoint.y() - theFrame->top() + theFrame->internalY() ) );
+#ifdef DEBUG_DTI
+ kdDebug() << "documentToInternal: returning LeftOfFrame " << iPoint.x() << "," << iPoint.y()
+ << " internalY=" << theFrame->internalY() << " because openLeftRect=" << openLeftRect
+ << " contains dPoint:" << dPoint.x() << "," << dPoint.y() << endl;
+#endif
+ relPos = LeftOfFrame;
+ return theFrame;
+ }
+ KoRect openTopRect( KoPoint( 0, 0 ), theFrame->innerRect().bottomRight() );
+#ifdef DEBUG_DTI
+ kdDebug() << "documentToInternal: openTopRect=" << openTopRect << endl;
+#endif
+ if ( openTopRect.contains( dPoint ) )
+ {
+ // We are at the top of this frame (...)
+ iPoint.setX( m_doc->ptToLayoutUnitPixX( dPoint.x() - theFrame->innerRect().left() ) );
+ iPoint.setY( m_doc->ptToLayoutUnitPixY( theFrame->internalY() ) );
+#ifdef DEBUG_DTI
+ kdDebug() << "documentToInternal: returning " << iPoint.x() << "," << iPoint.y()
+ << " internalY=" << theFrame->internalY() << " because openTopRect=" << openTopRect
+ << " contains dPoint:" << dPoint.x() << "," << dPoint.y() << endl;
+#endif
+ relPos = TopOfFrame;
+ return theFrame;
+ }
+ }
+ // Not found. This means we are under (or at the right of), the frames in pageNum.
+ // In that case, go for the first frame in the next page.
+ if ( pageNum + 1 >= (int)m_framesInPage.size() + m_firstPage )
+ {
+ // Under last frame of last page!
+ KWFrame *theFrame = m_frames.getLast();
+ iPoint.setX( m_doc->ptToLayoutUnitPixX( theFrame->innerWidth() ) );
+ iPoint.setY( m_doc->ptToLayoutUnitPixY( theFrame->innerHeight() ) );
+#ifdef DEBUG_DTI
+ kdDebug() << "documentToInternal: returning AtEnd " << iPoint.x() << "," << iPoint.y()
+ << " because we are under all frames of the last page" << endl;
+#endif
+ relPos = AtEnd;
+ return theFrame;
+ }
+ else
+ {
+ QPtrListIterator<KWFrame> frameIt( framesInPage( pageNum + 1 ) );
+ if ( frameIt.current() )
+ {
+ // There is a frame on the next page
+ KWFrame *theFrame = frameIt.current();
+ KoRect openTopRect( theFrame->innerRect() );
+ openTopRect.setTop( 0 );
+ if ( openTopRect.contains( dPoint ) ) // We are at the top of this frame
+ iPoint.setX( m_doc->ptToLayoutUnitPixX( dPoint.x() - theFrame->left() ) );
+ else
+ iPoint.setX( 0 ); // We are, hmm, on the left or right of the frames
+ iPoint.setY( m_doc->ptToLayoutUnitPixY( theFrame->internalY() ) );
+#ifdef DEBUG_DTI
+ kdDebug() << "documentToInternal: returning TopOfFrame " << iPoint.x() << "," << iPoint.y()
+ << " because we are under all frames of page " << pageNum << endl;
+#endif
+ relPos = TopOfFrame;
+ return theFrame;
+ } // else there is a gap (no frames on that page, but on some other further down)
+ // This case isn't handled (and should be VERY rare I think)
+ }
+
+ iPoint = m_doc->ptToLayoutUnitPix( dPoint ); // bah
+#ifdef DEBUG_DTI
+ kdDebug() << "documentToInternal: returning not found for " << iPoint.x() << "," << iPoint.y() << endl;
+#endif
+ return 0;
+}
+
+KWFrame * KWTextFrameSet::internalToDocumentWithHint( const QPoint &iPoint, KoPoint &dPoint, const KoPoint &hintDPoint ) const
+{
+#ifdef DEBUG_ITD
+ kdDebug() << "KWTextFrameSet::internalToDocumentWithHint hintDPoint: " << hintDPoint.x() << "," << hintDPoint.y() << endl;
+#endif
+ if ( !m_doc->layoutViewMode()->hasFrames() ) { // text viewmode
+ dPoint = m_doc->layoutUnitPtToPt( m_doc->pixelToPt( iPoint ) );
+ return m_frames.getFirst();
+ }
+ KWFrame *lastFrame = 0L;
+ QPtrListIterator<KWFrame> frameIt( frameIterator() );
+ for ( ; frameIt.current(); ++frameIt )
+ {
+ KWFrame *theFrame = frameIt.current();
+ QRect r( 0, m_doc->ptToLayoutUnitPixY( theFrame->internalY() ), m_doc->ptToLayoutUnitPixX( theFrame->innerWidth() )+1, m_doc->ptToLayoutUnitPixY( theFrame->innerHeight() )+1 );
+#ifdef DEBUG_ITD
+ kdDebug() << "ITD: r=" << r << " iPoint=" << iPoint.x() << "," << iPoint.y() << endl;
+#endif
+ // r is the frame in qrt coords
+ if ( r.contains( iPoint ) ) // both r and p are in layout units (aka internal)
+ {
+ dPoint = internalToDocumentKnowingFrame( iPoint, theFrame );
+#ifdef DEBUG_ITD
+ kdDebug() << "copy: " << theFrame->isCopy() << " hintDPoint.y()=" << hintDPoint.y() << " dPoint.y()=" << dPoint.y() << endl;
+#endif
+ // First test: No "hintDPoint" specified, go for the first match
+ // Second test: hintDPoint specified, check if we are far enough
+ if ( hintDPoint.isNull() || hintDPoint.y() <= dPoint.y() )
+ return theFrame;
+ // Remember that this frame matched, in case we find no further frame that matches
+ lastFrame = theFrame;
+ }
+ else if ( lastFrame )
+ {
+ return lastFrame;
+ }
+ }
+
+ // This happens when the parag is on a not-yet-created page (formatMore will notice afterwards)
+ // So it doesn't matter much what happens here, we'll redo it anyway.
+#ifdef DEBUG_ITD
+ kdDebug(32002) << "KWTextFrameSet::internalToDocumentWithHint " << iPoint.x() << "," << iPoint.y()
+ << " not in any frame of " << (void*)this << endl;
+#endif
+ dPoint = m_doc->layoutUnitPtToPt( m_doc->pixelToPt( iPoint ) ); // bah
+ return 0L;
+}
+
+// relPoint is in relative coordinates (pt)
+KoPoint KWTextFrameSet::internalToDocumentKnowingFrame( const KoPoint &relPoint, KWFrame* theFrame ) const
+{
+ // It's ok to have theFrame == 0 in the text viewmode, but not in other modes
+ if ( m_doc->layoutViewMode()->hasFrames() )
+ Q_ASSERT( theFrame );
+ if ( theFrame )
+ return KoPoint( relPoint.x() + theFrame->innerRect().x(),
+ relPoint.y() - theFrame->internalY() + theFrame->innerRect().y() );
+ else
+ return relPoint;
+}
+
+KoPoint KWTextFrameSet::internalToDocumentKnowingFrame( const QPoint &iPoint, KWFrame* theFrame ) const
+{
+ // Convert LU to relative coordinates (pt), then call the real internalToDocumentKnowingFrame().
+ return internalToDocumentKnowingFrame( m_doc->layoutUnitPtToPt( m_doc->pixelToPt( iPoint ) ), theFrame );
+}
+
+QPoint KWTextFrameSet::moveToPage( int currentPgNum, short int direction ) const
+{
+ if ( !isVisible() || m_frames.isEmpty() )
+ return QPoint();
+ //kdDebug() << "KWTextFrameSet::moveToPage currentPgNum=" << currentPgNum << " direction=" << direction << endl;
+ int num = currentPgNum + direction;
+ int pages = m_doc->pageCount();
+ for ( ; num >= 0 && num < pages ; num += direction )
+ {
+ //kdDebug() << "KWTextFrameSet::moveToPage num=" << num << " pages=" << pages << endl;
+ // Find the first frame on page num
+ if ( num < m_firstPage || num >= (int)m_framesInPage.size() + m_firstPage )
+ continue; // No frame on that page
+
+ //kdDebug() << "KWTextFrameSet::moveToPage ok for first frame in page " << num << endl;
+ QPtrListIterator<KWFrame> frameIt( framesInPage( num ) );
+ return QPoint( 0, m_doc->ptToLayoutUnitPixY( frameIt.current()->internalY() ) + 2 ); // found, ok.
+ }
+ // Not found. Go to top of first frame or bottom of last frame, depending on direction
+ if ( direction < 0 )
+ return QPoint( 0, m_doc->ptToLayoutUnitPixY( m_frames.getFirst()->internalY() ) + 2 );
+ else
+ {
+ KWFrame * theFrame = m_frames.getLast();
+ return QPoint( 0, m_doc->ptToLayoutUnitPixY( theFrame->internalY() + theFrame->innerHeight() ) );
+ }
+}
+
+void KWTextFrameSet::drawContents( QPainter *p, const QRect & crect, const QColorGroup &cg,
+ bool onlyChanged, bool resetChanged,
+ KWFrameSetEdit *edit, KWViewMode *viewMode,
+ KWFrameViewManager *fvm)
+{
+ m_currentViewMode = viewMode;
+ KWFrameSet::drawContents( p, crect, cg, onlyChanged, resetChanged, edit, viewMode, fvm );
+
+ // Main textframeset: draw the footnote line if there are footnotes
+ if ( isMainFrameset() && viewMode->hasFrames() )
+ {
+ // We stored the info "there's a footnote in this page" in the frame[s]
+ // of the maintextframeset for that page. Usually one, but could be more
+ // if there are columns. However we want to draw the line only once, so we
+ // do it here and not in drawFrame (we'd have problems with cliprect anyway).
+ if ( m_doc->footNoteSeparatorLineWidth() ==0.0)
+ return;
+
+ int pages = m_doc->pageCount();
+ KWPage *page = m_doc->pageManager()->page(m_doc->pageManager()->startPage());
+ double left = page->leftMargin();
+ double pageWidth = page->width() - page->rightMargin() - left;
+ double width = pageWidth * m_doc->footNoteSeparatorLineLength() / 100.0;
+ int numColumns = m_doc->numColumns();
+ for ( int pageNum = 0; pageNum < pages; pageNum++ )
+ {
+ //if ( viewMode->isPageVisible( pageNum ) )
+ {
+ uint frameNum = pageNum * numColumns /*+ col 0 here*/;
+ if ( frameNum < frameCount() ) // not true on the "endnotes-only" page
+ {
+ KWFrame* frame = this->frame( frameNum ); // ## or use framesInPage ?
+ //kdDebug() << " Footnote line: page " << pageNum << " found frame " << frameNum << " drawFootNoteLine=" << frame->drawFootNoteLine() << endl;
+ if ( frame->drawFootNoteLine() )
+ {
+ double y = frame->bottomLeft().y() + m_doc->headerFooterInfo().ptFootNoteBodySpacing / 2;
+ KoRect rect( left, y, width, 0 ); // this rect is flat
+ switch( m_doc->footNoteSeparatorLinePosition())
+ {
+ case SLP_LEFT:
+ break;
+ case SLP_CENTERED:
+ rect = KoRect( pageWidth/2.0+left-width/2.0, y,width,0);
+ break;
+ case SLP_RIGHT:
+ rect = KoRect( pageWidth+left-width, y,width,0);
+ break;
+ }
+
+ QRect flatRect = viewMode->normalToView( m_doc->zoomRect( rect ) );
+ //kdDebug() << " KWTextFrameSet::drawContents rect=" << rect << " zoomed:" << flatRect << endl;
+ flatRect.setBottom( flatRect.top() + 1 ); // #!@!@!& QRect....
+ if ( flatRect.intersects( crect ) ) {
+ p->save();
+ QPen pen( KoTextFormat::defaultTextColor( p ), // always in default fg color (and black when printing)
+ KoBorder::zoomWidthY( m_doc->footNoteSeparatorLineWidth(), m_doc, 1 ) ); // penwidth = zoomIt( 2 pt )
+ switch( m_doc->footNoteSeparatorLineType())
+ {
+ case SLT_SOLID:
+ pen.setStyle( SolidLine );
+ break;
+ case SLT_DASH:
+ pen.setStyle( DashLine );
+ break;
+ case SLT_DOT:
+ pen.setStyle( DotLine );
+ break;
+ case SLT_DASH_DOT:
+ pen.setStyle( DashDotLine );
+ break;
+ case SLT_DASH_DOT_DOT:
+ pen.setStyle( DashDotDotLine );
+ break;
+ }
+ p->setPen( pen );
+ p->drawLine( flatRect.left(), flatRect.top(), flatRect.right(), flatRect.top() );
+ //kdDebug() << " drawLine( " << flatRect.left() << ", " << flatRect.top() << ", " << flatRect.right() << ", " << flatRect.top() << endl;
+ p->restore();
+ }
+ }
+ }
+ }
+ }
+ }
+}
+
+void KWTextFrameSet::drawFrame( KWFrame *theFrame, QPainter *painter, const QRect &fcrect, const QRect &crect,
+ const QPoint& translationOffset,
+ KWFrame *settingsFrame, const QColorGroup &cg, bool onlyChanged, bool resetChanged,
+ KWFrameSetEdit *edit, KWViewMode *viewMode, bool drawUnderlyingFrames )
+{
+ // Detect if text frame needs transparency painting, to save time if it's using SolidPattern
+ // In theory this code should be in kwFrameSet, but currently only text frames obey m_backgroundColor.
+ if ( theFrame )
+ {
+ drawUnderlyingFrames &= theFrame->isTransparent();
+ }
+ KWFrameSet::drawFrame( theFrame, painter, fcrect, crect, translationOffset, settingsFrame, cg, onlyChanged, resetChanged, edit, viewMode, drawUnderlyingFrames );
+}
+
+void KWTextFrameSet::drawFrameContents( KWFrame *theFrame, QPainter *painter, const QRect &r,
+ const QColorGroup &cg, bool onlyChanged, bool resetChanged,
+ KWFrameSetEdit *edit, KWViewMode *viewMode )
+{
+ Q_ASSERT( r.isValid() );
+ // In this method the painter is translated to the frame's coordinate system
+ // (in the first frame (0,0) will be its topleft, in the second frame it will be (0,internalY) etc.
+
+ //kdDebug(32001) << "KWTextFrameSet::drawFrameContents " << name() << "(frame " << frameFromPtr( theFrame ) << ") crect(r)=" << r << " onlyChanged=" << onlyChanged << endl;
+ m_currentDrawnFrame = theFrame;
+ if ( theFrame ) // 0L in the text viewmode
+ {
+ // Update variables for each frame (e.g. for page-number)
+ // If more than KWPgNumVariable need this functionality, create an intermediary base class
+ QPtrListIterator<KoTextCustomItem> cit( textDocument()->allCustomItems() );
+ for ( ; cit.current() ; ++cit )
+ {
+ KWPgNumVariable * var = dynamic_cast<KWPgNumVariable *>( cit.current() );
+ if ( var && !var->isDeleted() )
+ {
+ QSize oldSize( var->width, var->height );
+ const int pageNumberOffset = kWordDocument()->variableCollection()->variableSetting()->startingPageNumber() - 1;
+ switch ( var->subType() )
+ {
+ case KWPgNumVariable::VST_PGNUM_CURRENT:
+ //kdDebug() << "KWTextFrameSet::drawFrame updating pgnum variable to " << theFrame->pageNumber()
+ // << " and invalidating parag " << var->paragraph() << endl;
+ var->setPgNum( theFrame->pageNumber() + pageNumberOffset );
+ break;
+ case KWPgNumVariable::VST_CURRENT_SECTION:
+ var->setSectionTitle( kWordDocument()->sectionTitle( theFrame->pageNumber() ) );
+ break;
+ case KWPgNumVariable::VST_PGNUM_PREVIOUS:
+ var->setPgNum( QMAX(theFrame->pageNumber()-1,0) + pageNumberOffset );
+ break;
+ case KWPgNumVariable::VST_PGNUM_NEXT:
+ var->setPgNum( theFrame->pageNumber() + 1 + pageNumberOffset );
+ break;
+ }
+
+ var->resize();
+ QSize newSize( var->width, var->height );
+ if ( oldSize != newSize )
+ var->paragraph()->invalidate( 0 ); // size has changed -> need reformatting !
+ var->paragraph()->setChanged( true );
+ }
+ }
+ }
+
+ KoTextCursor * cursor = edit ? (dynamic_cast<KWTextFrameSetEdit *>(edit) ? static_cast<KWTextFrameSetEdit *>(edit)->cursor() : 0) : 0;
+ uint drawingFlags = 0;
+ if ( viewMode->drawSelections() )
+ drawingFlags |= KoTextDocument::DrawSelections;
+ if ( !viewMode->drawFrameBackground() )
+ drawingFlags |= KoTextDocument::TransparentBackground;
+ if ( m_doc->backgroundSpellCheckEnabled() )
+ drawingFlags |= KoTextDocument::DrawMisspelledLine;
+ if ( m_doc->viewFormattingChars() )
+ drawingFlags |= KoTextDocument::DrawFormattingChars;
+
+ //kdDebug(32001) << "KWTextFrameSet::drawFrame calling drawWYSIWYG. cg base color:" << cg.brush( QColorGroup::Base) << endl;
+ KoTextParag * lastFormatted = textDocument()->drawWYSIWYG(
+ painter, r.x(), r.y(), r.width(), r.height(),
+ cg, kWordDocument(),
+ onlyChanged, false, cursor, resetChanged, drawingFlags );
+
+ // The last paragraph of this frame might have a bit in the next frame too.
+ // In that case, and if we're only drawing changed paragraphs, (and resetting changed),
+ // we have to set changed to true again, to draw the bottom of the parag in the next frame.
+ if ( onlyChanged && resetChanged )
+ {
+ // Finding the "last parag of the frame" is a bit tricky.
+ // It's usually the one before lastFormatted, except if it's actually lastParag :} [see KoTextDocument::draw]
+ KoTextParag * lastDrawn = lastFormatted->prev();
+ if ( lastFormatted == textDocument()->lastParag() && ( !lastDrawn || m_doc->layoutUnitToPixelY( lastDrawn->rect().bottom() ) < r.bottom() ) )
+ lastDrawn = lastFormatted;
+
+ //kdDebug(32002) << "KWTextFrameSet::drawFrame drawn. onlyChanged=" << onlyChanged << " resetChanged=" << resetChanged << " lastDrawn=" << lastDrawn->paragId() << " lastDrawn's bottom:" << lastDrawn->rect().bottom() << " r.bottom=" << r.bottom() << endl;
+ if ( lastDrawn && m_doc->layoutUnitToPixelY( lastDrawn->rect().bottom() ) > r.bottom() )
+ {
+ //kdDebug(32002) << "KWTextFrameSet::drawFrame setting lastDrawn " << lastDrawn->paragId() << " to changed" << endl;
+ lastDrawn->setChanged( true );
+ }
+ }
+
+ // NOTE: QTextView sets m_lastFormatted to lastFormatted here
+ // But when scrolling up, this causes to reformat a lot of stuff for nothing.
+ // And updateViewArea takes care of formatting things before we even arrive here.
+
+ // Blank area under the very last paragraph - QRT draws it up to textdoc->height,
+ // we have to draw it from there up to the bottom of the last frame.
+ if ( ( !lastFormatted || lastFormatted == textDocument()->lastParag() )
+ && viewMode->drawFrameBackground() )
+ {
+ // This is drawing code, so we convert everything to pixels
+ int docHeight = textDocument()->lastParag()->pixelRect(m_doc).bottom() + 1;
+ //QRect frameRect = m_doc->zoomRect( (theFrame->innerRect()) );
+
+ QSize availSize = viewMode->availableSizeForText( this );
+ QRect blank( 0, docHeight, availSize.width(), availSize.height() /*+ frameRect.height() ?? */ - docHeight );
+ //kdDebug(32002) << this << " Blank area: " << blank << endl;
+ painter->fillRect( blank, cg.brush( QColorGroup::Base ) );
+ // for debugging :)
+ //painter->setPen( QPen(Qt::blue, 1, DashLine) ); painter->drawRect( blank );
+ }
+ m_currentDrawnFrame = 0L;
+}
+
+void KWTextFrameSet::drawCursor( QPainter *p, KoTextCursor *cursor, bool cursorVisible, KWCanvas *canvas, KWFrame *theFrame )
+{
+ // This redraws the paragraph where the cursor is - with a small clip region around the cursor
+ m_currentViewMode = canvas->viewMode();
+ bool hasFrames = m_currentViewMode->hasFrames();
+ m_currentDrawnFrame = theFrame;
+
+ QRect normalFrameRect;
+ if (hasFrames)
+ normalFrameRect = m_doc->zoomRect( theFrame->innerRect() );
+ else
+ normalFrameRect = QRect( QPoint(0, 0), m_currentViewMode->contentsSize() );
+
+ KoTextParag* parag = cursor->parag();
+ QPoint topLeft = parag->rect().topLeft(); // in QRT coords
+ int lineY;
+ // Cursor height, in pixels
+ int cursorHeight = m_doc->layoutUnitToPixelY( topLeft.y(), parag->lineHeightOfChar( cursor->index(), 0, &lineY ) );
+ QPoint iPoint( topLeft.x() + cursor->x(),
+ topLeft.y() + lineY );
+
+#ifdef DEBUG_CURSOR
+ kdDebug() << "KWTextFrameSet::drawCursor topLeft=" << topLeft.x() << "," << topLeft.y()
+ << " x=" << cursor->x() << " y=" << lineY << endl;
+ kdDebug() << "KWTextFrameSet::drawCursor iPoint=" << iPoint.x() << "," << iPoint.y()
+ << " cursorHeight=" << cursorHeight << endl;
+#endif
+ KoPoint dPoint;
+ KoPoint hintDPoint = theFrame ? theFrame->innerRect().topLeft() : KoPoint();
+ if ( internalToDocumentWithHint( iPoint, dPoint, hintDPoint ) )
+ {
+#ifdef DEBUG_CURSOR
+ kdDebug() << " dPoint(doc, pts)=" << dPoint.x() << "," << dPoint.y() << endl;
+ QPoint debugPt = m_doc->zoomPoint( dPoint );
+ kdDebug() << " zoomed dPoint(doc, pixels)=" << debugPt.x() << "," << debugPt.y() << endl;
+#endif
+ QPoint vPoint = m_currentViewMode->normalToView( m_doc->zoomPoint( dPoint ) ); // from doc to view contents
+#ifdef DEBUG_CURSOR
+ kdDebug() << " vPoint(view, pixels)=" << vPoint.x() << "," << vPoint.y() << endl;
+#endif
+ // from now on, iPoint will be in pixels
+ iPoint = m_doc->layoutUnitToPixel( iPoint );
+ //int xadj = parag->at( cursor->index() )->pixelxadj;
+#ifdef DEBUG_CURSOR
+ //kdDebug() << " iPoint in pixels : " << iPoint.x() << "," << iPoint.y() << " will add xadj=" << xadj << endl;
+#endif
+ //iPoint.rx() += xadj;
+ //vPoint.rx() += xadj;
+ // very small clipping around the cursor
+ QRect clip( vPoint.x() - 5, vPoint.y(), 10, cursorHeight );
+
+#ifdef DEBUG_CURSOR
+ kdDebug() << " clip(view, before intersect)=" << clip << endl;
+#endif
+
+ QRect viewFrameRect = m_currentViewMode->normalToView( normalFrameRect );
+ clip &= viewFrameRect; // clip to frame
+#ifdef DEBUG_CURSOR
+ kdDebug() << "KWTextFrameSet::drawCursor normalFrameRect=" << normalFrameRect
+ << " clip(view, after intersect)=" << clip << endl;
+#endif
+
+ QRegion reg;
+ if ( hasFrames ) {
+ reg = frameClipRegion( p, theFrame, clip, m_currentViewMode );
+ if ( !isFloating() ) // problem with multiparent inline frames
+ reg &= p->xForm( viewFrameRect );
+ }
+
+ if ( !hasFrames || !reg.isEmpty() )
+ {
+#ifdef DEBUG_CURSOR
+ // for debug only!
+ //p->fillRect( clip, QBrush( Qt::red, QBrush::Dense3Pattern ) );
+#endif
+
+ p->save();
+ QColorGroup cg = QApplication::palette().active();
+
+ if ( hasFrames )
+ {
+ p->setClipRegion( reg );
+ // translate to qrt coords - after setting the clip region !
+ // see internalToDocumentWithHint
+ int translationX = viewFrameRect.left();
+ int translationY = viewFrameRect.top() - m_doc->zoomItY( theFrame->internalY() );
+#ifdef DEBUG_CURSOR
+ kdDebug() << " translating Y by viewFrameRect.top()-internalY in pixelY= " << viewFrameRect.top() << "-" << m_doc->zoomItY( theFrame->internalY() ) << "=" << viewFrameRect.top() - m_doc->zoomItY( theFrame->internalY() ) << endl;
+#endif
+ p->translate( translationX, translationY );
+ p->setBrushOrigin( p->brushOrigin().x() + translationX, p->brushOrigin().y() + translationY );
+
+ // The settings come from this frame
+ KWFrame * settings = settingsFrame( theFrame );
+
+ QBrush bgBrush( settings->backgroundColor() );
+ bgBrush.setColor( KWDocument::resolveBgColor( bgBrush.color(), p ) );
+ cg.setBrush( QColorGroup::Base, bgBrush );
+ // color of cursor, the inverse of the frame background
+ QColor background = bgBrush.color();
+ cg.setColor(QColorGroup::Text, QColor( 255 - background.red(),
+ 255 - background.green(), 255 - background.blue()) );
+ }
+ else if(dynamic_cast<KWViewModeText *>(m_currentViewMode) != 0)
+ p->translate( KWViewModeText::OFFSET, 0 );
+
+ QPixmap *pix = 0;
+ uint drawingFlags = KoTextDocument::DrawSelections;
+ if ( m_doc->backgroundSpellCheckEnabled() )
+ drawingFlags |= KoTextDocument::DrawMisspelledLine;
+ if ( m_doc->viewFormattingChars() )
+ drawingFlags |= KoTextDocument::DrawFormattingChars;
+
+ // To force the drawing to happen:
+ bool wasChanged = parag->hasChanged();
+ int oldLineChanged = parag->lineChanged();
+ int line; // line number
+ parag->lineStartOfChar( cursor->index(), 0, &line );
+ parag->setChanged( false ); // not all changed, only from a given line
+ parag->setLineChanged( line );
+
+ textDocument()->drawParagWYSIWYG(
+ p, parag,
+ QMAX(0, iPoint.x() - 5), // negative values create problems
+ iPoint.y(), clip.width(), clip.height(),
+ pix, cg, m_doc, // TODO view's zoom handler
+ cursorVisible, cursor, FALSE /*resetChanged*/, drawingFlags );
+
+ if ( wasChanged ) // Maybe we have more changes to draw, than those in the small cliprect
+ parag->setLineChanged( oldLineChanged ); // -1 = all
+ else
+ parag->setChanged( false );
+
+ p->restore();
+
+ //XIM Position
+ QPoint ximPoint = vPoint;
+ canvas->setXimPosition( ximPoint.x(), ximPoint.y(),
+ 0, cursorHeight - parag->lineSpacing( line ) );
+ }
+ }
+ m_currentDrawnFrame = 0L;
+}
+
+void KWTextFrameSet::layout()
+{
+ invalidate();
+ // Get the thing going though, repainting doesn't call formatMore
+ m_textobj->formatMore( 2 );
+}
+
+void KWTextFrameSet::invalidate()
+{
+ //kdDebug() << "KWTextFrameSet::invalidate " << name() << endl;
+ m_textobj->setLastFormattedParag( textDocument()->firstParag() );
+ textDocument()->invalidate(); // lazy layout, real update follows upon next repaint
+}
+
+void KWTextFrameSet::slotRepaintChanged()
+{
+ emit repaintChanged( this );
+}
+
+int KWTextFrameSet::paragraphs()
+{
+ int paragraphs = 0;
+ KoTextParag * parag = textDocument()->firstParag();
+ for ( ; parag ; parag = parag->next() )
+ paragraphs++;
+ return paragraphs;
+}
+
+int KWTextFrameSet::paragraphsSelected()
+{
+ int paragraphs = 0;
+ KoTextParag *parag = textDocument()->firstParag();
+ for ( ; parag ; parag = parag->next() ) {
+ if ( parag->hasSelection( KoTextDocument::Standard ) )
+ paragraphs++;
+ }
+ return paragraphs;
+}
+
+
+bool KWTextFrameSet::statistics( QProgressDialog *progress, ulong & charsWithSpace, ulong & charsWithoutSpace, ulong & words,
+ ulong & sentences, ulong & syllables, ulong & lines, bool selected )
+{
+ return m_textobj->statistics( progress, charsWithSpace, charsWithoutSpace, words, sentences, syllables, lines, selected );
+}
+
+// Only interested in the body textframeset, not in header/footer
+#define kdDebugBody(area) if ( frameSetInfo() == FI_BODY ) kdDebug(area)
+
+QValueList<KWFrame*> KWTextFrameSet::framesFromTo( int y1, int y2 ) const
+{
+ QValueList<KWFrame*> framesList;
+ KoPoint pt;
+ KWFrame * firstFrame = internalToDocument( QPoint(0, y1), pt );
+ if ( !firstFrame )
+ return framesList;
+ framesList.append( firstFrame );
+ uint frameIndex = const_cast<KWTextFrameSet *>(this)->m_frames.findRef( firstFrame );
+ while ( ++frameIndex < m_frames.count() ) {
+ KWFrame* f = frame( frameIndex );
+ if ( f->internalY() > y2 ) // too far down, we're done
+ break;
+ framesList.append( f );
+ }
+ return framesList;
+}
+
+// Helper for adjust*. There are 3 ways to use this method.
+// 1) marginLeft and marginRight set -> determination of left and right margins for adjustMargins
+// 2) marginRight set -> determination of right margin for adjustRMargin
+// 3) breakBegin, breakEnd set -> check whether we should jump over some frames
+// [when there is not enough space besides them]
+// reqMinWidth is the width that the formatter wants to use (current char/item)
+// validHeight is set to the height where marginLeft/marginRight applies (TODO)
+void KWTextFrameSet::getMargins( int yp, int h, int reqMinWidth,
+ int* marginLeft, int* marginRight, int* pageWidth,
+ int* validHeight,
+ int* breakBegin, int* breakEnd, KoTextParag* parag )
+{
+ // paragLeftMargin will be used as the minimum width needed for the parag,
+ // to "see" the parag.
+ // So we only apply the first line margin if it increases that width, i.e. if > 0.
+ // Otherwise only the first line might be visible, in a narrow passage.
+ int paragLeftMargin = parag ? parag->leftMargin() : 0;
+ if ( parag && !parag->string()->isRightToLeft() && parag->firstLineMargin() > 0 )
+ paragLeftMargin += parag->firstLineMargin();
+#ifdef DEBUG_MARGINS
+ kdDebugBody(32002) << " KWTextFrameSet " << this << "(" << name() << ") getMargins yp=" << yp
+ << " h=" << h << " called by "
+ << (marginLeft && marginRight ? "adjustMargins" : "formatVertically")
+ << " paragLeftMargin=" << paragLeftMargin
+ << endl;
+ // Both or none...
+ if (breakBegin) assert(breakEnd);
+ if (breakEnd) assert(breakBegin);
+ // Idem
+ if ( marginLeft ) { assert( marginRight ); assert( pageWidth ); }
+#endif
+
+ // List of text frames holding the paragraph (yp,yp+h)
+ // Usually there is only one, but you can have a paragraph
+ // starting in one frame/column and ending in another one.
+ QValueList<KWFrame*> textFrames = framesFromTo( yp, yp + h );
+ if (textFrames.isEmpty())
+ {
+#ifdef DEBUG_MARGINS
+ kdDebug(32002) << " getMargins: internalToDocument returned no text frames for y1=" << yp << " y2=" << yp + h << " ->aborting with 0 margins" << endl;
+#endif
+ // frame == 0 happens when the parag is under the last frame.
+ // On an auto-resizable frame, we know the frame will grow so we can go ahead
+ // and use its width.
+ if ( !m_frames.isEmpty() && m_frames.last()->frameBehavior() == KWFrame::AutoExtendFrame )
+ {
+ textFrames.append( m_frames.last() );
+ }
+ else
+ {
+ // On auto-create-new-frame, this means the parag is on a not-yet-created page
+ // (formatMore will notice afterwards)
+ // Abort then, no need to return precise values
+ // We also abort in the third case (Ignore)
+ if ( validHeight )
+ *validHeight = 0;
+ return;
+ }
+ }
+ else
+ {
+
+#ifdef DEBUG_MARGINS
+ kdDebugBody(32002) << " getMargins: internalToDocument returned " << textFrames.count() << " frames holding this paragraph" << endl;
+#endif
+ }
+ if ( validHeight )
+ *validHeight = h; // TODO
+
+ // Everything from there is in layout units
+ // Note: it is very important that this method works in internal coordinates.
+ // Otherwise, parags broken at the line-level (e.g. between two columns) are seen
+ // as still in one piece, and we miss the frames in the 2nd column.
+ int from = 0;
+ // TODO support for variable width... maybe it's enough to take the max here
+ int to = m_doc->ptToLayoutUnitPixX( textFrames.first()->innerWidth() );
+ if ( pageWidth )
+ *pageWidth = to;
+ bool init = false;
+
+#ifdef DEBUG_MARGINS
+ kdDebugBody(32002) << " getMargins: looking for frames between " << yp << " and " << yp+h << " (internal coords)" << endl;
+#endif
+ if ( m_doc->layoutViewMode()->shouldAdjustMargins() )
+ {
+ // Principle: for every frame on top at this height, we'll move from and to
+ // towards each other. The text flows between 'from' and 'to'
+ for ( QValueList<KWFrame*>::const_iterator txtit = textFrames.begin(), txtend = textFrames.end() ; txtit != txtend ; ++txtit ) {
+ KWFrame* theFrame = *txtit;
+ Q_ASSERT( theFrame->frameStack() );
+ QValueList<KWFrame*> onTop = theFrame->frameStack()->framesOnTop();
+ for (QValueListIterator<KWFrame*> fIt = onTop.begin(); from < to && fIt != onTop.end(); ++fIt )
+ {
+ if ( (*fIt)->runAround() == KWFrame::RA_BOUNDINGRECT )
+ {
+ KoRect rectOnTop = theFrame->intersect( (*fIt)->runAroundRect() );
+#ifdef DEBUG_MARGINS
+ kdDebugBody(32002) << " getMargins found frame on top " << (*fIt)->frameSet()->name() << " with rect-on-top at (normal coords) " << rectOnTop << endl;
+#endif
+ QPoint iTop, iBottom; // top and bottom of intersection in internal coordinates
+
+ if ( documentToInternal( rectOnTop.topLeft(), iTop ) &&
+ iTop.y() <= yp + h && // optimization
+ documentToInternal( rectOnTop.bottomRight(), iBottom ) )
+ {
+#ifdef DEBUG_MARGINS
+ kdDebugBody(32002) << " in internal coords: " << QRect(iTop,iBottom) << endl;
+#endif
+ // Look for intersection between yp -- yp+h and iTop -- iBottom
+ if ( QMAX( yp, iTop.y() ) <= QMIN( yp+h, iBottom.y() ) )
+ {
+#ifdef DEBUG_MARGINS
+ kdDebugBody(32002) << " getMargins iTop=" << iTop.x() << "," << iTop.y()
+ << " iBottom=" << iBottom.x() << "," << iBottom.y() << endl;
+#endif
+ int availLeft = QMAX( 0, iTop.x() - from );
+ int availRight = QMAX( 0, to - iBottom.x() );
+#ifdef DEBUG_MARGINS
+ kdDebugBody(32002) << " getMargins availLeft=" << availLeft
+ << " availRight=" << availRight << endl;
+#endif
+ bool chooseLeft = false;
+ switch ( (*fIt)->runAroundSide() ) {
+ case KWFrame::RA_LEFT:
+ chooseLeft = true;
+ break;
+ case KWFrame::RA_RIGHT:
+ break; // chooseLeft remains false
+ case KWFrame::RA_BIGGEST:
+ chooseLeft = ( availLeft > availRight ); // choose the max
+ };
+
+ if ( chooseLeft )
+ // flow text at the left of the frame
+ to = QMIN( to, from + availLeft - 1 ); // can only go left -> QMIN
+ else
+ // flow text at the right of the frame
+ from = QMAX( from, to - availRight + 1 ); // can only go right -> QMAX
+
+#ifdef DEBUG_MARGINS
+ kdDebugBody(32002) << " getMargins from=" << from << " to=" << to << endl;
+#endif
+ // If the available space is too small, give up on it
+ if ( to - from < reqMinWidth + paragLeftMargin )
+ {
+#ifdef DEBUG_MARGINS
+ kdDebugBody(32002) << " smaller than minimum=" << m_doc->ptToLayoutUnitPixX( 15 ) + paragLeftMargin << endl;
+#endif
+ from = to;
+ }
+
+ if ( breakEnd && from == to ) // no-space case
+ {
+ if ( !init ) // first time
+ {
+ init = true;
+ *breakBegin = iTop.y();
+ *breakEnd = iBottom.y();
+ }
+ else
+ {
+ *breakBegin = QMIN( *breakBegin, iTop.y() );
+ *breakEnd = QMAX( *breakEnd, iBottom.y() );
+ }
+#ifdef DEBUG_MARGINS
+ kdDebugBody(32002) << " getMargins iBottom.y=" << iBottom.y()
+ << " breakBegin=" << *breakBegin
+ << " breakEnd=" << *breakEnd << endl;
+#endif
+ }
+ } // else no intersection
+ }// else we got a 0L, or the iTop.y()<=yp+h test didn't work - wrong debug output
+ // kdDebugBody(32002) << " gerMargins: normalToInternal returned 0L" << endl;
+ }
+ }
+ }
+ }
+ if ( marginLeft /*&& marginRight && pageWidth -- implicit*/ )
+ {
+#ifdef DEBUG_MARGINS
+ kdDebugBody(32002) << " getMargins done. from=" << from << " to=" << to << endl;
+#endif
+ if ( from == to ) {
+ from = 0;
+ to = *pageWidth;
+ }
+
+ if ( marginLeft )
+ *marginLeft += from;
+ if ( marginRight )
+ {
+#ifdef DEBUG_MARGINS
+ kdDebug(32002) << " getMargins " << name()
+ << " page width=" << *pageWidth
+ << " to=" << to << endl;
+#endif
+ *marginRight += *pageWidth - to;
+ }
+ }
+}
+
+void KWTextFrameSet::adjustMargins( int yp, int h, int reqMinWidth, int& leftMargin, int& rightMargin, int& pageWidth, KoTextParag* parag )
+{
+#ifdef DEBUG_MARGINS
+ kdDebugBody(32002) << "KWTextFrameSet::adjustMargins called for paragraph " << (parag?parag->paragId():-1) << endl;
+#endif
+ int validHeight; // currently ignored (TODO)
+ getMargins( yp, h, reqMinWidth, &leftMargin, &rightMargin, &pageWidth, &validHeight, 0L, 0L, parag );
+#ifdef DEBUG_MARGINS
+ kdDebugBody(32002) << "KWTextFrameSet::adjustMargins(yp=" << yp << " h=" << h << " reqMinWidth=" << reqMinWidth << " returning"
+ << " leftMargin=" << leftMargin << " rightMargin=" << rightMargin
+ << " valid from " << yp << " to " << yp+validHeight << endl;
+#endif
+}
+
+// helper for formatVertically
+bool KWTextFrameSet::checkVerticalBreak( int & yp, int & hp, KoTextParag * parag, bool linesTogether, int breakBegin, int breakEnd )
+{
+ // We need the "+1" here because when skipping a frame on top, we want to be _under_
+ // its bottom. Without the +1, we hit the frame again on the next adjustLMargin call.
+
+ // Check for intersection between the parag (yp -- yp+hp) and the break area (breakBegin -- breakEnd)
+ if ( QMAX( yp, breakBegin ) <= QMIN( yp+hp, breakEnd ) )
+ {
+ if ( !parag || linesTogether ) // Paragraph-level breaking
+ {
+#ifdef DEBUG_FORMATVERTICALLY
+ kdDebug(32002) << "checkVerticalBreak ADJUSTING yp=" << yp << " hp=" << hp
+ << " breakEnd+2 [new value for yp]=" << breakEnd+2 << endl;
+#endif
+ yp = breakEnd + 1;
+ return true;
+ }
+ else // Line-level breaking
+ {
+ QMap<int, KoTextParagLineStart*>& lineStarts = parag->lineStartList();
+#ifdef DEBUG_FORMATVERTICALLY
+ kdDebug(32002) << "checkVerticalBreak parag " << parag->paragId()
+ << ". lineStarts has " << lineStarts.count()
+ << " items" << endl;
+#endif
+ int dy = 0;
+ int line = 0;
+ QMap<int, KoTextParagLineStart*>::Iterator it = lineStarts.begin();
+ for ( ; it != lineStarts.end() ; ++it, ++line )
+ {
+ KoTextParagLineStart * ls = it.data();
+ Q_ASSERT( ls );
+ int y = parag->rect().y() + ls->y;
+#ifdef DEBUG_FORMATVERTICALLY
+ kdDebug(32002) << "checkVerticalBreak parag " << parag->paragId()
+ << " line " << line << " ls->y=" << ls->y
+ << " ls->h=" << ls->h << " y=" << y
+ << " breakBegin=" << breakBegin
+ << " breakEnd=" << breakEnd << endl;
+#endif
+ if ( !dy )
+ {
+ if ( QMAX( y, breakBegin ) <= QMIN( y + ls->h, breakEnd ) )
+ {
+ if ( line == 0 ) // First line ? It's like a paragraph breaking then
+ {
+#ifdef DEBUG_FORMATVERTICALLY
+ kdDebug(32002) << "checkVerticalBreak parag " << parag->paragId()
+ << " BREAKING first line -> parag break" << endl;
+#endif
+ yp = breakEnd + 1;
+ return true;
+ }
+ dy = breakEnd + 1 - y;
+ ls->y = breakEnd + 1 - parag->rect().y();
+#ifdef DEBUG_FORMATVERTICALLY
+ kdDebug(32002) << "checkVerticalBreak parag " << parag->paragId()
+ << " BREAKING at line " << line << " dy=" << dy << " Setting ls->y to " << ls->y << ", y=" << breakEnd << endl;
+#endif
+ }
+ }
+ else
+ {
+ ls->y += dy;
+#ifdef DEBUG_FORMATVERTICALLY
+ if ( dy )
+ kdDebug(32002) << " moving down to position ls->y=" << ls->y << endl;
+#endif
+ }
+ }
+ parag->setMovedDown( true );
+ parag->setHeight( hp + dy );
+#ifdef DEBUG_FORMATVERTICALLY
+ kdDebug(32002) << "Paragraph height set to " << hp+dy << endl;
+#endif
+ hp += dy;
+ return true;
+ } // End of line-level breaking
+ }
+ return false;
+}
+
+int KWTextFrameSet::formatVertically( KoTextParag * _parag, const QRect& paragRect )
+{
+ // WARNING: in this whole method parag can be 0. See adjustFlow()
+ KWTextParag *parag = static_cast<KWTextParag *>( _parag );
+ if ( !m_doc->layoutViewMode()->shouldFormatVertically() )
+ {
+ return 0;
+ }
+
+#ifdef DEBUG_FORMATVERTICALLY
+ kdDebugBody(32002) << "KWTextFrameSet::formatVertically called for paragraph " << (parag?parag->paragId():-1) << endl;
+#endif
+
+ int yp = paragRect.y();
+ int hp = paragRect.height();
+ int oldHeight = hp;
+ int oldY = yp;
+
+ // This is called by KoTextFormatter to apply "vertical breaks".
+ // End of frames/pages lead to those "vertical breaks".
+ // What we do, is adjust the Y accordingly,
+ // to implement page-break at the paragraph level and at the line level.
+ // It's cumulative (the space of one break will be included in the further
+ // paragraph's y position), which makes it easy to implement.
+ // But don't forget that formatVertically is called twice for every parag, since the formatting
+ // is re-done after moving down.
+
+ bool linesTogether = parag ? parag->linesTogether() : true;
+ bool hardFrameBreak = parag ? parag->hardFrameBreakBefore() : false;
+ if ( !hardFrameBreak && parag && parag->prev() )
+ hardFrameBreak = static_cast<KWTextParag *>(parag->prev())->hardFrameBreakAfter();
+
+#ifdef DEBUG_FORMATVERTICALLY
+ kdDebugBody(32002) << "KWTextFrameSet::formatVertically parag=" << parag
+ << " linesTogether=" << linesTogether << " hardFrameBreak=" << hardFrameBreak
+ << " yp=" << yp
+ << " hp=" << hp << endl;
+#endif
+
+ int totalHeight = 0;
+ QPtrListIterator<KWFrame> frameIt( frameIterator() );
+ for ( ; frameIt.current(); ++frameIt )
+ {
+ int frameHeight = kWordDocument()->ptToLayoutUnitPixY( frameIt.current()->innerHeight() );
+ int bottom = totalHeight + frameHeight;
+ // Only skip bottom of frame if there is a next one or if there'll be another one created.
+ // ( Not for header/footer, for instance. )
+ bool check = frameIt.atLast() && frameIt.current()->frameBehavior() == KWFrame::AutoCreateNewFrame;
+ if ( !check )
+ {
+ // ## TODO optimize this [maybe we should simply start from the end in the main loop?]
+ // Or cache the attribute ( e.g. "frame->hasCopy()" ).
+ QPtrListIterator<KWFrame> nextFrame( frameIt );
+ while ( !check && !nextFrame.atLast() )
+ {
+ ++nextFrame;
+ if ( !nextFrame.current()->isCopy() )
+ check = true; // Found a frame after us that isn't a copy => we have somewhere for our overflow
+ }
+ }
+
+ if ( check )
+ {
+ if ( hardFrameBreak && yp > totalHeight && yp < bottom && !parag->wasMovedDown() )
+ {
+ // The paragraph wants a frame break before it, and is in the current frame
+ // The last check is for whether we did the frame break already
+ // (formatVertically is called twice for each paragraph, if a break was done)
+ yp = bottom /*+ 2*/;
+#ifdef DEBUG_FORMATVERTICALLY
+ kdDebug(32002) << "KWTextFrameSet::formatVertically -> HARD FRAME BREAK" << endl;
+ kdDebug(32002) << "KWTextFrameSet::formatVertically yp now " << yp << endl;
+#endif
+ break;
+ }
+
+#ifdef DEBUG_FORMATVERTICALLY
+ kdDebug(32002) << " formatVertically: frameHeight=" << frameHeight << " bottom=" << bottom << endl;
+#endif
+ // don't move down parags that have only one line and are bigger than the page (e.g. floating tables)
+ if ( hp < frameHeight || ( parag && parag->lineStartList().count() > 1 ) )
+ {
+ // breakBegin==breakEnd==bottom, since the next frame's top is the same as bottom, in QRT coords.
+ (void) checkVerticalBreak( yp, hp, parag, linesTogether, bottom, bottom );
+ // Some people write a single paragraph over 3 frames! So we have to keep looking, that's why we ignore the return value
+ }
+
+ }
+ if ( yp+hp < bottom )
+ break; // we've been past the parag, so stop here
+ totalHeight = bottom;
+ }
+
+#ifdef DEBUG_FORMATVERTICALLY
+ kdDebug(32002) << " formatVertically: now looking at RA_SKIP" << endl;
+#endif
+
+
+ // Another case for a vertical break is frames with the RA_SKIP flag
+ // Currently looking at all frames on top of all of our frames... maybe optimize better
+ frameIt.toFirst();
+ for ( ; frameIt.current(); ++frameIt )
+ {
+ Q_ASSERT( frameIt.current()->frameStack() );
+ QValueList<KWFrame*> onTop = frameIt.current()->frameStack()->framesOnTop();
+ for (QValueListIterator<KWFrame*> fIt = onTop.begin(); fIt != onTop.end(); ++fIt )
+ {
+ if ( (*fIt)->runAround() == KWFrame::RA_SKIP )
+ {
+ KoRect rectOnTop = frameIt.current()->intersect( (*fIt)->runAroundRect() );
+ QPoint iTop, iBottom; // top and bottom in internal coordinates
+ if ( documentToInternal( rectOnTop.topLeft(), iTop ) &&
+ iTop.y() <= yp + hp &&
+ documentToInternal( rectOnTop.bottomLeft(), iBottom ) &&
+ checkVerticalBreak( yp, hp, parag, linesTogether,
+ iTop.y(), iBottom.y() ) )
+ {
+ kdDebug(32002) << "KWTextFrameSet::formatVertically breaking around RA_SKIP frame yp="<<yp<<" hp=" << hp << endl;
+ // We don't "break;" here because there could be another such frame below the first one
+ // We assume that the frames on top are in order ( top to bottom ), btw.
+ // They should be, since updateFrames reorders before updating frames-on-top
+ }
+ }
+ }
+ }
+
+ // And the last case for a vertical break is RA_BOUNDINGRECT frames that
+ // leave no space by their side for any text (e.g. most tables)
+ int breakBegin = 0;
+ int breakEnd = 0;
+ int reqMinWidth = parag ? parag->string()->at( 0 ).width : 0;
+ getMargins( yp, hp, reqMinWidth, 0L, 0L, 0L, 0L, &breakBegin, &breakEnd, parag );
+ if ( breakEnd )
+ {
+ kdDebug(32002) << "KWTextFrameSet("<<name()<<")::formatVertically no-space case. breakBegin=" << breakBegin
+ << " breakEnd=" << breakEnd << " hp=" << hp << endl;
+ Q_ASSERT( breakBegin <= breakEnd );
+ if ( checkVerticalBreak( yp, hp, parag, linesTogether, breakBegin, breakEnd ) )
+ ; //kdDebug(32002) << "checkVerticalBreak ok." << endl;
+ else // shouldn't happen
+ kdWarning(32002) << "checkVerticalBreak didn't find it" << endl;
+ }
+
+ // ## TODO loop around those three methods until we don't move anymore ?
+
+ if ( parag )
+ {
+ if ( hp != oldHeight )
+ parag->setHeight( hp );
+ if ( yp != oldY ) {
+ QRect r = parag->rect();
+ r.moveBy( 0, yp - oldY );
+ parag->setRect( r );
+ parag->setMovedDown( true );
+ }
+ }
+#ifdef DEBUG_FORMATVERTICALLY
+ kdDebug() << "KWTextFrameSet::formatVertically returning " << ( yp + hp ) - ( oldY + oldHeight ) << endl;
+#endif
+ return ( yp + hp ) - ( oldY + oldHeight );
+}
+
+// adjustFlow is called e.g. to break the "top margin" of a paragraph.
+// There is no parag pointer in that case.
+int KWTextFrameSet::adjustFlow( int y, int w, int h )
+{
+ QRect r( 0, y, w, h );
+ return formatVertically( 0L, r );
+}
+
+void KWTextFrameSet::fixParagWidth( KWTextParag* parag )
+{
+ // Fixing the parag rect for the formatting chars (CR and frame break).
+ if ( parag && m_doc->viewFormattingChars() && parag->rect().width() < textDocument()->width() )
+ {
+ if ( parag->hardFrameBreakAfter() )
+ {
+ KoTextFormat * lastFormat = parag->at( parag->length() - 1 )->format();
+ const QFontMetrics& refFontMetrics = lastFormat->refFontMetrics();
+ // keep in sync with KWTextFrameSet::formatVertically
+ QString str = i18n( "--- Frame Break ---" );
+ int width = refFontMetrics.width( str );
+ parag->setWidth( QMIN( parag->rect().width() + width, textDocument()->width() ) );
+ }
+ else // default KoTextFormatter implementation
+ parag->fixParagWidth( true );
+ }
+}
+
+KWTextFrameSet::~KWTextFrameSet()
+{
+ textDocument()->takeFlow();
+ //kdDebug(32001) << "KWTextFrameSet::~KWTextFrameSet" << endl;
+ m_doc = 0L;
+ delete m_textobj;
+}
+
+// This struct is used for sorting frames.
+// Since pages are one below the other, simply sorting on (y, x) does what we want.
+struct FrameStruct
+{
+ KWFrame * frame;
+ bool operator < ( const FrameStruct & t ) const {
+ return compare(frame, t.frame) < 0;
+ }
+ bool operator <= ( const FrameStruct & t ) const {
+ return compare(frame, t.frame) <= 0;
+ }
+ bool operator > ( const FrameStruct & t ) const {
+ return compare(frame, t.frame) > 0;
+ }
+
+ /*
+ the sorting of all frames in the same frameset is done as all sorting
+ based on a simple frameOne > frameTwo question.
+ Frame frameOne is greater then frameTwo if the center point lies more down then (the whole of)
+ frame frameTwo. When they are equal, the X position is considered. */
+ int compare (const KWFrame *frameOne, const KWFrame *frameTwo) const {
+ // The first criteria is the page number though!
+ int pageOne = frameOne->pageNumber();
+ int pageTwo = frameTwo->pageNumber();
+ if( (pageOne == -1) ^ (pageTwo == -1)) {
+ if( pageOne == -1 )
+ return 5; // undefined is higher than defined.
+ return -5;
+ }
+ if ( pageOne > pageTwo ) return 4; // frameOne > frameTwo
+ if ( pageOne < pageTwo ) return -4; // frameOne < frameTwo
+
+ double centerX = frameOne->left() + (frameOne->width() /2);
+ // reverse the return values of the next two for RTL
+ if ( centerX > frameTwo->right()) return 3; // frameOne > frameTwo
+ if ( centerX < frameTwo->left()) return -3; // frameOne < frameTwo
+
+ // check the Y position. Y is greater only when it is below the other frame.
+ double centerY = frameOne->top() + (frameOne->height() /2);
+ if ( centerY > frameTwo->bottom() ) return 2; // frameOne > frameTwo
+ if ( centerY < frameTwo->top() ) return -2; // frameOne < frameTwo
+
+ // the center of frameOne lies inside frameTwo. Lets check the topleft pos.
+ if (frameOne->top() > frameTwo->top()) return 1;
+ return -1;
+ }
+};
+
+void KWTextFrameSet::updateFrames( int flags )
+{
+ // Not visible ? Don't bother then.
+ if ( !isVisible() ) {
+ //kdDebug(32002) << "KWTextFrameSet::updateFrames " << name() << " not visible" << endl;
+ m_textobj->setVisible(false);
+ return;
+ }
+ m_textobj->setVisible(true);
+
+ //kdDebug(32002) << "KWTextFrameSet::updateFrames " << name() << " frame-count=" << m_frames.count() << endl;
+
+ // Sort frames of this frameset on (y coord, x coord)
+ // Adjustment on 20-Jun-2002 which does not change the itent of this but moves the
+ // sorting from top-left of frame to the whole frame area. (TZ)
+
+ QValueList<FrameStruct> sortedFrames;
+
+ int width = 0;
+ QPtrListIterator<KWFrame> frameIter( frameIterator() );
+ for ( ; frameIter.current(); ++frameIter )
+ {
+ // Calculate max width while we're at it
+ //kdDebug(32002) << "KWTextFrameSet::updateFrames frame " << *frameIter.current() << " innerWidth=" << frameIter.current()->innerWidth() << "pt" << endl;
+ width = QMAX( width, m_doc->ptToLayoutUnitPixX( frameIter.current()->innerWidth()));
+ if ( flags & SortFrames )
+ {
+ FrameStruct str;
+ str.frame = frameIter.current();
+ sortedFrames.append( str );
+ }
+ }
+ if ( width != textDocument()->width() )
+ {
+ //kdDebug(32002) << "KWTextFrameSet::updateFrames setWidth " << width << " LU pixels." << endl;
+ //textDocument()->setMinimumWidth( -1, 0 );
+ textDocument()->setWidth( width + 1 ); // QRect semantics problem (#32866)
+ } //else kdDebug(32002) << "KWTextFrameSet::updateFrames width already " << width << " LU pixels." << endl;
+
+ if ( flags & SortFrames )
+ {
+ qHeapSort( sortedFrames );
+
+ // Re-fill the frames list with the frames in the right order
+ m_frames.setAutoDelete( false );
+ m_frames.clear();
+
+ QValueList<FrameStruct>::Iterator it = sortedFrames.begin();
+ for ( ; it != sortedFrames.end() ; ++it )
+ m_frames.append( (*it).frame );
+ }
+
+ double availHeight = 0;
+ double internalYpt = 0;
+ double lastRealFrameHeight = 0;
+ bool firstFrame = true;
+
+ QPtrListIterator<KWFrame> frameIt( m_frames );
+ for ( ; frameIt.current(); ++frameIt )
+ {
+ KWFrame* theFrame = frameIt.current();
+
+ if ( !theFrame->isCopy() )
+ internalYpt += lastRealFrameHeight;
+
+ theFrame->setInternalY( internalYpt );
+
+ // Update availHeight with the internal height of this frame - unless it's a copy
+ if ( !theFrame->isCopy() || firstFrame )
+ {
+ lastRealFrameHeight = theFrame->innerHeight();
+ availHeight += lastRealFrameHeight;
+ }
+ firstFrame = false;
+ }
+
+ m_textobj->setAvailableHeight( m_doc->ptToLayoutUnitPixY( availHeight ) );
+ //kdDebug(32002) << this << " (" << name() << ") KWTextFrameSet::updateFrames availHeight=" << availHeight
+ // << " (LU: " << m_doc->ptToLayoutUnitPixY( availHeight ) << ")" << endl;
+ m_frames.setAutoDelete( true );
+
+ KWFrameSet::updateFrames( flags );
+}
+
+int KWTextFrameSet::availableHeight() const
+{
+ return m_textobj->availableHeight();
+}
+
+KWFrame * KWTextFrameSet::internalToDocument( const KoPoint &relPoint, KoPoint &dPoint ) const
+{
+#ifdef DEBUG_ITD
+ kdDebug() << name() << " ITD called for relPoint=" << relPoint.x() << "," << relPoint.y() << endl;
+#endif
+ if ( !m_doc->layoutViewMode()->hasFrames() ) { // text viewmode
+ dPoint = relPoint;
+ return m_frames.getFirst();
+ }
+ // This does a binary search in the m_framesInPage array, with internalY as criteria
+ // We only look at the first frame of each page. Refining is done later on.
+ Q_ASSERT( !m_framesInPage.isEmpty() );
+ int len = m_framesInPage.count();
+ int n1 = 0;
+ int n2 = len - 1;
+ double internalY = 0.0;
+ int mid = 0;
+ bool found = FALSE;
+ while ( n1 <= n2 ) {
+ double res;
+ mid = (n1 + n2)/2;
+#ifdef DEBUG_ITD
+ kdDebug() << "ITD: begin. mid=" << mid << endl;
+#endif
+ Q_ASSERT( m_framesInPage[mid] ); // We have no null items
+ if ( m_framesInPage[mid]->isEmpty() )
+ res = -1;
+ else
+ {
+ KWFrame * theFrame = m_framesInPage[mid]->first();
+ internalY = theFrame->internalY();
+#ifdef DEBUG_ITD
+ kdDebug() << "ITD: relPoint.y=" << relPoint.y() << " internalY=" << internalY << endl;
+#endif
+ res = relPoint.y() - internalY;
+#ifdef DEBUG_ITD
+ kdDebug() << "ITD: res=" << res << endl;
+#endif
+ // Anything between this internalY (top) and internalY+height (bottom) is fine
+ // (Using the next page's first frame's internalY only works if there is a frame on the next page)
+ if ( res >= 0 )
+ {
+ double height = theFrame->innerHeight();
+#ifdef DEBUG_ITD
+ kdDebug() << "ITD: height=" << height << " -> the bottom is at " << internalY+height << endl;
+#endif
+ if ( relPoint.y() < internalY + height )
+ {
+#ifdef DEBUG_ITD
+ kdDebug() << "ITD: found a match " << mid << endl;
+#endif
+ found = true;
+ break;
+ }
+ }
+ }
+ // res == 0 can't happen in theory, but in practice it happens when a frame has a height of 0
+ // (e.g. newly imported table without correct row heights)
+ if ( res < 0 )
+ n2 = mid - 1;
+ else // if ( res >= 0 )
+ n1 = mid + 1;
+#ifdef DEBUG_ITD
+ kdDebug() << "ITD: End of loop. n1=" << n1 << " n2=" << n2 << endl;
+#endif
+ }
+ if ( !found )
+ {
+ // Not found (n2 < n1)
+ // We might have missed the frame because n2 has many frames
+ // (and we only looked at the first one).
+ mid = n2;
+#ifdef DEBUG_ITD
+ kdDebug() << "ITD: Setting mid to n2=" << mid << endl;
+#endif
+ if ( mid < 0 )
+ {
+#ifdef DEBUG_ITD
+ kdDebug(32002) << "KWTextFrameSet::internalToDocument " << relPoint.x() << "," << relPoint.y()
+ << " before any frame of " << (void*)this << endl;
+#endif
+ dPoint = relPoint; // "bah", I said above :)
+ return 0L;
+ }
+ }
+ // search to first of equal items
+ // This happens with copied frames, which have the same internalY
+ int result = mid;
+ while ( mid - 1 >= 0 )
+ {
+ mid--;
+ if ( !m_framesInPage[mid]->isEmpty() )
+ {
+ KWFrame * theFrame = m_framesInPage[mid]->first();
+#ifdef DEBUG_ITD
+ kdDebug() << "KWTextFrameSet::internalToDocument going back to page " << mid << " - frame: " << theFrame->internalY() << endl;
+#endif
+ if ( theFrame->internalY() == internalY ) // same internalY as the frame we found before
+ result = mid;
+ else
+ break;
+ }
+ }
+
+ // Now iterate over the frames in page 'result' and find the right one
+ QPtrListIterator<KWFrame> frameIt( *m_framesInPage[result] );
+ for ( ; frameIt.current(); ++frameIt )
+ {
+ KWFrame *theFrame = frameIt.current();
+ KoRect relRect( 0, theFrame->internalY(), theFrame->innerWidth(), theFrame->innerHeight() );
+#ifdef DEBUG_ITD
+ kdDebug() << "KWTextFrameSet::internalToDocument frame's relative rect:" << relRect << endl;
+#endif
+ if ( relRect.contains( relPoint ) ) // both relRect and relPoint are in "relative coordinates"
+ {
+ dPoint = internalToDocumentKnowingFrame( relPoint, theFrame );
+ return theFrame;
+ }
+ }
+#ifdef DEBUG_ITD
+ kdDebug(32002) << "KWTextFrameSet::internalToDocument " << relPoint.x() << "," << relPoint.y()
+ << " not in any frame of " << (void*)this << " (looked on page " << result << ")" << endl;
+#endif
+ dPoint = relPoint; // bah again
+ return 0L;
+}
+
+// same but with iPoint in LU
+KWFrame * KWTextFrameSet::internalToDocument( const QPoint &iPoint, KoPoint &dPoint ) const
+{
+ KoPoint relPoint = m_doc->layoutUnitPtToPt( m_doc->pixelToPt( iPoint ) );
+ return internalToDocument( relPoint, dPoint );
+}
+
+#ifndef NDEBUG
+void KWTextFrameSet::printDebug()
+{
+ KWFrameSet::printDebug();
+ if ( !isDeleted() )
+ {
+ kdDebug() << "KoTextDocument width = " << textDocument()->width() << " height = " << textDocument()->height() << endl;
+ }
+
+ QPtrListIterator<KoTextCustomItem> cit( textDocument()->allCustomItems() );
+ for ( ; cit.current() ; ++cit )
+ {
+ KWAnchor *anc = dynamic_cast<KWAnchor *>( cit.current() );
+ if (anc)
+ kdDebug() << "Inline framesets: " << anc->frameSet()->name() << endl;
+ }
+}
+#endif
+
+QDomElement KWTextFrameSet::saveInternal( QDomElement &parentElem, bool saveFrames, bool saveAnchorsFramesets )
+{
+ if ( m_frames.isEmpty() ) // Deleted frameset -> don't save
+ return QDomElement();
+
+ QDomElement framesetElem = parentElem.ownerDocument().createElement( "FRAMESET" );
+ parentElem.appendChild( framesetElem );
+
+ if ( m_groupmanager ) {
+ framesetElem.setAttribute( "grpMgr", m_groupmanager->name() );
+
+ KWTableFrameSet::Cell *cell = (KWTableFrameSet::Cell *)this;
+ framesetElem.setAttribute( "row", cell->firstRow() );
+ framesetElem.setAttribute( "col", cell->firstColumn() );
+ framesetElem.setAttribute( "rows", cell->rowSpan() );
+ framesetElem.setAttribute( "cols", cell->columnSpan() );
+ }
+ if ( protectContent() )
+ framesetElem.setAttribute( "protectContent", static_cast<int>(protectContent()));
+
+ KWFrameSet::saveCommon( framesetElem, saveFrames );
+
+ // Save paragraphs
+ KWTextParag *start = static_cast<KWTextParag *>( textDocument()->firstParag() );
+ while ( start ) {
+ start->save( framesetElem, saveAnchorsFramesets );
+ start = static_cast<KWTextParag *>( start->next() );
+ }
+
+ return framesetElem;
+}
+
+KWFrame* KWTextFrameSet::loadOasisTextFrame( const QDomElement& frameTag, const QDomElement &tag, KoOasisContext& context )
+{
+ context.styleStack().save();
+ context.fillStyleStack( frameTag, KoXmlNS::draw, "style-name", "graphic" ); // get the style for the graphics element
+
+ KWFrame* frame = loadOasisFrame( frameTag, context );
+
+ // Load minimum height - only available for text-box
+ bool hasMinHeight = tag.hasAttributeNS( KoXmlNS::fo, "min-height" );
+ if ( hasMinHeight ) {
+ double height = KoUnit::parseValue( tag.attributeNS( KoXmlNS::fo, "min-height", QString::null ) );
+ frame->setMinimumFrameHeight( height );
+ if ( height > frame->height() || !tag.hasAttributeNS( KoXmlNS::fo, "height" ) )
+ frame->setHeight( height );
+ }
+
+ // Load overflow behavior (OASIS 14.27.27, not in OO-1.1 DTD). This is here since it's only for text framesets.
+ const QString overflowBehavior = context.styleStack().attributeNS( KoXmlNS::style, "overflow-behavior" );
+ if ( frame->minimumFrameHeight() > 0 )
+ frame->setFrameBehavior( KWFrame::AutoExtendFrame );
+ else if ( overflowBehavior == "auto-create-new-frame" )
+ {
+ frame->setFrameBehavior( KWFrame::AutoCreateNewFrame );
+ frame->setNewFrameBehavior( KWFrame::Reconnect ); // anything else doesn't make sense
+ }
+ else if ( overflowBehavior.isEmpty() || overflowBehavior == "clip" )
+ frame->setFrameBehavior( KWFrame::Ignore );
+ else
+ kdWarning(32001) << "Unknown value for style:overflow-behavior: " << overflowBehavior << endl;
+
+ context.styleStack().restore();
+
+ return frame;
+}
+
+void KWTextFrameSet::loadOasisContent( const QDomElement &bodyElem, KoOasisContext& context )
+{
+ return m_textobj->loadOasisContent( bodyElem, context, m_doc->styleCollection() );
+}
+
+KWFrame* KWTextFrameSet::loadOasis( const QDomElement& frameTag, const QDomElement &tag, KoOasisContext& context )
+{
+ KWFrame* frame = loadOasisTextFrame( frameTag, tag, context );
+ loadOasisContent( tag, context );
+ return frame;
+}
+
+static void finishTOC( KoXmlWriter& writer )
+{
+ writer.endElement(); // text:table-of-content
+ writer.endElement(); // text:index-body
+}
+
+void KWTextFrameSet::saveOasisContent( KoXmlWriter& writer, KoSavingContext& context ) const
+{
+ // TODO save protectContent
+
+ QMap<const KoTextParag*, KoTextBookmarkList> bookmarksPerParagraph;
+ if ( m_doc->bookmarkList() )
+ bookmarksPerParagraph = m_doc->bookmarkList()->bookmarksPerParagraph();
+
+ // Basically just call saveOasis on every paragraph.
+ // But we do table-of-contents-handling (for kword) in addition,
+ // as well as bookmarks.
+ KoTextParag* parag = textDocument()->firstParag();
+ bool inTOC = false;
+ while ( parag ) {
+ bool tocParag = parag->partOfTableOfContents();
+ if ( tocParag != inTOC ) {
+ if ( tocParag ) { // first TOC paragraph
+ writer.startElement( "text:table-of-content" );
+ writer.addAttribute( "text:name", "Table Of Contents" );
+ writer.addAttribute( "text:protected", "false" ); // true by default in OO, but we don't support that yet anyway
+ writer.startElement( "text:table-of-content-source" );
+ // TODO writer.addAttribute( "text:outline-level", ... );
+ // TODO for each level writer.startElement( "text:table-of-content-entry-template" );
+ // TODO writer.endElement(); // text:table-of-content-entry-template
+ writer.endElement(); // text:table-of-content-source
+ writer.startElement( "text:index-body" );
+ writer.startElement( "text:index-title" );
+ writer.addAttribute( "text:name", "Table Of Contents Heading" );
+ } else {
+ finishTOC( writer );
+ }
+ }
+
+
+ // I want Qt4's QMap/QHash::value()!
+ KoSavingContext::BookmarkPositions bookmarkStarts, bookmarkEnds;
+ QMap<const KoTextParag*, KoTextBookmarkList>::const_iterator bkit = bookmarksPerParagraph.find( parag );
+ if ( bkit != bookmarksPerParagraph.end() ) {
+ // Massage a bit the bookmarks data; KoTextParag wants it ordered by position, for speed.
+ const KoTextBookmarkList& bookmarks = *bkit;
+ for ( KoTextBookmarkList::const_iterator it = bookmarks.begin(); it != bookmarks.end(); ++it )
+ {
+ const KoTextBookmark& bk = *it;
+ if ( bk.startParag() == parag )
+ bookmarkStarts.append( KoSavingContext::BookmarkPosition(
+ bk.bookmarkName(), bk.bookmarkStartIndex(),
+ bk.isSimple() ) );
+ if ( bk.endParag() == parag && !bk.isSimple() )
+ bookmarkEnds.append( KoSavingContext::BookmarkPosition( bk.bookmarkName(),
+ bk.bookmarkEndIndex(), false ) );
+ }
+ qHeapSort( bookmarkStarts );
+ qHeapSort( bookmarkEnds );
+ }
+ // should be done in all cases, even if both lists are empty
+ context.setBookmarkPositions( bookmarkStarts, bookmarkEnds );
+
+ // Save the whole parag, without the trailing space.
+ parag->saveOasis( writer, context, 0, parag->lastCharPos() );
+
+ if ( tocParag && !inTOC )
+ writer.endElement(); // text:index-title
+ inTOC = tocParag;
+
+ parag = parag->next();
+ }
+ if ( inTOC )
+ finishTOC( writer );
+}
+
+void KWTextFrameSet::saveOasis( KoXmlWriter& writer, KoSavingContext& context, bool saveFrames ) const
+{
+ // Save first frame with the whole contents
+ KWFrame* frame = m_frames.getFirst();
+ QString lastFrameName = name();
+ frame->startOasisFrame( writer, context.mainStyles(), lastFrameName );
+
+ QString nextFrameName = name() + "-";
+
+ writer.startElement( "draw:text-box" );
+ if ( frame->frameBehavior() == KWFrame::AutoExtendFrame )
+ writer.addAttributePt( "fo:min-height", frame->minimumFrameHeight() );
+ if ( m_frames.count() > 1 && saveFrames )
+ writer.addAttribute( "draw:chain-next-name", nextFrameName + "2" );
+ saveOasisContent( writer, context );
+ writer.endElement(); // draw:text-box
+ writer.endElement(); // draw:frame
+
+ // Save other frames using chaining
+ if ( saveFrames ) // false when called from KWDocument::saveSelectedFrames
+ {
+ int frameNumber = 2;
+ QPtrListIterator<KWFrame> frameIter( frameIterator() );
+ ++frameIter; // skip first frame, already saved
+ for ( ; frameIter.current(); ++frameIter, ++frameNumber )
+ {
+ const QString frameName = nextFrameName + QString::number( frameNumber );
+ frameIter.current()->startOasisFrame( writer, context.mainStyles(), frameName, lastFrameName );
+ lastFrameName = frameName; // this is used for copy-frames
+ writer.startElement( "draw:text-box" );
+ if ( frame->frameBehavior() == KWFrame::AutoExtendFrame )
+ writer.addAttributePt( "fo:min-height", frame->minimumFrameHeight() );
+ if ( frameNumber < (int)m_frames.count() )
+ writer.addAttribute( "draw:chain-next-name", nextFrameName + QString::number( frameNumber+1 ) );
+ // No contents. Well, OOo saves an empty paragraph, but I'd say that's wrong.
+ writer.endElement();
+ writer.endElement(); // draw:frame
+ }
+ }
+}
+
+void KWTextFrameSet::load( QDomElement &attributes, bool loadFrames )
+{
+ KWFrameSet::load( attributes, loadFrames );
+ if ( attributes.hasAttribute( "protectContent"))
+ setProtectContent((bool)attributes.attribute( "protectContent" ).toInt());
+
+ textDocument()->clear(false); // Get rid of dummy paragraph (and more if any)
+ m_textobj->setLastFormattedParag( 0L ); // no more parags, avoid UMR in next setLastFormattedParag call
+ KWTextParag *lastParagraph = 0L;
+
+ // <PARAGRAPH>
+ QDomElement paragraph = attributes.firstChild().toElement();
+ for ( ; !paragraph.isNull() ; paragraph = paragraph.nextSibling().toElement() )
+ {
+ if ( paragraph.tagName() == "PARAGRAPH" )
+ {
+ KWTextParag *parag = new KWTextParag( textDocument(), lastParagraph );
+ parag->load( paragraph );
+ if ( !lastParagraph ) // First parag
+ textDocument()->setFirstParag( parag );
+ lastParagraph = parag;
+ m_doc->progressItemLoaded();
+ }
+ }
+
+ if ( !lastParagraph ) // We created no paragraph
+ {
+ // Create an empty one, then. See KWTextDocument ctor.
+ textDocument()->clear( true );
+ static_cast<KWTextParag *>( textDocument()->firstParag() )->setStyle( m_doc->styleCollection()->findStyle( "Standard" ) );
+ }
+ else
+ textDocument()->setLastParag( lastParagraph );
+
+ m_textobj->setLastFormattedParag( textDocument()->firstParag() );
+ //kdDebug(32001) << "KWTextFrameSet::load done" << endl;
+}
+
+void KWTextFrameSet::finalize()
+{
+ KWFrameSet::finalize();
+ m_textobj->formatMore( 0 ); // just to get the timer going
+ // This is important in case of auto-resized frames or table cells,
+ // which come from an import filter, which didn't give them the right size.
+ // However it shouldn't start _now_ (so we use 0), because e.g. main frames
+ // don't have the right size yet (KWFrameLayout not done yet).
+}
+
+void KWTextFrameSet::setVisible(bool visible)
+{
+ setInlineFramesVisible( visible );
+ KWFrameSet::setVisible( visible );
+}
+
+void KWTextFrameSet::setInlineFramesVisible(bool visible)
+{
+ QPtrListIterator<KoTextCustomItem> cit( textDocument()->allCustomItems() );
+ for ( ; cit.current() ; ++cit )
+ {
+ KWAnchor *anc = dynamic_cast<KWAnchor *>( cit.current() );
+ if (anc)
+ anc->frameSet()->setVisible( visible );
+ }
+}
+
+void KWTextFrameSet::addTextFrameSets( QPtrList<KWTextFrameSet> & lst, bool onlyReadWrite )
+{
+ if (!textObject()->protectContent() || !onlyReadWrite)
+ lst.append(this);
+}
+
+void KWTextFrameSet::slotNewCommand( KCommand *cmd )
+{
+ m_doc->addCommand( cmd );
+}
+
+void KWTextFrameSet::ensureFormatted( KoTextParag * parag, bool emitAfterFormatting )
+{
+ if (!isVisible())
+ return;
+ m_textobj->ensureFormatted( parag, emitAfterFormatting );
+}
+
+bool KWTextFrameSet::slotAfterFormattingNeedMoreSpace( int bottom, KoTextParag *lastFormatted )
+{
+ int availHeight = availableHeight();
+#ifdef DEBUG_FORMAT_MORE
+ if(lastFormatted)
+ kdDebug(32002) << "slotAfterFormatting We need more space in " << name()
+ << " bottom=" << bottom + lastFormatted->rect().height()
+ << " availHeight=" << availHeight << endl;
+ else
+ kdDebug(32002) << "slotAfterFormatting We need more space in " << name()
+ << " bottom2=" << bottom << " availHeight=" << availHeight << endl;
+#endif
+ if ( m_frames.isEmpty() )
+ {
+ kdWarning(32002) << "slotAfterFormatting no more space, but no frame !" << endl;
+ return true; // abort
+ }
+
+ KWFrame::FrameBehavior frmBehavior = m_frames.last()->frameBehavior();
+ if ( frmBehavior == KWFrame::AutoExtendFrame && isProtectSize())
+ frmBehavior = KWFrame::Ignore;
+ if ( frmBehavior == KWFrame::AutoCreateNewFrame )
+ {
+ KWFrame *theFrame = settingsFrame( m_frames.last() );
+ double minHeight = s_minFrameHeight + theFrame->paddingTop() + theFrame->paddingBottom() + 5;
+ if ( availHeight < minHeight )
+ frmBehavior = KWFrame::Ignore;
+ }
+
+ int difference = ( bottom + 2 ) - availHeight; // in layout unit pixels
+#ifdef DEBUG_FORMAT_MORE
+ kdDebug(32002) << "AutoExtendFrame bottom=" << bottom << " availHeight=" << availHeight
+ << " => difference = " << difference << endl;
+#endif
+ if( lastFormatted && bottom + lastFormatted->rect().height() > availHeight ) {
+#ifdef DEBUG_FORMAT_MORE
+ kdDebug(32002) << " next will be off -> adding " << lastFormatted->rect().height() << endl;
+#endif
+ difference += lastFormatted->rect().height();
+ }
+
+ switch ( frmBehavior ) {
+ case KWFrame::AutoExtendFrame:
+ {
+ if(difference > 0) {
+ // There's no point in resizing a copy, so go back to the last non-copy frame
+ KWFrame *theFrame = settingsFrame( m_frames.last() );
+ double wantedPosition = 0;
+
+ // Footers and footnotes go up
+ if ( theFrame->frameSet()->isAFooter() || theFrame->frameSet()->isFootNote() )
+ {
+ // The Y position doesn't matter much, recalcFrames will reposition the frame
+ // But the point of this code is set the correct height for the frame.
+ double maxFooterSize = footerHeaderSizeMax( theFrame );
+ double diffPt = m_doc->layoutUnitPtToPt( m_doc->pixelYToPt( difference ) );
+ wantedPosition = theFrame->top() - diffPt;
+#ifdef DEBUG_FORMAT_MORE
+ kdDebug() << " diffPt=" << diffPt << " -> wantedPosition=" << wantedPosition << endl;
+#endif
+ if ( wantedPosition < 0 )
+ {
+ m_textobj->setLastFormattedParag( 0 );
+ return true; // abort
+ }
+
+ if ( wantedPosition != theFrame->top() &&
+ ( theFrame->frameSet()->isFootEndNote() ||
+ theFrame->bottom() - maxFooterSize <= wantedPosition ) ) // Apply maxFooterSize for footers only
+ {
+ theFrame->setTop( wantedPosition );
+#ifdef DEBUG_FORMAT_MORE
+ kdDebug() << " ok: frame=" << *theFrame << " bottom=" << theFrame->bottom() << " height=" << theFrame->height() << endl;
+#endif
+ frameResized( theFrame, true );
+ // We only got room for the next paragraph, we still have to keep the formatting going...
+ return false; // keep going
+ }
+ kdDebug() << "slotAfterFormatting didn't manage to get more space for footer/footnote, aborting" << endl;
+ return true; // abort
+ }
+ // Other frames are resized by the bottom
+
+ wantedPosition = m_doc->layoutUnitPtToPt( m_doc->pixelYToPt( difference ) ) + theFrame->bottom();
+ KWPage *page = m_doc->pageManager()->page( theFrame );
+ double pageBottom;
+ if(page)
+ pageBottom = page->offsetInDocument() + page->height() - page->bottomMargin();
+ else
+ pageBottom = theFrame->bottom();
+ double newPosition = QMIN( wantedPosition, pageBottom );
+ kdDebug(32002) << "wantedPosition=" << wantedPosition << " pageBottom=" << pageBottom
+ << " -> newPosition=" << newPosition << endl;
+
+ if ( theFrame->frameSet()->isAHeader() )
+ {
+ double maxHeaderSize=footerHeaderSizeMax( theFrame );
+ newPosition = QMIN( newPosition, maxHeaderSize + theFrame->top() );
+ }
+
+ newPosition = QMAX( newPosition, theFrame->top() ); // avoid negative heights
+ kdDebug(32002) << "newPosition=" << newPosition << endl;
+
+ bool resized = false;
+ if(theFrame->frameSet()->groupmanager()) {
+ KWTableFrameSet *table = theFrame->frameSet()->groupmanager();
+#ifdef DEBUG_FORMAT_MORE
+ kdDebug(32002) << "is table cell; just setting new minFrameHeight, to " << newPosition - theFrame->top() << endl;
+#endif
+ double newMinFrameHeight = newPosition - theFrame->top();
+ resized = QABS( newMinFrameHeight - theFrame->minimumFrameHeight() ) > 1E-10;
+ if ( resized ) {
+ theFrame->setMinimumFrameHeight( newMinFrameHeight );
+ KWTableFrameSet::Cell *cell = (KWTableFrameSet::Cell *)theFrame->frameSet();
+ table->recalcCols(cell->firstColumn(), cell->firstRow());
+ table->recalcRows(cell->firstColumn(), cell->firstRow());
+
+ if (! table->anchorFrameset() )
+ ;// do nothing
+ else if ( table->anchorFrameset() && table->anchorFrameset()->isAHeader() ) //we must recalculate the header frame size
+ {
+ theFrame = table->anchorFrameset()->frameIterator().getLast();
+ theFrame->setBottom(newPosition);
+ frameResized( theFrame, false );
+ }
+ else if ( table->anchorFrameset()->isAFooter() || table->anchorFrameset()->isFootNote() ) //we must recalculate the footer frame size
+ {
+ theFrame = table->anchorFrameset()->frameIterator().getLast();
+ // The Y position doesn't matter much, recalcFrames will reposition the frame
+ // But the point of this code is set the correct height for the frame.
+ double maxFooterSize = footerHeaderSizeMax( theFrame );
+ double diffPt = m_doc->layoutUnitPtToPt( m_doc->pixelYToPt( difference ) );
+ wantedPosition = theFrame->top() - diffPt;
+ if ( wantedPosition < 0 )
+ {
+ m_textobj->setLastFormattedParag( 0 );
+ return true; // abort
+ }
+
+ if ( wantedPosition != theFrame->top() &&
+ ( theFrame->frameSet()->isFootEndNote() ||
+ theFrame->bottom() - maxFooterSize <= wantedPosition ) ) // Apply maxFooterSize for footers only
+ {
+ theFrame->setTop( wantedPosition );
+ frameResized( theFrame, true );
+ // We only got room for the next paragraph, we still have to keep the formatting going...
+ }
+ }
+
+ m_doc->delayedRepaintAllViews();
+ }
+ return true; // abort formatting for now (not sure this is correct)
+ } else {
+ resized = QABS( theFrame->bottom() - newPosition ) > 1E-10;
+#ifdef DEBUG_FORMAT_MORE
+ kdDebug() << " bottom=" << theFrame->bottom() << " new position:" << newPosition << " wantedPosition=" << wantedPosition << " resized=" << resized << endl;
+#endif
+
+ if ( resized )
+ {
+#ifdef DEBUG_FORMAT_MORE
+ kdDebug(32002) << "slotAfterFormatting changing bottom from " << theFrame->bottom() << " to " << newPosition << endl;
+#endif
+ theFrame->setBottom(newPosition);
+ frameResized( theFrame, false );
+ }
+ }
+
+ if(newPosition < wantedPosition &&
+ (theFrame->newFrameBehavior() == KWFrame::Reconnect
+ && !theFrame->frameSet()->isEndNote())) // end notes are handled by KWFrameLayout
+ {
+ wantedPosition = wantedPosition - newPosition + theFrame->top() + page->height();
+#ifdef DEBUG_FORMAT_MORE
+ kdDebug(32002) << "Not enough room in this page -> creating new one, with a reconnect frame" << endl;
+ kdDebug(32002) << "new wantedPosition=" << wantedPosition << endl;
+#endif
+
+ // fall through to AutoCreateNewFrame
+ }
+ else if(newPosition < wantedPosition && (theFrame->newFrameBehavior() == KWFrame::NoFollowup)) {
+ if ( theFrame->frameSet()->isEndNote() ) // we'll need a new page
+ m_doc->delayedRecalcFrames( theFrame->pageNumber() );
+
+ m_textobj->setLastFormattedParag( 0 );
+ return true; // abort
+ } else {
+ if ( resized ) // we managed to resize a frame
+ return false; // keep going
+ return true; // abort
+ }
+ }
+ }
+
+ case KWFrame::AutoCreateNewFrame:
+ {
+ // We need a new frame in this frameset.
+ return createNewPageAndNewFrame( lastFormatted, difference );
+ }
+
+ case KWFrame::Ignore:
+#ifdef DEBUG_FORMAT_MORE
+ kdDebug(32002) << "slotAfterFormatting frame behaviour is Ignore" << endl;
+#endif
+ m_textobj->setLastFormattedParag( 0 );
+ return true; // abort
+ }
+ kdWarning() << "NEVERREACHED" << endl;
+ // NEVERREACHED
+ return true;
+}
+
+void KWTextFrameSet::slotAfterFormattingTooMuchSpace( int bottom )
+{
+ int availHeight = availableHeight();
+ // The + 2 here leaves 2 pixels below the last line. Without it we hit
+ // the "break at end of frame" case in formatVertically (!!).
+ int difference = availHeight - ( bottom + 2 );
+#ifdef DEBUG_FORMAT_MORE
+ kdDebug(32002) << "slotAfterFormatting less text than space (AutoExtendFrame). Frameset " << name() << " availHeight=" << availHeight << " bottom=" << bottom << " ->difference=" << difference << endl;
+#endif
+ // There's no point in resizing a copy, so go back to the last non-copy frame
+ KWFrame *theFrame = settingsFrame( m_frames.last() );
+#ifdef DEBUG_FORMAT_MORE
+ kdDebug(32002) << " frame is " << *theFrame << " footer:" << ( theFrame->frameSet()->isAFooter() || theFrame->frameSet()->isFootEndNote() ) << endl;
+#endif
+ if ( theFrame->frameSet()->isAFooter() || theFrame->frameSet()->isFootEndNote() )
+ {
+ double wantedPosition = theFrame->top() + m_doc->layoutUnitPtToPt( m_doc->pixelYToPt( difference ) );
+ Q_ASSERT( wantedPosition < theFrame->bottom() );
+ if ( wantedPosition != theFrame->top() )
+ {
+#ifdef DEBUG_FORMAT_MORE
+ kdDebug() << " top= " << theFrame->top() << " setTop " << wantedPosition << endl;
+#endif
+ theFrame->setTop( wantedPosition );
+#ifdef DEBUG_FORMAT_MORE
+ kdDebug() << " -> the frame is now " << *theFrame << endl;
+#endif
+ frameResized( theFrame, true );
+ }
+ }
+ else // header or other frame: resize bottom
+ {
+ double wantedPosition = theFrame->bottom() - m_doc->layoutUnitPtToPt( m_doc->pixelYToPt( difference ) );
+#ifdef DEBUG_FORMAT_MORE
+ kdDebug() << "slotAfterFormatting wantedPosition=" << wantedPosition << " top+minheight=" << theFrame->top() + s_minFrameHeight << endl;
+#endif
+ wantedPosition = QMAX( wantedPosition, theFrame->top() + s_minFrameHeight );
+ if( theFrame->frameSet()->groupmanager() ) {
+ if ( wantedPosition != theFrame->bottom()) {
+ KWTableFrameSet *table = theFrame->frameSet()->groupmanager();
+ // When a frame can be smaller we don't rescale it if it is a table, since
+ // we don't have the full picture of the change.
+ // We will set the minFrameHeight to the correct value and let the tables code
+ // do the rescaling based on all the frames in the row. (see KWTableFrameSet::recalcRows())
+ if(wantedPosition != theFrame->top() + theFrame->minimumFrameHeight()) {
+ theFrame->setMinimumFrameHeight(wantedPosition - theFrame->top());
+#ifdef DEBUG_FORMAT_MORE
+ kdDebug(32002) << "is table cell; only setting new minFrameHeight to " << theFrame->minimumFrameHeight() << ", recalcrows will do the rest" << endl;
+#endif
+ KWTableFrameSet::Cell *cell = (KWTableFrameSet::Cell *)theFrame->frameSet();
+ table->recalcCols(cell->firstColumn(), cell->firstRow());
+ table->recalcRows(cell->firstColumn(), cell->firstRow());
+
+ if (! table->anchorFrameset() )
+ ;// do nothing
+ else if ( table->anchorFrameset() && table->anchorFrameset()->isAHeader() )
+ {
+ theFrame = table->anchorFrameset()->frameIterator().getLast();
+ theFrame->setBottom(wantedPosition);
+ frameResized( theFrame, false );
+ }
+ else if ( table->anchorFrameset()->isAFooter() || table->anchorFrameset()->isFootEndNote() )
+ {
+ theFrame = table->anchorFrameset()->frameIterator().getLast();
+ double wantedPosition = theFrame->top() + m_doc->layoutUnitPtToPt( m_doc->pixelYToPt( difference ) );
+ Q_ASSERT( wantedPosition < theFrame->bottom() );
+ if ( wantedPosition != theFrame->top() )
+ {
+ theFrame->setTop( wantedPosition );
+ frameResized( theFrame, true );
+ }
+ }
+ m_doc->delayedRepaintAllViews();
+ }
+ }
+ } else {
+ // Also apply the frame's minimum height
+ wantedPosition = QMAX( wantedPosition, theFrame->top() + theFrame->minimumFrameHeight() );
+ if ( wantedPosition != theFrame->bottom()) {
+#ifdef DEBUG_FORMAT_MORE
+ kdDebug() << " the frame was " << *theFrame << endl;
+ kdDebug() << "setBottom " << wantedPosition << endl;
+#endif
+ theFrame->setBottom( wantedPosition );
+#ifdef DEBUG_FORMAT_MORE
+ kdDebug() << " -> the frame is now " << *theFrame << endl;
+#endif
+ frameResized( theFrame, true );
+ }
+ }
+ }
+}
+
+void KWTextFrameSet::slotAfterFormatting( int bottom, KoTextParag *lastFormatted, bool* abort )
+{
+ int availHeight = availableHeight();
+ if ( ( bottom > availHeight ) || // this parag is already off page
+ ( lastFormatted && bottom + lastFormatted->rect().height() > availHeight ) ) // or next parag will be off page
+ {
+ *abort = slotAfterFormattingNeedMoreSpace( bottom, lastFormatted );
+ }
+ // Handle the case where the last frame is empty, so we may want to
+ // remove the last page.
+ else if ( m_frames.count() > 1 && !lastFormatted && frameSetInfo() == KWFrameSet::FI_BODY
+ && bottom < availHeight - m_doc->ptToLayoutUnitPixY( m_frames.last()->innerHeight() ) )
+ {
+#ifdef DEBUG_FORMAT_MORE
+ kdDebug(32002) << "slotAfterFormatting too much space (bottom=" << bottom << ", availHeight=" << availHeight << ") , trying to remove last frame" << endl;
+#endif
+ // Remove the empty last frame, if it's an auto-created one (e.g. a
+ // continuation on the next page). Not when the user just created it!
+ if(m_frames.last()->frameBehavior() == KWFrame::AutoExtendFrame
+ && m_frames.last()->minimumFrameHeight() < 1E-10 ) { // i.e. equal to 0
+ deleteFrame(m_frames.last(), true);
+ m_doc->frameChanged( 0L );
+ }
+ if ( m_doc->processingType() == KWDocument::WP ) {
+ bool removed = m_doc->tryRemovingPages();
+ // Do all the recalc in one go. Speeds up deleting many pages.
+ if ( removed )
+ m_doc->afterRemovePages();
+ }
+ }
+ // Handle the case where the last frame is in AutoExtendFrame mode
+ // and there is less text than space
+ else if ( !lastFormatted && bottom + 2 < availHeight &&
+ (m_frames.last()->frameBehavior() == KWFrame::AutoExtendFrame&& !isProtectSize()) )
+ {
+ slotAfterFormattingTooMuchSpace( bottom );
+ *abort = false;
+ }
+
+ if ( m_doc->processingType() == KWDocument::WP
+ && this == m_doc->frameSet( 0 ) )
+ {
+ if ( m_lastTextDocHeight != textDocument()->height() )
+ {
+ m_lastTextDocHeight = textDocument()->height();
+ emit mainTextHeightChanged();
+ }
+ }
+}
+
+// This is called when a text frame with behaviour AutoCreateNewFrame
+// has more text than available frame height, so we need to create a new page
+// so that a followup frame is created for this one
+bool KWTextFrameSet::createNewPageAndNewFrame( KoTextParag* lastFormatted, int /*difference*/ )
+{
+ KWFrame* lastFrame = m_frames.last();
+ // This is only going to help us if the new frame is reconnected. Otherwise bail out.
+ if ( !lastFrame || lastFrame->newFrameBehavior() != KWFrame::Reconnect ) {
+ kdDebug(32002) << name() << " : frame is AutoCreateNewFrame but not Reconnect !?!? Aborting." << endl;
+ m_textobj->setLastFormattedParag( 0 );
+ return true; // abort
+ }
+
+//#ifdef DEBUG_FORMAT_MORE
+ kdDebug(32002) << "createNewPageAndNewFrame creating new frame in frameset " << name() << endl;
+//#endif
+ uint oldCount = m_frames.count();
+ int lastPageNumber = m_doc->pageManager()->lastPageNumber();
+ kdDebug(32002) << " last frame=" << lastFrame << " pagenum=" << lastFrame->pageNumber() << " lastPageNumber=" << lastPageNumber << " m_frames count=" << oldCount << endl;
+
+ // First create a new page for it if necessary
+ if ( lastFrame->pageNumber() == lastPageNumber )
+ {
+ // Let's first check if it will give us more space than we
+ // already have left in this page. Otherwise we'll loop infinitely.
+
+ int heightWeWillGet = 0; // in LU
+ if(isMainFrameset()) // is never added in the framesToCopyOnNewPage
+ heightWeWillGet += m_doc->ptToLayoutUnitPixY( m_frames.last()->height() );
+ else {
+ QPtrList<KWFrame> framesToCopy = m_doc->framesToCopyOnNewPage( lastPageNumber );
+ QPtrListIterator<KWFrame> frameIt( framesToCopy );
+ for ( ; frameIt.current(); ++frameIt )
+ if (frameIt.current()->frameSet() == this &&
+ frameIt.current()->newFrameBehavior()==KWFrame::Reconnect)
+ heightWeWillGet += m_doc->ptToLayoutUnitPixY( frameIt.current()->height() );
+ }
+
+ // This logic doesn't applies to tables though, since they can be broken over multiple pages
+ // TODO: lastFormatted->containsTable() or so (containsPageBreakableItem rather).
+
+ // "difference" doesn't apply if we're pasting multiple paragraphs.
+ // We want to compare the height of one paragraph, not all the missing height.
+ KoTextParag* parag = lastFormatted ? lastFormatted : textDocument()->lastParag();
+ // In fact the parag height isn't the right thing to test for - we should check
+ // for the highest character that remains to be positioned.
+ // Testcase: many big inline pictures in one paragraph.
+ int paragHeight = parag->rect().height();
+ kdDebug(32002) << "height we will get in the new page:" << heightWeWillGet << " parag " << parag << " height:" << paragHeight << endl;
+ if ( heightWeWillGet < paragHeight && !m_groupmanager )
+ {
+ kdDebug(32002) << "not enough height on the new page, not worth it" << endl;
+ m_textobj->setLastFormattedParag( 0 );
+ return true; // abort
+ }
+
+ KWPage *page = m_doc->appendPage();
+ if ( !m_doc->isLoading() )
+ m_doc->afterInsertPage( page->pageNumber() );
+ kdDebug(32002) << "now frames count=" << m_frames.count() << endl;
+ }
+
+ // Maybe creating the new page created the frame in this frameset, then we're done
+ // Otherwise let's create it ourselves:
+ if ( m_frames.count() == oldCount )
+ {
+ Q_ASSERT( !isMainFrameset() ); // ouch, should have gone to the appendPage case above...
+ // Otherwise, create a new frame on next page
+ kdDebug(32002) << "createNewPageAndNewFrame creating frame on page " << lastFrame->pageNumber()+1 << endl;
+ KWFrame *frm = lastFrame->getCopy();
+ frm->moveBy( 0, m_doc->pageManager()->page(frm)->height() );
+ addFrame( frm );
+ }
+
+ updateFrames();
+ Q_ASSERT(frame(0) && frame(0)->frameStack());
+ frame(0)->frameStack()->update();
+ /// We don't want to start from the beginning every time !
+ ////m_doc->invalidate();
+
+ // Reformat the last paragraph. If it's over the two pages, it will need
+ // the new page (e.g. for inline frames that need internalToDocument to work)
+ if ( lastFormatted )
+ lastFormatted = lastFormatted->prev();
+ else
+ lastFormatted = textDocument()->lastParag();
+
+ if ( lastFormatted )
+ {
+ m_textobj->setLastFormattedParag( lastFormatted );
+ lastFormatted->invalidate( 0 );
+ //This was a way to format the rest from here (recursively), but it didn't help much ensureCursorVisible()
+ //So instead I fixed formatMore to return formatMore(2) itself.
+ //m_textobj->formatMore( 2 );
+ return false; // keep going
+ }
+ m_doc->delayedRepaintAllViews();
+ return false; // all done
+}
+
+double KWTextFrameSet::footNoteSize( KWFrame *theFrame )
+{
+ double tmp =0.0;
+ int page = theFrame->pageNumber();
+ QPtrListIterator<KWFrameSet> fit = m_doc->framesetsIterator();
+ for ( ; fit.current() ; ++fit )
+ {
+ if((fit.current()->isFootNote() || fit.current()->isEndNote()) &&
+ fit.current()->isVisible())
+ {
+ KWFrame * frm=fit.current()->frame( 0 );
+ if(frm->pageNumber()==page )
+ tmp += frm->innerHeight()+m_doc->ptFootnoteBodySpacing();
+ }
+ }
+ return tmp;
+}
+
+
+double KWTextFrameSet::footerHeaderSizeMax( KWFrame *theFrame )
+{
+ KWPage *page = m_doc->pageManager()->page(theFrame);
+ Q_ASSERT( page );
+ if ( !page )
+ return 0;
+ double tmp = page->height() - page->bottomMargin() - page->topMargin() - 40;//default min 40 for page size
+ bool header=theFrame->frameSet()->isAHeader();
+ if( header ? m_doc->isHeaderVisible():m_doc->isFooterVisible() )
+ {
+ QPtrListIterator<KWFrameSet> fit = m_doc->framesetsIterator();
+ for ( ; fit.current() ; ++fit )
+ {
+ bool state = header ? fit.current()->isAFooter():fit.current()->isAHeader();
+ if(fit.current()->isVisible() && state)
+ {
+ KWFrame * frm=fit.current()->frame( 0 );
+ if(frm->pageNumber()==page->pageNumber() )
+ {
+ return (tmp-frm->innerHeight()-footNoteSize( theFrame ));
+ }
+ }
+ }
+ }
+ if (theFrame->frameSet()->isHeaderOrFooter())
+ return (tmp-footNoteSize( theFrame ));
+
+ return tmp;
+}
+
+void KWTextFrameSet::frameResized( KWFrame *theFrame, bool invalidateLayout )
+{
+ kdDebug(32002) << "KWTextFrameSet::frameResized " << theFrame << " " << *theFrame << " invalidateLayout=" << invalidateLayout << endl;
+ if ( theFrame->height() < 0 )
+ return; // safety!
+
+ KWFrameSet * fs = theFrame->frameSet();
+ Q_ASSERT( fs == this );
+ fs->updateFrames(); // update e.g. available height
+ Q_ASSERT(frame(0) && frame(0)->frameStack());
+ frame(0)->frameStack()->update();
+
+ theFrame->updateRulerHandles();
+
+ // Do a full KWFrameLayout if this will have influence on other frames, i.e.:
+ // * if we resized the last main text frame (the one before the first endnote)
+ // * if we resized an endnote
+ // Delay it though, to get the full height first.
+ if ( fs->isMainFrameset() || fs->isEndNote() )
+ m_doc->delayedRecalcFrames( theFrame->pageNumber() );
+ // * if we resized a header, footer, or footnote
+ else if ( fs->frameSetInfo() != KWFrameSet::FI_BODY )
+ m_doc->recalcFrames( theFrame->pageNumber(), -1 ); // warning this can delete theFrame!
+
+ // m_doc->frameChanged( theFrame );
+ // Warning, can't call layout() (frameChanged calls it)
+ // from here, since it calls formatMore() !
+ if ( invalidateLayout )
+ m_doc->invalidate(this);
+
+ // Can't repaint directly, we might be in a paint event already
+ m_doc->delayedRepaintAllViews();
+}
+
+bool KWTextFrameSet::isFrameEmpty( KWFrame * theFrame )
+{
+ KoTextParag * lastParag = textDocument()->lastParag();
+ // The problem is that if we format things here, and don't emit afterFormatting,
+ // we won't resize autoresize frames properly etc. (e.g. endnotes)
+ // Testcase for this problem: werner's footnote-1.doc
+ //ensureFormatted( lastParag, false ); // maybe true here would do too? slow if maintextframeset though.
+ if ( !lastParag->isValid() )
+ return false; // we don't know yet
+ int bottom = lastParag->rect().top() + lastParag->rect().height();
+
+ if ( theFrame->frameSet() == this ) // safety check
+ {
+ kdDebug() << "KWTextFrameSet::isFrameEmpty text bottom=(LU) " << bottom << " theFrame=" << theFrame << " " << *theFrame << " its internalY(LU)=" << m_doc->ptToLayoutUnitPixY( theFrame->internalY() ) << endl;
+ return bottom < m_doc->ptToLayoutUnitPixY( theFrame->internalY() );
+ }
+
+ kdWarning() << "KWTextFrameSet::isFrameEmpty called for frame " << theFrame << " which isn't a child of ours!" << endl;
+ if ( theFrame->frameSet()!=0L && theFrame->frameSet()->name()!=0L)
+ kdDebug() << "(this is " << name() << " and the frame belongs to " << theFrame->frameSet()->name() << ")" << endl;
+ return false;
+}
+
+bool KWTextFrameSet::canRemovePage( int num )
+{
+ kdDebug() << "KWTextFrameSet(" << name() << ")::canRemovePage " << num << endl;
+
+ // No frame on that page ? ok for us then
+ if ( num < m_firstPage || num >= (int)m_framesInPage.size() + m_firstPage ) {
+ kdDebug() << "No frame on that page. Number of frames: " << frameCount() << endl;
+ return true;
+ }
+
+ QPtrListIterator<KWFrame> frameIt( framesInPage( num ) );
+ for ( ; frameIt.current(); ++frameIt )
+ {
+ KWFrame * theFrame = frameIt.current();
+ kdDebug() << "canRemovePage: looking at " << theFrame << " pageNum=" << theFrame->pageNumber() << endl;
+ Q_ASSERT( theFrame->pageNumber() == num );
+ Q_ASSERT( theFrame->frameSet() == this );
+ bool isEmpty = isFrameEmpty( theFrame );
+ kdDebug() << "KWTextFrameSet(" << name() << ")::canRemovePage"
+ << " found a frame on page " << num << " empty:" << isEmpty << endl;
+ // Ok, so we have a frame on that page -> we can't remove it unless it's a copied frame OR it's empty
+ bool isCopy = theFrame->isCopy() && frameIt.current() != m_frames.first();
+ if ( !isCopy && !isEmpty )
+ return false;
+ }
+ return true;
+}
+
+void KWTextFrameSet::deleteFrame( unsigned int num, bool remove, bool recalc )
+{
+ KWFrame *frm = m_frames.at( num );
+ kdDebug() << "KWTextFrameSet(" << name() << ")::deleteFrame " << frm << " (" << num << ")" << endl;
+ if ( frm )
+ emit frameDeleted( frm );
+ KWFrameSet::deleteFrame( num, remove, recalc );
+}
+
+void KWTextFrameSet::updateViewArea( QWidget * w, KWViewMode* viewMode, const QPoint & nPointBottom )
+{
+ if (!isVisible(viewMode))
+ return;
+ int ah = availableHeight(); // make sure that it's not -1
+#ifdef DEBUG_VIEWAREA
+ kdDebug(32002) << "KWTextFrameSet::updateViewArea " << (void*)w << " " << w->name()
+ << " nPointBottom=" << nPointBottom.x() << "," << nPointBottom.y()
+ << " availHeight=" << ah << " textDocument()->height()=" << textDocument()->height() << endl;
+#endif
+
+ // Find last page that is visible
+ int maxPage = m_doc->pageManager()->pageNumber(m_doc->unzoomItY( nPointBottom.y() ));
+ int maxY = 0;
+ if ( maxPage < m_firstPage || maxPage >= (int)m_framesInPage.size() + m_firstPage )
+ maxY = ah;
+ else
+ {
+ // Find frames on that page, and keep the max bottom, in internal coordinates
+ QPtrListIterator<KWFrame> frameIt( framesInPage( maxPage ) );
+ for ( ; frameIt.current(); ++frameIt )
+ {
+ maxY = QMAX( maxY, m_doc->ptToLayoutUnitPixY( frameIt.current()->internalY() + frameIt.current()->innerHeight() ) );
+ }
+ }
+#ifdef DEBUG_VIEWAREA
+ kdDebug(32002) << "KWTextFrameSet (" << name() << ")::updateViewArea maxY now " << maxY << endl;
+#endif
+ m_textobj->setViewArea( w, maxY );
+ m_textobj->formatMore( 2 );
+}
+
+KCommand * KWTextFrameSet::setPageBreakingCommand( KoTextCursor * cursor, int pageBreaking )
+{
+ if ( !textDocument()->hasSelection( KoTextDocument::Standard ) &&
+ static_cast<KWTextParag *>(cursor->parag())->pageBreaking() == pageBreaking )
+ return 0L; // No change needed.
+
+ m_textobj->emitHideCursor();
+
+ m_textobj->storeParagUndoRedoInfo( cursor );
+
+ if ( !textDocument()->hasSelection( KoTextDocument::Standard ) ) {
+ KWTextParag *parag = static_cast<KWTextParag *>( cursor->parag() );
+ parag->setPageBreaking( pageBreaking );
+ m_textobj->setLastFormattedParag( cursor->parag() );
+ }
+ else
+ {
+ KoTextParag *start = textDocument()->selectionStart( KoTextDocument::Standard );
+ KoTextParag *end = textDocument()->selectionEnd( KoTextDocument::Standard );
+ m_textobj->setLastFormattedParag( start );
+ for ( ; start && start != end->next() ; start = start->next() )
+ static_cast<KWTextParag *>(start)->setPageBreaking( pageBreaking );
+ }
+
+ m_textobj->formatMore( 2 );
+ emit repaintChanged( this );
+ KoTextObject::UndoRedoInfo & undoRedoInfo = m_textobj->undoRedoInfoStruct();
+ undoRedoInfo.newParagLayout.pageBreaking = pageBreaking;
+ KoTextParagCommand *cmd = new KoTextParagCommand(
+ textDocument(), undoRedoInfo.id, undoRedoInfo.eid,
+ undoRedoInfo.oldParagLayouts, undoRedoInfo.newParagLayout,
+ KoParagLayout::PageBreaking );
+ textDocument()->addCommand( cmd );
+ undoRedoInfo.clear();
+ m_textobj->emitShowCursor();
+ m_textobj->emitUpdateUI( true );
+ m_textobj->emitEnsureCursorVisible();
+ // ## find a better name for the command
+ return new KoTextCommand( m_textobj, /*cmd, */i18n("Change Paragraph Attribute") );
+}
+
+KCommand * KWTextFrameSet::pasteOasis( KoTextCursor * cursor, const QByteArray & data, bool removeSelected )
+{
+ if (protectContent() )
+ return 0;
+
+ kdDebug(32001) << "KWTextFrameSet::pasteOasis data:" << data.size() << " bytes" << endl;
+ KMacroCommand * macroCmd = new KMacroCommand( i18n("Paste") );
+ if ( removeSelected && textDocument()->hasSelection( KoTextDocument::Standard ) )
+ macroCmd->addCommand( m_textobj->removeSelectedTextCommand( cursor, KoTextDocument::Standard ) );
+ m_textobj->emitHideCursor();
+ m_textobj->setLastFormattedParag( cursor->parag()->prev() ?
+ cursor->parag()->prev() : cursor->parag() );
+
+ KWOasisPasteCommand * cmd = new KWOasisPasteCommand( textDocument(), cursor->parag()->paragId(), cursor->index(), data );
+ textDocument()->addCommand( cmd );
+
+ macroCmd->addCommand( new KoTextCommand( m_textobj, /*cmd, */QString::null ) );
+
+ *cursor = *( cmd->execute( cursor ) );
+
+ // not enough when pasting many pages. We need the cursor's parag to be formatted.
+ //m_textobj->formatMore( 2 );
+ ensureFormatted( cursor->parag() );
+
+ emit repaintChanged( this );
+ m_textobj->emitEnsureCursorVisible();
+ m_textobj->emitUpdateUI( true );
+ m_textobj->emitShowCursor();
+ m_textobj->selectionChangedNotify();
+ return macroCmd;
+}
+
+void KWTextFrameSet::insertTOC( KoTextCursor * cursor )
+{
+ m_textobj->emitHideCursor();
+ KMacroCommand * macroCmd = new KMacroCommand( i18n("Insert Table of Contents") );
+
+ // Remove old TOC
+
+ KoTextCursor *cur= KWInsertTOCCommand::removeTOC( this, cursor, macroCmd );
+
+ // Insert new TOC
+
+ KoTextDocCommand * cmd = new KWInsertTOCCommand( this,cur ? cur->parag(): cursor->parag() );
+ textDocument()->addCommand( cmd );
+ macroCmd->addCommand( new KoTextCommand( m_textobj, QString::null ) );
+ *cursor = *( cmd->execute( cursor ) );
+
+ m_textobj->setLastFormattedParag( textDocument()->firstParag() );
+ m_textobj->formatMore( 2 );
+ emit repaintChanged( this );
+ m_textobj->emitEnsureCursorVisible();
+ m_textobj->emitUpdateUI( true );
+ m_textobj->emitShowCursor();
+
+ m_doc->addCommand( macroCmd );
+}
+
+KNamedCommand* KWTextFrameSet::insertFrameBreakCommand( KoTextCursor *cursor )
+{
+ KMacroCommand* macroCmd = new KMacroCommand( QString::null );
+ macroCmd->addCommand( m_textobj->insertParagraphCommand( cursor ) );
+ KWTextParag *parag = static_cast<KWTextParag *>( cursor->parag() );
+ if(parag->prev()) {
+ parag=static_cast<KWTextParag *> (parag->prev());
+ cursor->setParag( parag );
+ cursor->setIndex( parag->length() - 1 );
+ }
+ macroCmd->addCommand( setPageBreakingCommand( cursor, parag->pageBreaking() | KoParagLayout::HardFrameBreakAfter ) );
+ Q_ASSERT( parag->next() );
+ if ( parag->next() ) {
+ cursor->setParag( parag->next() );
+ cursor->setIndex( 0 );
+ }
+ return macroCmd;
+}
+
+void KWTextFrameSet::insertFrameBreak( KoTextCursor *cursor )
+{
+ clearUndoRedoInfo();
+ m_textobj->emitHideCursor();
+ KNamedCommand* cmd = insertFrameBreakCommand( cursor );
+ cmd->setName( i18n( "Insert Break After Paragraph" ) );
+ m_doc->addCommand( cmd );
+
+ m_textobj->setLastFormattedParag( cursor->parag() );
+ m_textobj->formatMore( 2 );
+ emit repaintChanged( this );
+ m_textobj->emitEnsureCursorVisible();
+ m_textobj->emitUpdateUI( true );
+ m_textobj->emitShowCursor();
+}
+
+QRect KWTextFrameSet::paragRect( KoTextParag * parag ) const
+{
+ // ## Warning. Imagine a paragraph cut in two pieces (at the line-level),
+ // between two columns. A single rect in internal coords, but two rects in
+ // normal coords. QRect( topLeft, bottomRight ) is just plain wrong.
+ // Currently this method is only used for "ensure visible" so that's fine, but
+ // we shouldn't use it for more precise stuff.
+ KoPoint p;
+ (void)internalToDocument( parag->rect().topLeft(), p );
+ QPoint topLeft = m_doc->zoomPoint( p );
+ (void)internalToDocument( parag->rect().bottomRight(), p );
+ QPoint bottomRight = m_doc->zoomPoint( p );
+ return QRect( topLeft, bottomRight );
+}
+
+void KWTextFrameSet::findPosition( const KoPoint &dPoint, KoTextParag * & parag, int & index )
+{
+ KoTextCursor cursor( textDocument() );
+
+ QPoint iPoint;
+ if ( documentToInternal( dPoint, iPoint ) )
+ {
+ cursor.place( iPoint, textDocument()->firstParag() );
+ parag = cursor.parag();
+ index = cursor.index();
+ }
+ else
+ {
+ // Not found, maybe under everything ?
+ parag = textDocument()->lastParag();
+ if ( parag )
+ index = parag->length() - 1;
+ }
+}
+
+bool KWTextFrameSet::minMaxInternalOnPage( int pageNum, int& topLU, int& bottomLU ) const
+{
+ QPtrListIterator<KWFrame> frameIt( framesInPage( pageNum ) );
+ if ( !frameIt.current() )
+ return false;
+
+ // Look at all frames in the page, and keep min and max "internalY" positions
+ double topPt = frameIt.current()->internalY();
+ double bottomPt = topPt + frameIt.current()->height();
+
+ for ( ; frameIt.current(); ++frameIt )
+ {
+ double y = frameIt.current()->internalY();
+ topPt = QMIN( topPt, y );
+ bottomPt = QMAX( bottomPt, y + frameIt.current()->height() );
+ }
+ // Convert to layout units
+ topLU = m_doc->ptToLayoutUnitPixY( topPt );
+ bottomLU = m_doc->ptToLayoutUnitPixY( bottomPt );
+ return true;
+}
+
+KoTextParag* KWTextFrameSet::paragAtLUPos( int yLU ) const
+{
+ KoTextParag* parag = textDocument()->firstParag();
+ for ( ; parag ; parag = parag->next() )
+ {
+ if ( parag->rect().bottom() >= yLU )
+ return parag;
+ }
+ return 0L;
+}
+
+KCommand * KWTextFrameSet::deleteAnchoredFrame( KWAnchor * anchor )
+{
+ kdDebug() << "KWTextFrameSet::deleteAnchoredFrame anchor->index=" << anchor->index() << endl;
+ Q_ASSERT( anchor );
+ KoTextCursor c( textDocument() );
+ c.setParag( anchor->paragraph() );
+ c.setIndex( anchor->index() );
+
+ textDocument()->setSelectionStart( KoTextDocument::Temp, &c );
+ c.setIndex( anchor->index() + 1 );
+ textDocument()->setSelectionEnd( KoTextDocument::Temp, &c );
+ KCommand *cmd = m_textobj->removeSelectedTextCommand( &c, KoTextDocument::Temp );
+
+ m_doc->repaintAllViews();
+ return cmd;
+}
+
+bool KWTextFrameSet::hasSelection() const
+{
+ return m_textobj->hasSelection();
+}
+
+QString KWTextFrameSet::selectedText() const
+{
+ return m_textobj->selectedText();
+}
+
+QString KWTextFrameSet::toPlainText() const
+{
+ return m_textobj->textDocument()->plainText();
+}
+
+void KWTextFrameSet::highlightPortion( KoTextParag * parag, int index, int length, KWCanvas * canvas, bool repaint, KDialogBase* dialog )
+{
+ Q_ASSERT( isVisible() );
+ Q_ASSERT( m_textobj->isVisible() );
+ //kdDebug() << "highlighting in " << name() << " parag=" << parag->paragId() << " index=" << index << " repaint=" << repaint << endl;
+ m_textobj->highlightPortion( parag, index, length, repaint );
+ if ( repaint ) {
+ // Position the cursor
+ canvas->editTextFrameSet( this, parag, index );
+ // Ensure text is fully visible
+ QRect expose = canvas->viewMode()->normalToView( paragRect( parag ) );
+ canvas->ensureVisible( (expose.left()+expose.right()) / 2, // point = center of the rect
+ (expose.top()+expose.bottom()) / 2,
+ (expose.right()-expose.left()) / 2, // margin = half-width of the rect
+ (expose.bottom()-expose.top()) / 2);
+ if ( dialog ) {
+ //kdDebug() << k_funcinfo << " dialog=" << dialog << " avoiding rect=" << expose << endl;
+ QRect globalRect( expose );
+ globalRect.moveTopLeft( canvas->mapToGlobal( globalRect.topLeft() ) );
+ KDialog::avoidArea( dialog, globalRect );
+ }
+ }
+}
+
+void KWTextFrameSet::removeHighlight( bool repaint )
+{
+ m_textobj->removeHighlight( repaint );
+}
+
+void KWTextFrameSet::clearUndoRedoInfo()
+{
+ m_textobj->clearUndoRedoInfo();
+}
+
+void KWTextFrameSet::applyStyleChange( KoStyleChangeDefMap changed )
+{
+ m_textobj->applyStyleChange( changed );
+}
+
+// KoTextFormatInterface methods
+KoTextFormat *KWTextFrameSet::currentFormat() const
+{
+ return m_textobj->currentFormat();
+}
+
+KCommand *KWTextFrameSet::setChangeCaseOfTextCommand(KoChangeCaseDia::TypeOfCase _type)
+{
+ KoTextDocument *textdoc = m_textobj->textDocument();
+ textdoc->selectAll( KoTextDocument::Standard );
+ KoTextCursor *cursor = new KoTextCursor( textDocument() );
+ KCommand* cmd = m_textobj->changeCaseOfText(cursor, _type);
+ textdoc->removeSelection( KoTextDocument::Standard );
+ delete cursor;
+ return cmd;
+}
+
+
+KCommand *KWTextFrameSet::setFormatCommand( const KoTextFormat * newFormat, int flags, bool zoomFont )
+{
+ m_textobj->textDocument()->selectAll( KoTextDocument::Temp );
+ KCommand *cmd = m_textobj->setFormatCommand( 0L, 0L, newFormat, flags, zoomFont, KoTextDocument::Temp );
+ m_textobj->textDocument()->removeSelection( KoTextDocument::Temp );
+ return cmd;
+}
+
+const KoParagLayout * KWTextFrameSet::currentParagLayoutFormat() const
+{
+ return m_textobj->currentParagLayoutFormat();
+}
+
+bool KWTextFrameSet::rtl() const
+{
+ return m_textobj->rtl();
+}
+
+
+KCommand *KWTextFrameSet::setParagLayoutFormatCommand( KoParagLayout *newLayout,int flags, int marginIndex)
+{
+ return m_textobj->setParagLayoutFormatCommand(newLayout, flags, marginIndex);
+}
+
+class KWFootNoteVarList : public QPtrList< KWFootNoteVariable >
+{
+protected:
+ virtual int compareItems(QPtrCollection::Item a, QPtrCollection::Item b)
+ {
+ KWFootNoteVariable* vara = ((KWFootNoteVariable *)a);
+ KWFootNoteVariable* varb = ((KWFootNoteVariable *)b);
+ if ( vara->paragraph() == varb->paragraph() ) {
+ // index() is a bit slow. But this is only called when there are
+ // two footnotes in the same paragraph.
+ int indexa = vara->index();
+ int indexb = varb->index();
+ return indexa < indexb ? -1 : indexa == indexb ? 0 : 1;
+ }
+ if ( vara->paragraph()->paragId() < varb->paragraph()->paragId() )
+ return -1;
+ return 1;
+ }
+};
+
+void KWTextFrameSet::renumberFootNotes( bool repaint )
+{
+ KWFootNoteVarList lst;
+ QPtrListIterator<KoTextCustomItem> cit( textDocument()->allCustomItems() );
+ for ( ; cit.current() ; ++cit )
+ {
+ KWFootNoteVariable *fnv = dynamic_cast<KWFootNoteVariable *>( cit.current() );
+ if (fnv && !fnv->isDeleted() && (fnv->frameSet() && !fnv->frameSet()->isDeleted()))
+ lst.append( fnv );
+ }
+ lst.sort();
+ short int footNoteVarNumber = 0; // absolute order number [internal, not saved nor displayed]
+ short int endNoteVarNumber = 0;
+ short int footNoteNumDisplay = 1; // the number being displayed
+ short int endNoteNumDisplay = 1;
+ bool needRepaint = false;
+ QPtrListIterator< KWFootNoteVariable > vit( lst );
+
+ //create a list with all manual footnotes numbers
+ QValueList<int> addedNums;
+ for ( ; vit.current() ; ++vit )
+ {
+ KWFootNoteVariable* var = vit.current();
+ if ( var->numberingType()==KWFootNoteVariable::Manual )
+ {
+ uint const num = var->text().toUInt();
+ if ( num != 0 )
+ addedNums.append( num );
+ }
+ }
+
+ for ( vit.toFirst() ; vit.current() ; )
+ {
+ KWFootNoteVariable* var = vit.current();
+ bool endNote = var->noteType() == EndNote;
+ short int & varNumber = endNote ? endNoteVarNumber : footNoteVarNumber;
+ short int & numDisplay = endNote ? endNoteNumDisplay : footNoteNumDisplay;
+ ++varNumber;
+ bool changed = false;
+ if ( varNumber != var->num() || var->numberingType()==KWFootNoteVariable::Manual )
+ {
+ changed = true;
+ var->setNum( varNumber );
+ }
+ if ( var->numberingType()==KWFootNoteVariable::Auto )
+ {
+ if ( addedNums.contains( numDisplay ) != 0 ) // the automatic generated number should not be equal to a manual one
+ {
+ numDisplay++;
+ continue; //try with the next number
+ }
+ if ( numDisplay != var->numDisplay() )
+ {
+ changed = true;
+ var->setNumDisplay( numDisplay );
+ }
+ numDisplay++;
+ }
+ if ( changed )
+ {
+ if ( var->frameSet() ) //safety
+ {
+ QString fsName = endNote ? i18n("Endnote %1") : i18n("Footnote %1");
+ if ( var->numberingType()== KWFootNoteVariable::Manual)
+ var->frameSet()->setName( m_doc->generateFramesetName(fsName));
+ else
+ var->frameSet()->setName( fsName.arg( var->text() ) );
+ var->frameSet()->setCounterText( var->text() );
+ }
+ var->resize();
+ var->paragraph()->invalidate(0);
+ var->paragraph()->setChanged( true );
+ needRepaint = true;
+ }
+ ++vit;
+ }
+ if ( needRepaint && repaint )
+ m_doc->slotRepaintChanged( this );
+}
+
+KoTextDocCommand *KWTextFrameSet::deleteTextCommand( KoTextDocument *textdoc, int id, int index, const QMemArray<KoTextStringChar> & str, const CustomItemsMap & customItemsMap, const QValueList<KoParagLayout> & oldParagLayouts )
+{
+ return new KWTextDeleteCommand( textdoc, id, index, str, customItemsMap, oldParagLayouts );
+}
+
+QByteArray KWTextFrameSet::sortText(SortType type) const
+{
+ const KoTextCursor c1 = textDocument()->selectionStartCursor(KoTextDocument::Standard );
+ const KoTextCursor c2 = textDocument()->selectionEndCursor( KoTextDocument::Standard );
+ if ( c1.parag() == c2.parag() )
+ return QByteArray();
+ else
+ {
+ // ( paragraph text -> paragraph ) map. Note that this sorts on the key automatically.
+ QMap<QString, const KoTextParag*> sortMap;
+ sortMap.insert( c1.parag()->toString(0), c1.parag() );
+
+ const KoTextParag *p = c1.parag()->next();
+ while ( p && p != c2.parag() ) {
+ sortMap.insert( p->toString(0), p );
+ p = p->next();
+ }
+ sortMap.insert( c2.parag()->toString(0), c2.parag());
+
+ typedef QValueList<const KoTextParag *> ParagList;
+ ParagList sortedParags = sortMap.values();
+ if ( type == KW_SORTDECREASE )
+ {
+ // I could use an STL algorithm here, but only if Qt was compiled with STL support...
+ ParagList newList;
+ for ( ParagList::const_iterator it = sortedParags.begin(),
+ end = sortedParags.end();
+ it != end ; ++it ) {
+ newList.prepend( *it );
+ }
+ sortedParags = newList;
+ }
+
+ KWOasisSaver oasisSaver( m_doc );
+ oasisSaver.saveParagraphs( sortedParags );
+ if ( !oasisSaver.finish() )
+ return QByteArray();
+ return oasisSaver.data();
+ }
+}
+
+// This is used when loading (KWTextDocument::loadOasisFootnote)
+// and when inserting from the GUI (KWTextFrameSetEdit::insertFootNote),
+// so don't add any 'repaint' or 'recalc' code here
+KWFootNoteFrameSet * KWTextFrameSet::insertFootNote( NoteType noteType, KWFootNoteVariable::Numbering numType, const QString &manualString )
+{
+ kdDebug() << "KWTextFrameSetEdit::insertFootNote " << endl;
+ KWDocument * doc = m_doc;
+ KWFootNoteVariable * var = new KWFootNoteVariable( textDocument(), doc->variableFormatCollection()->format( "NUMBER" ), doc->variableCollection(), doc );
+ var->setNoteType( noteType );
+ var->setNumberingType( numType );
+ if ( numType == KWFootNoteVariable::Manual )
+ var->setManualString( manualString );
+
+ // Now create text frameset which will hold the variable's contents
+ KWFootNoteFrameSet *fs = new KWFootNoteFrameSet( doc, i18n( "Footnotes" ) );
+ fs->setFrameSetInfo( KWFrameSet::FI_FOOTNOTE );
+
+ doc->addFrameSet( fs );
+
+ // Bind the footnote variable and its text frameset
+ var->setFrameSet( fs );
+ fs->setFootNoteVariable( var );
+
+ return fs;
+}
+
+KoVariable* KWTextFrameSet::variableUnderMouse( const KoPoint& dPoint )
+{
+ QPoint iPoint;
+ if ( documentToInternal( dPoint, iPoint ) )
+ return textObject()->variableAtPoint( iPoint );
+ return 0;
+}
+
+KoLinkVariable* KWTextFrameSet::linkVariableUnderMouse( const KoPoint& dPoint )
+{
+ QPoint iPoint;
+ if ( documentToInternal( dPoint, iPoint ) )
+ {
+ KoLinkVariable* linkVariable = dynamic_cast<KoLinkVariable *>( textObject()->variableAtPoint( iPoint ) );
+ return linkVariable;
+ }
+ return 0;
+}
+
+///////////////////////////////////////////////////////////////////////////////
+
+KWTextFrameSetEdit::KWTextFrameSetEdit( KWTextFrameSet * fs, KWCanvas * canvas )
+ : KoTextView( fs->textObject() ), KWFrameSetEdit( fs, canvas ), m_rtl( false )
+{
+ setBackSpeller( fs->kWordDocument()->backSpeller() );
+ //kdDebug(32001) << "KWTextFrameSetEdit::KWTextFrameSetEdit " << fs->name() << endl;
+ KoTextView::setReadWrite( fs->kWordDocument()->isReadWrite() );
+ KoTextObject* textobj = fs->textObject();
+ connect( textobj, SIGNAL( selectionChanged(bool) ), canvas, SIGNAL( selectionChanged(bool) ) );
+ connect( fs, SIGNAL( frameDeleted(KWFrame *) ), this, SLOT( slotFrameDeleted(KWFrame *) ) );
+ connect( textView(), SIGNAL( cut() ), SLOT( cut() ) );
+ connect( textView(), SIGNAL( copy() ), SLOT( copy() ) );
+ connect( textView(), SIGNAL( paste() ), SLOT( paste() ) );
+ updateUI( true, true );
+
+ if( canvas->gui() && canvas->gui()->getHorzRuler())
+ {
+ if ( !textobj->protectContent() )
+ canvas->gui()->getHorzRuler()->changeFlags(KoRuler::F_INDENTS | KoRuler::F_TABS);
+ else
+ canvas->gui()->getHorzRuler()->changeFlags(0);
+ }
+
+ setOverwriteMode( canvas->overwriteMode() );
+}
+
+KWTextFrameSetEdit::~KWTextFrameSetEdit()
+{
+ //kdDebug(32001) << "KWTextFrameSetEdit::~KWTextFrameSetEdit" << endl;
+ //m_canvas->gui()->getHorzRuler()->changeFlags(0);
+}
+
+KoTextViewIface* KWTextFrameSetEdit::dcopObject()
+{
+ if ( !dcop )
+ dcop = new KWordTextFrameSetEditIface( this );
+
+ return dcop;
+}
+
+void KWTextFrameSetEdit::terminate(bool removeSelection)
+{
+ disconnect( textView()->textObject(), SIGNAL( selectionChanged(bool) ), m_canvas, SIGNAL( selectionChanged(bool) ) );
+ textView()->terminate(removeSelection);
+}
+
+void KWTextFrameSetEdit::slotFrameDeleted( KWFrame *frm )
+{
+ if ( m_currentFrame == frm )
+ m_currentFrame = 0L;
+}
+
+void KWTextFrameSetEdit::paste()
+{
+ QMimeSource *data = QApplication::clipboard()->data();
+ int provides = KWView::checkClipboard( data );
+ pasteData( data, provides, false );
+}
+
+void KWTextFrameSetEdit::pasteData( QMimeSource* data, int provides, bool drop )
+{
+ if ( provides & KWView::ProvidesOasis )
+ {
+ KCommand* cmd = pasteOasisCommand( data );
+ if ( cmd )
+ frameSet()->kWordDocument()->addCommand(cmd);
+ }
+ else if ( provides & KWView::ProvidesPlainText )
+ {
+ // Note: QClipboard::text() seems to do a better job than encodedData( "text/plain" )
+ // In particular it handles charsets (in the mimetype).
+ const QString text = QApplication::clipboard()->text();
+ const bool removeSelected = !drop;
+ if ( !text.isEmpty() )
+ textObject()->pasteText( cursor(), text, currentFormat(), removeSelected );
+ }
+ else {
+ kdWarning(32002) << "Unhandled case in KWTextFrameSetEdit::pasteData: provides=" << provides << endl;
+ }
+ // be sure that the footnote number didn't got erased
+ KWFootNoteFrameSet *footNote = dynamic_cast<KWFootNoteFrameSet *>(textFrameSet());
+ if ( footNote )
+ {
+ KoParagCounter *counter = footNote->textDocument()->firstParag()->counter();
+ if ( !counter || ( counter->numbering() != KoParagCounter::NUM_FOOTNOTE ) )
+ footNote->setCounterText( footNote->footNoteVariable()->text() );
+ frameSet()->kWordDocument()->slotRepaintChanged( frameSet() );
+ }
+}
+
+KCommand* KWTextFrameSetEdit::pasteOasisCommand( QMimeSource* data )
+{
+ // Find which mimetype it was (could be oasis text, oasis presentation etc.)
+ QCString returnedTypeMime = KoTextObject::providesOasis( data );
+ if ( !returnedTypeMime.isEmpty() )
+ {
+ QByteArray arr = data->encodedData( returnedTypeMime );
+ Q_ASSERT( !arr.isEmpty() );
+ if ( arr.size() )
+ return textFrameSet()->pasteOasis( cursor(), arr, true );
+ }
+ return 0;
+}
+
+void KWTextFrameSetEdit::cut()
+{
+ if ( textDocument()->hasSelection( KoTextDocument::Standard ) ) {
+ copy();
+ textObject()->removeSelectedText( cursor() );
+ }
+}
+
+void KWTextFrameSetEdit::copy()
+{
+ if ( textDocument()->hasSelection( KoTextDocument::Standard ) ) {
+ QDragObject *drag = newDrag( 0 );
+ QApplication::clipboard()->setData( drag );
+ }
+}
+
+bool KWTextFrameSetEdit::doIgnoreDoubleSpace(KoTextParag * parag,
+ int index,QChar ch )
+{
+ if( textFrameSet()->kWordDocument()->allowAutoFormat())
+ {
+ KoAutoFormat * autoFormat = textFrameSet()->kWordDocument()->autoFormat();
+ if( autoFormat )
+ {
+ return autoFormat->doIgnoreDoubleSpace( parag, index,ch );
+ }
+ }
+ return false;
+
+}
+
+
+void KWTextFrameSetEdit::doAutoFormat( KoTextCursor* cursor, KoTextParag *parag, int index, QChar ch )
+{
+ if( textFrameSet()->kWordDocument()->allowAutoFormat() )
+ {
+ KoAutoFormat * autoFormat = textFrameSet()->kWordDocument()->autoFormat();
+ if( autoFormat )
+ autoFormat->doAutoFormat( cursor, parag, index, ch, textObject());
+ }
+}
+
+bool KWTextFrameSetEdit::doCompletion( KoTextCursor* cursor, KoTextParag *parag, int index )
+{
+ if( textFrameSet()->kWordDocument()->allowAutoFormat() )
+ {
+ KoAutoFormat * autoFormat = textFrameSet()->kWordDocument()->autoFormat();
+ if( autoFormat )
+ return autoFormat->doCompletion( cursor, parag, index, textObject());
+ }
+ return false;
+}
+
+bool KWTextFrameSetEdit::doToolTipCompletion( KoTextCursor* cursor, KoTextParag *parag, int index, int keyPressed )
+{
+ if( textFrameSet()->kWordDocument()->allowAutoFormat() )
+ {
+ KoAutoFormat * autoFormat = textFrameSet()->kWordDocument()->autoFormat();
+ if( autoFormat )
+ return autoFormat->doToolTipCompletion( cursor, parag, index, textObject(), keyPressed);
+ }
+ return false;
+}
+
+void KWTextFrameSetEdit::showToolTipBox(KoTextParag *parag, int index, QWidget *widget, const QPoint &pos)
+{
+ if( textFrameSet()->kWordDocument()->allowAutoFormat() )
+ {
+ KoAutoFormat * autoFormat = textFrameSet()->kWordDocument()->autoFormat();
+ if( autoFormat )
+ autoFormat->showToolTipBox(parag, index, widget, pos);
+ }
+}
+
+void KWTextFrameSetEdit::removeToolTipCompletion()
+{
+ if( textFrameSet()->kWordDocument()->allowAutoFormat() )
+ {
+ KoAutoFormat * autoFormat = textFrameSet()->kWordDocument()->autoFormat();
+ if( autoFormat )
+ autoFormat->removeToolTipCompletion();
+ }
+}
+
+void KWTextFrameSetEdit::textIncreaseIndent()
+{
+ kdDebug(32001) << "Increasing list" << endl;
+ m_canvas->gui()->getView()->textIncreaseIndent();
+}
+
+bool KWTextFrameSetEdit::textDecreaseIndent()
+{
+ if (currentLeftMargin()>0)
+ {
+ kdDebug(32001) << "Decreasing list" << endl;
+ m_canvas->gui()->getView()->textDecreaseIndent();
+ return true;
+ }
+ else
+ return false;
+}
+
+void KWTextFrameSetEdit::startDrag()
+{
+ textView()->dragStarted();
+ m_canvas->dragStarted();
+ QDragObject *drag = newDrag( m_canvas->viewport() );
+ if ( !frameSet()->kWordDocument()->isReadWrite() )
+ drag->dragCopy();
+ else {
+ bool move = ( drag->drag() );
+ if ( move )
+ {
+#if 0
+ if ( QDragObject::target() != m_canvas && QDragObject::target() != m_canvas->viewport() ) {
+ //This is when dropping text _out_ of KWord. Since we have Move and Copy
+ //options (Copy being accessed by pressing CTRL), both are possible.
+ //But is that intuitive enough ? Doesn't the user expect a Copy in all cases ?
+ //Losing the selected text when dropping out of kword seems quite unexpected to me.
+ //Undecided about this........
+ textObject()->removeSelectedText( cursor() );
+ }
+#endif
+ }
+ }
+}
+
+QDragObject * KWTextFrameSetEdit::newDrag( QWidget * parent )
+{
+ KWTextFrameSet* fs = textFrameSet();
+ return fs->kWordDocument()->dragSelected( parent, fs );
+}
+
+void KWTextFrameSetEdit::ensureCursorVisible()
+{
+ //kdDebug() << "KWTextFrameSetEdit::ensureCursorVisible paragId=" << cursor()->parag()->paragId() << " cursor->index()=" << cursor()->index() << endl;
+ KoTextParag * parag = cursor()->parag();
+ int idx = cursor()->index();
+ textFrameSet()->ensureFormatted( parag );
+ KoTextStringChar *chr = parag->at( idx );
+ int cursorHeight = parag->lineHeightOfChar( idx );
+ int x = parag->rect().x() + cursor()->x(); // this includes +charwidth for an RTL char
+ //kdDebug() << "parag->rect().x()=" << parag->rect().x() << " x=" << cursor()->x() << endl;
+ int y = 0; int dummy;
+ parag->lineHeightOfChar( idx, &dummy, &y );
+ y += parag->rect().y();
+ //kdDebug() << "KWTextFrameSetEdit::ensureCursorVisible y=" << y << endl;
+ // make sure one char is visible before, and one after
+ KoTextStringChar *chrLeft = idx > 0 ? chr-1 : chr;
+ // which char is on the left and which one is on the right depends on chr->rightToLeft
+ int areaLeft = chr->rightToLeft ? chr->width : chrLeft->width;
+ int areaRight = chr->rightToLeft ? chrLeft->width : chr->width;
+ KoPoint pt;
+ KoPoint hintDPoint;
+ if ( m_currentFrame )
+ hintDPoint = m_currentFrame->topLeft();
+ KWFrame * theFrame = textFrameSet()->internalToDocumentWithHint( QPoint(x, y), pt, hintDPoint );
+ //kdDebug() << "KWTextFrameSetEdit::ensureCursorVisible frame=" << theFrame << " m_currentFrame=" << m_currentFrame << endl;
+ if ( theFrame && m_currentFrame != theFrame )
+ {
+ m_currentFrame = theFrame;
+ m_canvas->gui()->getView()->updatePageInfo();
+ }
+ QPoint cursorPos = textFrameSet()->kWordDocument()->zoomPoint( pt );
+ cursorPos = m_canvas->viewMode()->normalToView( cursorPos );
+ areaLeft = textFrameSet()->kWordDocument()->layoutUnitToPixelX( areaLeft ) + 1;
+ areaRight = textFrameSet()->kWordDocument()->layoutUnitToPixelX( areaRight ) + 1;
+ cursorHeight = textFrameSet()->kWordDocument()->layoutUnitToPixelY( cursorHeight );
+ //kdDebug() << "KWTextFrameSetEdit::ensureCursorVisible pt=" << pt << " cursorPos=" << cursorPos
+ // << " areaLeft=" << areaLeft << " areaRight=" << areaRight << " y=" << y << endl;
+ m_canvas->ensureVisible( cursorPos.x() - areaLeft, cursorPos.y() + cursorHeight / 2, areaLeft + areaRight, cursorHeight / 2 + 2 );
+}
+
+bool KWTextFrameSetEdit::enterCustomItem( KoTextCustomItem* customItem, bool fromRight )
+{
+ KWAnchor* anchor = dynamic_cast<KWAnchor*>( customItem );
+ if ( anchor ) {
+ KWFrameSet* frameSet = anchor->frameSet();
+ if ( frameSet->type() == FT_FORMULA || frameSet->type() == FT_TEXT ) {
+
+ // store the instance variable we need after "delete this"
+ KWCanvas* canvas = m_canvas;
+
+ // this will "delete this"!
+ m_canvas->editFrameSet( frameSet );
+
+ // We assume that `editFrameSet' succeeded.
+ if ( fromRight ) {
+ KWFrameSetEdit* edit = canvas->currentFrameSetEdit();
+ if ( frameSet->type() == FT_FORMULA )
+ static_cast<KWFormulaFrameSetEdit*>( edit )->moveEnd();
+ else
+ static_cast<KWTextFrameSetEdit*>( edit )->moveCursor( MoveEnd );
+ }
+
+ if ( frameSet->type() == FT_FORMULA )
+ {
+ // A FormulaFrameSetEdit looks a little different from
+ // a FormulaFrameSet. (Colors)
+ static_cast<KWFormulaFrameSet*>( frameSet )->setChanged();
+ canvas->repaintChanged( frameSet, true );
+ }
+ return true;
+ }
+ }
+ return false;
+}
+
+void KWTextFrameSetEdit::keyPressEvent( QKeyEvent* e )
+{
+ // Handle moving into inline frames (e.g. formula frames).
+ if ( !( e->state() & ControlButton ) && !( e->state() & ShiftButton ) )
+ {
+ if (e->state() != Qt::NoButton)
+ removeToolTipCompletion();
+ switch ( e->key() ) {
+ case Key_Left: {
+ KoTextCursor* cursor = textView()->cursor();
+ KoTextParag* parag = cursor->parag();
+ int index = cursor->index();
+ if ( index > 0 ) {
+ KoTextStringChar* ch = parag->at( index-1 );
+ if ( ch->isCustom() ) {
+ KoTextCustomItem* customItem = ch->customItem();
+ if ( enterCustomItem( customItem, true ) ) {
+ // Don't do anything here, "this" is deleted!
+ return;
+ }
+ }
+ }
+ if ( index == 0 && !parag->prev() )
+ if ( exitLeft() )
+ return;
+ break;
+ }
+ case Key_Right: {
+ KoTextCursor* cursor = textView()->cursor();
+ KoTextParag* parag = cursor->parag();
+ int index = cursor->index();
+ if ( index < parag->length() - 1 ) {
+ KoTextStringChar* ch = parag->at( index );
+ if ( ch->isCustom() ) {
+ KoTextCustomItem* customItem = ch->customItem();
+ if ( enterCustomItem( customItem, false ) ) {
+ // Don't do anything here, "this" is deleted!
+ return;
+ }
+ }
+ } else if ( /*at end, covered by previous if, && */ !parag->next() )
+ if ( exitRight() )
+ return;
+ break;
+ }
+ }
+ }
+ // Calculate position of tooltip for autocompletion
+ QPoint pos = textFrameSet()->cursorPos( cursor(), m_canvas, m_currentFrame );
+ textView()->handleKeyPressEvent( e, m_canvas, pos );
+}
+
+void KWTextFrameSetEdit::keyReleaseEvent( QKeyEvent* e )
+{
+ textView()->handleKeyReleaseEvent( e );
+}
+
+void KWTextFrameSetEdit::imStartEvent( QIMEvent* e )
+{
+ textView()->handleImStartEvent( e );
+}
+
+void KWTextFrameSetEdit::imComposeEvent( QIMEvent* e )
+{
+ textView()->handleImComposeEvent( e );
+}
+
+void KWTextFrameSetEdit::imEndEvent( QIMEvent* e )
+{
+ textView()->handleImEndEvent( e );
+}
+
+void KWTextFrameSetEdit::mousePressEvent( QMouseEvent *e, const QPoint &, const KoPoint & dPoint )
+{
+ if ( dPoint.x() < 0 || dPoint.y() < 0 )
+ return; // Ignore clicks completely outside of the page (e.g. in the gray area, or ruler)
+
+ textFrameSet()->textObject()->clearUndoRedoInfo();
+ if ( m_currentFrame )
+ hideCursor(); // Need to do that with the old m_currentFrame
+
+ QPoint iPoint;
+ KWTextFrameSet::RelativePosition relPos;
+ KWFrame * theFrame = textFrameSet()->documentToInternalMouseSelection( dPoint, iPoint, relPos, m_canvas->viewMode() );
+ if ( theFrame && m_currentFrame != theFrame )
+ {
+ m_currentFrame = theFrame;
+ m_canvas->gui()->getView()->updatePageInfo();
+ }
+
+ if ( m_currentFrame )
+ {
+ // Let KoTextView handle the mousepress event - but don't let it start
+ // a drag if clicking on the left of the text (out of the frame itself)
+ bool addParag = textView()->handleMousePressEvent( e, iPoint, relPos != KWTextFrameSet::LeftOfFrame, frameSet()->kWordDocument()->insertDirectCursor() );
+
+
+ // Clicked on the left of the text -> select the whole paragraph
+ if ( relPos == KWTextFrameSet::LeftOfFrame )
+ textView()->selectParagUnderCursor( *textView()->cursor() );
+ if ( addParag )
+ frameSet()->kWordDocument()->setModified(true );
+ }
+ // else mightStartDrag = FALSE; necessary?
+
+ if ( e->button() != LeftButton )
+ return;
+ KoVariable* var = variable();
+ if ( var )
+ {
+ KWFootNoteVariable * footNoteVar = dynamic_cast<KWFootNoteVariable *>( var );
+ if ( footNoteVar )
+ {
+ footNoteVar->frameSet()->startEditing( m_canvas );
+ // --- and now we are deleted! ---
+ }
+ }
+}
+
+void KWTextFrameSetEdit::mouseMoveEvent( QMouseEvent * e, const QPoint & nPoint, const KoPoint & )
+{
+ if ( textView()->maybeStartDrag( e ) )
+ return;
+ if ( nPoint.x() < 0 || nPoint.y() < 0 )
+ return; // Ignore clicks completely outside of the page (e.g. in the gray area, or ruler)
+
+ QPoint iPoint;
+ KoPoint dPoint = frameSet()->kWordDocument()->unzoomPoint( nPoint );
+ KWTextFrameSet::RelativePosition relPos;
+ if ( nPoint.y() > 0 && textFrameSet()->documentToInternalMouseSelection( dPoint, iPoint, relPos , m_canvas->viewMode()) )
+ {
+ if ( relPos == KWTextFrameSet::LeftOfFrame )
+ textView()->extendParagraphSelection( iPoint );
+ else
+ textView()->handleMouseMoveEvent( e, iPoint );
+ }
+
+}
+
+bool KWTextFrameSetEdit::openLink( KoLinkVariable* variable )
+{
+ KWTextFrameSet* fs = textFrameSet();
+ KWDocument* doc = fs->kWordDocument();
+ if ( doc->variableCollection()->variableSetting()->displayLink() ) {
+
+ const QString url = variable->url();
+ if( url.startsWith("bkm://") )
+ {
+ const KoTextBookmark* bookmark = doc->bookmarkByName(url.mid(6) );
+ if ( bookmark )
+ {
+ cursor()->setParag( bookmark->startParag() );
+ ensureCursorVisible();
+ return true;
+ }
+ }
+ KoTextView::openLink( variable );
+ return true;
+ }
+ return false;
+}
+
+void KWTextFrameSetEdit::openLink()
+{
+ KoLinkVariable* v = linkVariable();
+ if ( v )
+ openLink( v );
+}
+
+void KWTextFrameSetEdit::mouseReleaseEvent( QMouseEvent *, const QPoint &, const KoPoint & )
+{
+ textView()->handleMouseReleaseEvent();
+}
+
+void KWTextFrameSetEdit::mouseDoubleClickEvent( QMouseEvent *e, const QPoint &, const KoPoint & )
+{
+ textView()->handleMouseDoubleClickEvent( e, QPoint() /* Currently unused */ );
+}
+
+void KWTextFrameSetEdit::dragEnterEvent( QDragEnterEvent * e )
+{
+ int provides = KWView::checkClipboard( e );
+ if ( !frameSet()->kWordDocument()->isReadWrite() || provides == 0 )
+ {
+ e->ignore();
+ return;
+ }
+ e->acceptAction();
+}
+
+void KWTextFrameSetEdit::dragMoveEvent( QDragMoveEvent * e, const QPoint &nPoint, const KoPoint & )
+{
+ int provides = KWView::checkClipboard( e );
+ if ( !frameSet()->kWordDocument()->isReadWrite() || provides == 0 )
+ {
+ e->ignore();
+ return;
+ }
+ // place cursor - unless dropping an image. well it's hard to know if the user
+ // wants the dropped image to be inline or absolute positioned.
+ if ( provides & ( KWView::ProvidesOasis | KWView::ProvidesPlainText | KWView::ProvidesFormula ) )
+ {
+ QPoint iPoint;
+ KoPoint dPoint = frameSet()->kWordDocument()->unzoomPoint( nPoint );
+ if ( textFrameSet()->documentToInternal( dPoint, iPoint ) )
+ {
+ textObject()->emitHideCursor();
+ placeCursor( iPoint );
+ textObject()->emitShowCursor();
+ }
+ }
+ e->acceptAction();
+}
+
+void KWTextFrameSetEdit::dragLeaveEvent( QDragLeaveEvent * )
+{
+}
+
+void KWTextFrameSetEdit::dropEvent( QDropEvent * e, const QPoint & nPoint, const KoPoint &, KWView* view )
+{
+ int provides = KWView::checkClipboard( e );
+ if ( frameSet()->kWordDocument()->isReadWrite() && provides )
+ {
+ e->acceptAction();
+ KoTextCursor dropCursor( textDocument() );
+ QPoint dropPoint;
+ KoPoint dPoint = frameSet()->kWordDocument()->unzoomPoint( nPoint );
+ if ( !textFrameSet()->documentToInternal( dPoint, dropPoint ) )
+ return; // Don't know where to paste
+
+ dropCursor.place( dropPoint, textDocument()->firstParag() );
+ kdDebug(32001) << "KWTextFrameSetEdit::dropEvent dropCursor at parag=" << dropCursor.parag()->paragId() << " index=" << dropCursor.index() << endl;
+
+ if ( ( e->source() == m_canvas ||
+ e->source() == m_canvas->viewport() ) &&
+ e->action() == QDropEvent::Move &&
+ // this is the indicator that the source and dest text objects are the same
+ textDocument()->hasSelection( KoTextDocument::Standard ) ) {
+
+ KCommand *cmd = textView()->prepareDropMove( dropCursor );
+ if(cmd)
+ {
+ KMacroCommand* macroCmd = new KMacroCommand( i18n( "Move Text" ) );
+ macroCmd->addCommand(cmd);
+
+ cmd = pasteOasisCommand( e );
+ if ( cmd )
+ macroCmd->addCommand(cmd);
+ //relayout textframeset after a dnd otherwise autoextend
+ //frameset is not re-layouted
+ textFrameSet()->layout();
+ frameSet()->kWordDocument()->addCommand( macroCmd );
+ }
+ return;
+ }
+ else
+ { // drop coming from outside -> forget about current selection
+ textDocument()->removeSelection( KoTextDocument::Standard );
+ textObject()->selectionChangedNotify();
+ }
+
+ // The cursor is already correctly positioned, all we need to do is to "paste" the dropped data.
+ view->pasteData( e, true );
+ }
+}
+
+void KWTextFrameSetEdit::focusInEvent()
+{
+ textView()->focusInEvent();
+}
+
+void KWTextFrameSetEdit::focusOutEvent()
+{
+ textView()->focusOutEvent();
+}
+
+void KWTextFrameSetEdit::selectAll()
+{
+ textObject()->selectAll( true );
+}
+
+void KWTextFrameSetEdit::drawCursor( bool visible )
+{
+#ifdef DEBUG_CURSOR
+ kdDebug() << "KWTextFrameSetEdit::drawCursor " << visible << endl;
+#endif
+ KoTextView::drawCursor( visible );
+ if ( !cursor()->parag() )
+ return;
+
+ if ( !cursor()->parag()->isValid() )
+ textFrameSet()->ensureFormatted( cursor()->parag() );
+
+ if ( !frameSet()->kWordDocument()->isReadWrite() )
+ return;
+ if ( m_canvas->viewMode()->hasFrames() && !m_currentFrame )
+ return;
+
+ QPainter p( m_canvas->viewport() );
+ p.translate( -m_canvas->contentsX(), -m_canvas->contentsY() );
+ p.setBrushOrigin( -m_canvas->contentsX(), -m_canvas->contentsY() );
+
+ textFrameSet()->drawCursor( &p, cursor(), visible, m_canvas, m_currentFrame );
+}
+
+bool KWTextFrameSetEdit::pgUpKeyPressed()
+{
+ QRect crect( m_canvas->contentsX(), m_canvas->contentsY(),
+ m_canvas->visibleWidth(), m_canvas->visibleHeight() );
+ crect = m_canvas->viewMode()->viewToNormal( crect );
+
+ // Go up of 90% of crect.height()
+ int h = frameSet()->kWordDocument()->pixelToLayoutUnitY( (int)( (double)crect.height() * 0.9 ) );
+ KoTextParag *s = textView()->cursor()->parag();
+ KoTextParag* oldParag = s;
+ int y = s->rect().y();
+ while ( s ) {
+ if ( y - s->rect().y() >= h )
+ break;
+ s = s->prev();
+ }
+
+ if ( !s )
+ s = textDocument()->firstParag();
+
+ textView()->cursor()->setParag( s );
+ textView()->cursor()->setIndex( 0 );
+ if ( s == oldParag )
+ {
+ m_canvas->viewportScroll( true );
+ return false;
+ }
+ return true;
+}
+
+bool KWTextFrameSetEdit::pgDownKeyPressed()
+{
+ QRect crect( m_canvas->contentsX(), m_canvas->contentsY(),
+ m_canvas->visibleWidth(), m_canvas->visibleHeight() );
+ crect = m_canvas->viewMode()->viewToNormal( crect );
+ // Go down of 90% of crect.height()
+ int h = frameSet()->kWordDocument()->pixelToLayoutUnitY( (int)( (double)crect.height() * 0.9 ) );
+
+ KoTextCursor *cursor = textView()->cursor();
+ KoTextParag *s = cursor->parag();
+ KoTextParag* oldParag = s;
+ int y = s->rect().y();
+ while ( s ) {
+ if ( s->rect().y() - y >= h )
+ break;
+ s = s->next();
+ }
+
+ if ( !s ) {
+ s = textDocument()->lastParag();
+ cursor->setParag( s );
+ cursor->setIndex( s->length() - 1 );
+ } else {
+ cursor->setParag( s );
+ cursor->setIndex( 0 );
+ }
+ if ( s == oldParag )
+ {
+ m_canvas->viewportScroll( false );
+ return false;
+ }
+ return true;
+}
+
+void KWTextFrameSetEdit::ctrlPgUpKeyPressed()
+{
+ if ( m_currentFrame )
+ {
+ QPoint iPoint = textFrameSet()->moveToPage( m_currentFrame->pageNumber(), -1 );
+ if ( !iPoint.isNull() )
+ placeCursor( iPoint );
+ }
+}
+
+void KWTextFrameSetEdit::ctrlPgDownKeyPressed()
+{
+ if ( m_currentFrame )
+ {
+ QPoint iPoint = textFrameSet()->moveToPage( m_currentFrame->pageNumber(), +1 );
+ if ( !iPoint.isNull() )
+ placeCursor( iPoint );
+ }
+}
+
+void KWTextFrameSetEdit::setCursor( KoTextParag* parag, int index )
+{
+ cursor()->setParag( parag );
+ cursor()->setIndex( index );
+}
+
+void KWTextFrameSetEdit::insertExpression(const QString &_c)
+{
+ if(textObject()->hasSelection() )
+ frameSet()->kWordDocument()->addCommand(textObject()->replaceSelectionCommand(
+ cursor(), _c, i18n("Insert Expression")));
+ else
+ textObject()->insert( cursor(), currentFormat(), _c, i18n("Insert Expression") );
+}
+
+void KWTextFrameSetEdit::insertFloatingFrameSet( KWFrameSet * fs, const QString & commandName )
+{
+ textObject()->clearUndoRedoInfo();
+ CustomItemsMap customItemsMap;
+ QString placeHolders;
+ // TODO support for multiple floating items (like multiple-page tables)
+ int frameNumber = 0;
+ int index = 0;
+ int insertFlags = KoTextObject::DoNotRemoveSelected;
+ { // the loop will start here :)
+ KWAnchor * anchor = fs->createAnchor( textFrameSet()->textDocument(), frameNumber );
+ if ( frameNumber == 0 && anchor->ownLine() && cursor()->index() > 0 ) // enforce start of line - currently unused
+ {
+ kdDebug() << "ownline -> prepending \\n" << endl;
+ placeHolders += QChar('\n');
+ index++;
+ insertFlags |= KoTextObject::CheckNewLine;
+ }
+ placeHolders += KoTextObject::customItemChar();
+ customItemsMap.insert( index, anchor );
+ }
+ fs->setAnchored( textFrameSet() );
+ textObject()->insert( cursor(), currentFormat(), placeHolders,
+ commandName, KoTextDocument::Standard, insertFlags,
+ customItemsMap );
+}
+
+void KWTextFrameSetEdit::insertLink(const QString &_linkName, const QString & hrefName)
+{
+ KWDocument * doc = frameSet()->kWordDocument();
+ KoVariable * var = new KoLinkVariable( textFrameSet()->textDocument(), _linkName, hrefName, doc->variableFormatCollection()->format( "STRING" ), doc->variableCollection() );
+ insertVariable( var );
+}
+
+void KWTextFrameSetEdit::insertComment(const QString &_comment)
+{
+ KWDocument * doc = frameSet()->kWordDocument();
+ KoVariable * var = new KoNoteVariable( textFrameSet()->textDocument(), _comment, doc->variableFormatCollection()->format( "STRING" ), doc->variableCollection() );
+ insertVariable( var );
+}
+
+
+void KWTextFrameSetEdit::insertCustomVariable( const QString &name)
+{
+ KWDocument * doc = frameSet()->kWordDocument();
+ KoVariable * var = new KoCustomVariable( textFrameSet()->textDocument(), name, doc->variableFormatCollection()->format( "STRING" ), doc->variableCollection());
+ insertVariable( var );
+}
+
+void KWTextFrameSetEdit::insertFootNote( NoteType noteType, KWFootNoteVariable::Numbering numType, const QString &manualString )
+{
+ KWFootNoteFrameSet *fs = textFrameSet()->insertFootNote( noteType, numType, manualString );
+ KWFootNoteVariable * var = fs->footNoteVariable();
+
+ // Place the frame on the correct page, but the exact coordinates
+ // will be determined by recalcFrames (KWFrameLayout)
+ int pageNum = m_currentFrame->pageNumber();
+ fs->createInitialFrame( pageNum );
+
+ insertVariable( var );
+
+ // Re-number footnote variables
+ textFrameSet()->renumberFootNotes();
+
+ // Layout the footnote frame
+ textFrameSet()->kWordDocument()->recalcFrames( pageNum, -1 ); // we know that for sure nothing changed before this page.
+
+ //KoTextParag* parag = fs->textDocument()->firstParag();
+ //parag->truncate(0); // why? we just created it, anyway...
+
+ // And now edit the footnote frameset - all WPs do that it seems.
+ fs->startEditing( m_canvas );
+ // --- and now we are deleted! ---
+}
+
+void KWTextFrameSetEdit::insertVariable( int type, int subtype )
+{
+ kdDebug() << "KWTextFrameSetEdit::insertVariable " << type << endl;
+ KWDocument * doc = frameSet()->kWordDocument();
+
+ KoVariable * var = 0L;
+ bool refreshCustomMenu = false;
+ if ( type == VT_CUSTOM )
+ {
+ KoCustomVarDialog dia( m_canvas );
+ if ( dia.exec() == QDialog::Accepted )
+ {
+ KoCustomVariable *v = new KoCustomVariable( textFrameSet()->textDocument(), dia.name(), doc->variableFormatCollection()->format( "STRING" ),doc->variableCollection() );
+ v->setValue( dia.value() );
+ var = v;
+ refreshCustomMenu = true;
+ }
+ }
+ else if ( type == VT_MAILMERGE )
+ {
+ KWMailMergeVariableInsertDia dia( m_canvas, doc->mailMergeDataBase() );
+ if ( dia.exec() == QDialog::Accepted )
+ {
+ var = new KWMailMergeVariable( textFrameSet()->textDocument(), dia.getName(), doc->variableFormatCollection()->format( "STRING" ),doc->variableCollection(),doc );
+ }
+ }
+ else
+ var = doc->variableCollection()->createVariable( type, subtype, doc->variableFormatCollection(), 0L, textFrameSet()->textDocument(), doc, 0);
+ if ( var)
+ insertVariable( var, 0L /*means currentFormat()*/, refreshCustomMenu);
+}
+
+void KWTextFrameSetEdit::insertVariable( KoVariable *var, KoTextFormat *format /*=0*/, bool refreshCustomMenu )
+{
+ if ( var )
+ {
+ CustomItemsMap customItemsMap;
+ customItemsMap.insert( 0, var );
+ if (!format)
+ format = currentFormat();
+ kdDebug() << "KWTextFrameSetEdit::insertVariable inserting into paragraph" << endl;
+#ifdef DEBUG_FORMATS
+ kdDebug() << "KWTextFrameSetEdit::insertVariable format=" << format << endl;
+#endif
+ textObject()->insert( cursor(), format, KoTextObject::customItemChar(),
+ i18n("Insert Variable"),
+ KoTextDocument::Standard,
+ KoTextObject::DoNotRemoveSelected,
+ customItemsMap );
+ frameSet()->kWordDocument()->slotRepaintChanged( frameSet() );
+ if ( var->type()==VT_CUSTOM && refreshCustomMenu)
+ frameSet()->kWordDocument()->refreshMenuCustomVariable();
+ }
+}
+
+void KWTextFrameSetEdit::insertWPPage()
+{
+ KWTextFrameSet* textfs = textFrameSet();
+ textfs->clearUndoRedoInfo();
+ KoTextObject* textobj = textObject();
+ KWDocument * doc = frameSet()->kWordDocument();
+ int pages = doc->pageCount();
+ int columns = doc->numColumns();
+ // There could be N columns. In that case we may need to add up to N framebreaks.
+ int inserted = 0;
+ KMacroCommand* macroCmd = new KMacroCommand( i18n("Insert Page") );
+ do {
+ macroCmd->addCommand( textfs->insertFrameBreakCommand( cursor() ) );
+ textobj->setLastFormattedParag( cursor()->parag() );
+ textobj->formatMore( 2 );
+ } while ( pages == doc->pageCount() && ++inserted <= columns );
+ if ( pages == doc->pageCount() )
+ kdWarning(32002) << k_funcinfo << " didn't manage to insert a new page! inserted=" << inserted << " columns=" << columns << " pages=" << pages << endl;
+
+ doc->addCommand( macroCmd );
+
+ textfs->slotRepaintChanged();
+ textobj->emitEnsureCursorVisible();
+ textobj->emitUpdateUI( true );
+ textobj->emitShowCursor();
+}
+
+KoBorder KWTextFrameSetEdit::border(KoBorder::BorderType type) {
+ if(type == KoBorder::LeftBorder)
+ return m_paragLayout.leftBorder;
+ if(type == KoBorder::RightBorder)
+ return m_paragLayout.rightBorder;
+ if(type == KoBorder::TopBorder)
+ return m_paragLayout.topBorder;
+ return m_paragLayout.bottomBorder;
+}
+
+// Update the GUI toolbar button etc. to reflect the current cursor position.
+void KWTextFrameSetEdit::updateUI( bool updateFormat, bool force )
+{
+ // Update UI - only for those items which have changed
+ KoTextView::updateUI( updateFormat, force );
+
+ // Paragraph settings
+ KWTextParag * parag = static_cast<KWTextParag *>(cursor()->parag());
+
+ if ( m_paragLayout.alignment != parag->resolveAlignment() || force ) {
+ m_paragLayout.alignment = parag->resolveAlignment();
+ m_canvas->gui()->getView()->showAlign( m_paragLayout.alignment );
+ }
+
+ // Counter
+ if ( !m_paragLayout.counter )
+ m_paragLayout.counter = new KoParagCounter; // we can afford to always have one here
+ KoParagCounter::Style cstyle = m_paragLayout.counter->style();
+ if ( parag->counter() )
+ *m_paragLayout.counter = *parag->counter();
+ else
+ {
+ m_paragLayout.counter->setNumbering( KoParagCounter::NUM_NONE );
+ m_paragLayout.counter->setStyle( KoParagCounter::STYLE_NONE );
+ }
+ if ( m_paragLayout.counter->style() != cstyle || force )
+ m_canvas->gui()->getView()->showCounter( * m_paragLayout.counter );
+
+ if(m_paragLayout.leftBorder!=parag->leftBorder() ||
+ m_paragLayout.rightBorder!=parag->rightBorder() ||
+ m_paragLayout.topBorder!=parag->topBorder() ||
+ m_paragLayout.bottomBorder!=parag->bottomBorder() || force )
+ {
+ m_paragLayout.leftBorder = parag->leftBorder();
+ m_paragLayout.rightBorder = parag->rightBorder();
+ m_paragLayout.topBorder = parag->topBorder();
+ m_paragLayout.bottomBorder = parag->bottomBorder();
+ m_canvas->gui()->getView()->updateBorderButtons( m_paragLayout.leftBorder, m_paragLayout.rightBorder, m_paragLayout.topBorder, m_paragLayout.bottomBorder );
+ }
+
+ if ( !parag->style() )
+ kdWarning() << "Paragraph " << parag->paragId() << " has no style" << endl;
+ else if ( m_paragLayout.style != parag->style() || force )
+ {
+ m_paragLayout.style = parag->style();
+ m_canvas->gui()->getView()->showStyle( m_paragLayout.style->name() );
+ }
+
+ if( m_paragLayout.margins[QStyleSheetItem::MarginLeft] != parag->margin(QStyleSheetItem::MarginLeft)
+ || m_paragLayout.margins[QStyleSheetItem::MarginFirstLine] != parag->margin(QStyleSheetItem::MarginFirstLine)
+ || m_paragLayout.margins[QStyleSheetItem::MarginRight] != parag->margin(QStyleSheetItem::MarginRight)
+ || parag->string()->isRightToLeft() != m_rtl
+ || force )
+ {
+ m_paragLayout.margins[QStyleSheetItem::MarginFirstLine] = parag->margin(QStyleSheetItem::MarginFirstLine);
+ m_paragLayout.margins[QStyleSheetItem::MarginLeft] = parag->margin(QStyleSheetItem::MarginLeft);
+ m_paragLayout.margins[QStyleSheetItem::MarginRight] = parag->margin(QStyleSheetItem::MarginRight);
+ if ( m_rtl != parag->string()->isRightToLeft() && parag->counter() )
+ {
+ parag->counter()->invalidate();
+ parag->setChanged( true ); // repaint
+ }
+ m_rtl = parag->string()->isRightToLeft();
+ m_canvas->gui()->getView()->showRulerIndent( m_paragLayout.margins[QStyleSheetItem::MarginLeft], m_paragLayout.margins[QStyleSheetItem::MarginFirstLine], m_paragLayout.margins[QStyleSheetItem::MarginRight], m_rtl );
+ }
+ if( m_paragLayout.tabList() != parag->tabList() || force)
+ {
+ m_paragLayout.setTabList( parag->tabList() );
+ KoRuler * hr = m_canvas->gui()->getHorzRuler();
+ if ( hr )
+ hr->setTabList( parag->tabList() );
+ }
+ if( m_paragLayout.lineSpacingType != parag->paragLayout().lineSpacingType || force)
+ {
+ m_paragLayout.lineSpacingType = parag->paragLayout().lineSpacingType;
+ m_canvas->gui()->getView()->showSpacing( m_paragLayout.lineSpacingType );
+ }
+ // There are more paragraph settings, but those that are not directly
+ // visible in the UI don't need to be handled here.
+ // For instance parag stuff, borders etc.
+}
+
+void KWTextFrameSetEdit::showFormat( KoTextFormat *format )
+{
+ m_canvas->gui()->getView()->showFormat( *format );
+}
+
+QPoint KWTextFrameSet::cursorPos( KoTextCursor *cursor, KWCanvas* canvas, KWFrame* currentFrame )
+{
+ KWViewMode *viewMode = canvas->viewMode();
+
+ KoTextParag* parag = cursor->parag();
+ const QPoint topLeft = parag->rect().topLeft(); // in QRT coords
+ int lineY;
+ parag->lineHeightOfChar( cursor->index(), 0, &lineY );
+ // iPoint is the topright corner of the current character
+ QPoint iPoint( topLeft.x() + cursor->x() + parag->at( cursor->index() )->width, topLeft.y() + lineY );
+
+ KoPoint dPoint;
+ QPoint vPoint;
+ KoPoint hintDPoint = currentFrame ? currentFrame->innerRect().topLeft() : KoPoint();
+ if ( internalToDocumentWithHint( iPoint, dPoint, hintDPoint ) )
+ {
+ vPoint = viewMode->normalToView( m_doc->zoomPoint( dPoint ) ); // from doc to view contents
+ vPoint.rx() -= canvas->contentsX();
+ vPoint.ry() -= canvas->contentsY();
+ } // else ... ?
+ return vPoint;
+}
+
+//////
+
+bool KWFootNoteFrameSet::isFootNote() const
+{
+ if ( !m_footNoteVar ) {
+ kdWarning() << k_funcinfo << " called too early? No footnote var." << endl;
+ return false;
+ }
+ return ( m_footNoteVar->noteType() == FootNote );
+}
+
+bool KWFootNoteFrameSet::isEndNote() const
+{
+ if ( !m_footNoteVar ) {
+ kdWarning() << k_funcinfo << " called too early? No footnote var." << endl;
+ return false;
+ }
+ return ( m_footNoteVar->noteType() == EndNote );
+}
+
+
+
+void KWFootNoteFrameSet::createInitialFrame( int pageNum )
+{
+ KWFrame *frame = new KWFrame(this, 0, m_doc->pageManager()->topOfPage(pageNum) + 1, 20, 20 );
+ frame->setFrameBehavior(KWFrame::AutoExtendFrame);
+ frame->setNewFrameBehavior(KWFrame::NoFollowup);
+ addFrame( frame );
+}
+
+void KWFootNoteFrameSet::startEditing( KWCanvas* canvas )
+{
+ canvas->editFrameSet( this );
+
+ // Ensure cursor is visible
+ KWTextFrameSetEdit *textedit = dynamic_cast<KWTextFrameSetEdit *>(canvas->currentFrameSetEdit()->currentTextEdit());
+ if ( textedit )
+ textedit->ensureCursorVisible();
+}
+
+void KWFootNoteFrameSet::setFootNoteVariable( KWFootNoteVariable* var )
+{
+ m_footNoteVar = var;
+}
+
+void KWFootNoteFrameSet::setCounterText( const QString& text )
+{
+ KoTextParag* parag = textDocument()->firstParag();
+ Q_ASSERT( parag );
+ if ( parag ) {
+ KoParagCounter counter;
+ counter.setNumbering( KoParagCounter::NUM_FOOTNOTE );
+ counter.setPrefix( text );
+ counter.setSuffix( QString::null );
+ parag->setCounter( counter );
+ }
+}
+
+KWordFrameSetIface* KWFootNoteFrameSet::dcopObject()
+{
+ if ( !m_dcop )
+ m_dcop = new KWFootNoteFrameSetIface( this );
+
+ return m_dcop;
+}
+
+#include "KWTextFrameSet.moc"
diff --git a/kword/KWTextFrameSet.h b/kword/KWTextFrameSet.h
new file mode 100644
index 00000000..97aba949
--- /dev/null
+++ b/kword/KWTextFrameSet.h
@@ -0,0 +1,547 @@
+/* This file is part of the KDE project
+ Copyright (C) 1998, 1999, 2000 Reginald Stadlbauer <reggie@kde.org>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+*/
+
+#ifndef kwtextframeset_h
+#define kwtextframeset_h
+
+#include "KoRichText.h"
+#include "KWFrameSet.h"
+#include "KWFrameSetEdit.h"
+#include <KoTextView.h>
+#include <KoParagLayout.h>
+#include <KoChangeCaseDia.h>
+#include "KWVariable.h"
+
+class KoGenStyles;
+class KoParagStyle;
+class KWDocument;
+class DCOPObject;
+#ifndef KWTextFormat
+#define KWTextFormat KoTextFormat
+#endif
+class KWViewMode;
+class KWTextDocument;
+class KWordFrameSetIface;
+class KWFrame;
+class KWFrameViewManager;
+
+class KoTextObject;
+class KoDataToolInfo;
+class KoVariable;
+
+class KAction;
+class KNamedCommand;
+class KMacroCommand;
+
+class QDragObject;
+class QProgressDialog;
+
+/**
+ * Class: KWTextFrameSet
+ * Contains text (KoTextObject) and frames to display that text.
+ *
+ * This class implements the KoTextFormatInterface methods for "apply to the
+ * whole text object". This is how "setBold", "setItalic" etc. can apply to
+ * a whole text frameset.
+ */
+class KWTextFrameSet : public KWFrameSet, public KoTextFlow, public KoTextFormatInterface
+{
+ Q_OBJECT
+public:
+ /// Cnstructor
+ KWTextFrameSet( KWDocument *_doc, const QString & name );
+ /// Used for OASIS loading
+ KWTextFrameSet( KWDocument* doc, const QDomElement& tag, KoOasisContext& context );
+ /// Destructor
+ ~KWTextFrameSet();
+
+ virtual KWordFrameSetIface* dcopObject();
+
+/** The type of frameset. Use this to differentiate between different instantiations of
+ * the framesets. Each implementation will return a different frameType.
+ */
+ virtual FrameSetType type() const { return FT_TEXT; }
+
+ virtual KWFrameSetEdit * createFrameSetEdit( KWCanvas * canvas );
+
+ /** Return the contained text object */
+ KoTextObject * textObject() const { return m_textobj; }
+
+ KoTextDocument *textDocument() const;
+ KWTextDocument *kwTextDocument() const;
+
+ void setProtectContent ( bool _protect ) { textObject()->setProtectContent(_protect);}
+ bool protectContent() const { return textObject()->protectContent();}
+
+ void clearUndoRedoInfo();
+
+ /** Convert the @p dPoint in the normal coordinate system (and in pt)
+ * into a point (@p iPoint) in the internal qtextdoc coordinates (in layout units). */
+ KWFrame * documentToInternal( const KoPoint &dPoint, QPoint &iPoint ) const;
+
+ /// used by documentToInternalMouseSelection()
+ enum RelativePosition { InsideFrame, LeftOfFrame, TopOfFrame, AtEnd };
+ KWFrame * documentToInternalMouseSelection( const KoPoint &dPoint, QPoint &iPoint, RelativePosition& relPos, KWViewMode *viewMode ) const;
+
+ /** Convert the @p in the internal qtextdoc coordinates (in layout units)
+ * into a point in the document coordinate system (in pt).
+ * Also returns the frame in which this point is. */
+ KWFrame * internalToDocument( const KoPoint &relPoint, KoPoint &dPoint ) const;
+ // version taking a LU point as input
+ KWFrame * internalToDocument( const QPoint &iPoint, KoPoint &dPoint ) const;
+
+ /** Same as internalToDocument, but goes directly to the normal coords (zoomed)
+ * since this method is used for view stuff only (mouse).
+ * @param hintDPoint hint, in case of copied frames. If specified, its y
+ * value will be used as a minimum on the returned result, to prefer a frame
+ * over any of its copies (e.g. in the header/footer case).
+ * @param iPoint internal document point
+ * @param dPoint the other point
+ */
+ KWFrame * internalToDocumentWithHint( const QPoint &iPoint, KoPoint &dPoint, const KoPoint &hintDPoint ) const;
+
+ /** A variant of internalToDocument, when the frame is already known.
+ * Both faster, and more correct for inline frames that spawn over multiple containing frames
+ */
+ KoPoint internalToDocumentKnowingFrame( const KoPoint &relPoint, KWFrame* theFrame ) const;
+ // [deprecated?] version taking a LU point as input
+ KoPoint internalToDocumentKnowingFrame( const QPoint &iPoint, KWFrame* theFrame ) const;
+
+ /** Implementation of Ctrl+PageUp/PageDown
+ * Returns a point in layout units (for placing the cursor) */
+ QPoint moveToPage( int currentPgNum, short int direction ) const;
+
+ /** Return the available height in pixels (sum of all frames' height, with zoom applied)
+ * Used to know if we need to create more pages. */
+ virtual int availableHeight() const;
+
+ /** Return true if the last frame is empty */
+ bool isFrameEmpty( KWFrame * frame );
+ virtual bool canRemovePage( int num );
+ // reimp for internal reasons
+ virtual void deleteFrame( unsigned int num, bool remove = true, bool recalc = true );
+ void deleteFrame( KWFrame *frm, bool remove = true, bool recalc = true )
+ { KWFrameSet::deleteFrame( frm, remove, recalc ); } // strange C++ feature ;)
+
+ /** reshuffle frames so text is always displayed from top-left down and then right.
+ * @param flags
+ */
+ virtual void updateFrames( int flags = 0xff );
+
+ /** Views notify the KWTextFrameSet of which area of the text
+ * they're looking at, so that formatMore() ensures it's always formatted
+ * correctly.
+ * @param w the wigdet (usually kwcanvas) that identifies the view
+ * @param w the current viewmode (to make sure the frameset is visible)
+ * @param nPointBottom the max the view looks at, in normal coordinates
+ * @param viewMode the current viewMode
+ */
+ void updateViewArea( QWidget * w, KWViewMode* viewMode, const QPoint & nPointBottom );
+
+ virtual QDomElement save( QDomElement &parentElem, bool saveFrames = true )
+ { return saveInternal( parentElem, saveFrames, false ); }
+ /** save to XML - when copying to clipboard (includes floating framesets) */
+ virtual QDomElement toXML( QDomElement &parentElem, bool saveFrames = true )
+ { return saveInternal( parentElem, saveFrames, true ); }
+
+ virtual void load( QDomElement &attributes, bool loadFrames = true );
+ /// Load the contents of a frame (i.e. the text)
+ void loadOasisContent( const QDomElement &bodyElem, KoOasisContext& context );
+ /// Load a complete textbox (frame and text)
+ KWFrame* loadOasis( const QDomElement& frame, const QDomElement &bodyElem, KoOasisContext& context );
+
+ /// Load a frame and add it to this frameset - called by KWOasisLoader
+ KWFrame* loadOasisTextFrame( const QDomElement& frameTag, const QDomElement &tag, KoOasisContext& context );
+
+ /// Save the contents of a frame (i.e. the text)
+ void saveOasisContent( KoXmlWriter& writer, KoSavingContext& context ) const;
+ /// Save a complete textbox (frame and text)
+ virtual void saveOasis( KoXmlWriter& writer, KoSavingContext& context, bool saveFrames ) const;
+
+ virtual QString toPlainText() const;
+
+ virtual void finalize();
+ //virtual void preparePrinting( QPainter *painter, QProgressDialog *progress, int &processedParags );
+
+ /** return true if some text is selected */
+ bool hasSelection() const;
+ /** returns the selected text [without formatting] if hasSelection() */
+ QString selectedText() const;
+
+ virtual void drawContents( QPainter *painter, const QRect &crect,
+ const QColorGroup &cg, bool onlyChanged, bool resetChanged,
+ KWFrameSetEdit* edit, KWViewMode *viewMode,
+ KWFrameViewManager *frameViewManager );
+
+ virtual void drawFrame( KWFrame * frame, QPainter *painter, const QRect& fcrect, const QRect& crect,
+ const QPoint& translationOffset,
+ KWFrame *settingsFrame, const QColorGroup &cg, bool onlyChanged, bool resetChanged,
+ KWFrameSetEdit * edit, KWViewMode *viewMode, bool drawUnderlyingFrames );
+
+ virtual void drawFrameContents( KWFrame * frame, QPainter *painter, const QRect & fcrect,
+ const QColorGroup &cg, bool onlyChanged, bool resetChanged,
+ KWFrameSetEdit * edit, KWViewMode *viewMode );
+
+ void drawCursor( QPainter *p, KoTextCursor *cursor, bool cursorVisible, KWCanvas *canvas, KWFrame *currentFrame );
+ QPoint cursorPos( KoTextCursor *cursor, KWCanvas* canvas, KWFrame* currentFrame );
+
+
+ KCommand* pasteOasis( KoTextCursor * cursor, const QByteArray & data, bool removeSelected );
+ void insertTOC( KoTextCursor * cursor );
+ KNamedCommand* insertFrameBreakCommand( KoTextCursor *cursor );
+ void insertFrameBreak( KoTextCursor * cursor );
+ KCommand * setPageBreakingCommand( KoTextCursor * cursor, int pageBreaking );
+
+ QRect paragRect( KoTextParag * parag ) const; // in normal coords
+
+ KCommand *deleteAnchoredFrame( KWAnchor * anchor );
+ void findPosition( const KoPoint &dPoint, KoTextParag * & parag, int & index );
+
+ /** Highlighting support (for search/replace, spellchecking etc.) */
+ void highlightPortion( KoTextParag * parag, int index, int length, KWCanvas * canvas, bool repaint = true, KDialogBase* dialog = 0 );
+ void removeHighlight( bool repaint = true );
+
+ virtual void addTextFrameSets( QPtrList<KWTextFrameSet> &lst, bool onlyReadWrite=false );
+
+ /** Update the paragraph that use the given style, after this style was changed.
+ * The flags tell which changes should be applied.
+ * @param changed the changed style map
+ */
+ void applyStyleChange( KoStyleChangeDefMap changed );
+
+ /** set the visibility of the frameset. */
+ virtual void setVisible( bool v );
+
+ /** Show or hide all inline frames that are inside this frameset */
+ void setInlineFramesVisible(bool);
+
+#ifndef NDEBUG
+ virtual void printDebug();
+#endif
+
+ /** Invalidate all paragraphs and start re-formatting */
+ virtual void layout();
+ /** Invalidate all paragraphs (causes a re-flow of the text upon next redraw) */
+ virtual void invalidate();
+
+ virtual int paragraphs();
+ virtual int paragraphsSelected();
+ /** Calculate statistics for this frameset */
+ virtual bool statistics( QProgressDialog *progress, ulong & charsWithSpace, ulong & charsWithoutSpace,
+ ulong & words, ulong& sentences, ulong & syllables, ulong & lines, bool selected );
+
+ /** reimplemented from KoTextFlow, implements flowing around frames etc. */
+ virtual void adjustMargins( int yp, int h, int reqMinWidth, int& leftMargin, int& rightMargin, int& pageWidth, KoTextParag* parag );
+ /** reimplemented from KoTextParag, adjusts y and returns the shift. */
+ virtual int adjustFlow( int y, int w, int h );
+
+ /** Called by KWTextFormatter. Implements page breaking, breaking around frames, etc. */
+ int formatVertically( KoTextParag *parag, const QRect& rect );
+ /** Called by KWTextFormatter::postFormat() */
+ void fixParagWidth( KWTextParag* parag );
+
+ /** Make sure this paragraph is formatted
+ * If formatting happens, the afterFormatting signal will only be emitted if emitAfterFormatting is true.
+ * This prevents re-entrancy if ensureFormatting is called by canRemovePage (from another frameset's
+ * slotAfterFormatting) */
+ void ensureFormatted( KoTextParag * parag, bool emitAfterFormatting = true );
+
+ /** The viewmode that was passed to drawContents. Special hook for KWAnchor. Don't use. */
+ KWViewMode * currentViewMode() const { return m_currentViewMode; }
+ /** The frame that we are currently drawing in drawFrame. Stored here since we can't pass it
+ * through QRT's drawing methods. Used by e.g. KWAnchor. */
+ KWFrame * currentDrawnFrame() const { return m_currentDrawnFrame; }
+
+ /** Let KoTextFormatInterface access the current format */
+ virtual KoTextFormat * currentFormat() const;
+
+ /** Let KoTextFormatInterface set the modified format */
+ virtual KCommand *setFormatCommand( const KoTextFormat * newFormat, int flags, bool zoomFont = false );
+
+ /** Let KoTextFormatInterface access the current parag layout */
+ virtual const KoParagLayout * currentParagLayoutFormat() const;
+
+ virtual bool rtl() const ;
+
+
+ /** Let KoTextFormatInterface set a modified current parag layout */
+ virtual KCommand *setParagLayoutFormatCommand( KoParagLayout *newLayout, int flags, int marginIndex=-1);
+
+ virtual KCommand *setChangeCaseOfTextCommand(KoChangeCaseDia::TypeOfCase _type);
+
+ /** (Assuming this==main frameset), recalc the foot note numbers */
+ void renumberFootNotes( bool repaint = true );
+
+ /**
+ * Iteration over text objects - used by KWBgSpellCheck
+ */
+ virtual KWTextFrameSet* nextTextObject( KWFrameSet * ) { return this;}
+
+ /**
+ * Return the min and max LU coordinates for the text in the given page,
+ * if the frameset has any frames in this page.
+ * Used by e.g. KWDoc::sectionTitle and KWFrameLayout.
+ */
+ bool minMaxInternalOnPage( int pageNum, int& topLU, int& bottomLU ) const;
+
+ /**
+ * Find the parag at the given Y position (in LU)
+ */
+ KoTextParag* paragAtLUPos( int yLU ) const;
+
+ /**
+ * Insert a footnote (var and frameset). Shared code for loading and inserting from GUI.
+ */
+ KWFootNoteFrameSet * insertFootNote( NoteType noteType, KWFootNoteVariable::Numbering numType, const QString &manualString );
+
+ KoTextDocCommand *deleteTextCommand( KoTextDocument *textdoc, int id, int index, const QMemArray<KoTextStringChar> & str, const CustomItemsMap & customItemsMap, const QValueList<KoParagLayout> & oldParagLayouts );
+
+ QString copyTextParag( KoXmlWriter& writer, KoSavingContext& context, int selectionId );
+
+ /// Sort selected paragraphs
+ /// Return a complete OASIS store, ready for "pasting"
+ QByteArray sortText(SortType type) const;
+
+ KoLinkVariable* linkVariableUnderMouse( const KoPoint& dPoint );
+ KoVariable* variableUnderMouse( const KoPoint& dPoint );
+
+signals:
+ /** Tell the Edit object that this frame got deleted */
+ void frameDeleted( KWFrame* frame );
+
+ /** Tell the text viewmode that the height of the text might have changed */
+ void mainTextHeightChanged();
+
+public slots:
+ // Connected to KoTextObject
+ void slotRepaintChanged();
+
+protected slots:
+ // All those slots are connected to KoTextObject
+ void slotAvailableHeightNeeded();
+ void slotAfterFormatting( int bottom, KoTextParag *lastFormatted, bool* abort );
+ void slotNewCommand( KCommand *cmd );
+ void slotParagraphDeleted(KoTextParag*_parag);
+ void slotParagraphCreated(KoTextParag*_parag);
+ void slotParagraphModified(KoTextParag*_parag, int /*KoTextParag::ParagModifyType*/, int, int);
+
+
+protected: // for testing purposes
+ KWTextFrameSet( const QString & name );
+
+private:
+ void init();
+ bool slotAfterFormattingNeedMoreSpace( int bottom, KoTextParag *lastFormatted );
+ void slotAfterFormattingTooMuchSpace( int bottom );
+ void getMargins( int yp, int h, int reqMinWidth, int* marginLeft, int* marginRight, int* pageWidth, int* validHeight,
+ int* breakBegin, int* breakEnd, KoTextParag* parag );
+ bool checkVerticalBreak( int & yp, int & h, KoTextParag * parag, bool linesTogether, int breakBegin, int breakEnd );
+ void frameResized( KWFrame *theFrame, bool invalidateLayout );
+ /**
+ * Return the list of frames containing the text that goes from @p y1 to @p y2
+ * (in internal coordinates).
+ */
+ QValueList<KWFrame*> framesFromTo( int y1, int y2 ) const;
+ double footerHeaderSizeMax( KWFrame *theFrame );
+ double footNoteSize( KWFrame *theFrame );
+ QDomElement saveInternal( QDomElement &parentElem, bool saveFrames, bool saveAnchorsFramesets );
+ bool createNewPageAndNewFrame( KoTextParag* lastFormatted, int difference );
+
+private:
+ /** The contained text object */
+ KoTextObject * m_textobj;
+ /** The viewmode we currently used (while drawing). For internal purposes (KWAnchor). */
+ KWViewMode * m_currentViewMode;
+ /** The frame currently being drawn. */
+ KWFrame * m_currentDrawnFrame;
+ /** For the mainTextHeightChanged signal. */
+ int m_lastTextDocHeight;
+};
+
+/**
+ * Object that is created to edit a Text frame set (KWTextFrameSet).
+ * It handles all the events for it.
+ * In terms of doc/view design, this object is part of the _view_.
+ * There can be several KWFrameSetEdit objects for the same frameset,
+ * but there is only one KWFrameSetEdit object per view at a given moment.
+ */
+class KWTextFrameSetEdit : public KoTextView, public KWFrameSetEdit
+{
+ Q_OBJECT
+public:
+ KWTextFrameSetEdit( KWTextFrameSet * fs, KWCanvas * canvas );
+ virtual ~KWTextFrameSetEdit();
+
+ virtual KoTextViewIface* dcopObject();
+
+ virtual KWFrameSetEdit* currentTextEdit(){return this;}
+
+ virtual void terminate(bool removeselection=true);
+
+ KWTextFrameSet * textFrameSet() const
+ {
+ return static_cast<KWTextFrameSet*>(frameSet());
+ }
+ KoTextDocument * textDocument() const
+ {
+ return textFrameSet()->textDocument();
+ }
+
+ // Just in case we change to containing a textview instead
+ KoTextView * textView() { return this; }
+
+ // Events forwarded by the canvas (when being in "edit" mode)
+ virtual void keyPressEvent( QKeyEvent * );
+ virtual void keyReleaseEvent( QKeyEvent * );
+ virtual void imStartEvent( QIMEvent * );
+ virtual void imComposeEvent( QIMEvent * );
+ virtual void imEndEvent( QIMEvent * );
+ virtual void mousePressEvent( QMouseEvent *, const QPoint &, const KoPoint & );
+ virtual void mouseMoveEvent( QMouseEvent *, const QPoint &, const KoPoint & ); // only called if button is pressed
+ virtual void mouseReleaseEvent( QMouseEvent *, const QPoint &, const KoPoint & );
+ virtual void mouseDoubleClickEvent( QMouseEvent *, const QPoint &, const KoPoint & );
+ virtual void dragEnterEvent( QDragEnterEvent * );
+ virtual void dragMoveEvent( QDragMoveEvent *, const QPoint &, const KoPoint & );
+ virtual void dragLeaveEvent( QDragLeaveEvent * );
+ virtual void dropEvent( QDropEvent *, const QPoint &, const KoPoint &, KWView* view );
+ virtual void focusInEvent();
+ virtual void focusOutEvent();
+ virtual void selectAll();
+
+ // Reimplemented from KoTextView
+ virtual void drawCursor( bool b );
+ virtual void showFormat( KoTextFormat *format );
+ virtual bool pgUpKeyPressed();
+ virtual bool pgDownKeyPressed();
+ virtual void ctrlPgUpKeyPressed();
+ virtual void ctrlPgDownKeyPressed();
+
+ void setCursor( KoTextParag* parag, int index );
+
+ void insertFrameBreak() { textFrameSet()->insertFrameBreak( cursor() ); }
+ void insertWPPage();
+ void insertVariable( int type, int subtype = 0 );
+ void insertFootNote( NoteType noteType, KWFootNoteVariable::Numbering numType, const QString& manualString );
+ void insertCustomVariable( const QString &name);
+ void insertVariable( KoVariable *var,
+ KoTextFormat *format = 0 /*means currentFormat()*/,
+ bool refreshCustomMenu = false/*don't refresh all the time custom menu*/ );
+
+ void insertLink(const QString &_linkName, const QString & hrefName);
+ void insertComment(const QString &_comment);
+
+ void insertExpression(const QString &_c);
+ void insertFloatingFrameSet( KWFrameSet * fs, const QString & commandName );
+ void insertTOC() { textFrameSet()->insertTOC( cursor() ); }
+ KCommand * setPageBreakingCommand( int pageBreaking )
+ { return textFrameSet()->setPageBreakingCommand( cursor(), pageBreaking ); }
+
+
+ //const KoParagLayout & currentParagLayout() const { return m_paragLayout; }
+ double currentLeftMargin() const { return m_paragLayout.margins[QStyleSheetItem::MarginLeft]; }
+
+ virtual void removeToolTipCompletion();
+
+ //bool isLinkVariable(const KoPoint &, bool setUrl=false);
+
+ /// Called by KoTextView when clicking on a link
+ bool openLink( KoLinkVariable* variable );
+ /// Called by KWView when using the action
+ void openLink();
+
+ void pasteData( QMimeSource* data, int provides, bool drop );
+ KCommand* pasteOasisCommand( QMimeSource* data );
+
+ /**
+ * Return the requested border of the paragraph that the cursor currently is in.
+ * @param type specifies which of the borders to return;
+ * @return the requested border of the current paragraph
+ */
+ KoBorder border(KoBorder::BorderType type);
+
+public slots:
+ // Reimplemented from KWFrameSet and connected to KoTextView's signals
+ virtual void cut();
+ virtual void copy();
+ virtual void paste();
+
+ // Reimplemented from KoTextView
+ virtual void updateUI( bool updateFormat, bool force = false );
+ virtual void ensureCursorVisible();
+
+protected:
+ // Reimplemented from KoTextView
+ virtual void doAutoFormat( KoTextCursor* cursor, KoTextParag *parag, int index, QChar ch );
+ virtual bool doIgnoreDoubleSpace(KoTextParag * parag, int index,QChar ch );
+ virtual bool doCompletion( KoTextCursor* cursor, KoTextParag *parag, int index );
+ virtual bool doToolTipCompletion( KoTextCursor* cursor, KoTextParag *parag, int index,int keyPress );
+ virtual void showToolTipBox(KoTextParag *parag, int index, QWidget *widget, const QPoint &pos);
+ virtual void textIncreaseIndent();
+ virtual bool textDecreaseIndent();
+
+ virtual void startDrag();
+ QDragObject * newDrag( QWidget * parent );
+
+private slots:
+ void slotFrameDeleted(KWFrame *);
+
+private:
+ bool enterCustomItem( KoTextCustomItem* customItem, bool fromRight );
+
+ KoParagLayout m_paragLayout;
+ bool m_rtl; // maybe make part of KoParagLayout later
+};
+
+class KWFootNoteVariable;
+class KWFootNoteFrameSet : public KWTextFrameSet
+{
+public:
+ /** constructor */
+ KWFootNoteFrameSet( KWDocument *doc, const QString & name )
+ : KWTextFrameSet( doc, name ), m_footNoteVar( 0L ) {}
+
+ virtual KWordFrameSetIface* dcopObject();
+
+ void setFootNoteVariable( KWFootNoteVariable* var );
+ KWFootNoteVariable* footNoteVariable() const { return m_footNoteVar; }
+
+ /** Create the first frame for this frameset.
+ * KWFrameLayout will reposition it at the correct place.
+ */
+ void createInitialFrame( int pageNum );
+
+ /**
+ * Edit and ensure cursor is visible. Helper function which is useful because
+ * the caller is usually a KWFrameSetEdit, which gets deleted by the
+ * editFrameSet() call.
+ */
+ void startEditing( KWCanvas* canvas );
+
+ /** Called by KWTextFrameSet::renumberFootNotes.
+ * Sets the text of the parag-counter in the footnote text.
+ */
+ void setCounterText( const QString& text );
+
+ virtual bool isFootNote() const;
+ virtual bool isEndNote() const;
+
+private:
+ KWFootNoteVariable* m_footNoteVar;
+};
+#endif
diff --git a/kword/KWTextImage.cpp b/kword/KWTextImage.cpp
new file mode 100644
index 00000000..4f2cde40
--- /dev/null
+++ b/kword/KWTextImage.cpp
@@ -0,0 +1,161 @@
+/* This file is part of the KDE project
+ Copyright (C) 2001 David Faure <faure@kde.org>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+*/
+
+#include <kdebug.h>
+
+#include <KoPictureCollection.h>
+
+#include "KWDocument.h"
+#include "defs.h"
+#include "KWTextFrameSet.h"
+
+#include "KWTextImage.h"
+
+KWTextImage::KWTextImage( KWTextDocument *textdoc, const QString & filename )
+ : KoTextCustomItem( textdoc ), place( PlaceInline )
+{
+ KWDocument * doc = textdoc->textFrameSet()->kWordDocument();
+ if ( !filename.isEmpty() )
+ {
+ m_image = doc->pictureCollection()->loadPicture( filename );
+ Q_ASSERT( !m_image.isNull() );
+ resize(); // Zoom if necessary
+ }
+}
+
+void KWTextImage::setImage( const KoPictureCollection & collection )
+{
+ kdDebug(32001) << "Loading text image " << m_image.getKey().toString() << " (in KWTextImage::setImage)" << endl;
+ m_image=collection.findPicture( m_image.getKey() );
+ Q_ASSERT( !m_image.isNull() );
+ kdDebug(32001) << "size: " << m_image.getOriginalSize().width() << "x" << m_image.getOriginalSize().height() << endl;
+ resize();
+}
+
+void KWTextImage::resize()
+{
+ if ( m_deleted )
+ return;
+ if ( !m_image.isNull() ) {
+ //KWDocument * doc = static_cast<KWTextDocument *>(parent)->textFrameSet()->kWordDocument();
+ width = m_image.getOriginalSize().width();
+ // width is a 100%-zoom pixel size. We want a LU pixel size -> we simply need 'to LU', i.e. ptToLayoutPt
+ width = KoTextZoomHandler::ptToLayoutUnitPt( width );
+ height = m_image.getOriginalSize().height();
+ height = KoTextZoomHandler::ptToLayoutUnitPt( height );
+ kdDebug() << "KWTextImage::resize: " << width << ", " << height << endl;
+ // no! m_image.setSize( QSize( width, height ) );
+ }
+}
+
+void KWTextImage::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)
+{
+ if ( drawingShadow )
+ return;
+
+ // (x,y) is the position of the inline item (in pixels)
+ // (wpix,hpix) is the size of the inline item (in pixels)
+ // (cx,cy,cw,ch) is the rectangle to be painted, in pixels too
+ if ( m_image.isNull() ) {
+ kdDebug() << "KWTextImage::draw null image!" << endl;
+ p->fillRect( x, y, 50, 50, cg.dark() );
+ return;
+ }
+
+ QSize imgSize( wpix, hpix );
+
+ QRect rect( QPoint(x, y), imgSize );
+ if ( !rect.intersects( QRect( cx, cy, cw, ch ) ) )
+ return;
+
+ QPixmap pixmap=m_image.generatePixmap( imgSize, true );
+ //if ( placement() == PlaceInline )
+ p->drawPixmap( x, y, pixmap );
+ //else
+ // p->drawPixmap( cx, cy, pixmap, cx - x, cy - y, cw, ch );
+
+ if ( selected && placement() == PlaceInline && p->device()->devType() != QInternal::Printer ) {
+ p->fillRect( rect , QBrush( cg.highlight(), QBrush::Dense4Pattern) );
+ }
+}
+
+void KWTextImage::save( QDomElement & parentElem )
+{
+ // This code is similar to KWPictureFrameSet::save
+ KWDocument * doc = static_cast<KWTextDocument *>(parent)->textFrameSet()->kWordDocument();
+
+ QDomElement imageElem = parentElem.ownerDocument().createElement( "PICTURE" );
+ parentElem.appendChild( imageElem );
+ //imageElem.setAttribute( "keepAspectRatio", "true" );
+ QDomElement elem = parentElem.ownerDocument().createElement( "KEY" );
+ imageElem.appendChild( elem );
+ image().getKey().saveAttributes( elem );
+ // Now we must take care that a <KEY> element will be written as a child of <PICTURES>
+ doc->addTextImageRequest( this );
+}
+
+void KWTextImage::load( QDomElement & parentElem )
+{
+ // This code is similar to KWPictureFrameSet::load
+ KWDocument * doc = static_cast<KWTextDocument *>(parent)->textFrameSet()->kWordDocument();
+
+ // <IMAGE> (KOffice 1.0) or <PICTURE> (KWord 1.2)
+ QDomNode node=parentElem.namedItem( "PICTURE" );
+ if ( node.isNull() )
+ {
+ node=parentElem.namedItem( "IMAGE" );
+ }
+ QDomElement image = node.toElement();
+ if ( image.isNull() )
+ image = parentElem; // The data is directly child of <FORMAT>
+ // <KEY>
+ QDomElement keyElement = image.namedItem( "KEY" ).toElement();
+ if ( !keyElement.isNull() )
+ {
+ KoPictureKey key;
+ key.loadAttributes( keyElement );
+ m_image.setKey(key);
+ doc->addTextImageRequest( this );
+ }
+ else
+ {
+ // <FILENAME> (old format, up to KWord-1.1-beta2)
+ QDomElement filenameElement = image.namedItem( "FILENAME" ).toElement();
+ if ( !filenameElement.isNull() )
+ {
+ QString filename = filenameElement.attribute( "value" );
+ m_image.setKey( KoPictureKey( filename ) );
+ doc->addTextImageRequest( this );
+ }
+ else
+ {
+ kdError(32001) << "Missing KEY or FILENAME tag in IMAGE (KWTextImage::load)" << endl;
+ }
+ }
+}
+
+KoPictureKey KWTextImage::getKey( void ) const
+{
+ return m_image.getKey();
+}
+
+void KWTextImage::saveOasis( KoXmlWriter&, KoSavingContext& ) const
+{
+ // Not implemented
+}
diff --git a/kword/KWTextImage.h b/kword/KWTextImage.h
new file mode 100644
index 00000000..19f7c334
--- /dev/null
+++ b/kword/KWTextImage.h
@@ -0,0 +1,74 @@
+/* This file is part of the KDE project
+ Copyright (C) 2001 David Faure <faure@kde.org>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+*/
+
+#ifndef kwtextimage_h
+#define kwtextimage_h
+
+#include <KoPictureKey.h>
+#include <KoPicture.h>
+
+#include <KWTextDocument.h>
+
+/**
+ * This class is used by "Insert Picture", i.e. having an image inline in a paragraph.
+ * It is going to be removed from KWord (inline picture frames are so much better),
+ * but we might need it in KPresenter !
+ */
+class KWTextImage : public KoTextCustomItem
+{
+public:
+ /**
+ * Set filename to load a real file from the disk
+ * Otherwise use setImage() - this is what's done on loading
+ */
+ KWTextImage( KWTextDocument *textdoc, const QString & filename );
+ ~KWTextImage()
+ {
+ // Remove image from collection ?
+ }
+
+ virtual Placement placement() const { return place; }
+ virtual void resize();
+ virtual int widthHint() const { return width; }
+ virtual int minimumWidth() const { return width; }
+
+ void setImage( const KoPictureCollection & collection );
+
+ KoPicture image() const { return m_image; }
+
+ virtual void 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 );
+
+ // Save to XML
+ virtual void save( QDomElement & formatElem );
+ virtual void saveOasis( KoXmlWriter&, KoSavingContext& ) const;
+ virtual int typeId() const { return 2; }
+
+ void load( QDomElement & formatElem );
+
+ /**
+ * Get the key of the picture
+ */
+ KoPictureKey getKey( void ) const;
+private:
+ Placement place;
+ KoPicture m_image;
+ QSize m_size; // Size of image
+};
+
+#endif
diff --git a/kword/KWTextParag.cpp b/kword/KWTextParag.cpp
new file mode 100644
index 00000000..152e2f70
--- /dev/null
+++ b/kword/KWTextParag.cpp
@@ -0,0 +1,859 @@
+/* This file is part of the KDE project
+ Copyright (C) 2001 David Faure <faure@kde.org>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+*/
+
+#include "KWTextParag.h"
+#include "KWDocument.h"
+#include "KWAnchor.h"
+#include "KWTextImage.h"
+#include "KWTextFrameSet.h"
+#include "KWVariable.h"
+#include "KWLoadingInfo.h"
+
+#include <KoVariable.h>
+#include <KoParagCounter.h>
+#include <KoOasisContext.h>
+#include <KoXmlNS.h>
+#include <KoOasisStyles.h>
+
+#include <kglobalsettings.h>
+#include <klocale.h>
+#include <kdebug.h>
+#include <assert.h>
+
+//#define DEBUG_FORMATTING
+#undef S_NONE // Solaris defines it in sys/signal.h
+
+// Called by KoTextParag::drawParagString - all params are in pixel coordinates
+void KWTextParag::drawFormattingChars( QPainter &painter, int start, int len,
+ int lastY_pix, int baseLine_pix, int h_pix, // in pixels
+ bool drawSelections,
+ KoTextFormat *lastFormat, const QMemArray<int> &selectionStarts,
+ const QMemArray<int> &selectionEnds, const QColorGroup &cg,
+ bool rightToLeft, int line, KoTextZoomHandler* zh,
+ int whichFormattingChars )
+{
+ KWTextFrameSet * textfs = kwTextDocument()->textFrameSet();
+ if ( !textfs )
+ return;
+ KWDocument * doc = textfs->kWordDocument();
+ if ( !doc || !doc->viewFormattingChars() )
+ return;
+ // We set whichFormattingChars before calling KoTextFormat::drawFormattingChars
+ whichFormattingChars = 0;
+ if ( doc->viewFormattingSpace() )
+ whichFormattingChars |= FormattingSpace;
+ if ( doc->viewFormattingBreak() )
+ whichFormattingChars |= FormattingBreak;
+ if ( doc->viewFormattingEndParag() )
+ whichFormattingChars |= FormattingEndParag;
+ if ( doc->viewFormattingTabs() )
+ whichFormattingChars |= FormattingTabs;
+
+ if ( !whichFormattingChars )
+ return;
+ if ( start + len == length() && (whichFormattingChars & FormattingBreak) && hardFrameBreakAfter() )
+ {
+ painter.save();
+ QPen pen( KGlobalSettings::linkColor() ); // #101820
+ painter.setPen( pen );
+ //kdDebug() << "KWTextParag::drawFormattingChars start=" << start << " len=" << len << " length=" << length() << endl;
+ // keep in sync with KWTextFrameSet::formatVertically
+ QString str = i18n( "--- Frame Break ---" );
+ int width = 0;
+ //width = lastFormat->screenStringWidth( zh, str );
+ width = lastFormat->screenFontMetrics( zh ).width( str );
+ QColorGroup cg2( cg );
+ //cg2.setColor( QColorGroup::Base, Qt::green ); // for debug
+ int last = length() - 1;
+ KoTextStringChar &ch = string()->at( last );
+ int x = zh->layoutUnitToPixelX( ch.x );// + ch.pixelxadj;
+
+ KoTextFormat format( *lastFormat );
+ format.setColor( pen.color() ); // ### A bit slow, maybe pass the color to drawParagStringInternal ?
+ KoTextParag::drawParagStringInternal(
+ painter, str, 0, str.length(),
+ x, lastY_pix, // startX and lastY
+ zh->layoutUnitToPixelY( ch.ascent() ), // baseline
+ width, zh->layoutUnitToPixelY( ch.height() ), // bw and h
+ drawSelections, &format, selectionStarts,
+ selectionEnds, cg2, rightToLeft, line, zh, false );
+ // Clear 'paint end of line' flag, we don't want it overwriting the above
+ whichFormattingChars &= ~FormattingEndParag;
+ painter.restore();
+ }
+
+ KoTextParag::drawFormattingChars( painter, start, len,
+ lastY_pix, baseLine_pix, h_pix,
+ drawSelections,
+ lastFormat, selectionStarts,
+ selectionEnds, cg, rightToLeft,
+ line, zh, whichFormattingChars );
+}
+
+void KWTextParag::setPageBreaking( int pb )
+{
+ m_layout.pageBreaking = pb;
+ invalidate(0);
+ if ( next() && ( pb & KoParagLayout::HardFrameBreakAfter ) )
+ next()->invalidate(0);
+}
+
+KWTextDocument * KWTextParag::kwTextDocument() const
+{
+ return static_cast<KWTextDocument *>( document() );
+}
+
+//static
+QDomElement KWTextParag::saveFormat( QDomDocument & doc, KoTextFormat * curFormat, KoTextFormat * refFormat, int pos, int len )
+{
+ //kdDebug() << "KWTextParag::saveFormat refFormat=" << ( refFormat ? refFormat->key() : "none" )
+ // << " curFormat=" << curFormat->key()
+ // << " pos=" << pos << " len=" << len << endl;
+ QDomElement formatElem = doc.createElement( "FORMAT" );
+ formatElem.setAttribute( "id", 1 ); // text format
+ if ( len ) // 0 when saving the format of a style
+ {
+ formatElem.setAttribute( "pos", pos );
+ formatElem.setAttribute( "len", len );
+ }
+ QDomElement elem;
+ if( !refFormat || curFormat->font().weight() != refFormat->font().weight() )
+ {
+ elem = doc.createElement( "WEIGHT" );
+ formatElem.appendChild( elem );
+ elem.setAttribute( "value", curFormat->font().weight() );
+ }
+ if( !refFormat || curFormat->color() != refFormat->color() )
+ {
+ if ( curFormat->color().isValid() )
+ {
+ elem = doc.createElement( "COLOR" );
+ formatElem.appendChild( elem );
+ elem.setAttribute( "red", curFormat->color().red() );
+ elem.setAttribute( "green", curFormat->color().green() );
+ elem.setAttribute( "blue", curFormat->color().blue() );
+ }
+ else
+ {
+ if ( refFormat )
+ {
+ elem = doc.createElement( "COLOR" );
+ formatElem.appendChild( elem );
+ elem.setAttribute( "red", -1 );
+ elem.setAttribute( "green", -1 );
+ elem.setAttribute( "blue", -1 );
+ }
+ }
+ }
+ if( !refFormat || curFormat->font().family() != refFormat->font().family() )
+ {
+ elem = doc.createElement( "FONT" );
+ formatElem.appendChild( elem );
+ elem.setAttribute( "name", curFormat->font().family() );
+ }
+ if( !refFormat || curFormat->pointSize() != refFormat->pointSize() )
+ {
+ elem = doc.createElement( "SIZE" );
+ formatElem.appendChild( elem );
+ elem.setAttribute( "value", curFormat->pointSize() );
+ }
+ if( !refFormat || curFormat->font().italic() != refFormat->font().italic() )
+ {
+ elem = doc.createElement( "ITALIC" );
+ formatElem.appendChild( elem );
+ elem.setAttribute( "value", static_cast<int>(curFormat->font().italic()) );
+ }
+ if( !refFormat
+ || curFormat->underlineType() != refFormat->underlineType()
+ || curFormat->textUnderlineColor() !=refFormat->textUnderlineColor()
+ || curFormat->underlineStyle() !=refFormat->underlineStyle()
+ || curFormat->wordByWord() != refFormat->wordByWord())
+ {
+ elem = doc.createElement( "UNDERLINE" );
+ formatElem.appendChild( elem );
+ if ( curFormat->doubleUnderline() )
+ elem.setAttribute( "value", "double" );
+ else if ( curFormat->underlineType() == KoTextFormat::U_SIMPLE_BOLD)
+ elem.setAttribute( "value", "single-bold" );
+ else if( curFormat->underlineType()==KoTextFormat::U_WAVE)
+ elem.setAttribute( "value", "wave" );
+ else
+ elem.setAttribute( "value", static_cast<int>(curFormat->underline()) );
+ QString strLineType=KoTextFormat::underlineStyleToString( curFormat->underlineStyle() );
+ elem.setAttribute( "styleline", strLineType );
+ if ( curFormat->textUnderlineColor().isValid() )
+ elem.setAttribute( "underlinecolor", curFormat->textUnderlineColor().name() );
+
+ elem.setAttribute( "wordbyword" , static_cast<int>(curFormat->wordByWord()));
+ }
+ if( !refFormat
+ || curFormat->strikeOutType() != refFormat->strikeOutType()
+ || curFormat->strikeOutStyle()!= refFormat->strikeOutStyle()
+ || curFormat->wordByWord() != refFormat->wordByWord())
+ {
+ elem = doc.createElement( "STRIKEOUT" );
+ formatElem.appendChild( elem );
+ if ( curFormat->doubleStrikeOut() )
+ elem.setAttribute( "value", "double" );
+ else if ( curFormat->strikeOutType() == KoTextFormat::S_SIMPLE_BOLD)
+ elem.setAttribute( "value", "single-bold" );
+ else
+ elem.setAttribute( "value", static_cast<int>(curFormat->strikeOut()) );
+ QString strLineType=KoTextFormat::strikeOutStyleToString( curFormat->strikeOutStyle() );
+ elem.setAttribute( "styleline", strLineType );
+ elem.setAttribute( "wordbyword" , static_cast<int>(curFormat->wordByWord()));
+ }
+ if( !refFormat || (curFormat->vAlign() != refFormat->vAlign())
+ || (curFormat->relativeTextSize() != refFormat->relativeTextSize()))
+ {
+ elem = doc.createElement( "VERTALIGN" );
+ formatElem.appendChild( elem );
+ elem.setAttribute( "value", static_cast<int>(curFormat->vAlign()) );
+ if ( curFormat->relativeTextSize()!=0.66)
+ elem.setAttribute( "relativetextsize", curFormat->relativeTextSize() );
+ }
+ if( !refFormat || curFormat->textBackgroundColor() != refFormat->textBackgroundColor() )
+ {
+ if ( curFormat->textBackgroundColor().isValid())
+ {
+ elem = doc.createElement( "TEXTBACKGROUNDCOLOR" );
+ formatElem.appendChild( elem );
+ elem.setAttribute( "red", curFormat->textBackgroundColor().red() );
+ elem.setAttribute( "green", curFormat->textBackgroundColor().green() );
+ elem.setAttribute( "blue", curFormat->textBackgroundColor().blue() );
+ }
+ else
+ {
+ if ( refFormat )
+ {
+ elem = doc.createElement( "TEXTBACKGROUNDCOLOR" );
+ formatElem.appendChild( elem );
+ elem.setAttribute( "red", -1 );
+ elem.setAttribute( "green", -1 );
+ elem.setAttribute( "blue", -1 );
+ }
+ }
+ }
+ if( !refFormat ||
+ ( curFormat->shadowDistanceX() != refFormat->shadowDistanceX()
+ || ( curFormat->shadowDistanceY() != refFormat->shadowDistanceY() )
+ || ( curFormat->shadowColor() != refFormat->shadowColor() ) ) )
+ {
+ elem = doc.createElement( "SHADOW" );
+ formatElem.appendChild( elem );
+ elem.setAttribute( "text-shadow", curFormat->shadowAsCss() );
+ }
+ if( !refFormat || curFormat->offsetFromBaseLine() != refFormat->offsetFromBaseLine())
+ {
+ elem = doc.createElement( "OFFSETFROMBASELINE" );
+ formatElem.appendChild( elem );
+ elem.setAttribute( "value", curFormat->offsetFromBaseLine() );
+ }
+ if( !refFormat || curFormat->attributeFont() != refFormat->attributeFont())
+ {
+ elem = doc.createElement( "FONTATTRIBUTE" );
+ formatElem.appendChild( elem );
+ elem.setAttribute( "value", KoTextFormat::attributeFontToString(curFormat->attributeFont()) );
+ }
+ if( !refFormat || curFormat->language() != refFormat->language())
+ {
+ elem = doc.createElement( "LANGUAGE" );
+ formatElem.appendChild( elem );
+ elem.setAttribute( "value", curFormat->language() );
+ }
+ return formatElem;
+}
+
+void KWTextParag::save( QDomElement &parentElem, bool saveAnchorsFramesets )
+{
+ // The QMAX below ensures that although we don't save the trailing space
+ // in the normal case, we do save it for empty paragraphs (#30336)
+ save( parentElem, 0, QMAX( 0, length()-2 ), saveAnchorsFramesets );
+}
+
+void KWTextParag::save( QDomElement &parentElem, int from /* default 0 */,
+ int to /* default length()-2 */,
+ bool saveAnchorsFramesets /* default false */ )
+{
+ QDomDocument doc = parentElem.ownerDocument();
+ QDomElement paragElem = doc.createElement( "PARAGRAPH" );
+ parentElem.appendChild( paragElem );
+ QDomElement textElem = doc.createElement( "TEXT" );
+ textElem.setAttribute("xml:space", "preserve");
+ paragElem.appendChild( textElem );
+ if ( partOfTableOfContents() )
+ paragElem.setAttribute( "toc", "true" );
+ QString text = string()->toString();
+ Q_ASSERT( text.right(1)[0] == ' ' );
+ textElem.appendChild( doc.createTextNode( text.mid( from, to - from + 1 ) ) );
+
+ QDomElement formatsElem = doc.createElement( "FORMATS" );
+ int startPos = -1;
+ int index = 0; // Usually same as 'i' but if from>0, 'i' indexes the parag's text and this one indexes the output
+ KoTextFormat *curFormat = paragraphFormat();
+ for ( int i = from; i <= to; ++i, ++index )
+ {
+ KoTextStringChar & ch = string()->at(i);
+ KoTextFormat * newFormat = static_cast<KoTextFormat *>( ch.format() );
+ if ( ch.isCustom() )
+ {
+ if ( startPos > -1 && curFormat) { // Save former format
+ QDomElement formatElem = saveFormat( doc, curFormat,
+ paragraphFormat(), startPos, index-startPos );
+ if ( !formatElem.firstChild().isNull() ) // Don't save an empty format tag
+ formatsElem.appendChild( formatElem );
+ }
+
+ QDomElement formatElem = saveFormat( doc, newFormat, paragraphFormat(), index, 1 );
+ formatsElem.appendChild( formatElem );
+ KoTextCustomItem* customItem = ch.customItem();
+ formatElem.setAttribute( "id", customItem->typeId() );
+ customItem->save( formatElem );
+ startPos = -1;
+ curFormat = paragraphFormat();
+ // Save the contents of the frameset inside the anchor
+ // This is NOT used when saving, but it is used when copying an inline frame
+ if ( saveAnchorsFramesets )
+ {
+ KWFrameSet* inlineFs = 0L;
+ if ( dynamic_cast<KWAnchor *>( customItem ) )
+ inlineFs = static_cast<KWAnchor *>( customItem )->frameSet();
+ else if ( dynamic_cast<KWFootNoteVariable *>( customItem ) )
+ inlineFs = static_cast<KWFootNoteVariable *>( customItem )->frameSet();
+
+ if ( inlineFs )
+ {
+ // Save inline framesets at the toplevel. Necessary when copying a textframeset that
+ // itself includes an inline frameset - we want all frameset tags at the toplevel.
+ QDomElement elem = doc.documentElement();
+ kdDebug() << " saving into " << elem.tagName() << endl;
+ inlineFs->toXML( elem );
+ }
+ }
+ }
+ else
+ {
+ if ( newFormat != curFormat )
+ {
+ // Format changed.
+ if ( startPos > -1 && curFormat) { // Save former format
+ QDomElement formatElem = saveFormat( doc, curFormat, paragraphFormat(), startPos, index-startPos );
+ if ( !formatElem.firstChild().isNull() ) // Don't save an empty format tag
+ formatsElem.appendChild( formatElem );
+ }
+
+ // Format different from paragraph's format ?
+ if( newFormat != paragFormat() )
+ {
+ startPos = index;
+ curFormat = newFormat;
+ }
+ else
+ {
+ startPos = -1;
+ curFormat = paragraphFormat();
+ }
+ }
+ }
+ }
+ if ( startPos > -1 && index > startPos && curFormat) { // Save last format
+ QDomElement formatElem = saveFormat( doc, curFormat, paragraphFormat(), startPos, index-startPos );
+ if ( !formatElem.firstChild().isNull() ) // Don't save an empty format tag
+ formatsElem.appendChild( formatElem );
+ }
+
+ if (!formatsElem.firstChild().isNull()) // Do we have formats to save ?
+ paragElem.appendChild( formatsElem );
+
+
+ QDomElement layoutElem = doc.createElement( "LAYOUT" );
+ paragElem.appendChild( layoutElem );
+
+ // save with the real alignment (left or right, not auto)
+ m_layout.saveParagLayout( layoutElem, resolveAlignment() );
+
+ // Paragraph's format
+ // ## Maybe we should have a "default format" somewhere and
+ // pass it instead of 0L, to only save the non-default attributes
+ // But this would break all export filters again.
+ QDomElement paragFormatElement = saveFormat( doc, paragraphFormat(), 0L, 0, to - from + 1 );
+ layoutElem.appendChild( paragFormatElement );
+}
+
+//static
+KoTextFormat KWTextParag::loadFormat( QDomElement &formatElem, KoTextFormat * refFormat, const QFont & defaultFont, const QString & defaultLanguage, bool hyphanation )
+{
+ KoTextFormat format;
+ //todo fixme !!!!!!!!!!!!
+ format.setHyphenation( hyphanation );
+ QFont font;
+ if ( refFormat )
+ {
+ format = *refFormat;
+ format.setCollection( 0 ); // Out of collection copy
+ font = format.font();
+ }
+ else
+ {
+ font = defaultFont;
+ }
+
+ QDomElement elem;
+ elem = formatElem.namedItem( "FONT" ).toElement();
+ if ( !elem.isNull() )
+ {
+ font.setFamily( elem.attribute("name") );
+ }
+ else if ( !refFormat )
+ { // No reference format and no FONT tag -> use default font
+ font = defaultFont;
+ }
+ elem = formatElem.namedItem( "WEIGHT" ).toElement();
+ if ( !elem.isNull() )
+ font.setWeight( elem.attribute( "value" ).toInt() );
+ elem = formatElem.namedItem( "SIZE" ).toElement();
+ if ( !elem.isNull() )
+ font.setPointSize( elem.attribute("value").toInt() );
+ elem = formatElem.namedItem( "ITALIC" ).toElement();
+ if ( !elem.isNull() )
+ font.setItalic( elem.attribute("value").toInt() == 1 );
+ elem = formatElem.namedItem( "UNDERLINE" ).toElement();
+ if ( !elem.isNull() ) {
+ QString value = elem.attribute("value");
+ if ( value == "0" || value == "1" )
+ format.setUnderlineType( (value.toInt() == 1)?KoTextFormat::U_SIMPLE: KoTextFormat::U_NONE );
+ else if ( value == "single" ) // value never used when saving, but why not support it? ;)
+ format.setUnderlineType ( KoTextFormat::U_SIMPLE);
+ else if ( value == "double" )
+ format.setUnderlineType ( KoTextFormat::U_DOUBLE);
+ else if ( value == "single-bold" )
+ format.setUnderlineType ( KoTextFormat::U_SIMPLE_BOLD);
+ else if( value =="wave")
+ format.setUnderlineType ( KoTextFormat::U_WAVE);
+ if ( elem.hasAttribute("styleline" ))
+ {
+ QString strLineType = elem.attribute("styleline");
+ format.setUnderlineStyle( KoTextFormat::stringToUnderlineStyle( strLineType ));
+ }
+ if ( elem.hasAttribute("underlinecolor"))
+ {
+ QColor col( QColor(elem.attribute("underlinecolor")));
+ format.setTextUnderlineColor( col );
+ }
+ if ( elem.hasAttribute( "wordbyword" ))
+ format.setWordByWord( elem.attribute("wordbyword").toInt()==1);
+ }
+ elem = formatElem.namedItem( "STRIKEOUT" ).toElement();
+ if ( !elem.isNull() )
+ {
+ QString value = elem.attribute("value");
+ if ( value == "0" || value == "1" )
+ format.setStrikeOutType( (value.toInt() == 1)?KoTextFormat::S_SIMPLE: KoTextFormat::S_NONE );
+ else if ( value == "single" ) // value never used when saving, but why not support it? ;)
+ format.setStrikeOutType ( KoTextFormat::S_SIMPLE);
+ else if ( value == "double" )
+ format.setStrikeOutType ( KoTextFormat::S_DOUBLE);
+ else if ( value =="single-bold" )
+ format.setStrikeOutType ( KoTextFormat::S_SIMPLE_BOLD);
+
+ if ( elem.hasAttribute("styleline" ))
+ {
+ QString strLineType = elem.attribute("styleline");
+ format.setStrikeOutStyle( KoTextFormat::stringToStrikeOutStyle( strLineType ));
+ }
+ if ( elem.hasAttribute( "wordbyword" ))
+ format.setWordByWord( elem.attribute("wordbyword").toInt()==1);
+ }
+ // ######## Not needed in 3.0?
+ /*
+ elem = formatElem.namedItem( "CHARSET" ).toElement();
+ if ( !elem.isNull() )
+ font.setCharSet( (QFont::CharSet) elem.attribute("value").toInt() );
+ */
+ format.setFont( font );
+
+ elem = formatElem.namedItem( "VERTALIGN" ).toElement();
+ if ( !elem.isNull() )
+ {
+ format.setVAlign( static_cast<KoTextFormat::VerticalAlignment>( elem.attribute("value").toInt() ) );
+ if (elem.hasAttribute("relativetextsize"))
+ format.setRelativeTextSize(elem.attribute("relativetextsize").toDouble());
+ }
+ elem = formatElem.namedItem( "COLOR" ).toElement();
+ if ( !elem.isNull() )
+ {
+ int red = elem.attribute("red").toInt();
+ int green = elem.attribute("green").toInt();
+ int blue = elem.attribute("blue").toInt();
+ if ( red == -1 && blue == -1 && green == -1 )
+ format.setColor( QColor() );
+ else
+ format.setColor( QColor(red,green,blue) );
+ }
+ elem = formatElem.namedItem( "TEXTBACKGROUNDCOLOR" ).toElement();
+ if ( !elem.isNull() )
+ {
+ int red = elem.attribute("red").toInt();
+ int green = elem.attribute("green").toInt();
+ int blue = elem.attribute("blue").toInt();
+ if ( red == -1 && blue == -1 && green == -1 )
+ format.setTextBackgroundColor( QColor() );
+ else
+ format.setTextBackgroundColor( QColor(red,green,blue) );
+ }
+ elem = formatElem.namedItem( "SHADOW" ).toElement();
+ if ( !elem.isNull() )
+ {
+ format.parseShadowFromCss( elem.attribute( "text-shadow" ) );
+ } else {
+ // Compat with koffice-1.2
+ elem = formatElem.namedItem( "SHADOWTEXT" ).toElement();
+ if ( !elem.isNull() && elem.attribute("value").toInt() && KoParagLayout::shadowCssCompat )
+ {
+ // Retrieve shadow attributes from KoParagLayout
+ // We don't have its pointer, so shadowCssCompat is static.
+ format.parseShadowFromCss( *KoParagLayout::shadowCssCompat );
+ }
+ }
+
+ elem = formatElem.namedItem( "OFFSETFROMBASELINE" ).toElement();
+ if ( !elem.isNull() )
+ format.setOffsetFromBaseLine( elem.attribute("value").toInt());
+
+ elem = formatElem.namedItem( "FONTATTRIBUTE" ).toElement();
+ if ( !elem.isNull() )
+ format.setAttributeFont( KoTextFormat::stringToAttributeFont(elem.attribute("value")));
+
+ elem = formatElem.namedItem( "LANGUAGE" ).toElement();
+ if ( !elem.isNull() )
+ format.setLanguage( elem.attribute("value") );
+ else if ( !refFormat )// No reference format and no LANGUAGE tag -> use default font
+ format.setLanguage( defaultLanguage );
+
+ //kdDebug() << "KWTextParag::loadFormat format=" << format.key() << endl;
+ return format;
+}
+
+void KWTextParag::loadLayout( QDomElement & attributes )
+{
+ QDomElement layout = attributes.namedItem( "LAYOUT" ).toElement();
+ if ( !layout.isNull() )
+ {
+ KWDocument * doc = kwTextDocument()->textFrameSet()->kWordDocument();
+ KoParagLayout paragLayout = loadParagLayout( layout, doc, true );
+ setParagLayout( paragLayout );
+
+ // Load default format from style.
+ KoTextFormat *defaultFormat = style() ? &style()->format() : 0L;
+ QDomElement formatElem = layout.namedItem( "FORMAT" ).toElement();
+ if ( !formatElem.isNull() )
+ {
+ // Load paragraph format
+ KoTextFormat f = loadFormat( formatElem, defaultFormat, doc->defaultFont(), doc->globalLanguage(), doc->globalHyphenation() );
+ setFormat( document()->formatCollection()->format( &f ) );
+ }
+ else // No paragraph format
+ {
+ if ( defaultFormat ) // -> use the one from the style
+ setFormat( document()->formatCollection()->format( defaultFormat ) );
+ }
+ }
+ else
+ {
+ // Even the simplest import filter should do <LAYOUT><NAME value="Standard"/></LAYOUT>
+ kdWarning(32001) << "No LAYOUT tag in PARAGRAPH, dunno what layout to apply" << endl;
+ }
+}
+
+void KWTextParag::load( QDomElement &attributes )
+{
+ loadLayout( attributes );
+
+ // Set the text after setting the paragraph format - so that the format applies
+ QDomElement element = attributes.namedItem( "TEXT" ).toElement();
+ if ( !element.isNull() )
+ {
+ //kdDebug() << "KWTextParag::load '" << element.text() << "'" << endl;
+ append( element.text() );
+ // Apply default format - this should be automatic !!
+ setFormat( 0, string()->length(), paragFormat(), TRUE );
+ }
+
+ if ( attributes.attribute( "toc" ) == "true" )
+ setPartOfTableOfContents( true );
+
+ loadFormatting( attributes );
+
+ setChanged( true );
+ invalidate( 0 );
+}
+
+void KWTextParag::loadFormatting( QDomElement &attributes, int offset, bool loadFootNote )
+{
+
+ QValueList<int> removeLenList;
+ QValueList<int> removePosList;
+
+ KWDocument * doc = kwTextDocument()->textFrameSet()->kWordDocument();
+ QDomElement formatsElem = attributes.namedItem( "FORMATS" ).toElement();
+ if ( !formatsElem.isNull() )
+ {
+ QDomElement formatElem = formatsElem.firstChild().toElement();
+ for ( ; !formatElem.isNull() ; formatElem = formatElem.nextSibling().toElement() )
+ {
+ if ( formatElem.tagName() == "FORMAT" )
+ {
+ int index = formatElem.attribute( "pos" ).toInt() + offset;
+ int len = formatElem.attribute( "len" ).toInt();
+
+ int id = formatElem.attribute( "id" ).toInt();
+ switch( id ) {
+ case 1: // Normal text
+ {
+ KoTextFormat f = loadFormat( formatElem, paragraphFormat(), doc->defaultFont(),doc->globalLanguage(), doc->globalHyphenation() );
+ //kdDebug(32002) << "KWTextParag::loadFormatting applying formatting from " << index << " to " << index+len << endl;
+ setFormat( index, len, document()->formatCollection()->format( &f ) );
+ break;
+ }
+ case 2: // Picture
+ {
+ len = 1; // it was missing from old 1.0 files
+
+ // The character matching this format is probably a QChar(1)
+ // However, as it is an invalid XML character, we must replace it
+ // or it will be written out while save the file.
+ KoTextStringChar& ch = string()->at(index);
+ if (ch.c.unicode()==1)
+ {
+ kdDebug() << "Replacing QChar(1) (in KWTextParag::loadFormatting)" << endl;
+ ch.c='#';
+ }
+
+ KWTextImage * custom = new KWTextImage( kwTextDocument(), QString::null );
+ kdDebug() << "KWTextParag::loadFormatting insertCustomItem" << endl;
+ paragFormat()->addRef();
+ setCustomItem( index, custom, paragFormat() );
+ custom->load( formatElem );
+ break;
+ }
+ case 3: // Tabulator
+ {
+ len = 1; // it was missing from old 1.0 files
+
+ // We have to replace the # or QChar(1) by a tabulator
+ KoTextStringChar& ch = string()->at(index);
+ ch.c='\t';
+
+ // I assume that we need the same treatment as for id == 1
+ KoTextFormat f = loadFormat( formatElem, paragraphFormat(), doc->defaultFont(),doc->globalLanguage(), doc->globalHyphenation() );
+ //kdDebug(32002) << "KWTextParag::loadFormatting applying formatting from " << index << " to " << index+len << endl;
+ setFormat( index, len, document()->formatCollection()->format( &f ) );
+ break;
+ }
+ case 4: // Variable
+ {
+ QDomElement varElem = formatElem.namedItem( "VARIABLE" ).toElement();
+ bool oldDoc = false;
+ if ( varElem.isNull() )
+ {
+ // Not found, must be an old document -> the tags were directly
+ // under the FORMAT tag.
+ varElem = formatElem;
+ oldDoc = true;
+ }
+ QDomElement typeElem = varElem.namedItem( "TYPE" ).toElement();
+ if ( typeElem.isNull() )
+ kdWarning(32001) <<
+ ( oldDoc ? "No <TYPE> in <FORMAT> with id=4, for a variable [old document assumed] !"
+ : "No <TYPE> found in <VARIABLE> tag!" ) << endl;
+ else
+ {
+ int type = typeElem.attribute( "type" ).toInt();
+ QString key = typeElem.attribute( "key" );
+ kdDebug() << "KWTextParag::loadFormatting variable type=" << type << " key=" << key << endl;
+ KoVariableFormat * varFormat = key.isEmpty() ? 0 : doc->variableFormatCollection()->format( key.latin1() );
+ // If varFormat is 0 (no key specified), the default format will be used.
+ int correct = 0;
+ if (typeElem.hasAttribute( "correct" ))
+ correct = typeElem.attribute("correct").toInt();
+ KoVariable * var =doc->variableCollection()->createVariable( type, -1, doc->variableFormatCollection(), varFormat,kwTextDocument(),doc, correct, true , loadFootNote);
+ if ( var )
+ {
+ var->load( varElem );
+ KoTextFormat f = loadFormat( formatElem, paragraphFormat(), doc->defaultFont(),doc->globalLanguage(), doc->globalHyphenation() );
+ setCustomItem( index, var, document()->formatCollection()->format( &f ) );
+ }
+ if(len>1) {
+ removePosList.append(index+1);
+ removeLenList.append(len-1);
+ }
+ }
+ break;
+ }
+ case 6: // Anchor
+ {
+ Q_ASSERT( len == 1 );
+ QDomElement anchorElem = formatElem.namedItem( "ANCHOR" ).toElement();
+ if ( !anchorElem.isNull() ) {
+ QString type = anchorElem.attribute( "type" );
+ if ( type == "grpMgr" /* old syntax */ || type == "frameset" )
+ {
+ QString framesetName = anchorElem.attribute( "instance" );
+ KWAnchorPosition pos;
+ pos.textfs = kwTextDocument()->textFrameSet();
+ pos.paragId = paragId();
+ pos.index = index;
+ doc->addAnchorRequest( framesetName, pos );
+ }
+ else
+ kdWarning() << "Anchor type not supported: " << type << endl;
+ }
+ else
+ kdWarning() << "Missing ANCHOR tag" << endl;
+ break;
+ }
+ default:
+ kdWarning() << "KWTextParag::loadFormatting id=" << id << " not supported" << endl;
+ break;
+ }
+ }
+ }
+ }
+ for(unsigned int i=0; i < removeLenList.count(); i++) {
+ remove(*removePosList.at(i), *removeLenList.at(i));
+ }
+}
+
+void KWTextParag::setParagLayout( const KoParagLayout & layout, int flags, int marginIndex )
+{
+ KoTextParag::setParagLayout( layout, flags, marginIndex );
+
+ if ( flags & KoParagLayout::PageBreaking )
+ setPageBreaking( layout.pageBreaking );
+}
+
+//////////
+
+// Create a KoParagLayout from XML.
+KoParagLayout KWTextParag::loadParagLayout( QDomElement & parentElem, KWDocument *doc, bool findStyle )
+{
+ KoParagLayout layout;
+
+ // Only when loading paragraphs, not when loading styles
+ if ( findStyle )
+ {
+ KoParagStyle *style;
+ // Name of the style. If there is no style, then we do not supply
+ // any default!
+ QDomElement element = parentElem.namedItem( "NAME" ).toElement();
+ if ( !element.isNull() )
+ {
+ QString styleName = element.attribute( "value" );
+ style = doc->styleCollection()->findStyle( styleName );
+ if (!style)
+ {
+ kdError(32001) << "Cannot find style \"" << styleName << "\" specified in paragraph LAYOUT - using Standard" << endl;
+ style = doc->styleCollection()->findStyle( "Standard" );
+ }
+ //else kdDebug() << "KoParagLayout::KoParagLayout setting style to " << style << " " << style->name() << endl;
+ }
+ else
+ {
+ kdError(32001) << "Missing NAME tag in paragraph LAYOUT - using Standard" << endl;
+ style = doc->styleCollection()->findStyle( "Standard" );
+ }
+ Q_ASSERT(style);
+ layout.style = style;
+ }
+
+ KoParagLayout::loadParagLayout( layout, parentElem, doc->syntaxVersion() );
+
+ return layout;
+}
+
+void KWTextParag::join( KoTextParag *parag )
+{
+ m_layout.pageBreaking &= ~(KoParagLayout::HardFrameBreakBefore|KoParagLayout::HardFrameBreakAfter);
+ KoTextParag::join( parag );
+}
+
+void KWTextParag::loadOasis( const QDomElement& paragElement, KoOasisContext& context, KoStyleCollection *styleCollection, uint& pos )
+{
+ KoTextParag::loadOasis( paragElement, context, styleCollection, pos );
+
+ KWTextFrameSet* textfs = kwTextDocument()->textFrameSet();
+ if ( textfs->isMainFrameset() && textfs->kWordDocument()->isLoading() /*not during copy/paste*/ )
+ {
+ KWDocument * doc = textfs->kWordDocument();
+ QString& currentMasterPageRef = doc->loadingInfo()->m_currentMasterPage;
+ const QString styleName = paragElement.attributeNS( KoXmlNS::text, "style-name", QString::null );
+ if ( !styleName.isEmpty() )
+ {
+ const QDomElement* paragraphStyle = context.oasisStyles().findStyle( styleName, "paragraph" );
+ QString masterPageName = paragraphStyle ? paragraphStyle->attributeNS( KoXmlNS::style, "master-page-name", QString::null ) : QString::null;
+
+ // In KWord we don't support sections so the first paragraph is the one that determines the page layout.
+ if ( prev() == 0 ) {
+ if ( masterPageName.isEmpty() )
+ masterPageName = "Standard"; // Seems to be a builtin name for the default layout...
+ currentMasterPageRef = masterPageName; // do this first to avoid recursion
+ context.styleStack().save();
+ context.styleStack().setTypeProperties( "paragraph" );
+ context.addStyles( paragraphStyle, "paragraph" );
+ // This is quite ugly... OOo stores the starting page-number in the first paragraph style...
+ QString pageNumber = context.styleStack().attributeNS( KoXmlNS::style, "page-number" );
+ if ( !pageNumber.isEmpty() )
+ doc->variableCollection()->variableSetting()->setStartingPageNumber( pageNumber.toInt() );
+ context.styleStack().restore();
+
+ doc->loadOasisPageLayout( masterPageName, context ); // page layout
+ }
+ else if ( !masterPageName.isEmpty() // empty means no change
+ && masterPageName != currentMasterPageRef )
+ {
+ // Detected a change in the master page -> this means we have to use a new page layout
+ // and insert a frame break if not on the first paragraph.
+ kdDebug(32001) << "KWTextParag::loadOasis: change of master page detected: from " << currentMasterPageRef << " to " << masterPageName << " -> inserting page break" << endl;
+ currentMasterPageRef = masterPageName;
+ // [see also KoParagLayout for the 'normal' way to insert page breaks]
+ m_layout.pageBreaking |= KoParagLayout::HardFrameBreakBefore;
+ // We have no way to load/use the new page layout, KWord doesn't have "sections".
+ }
+ }
+ }
+}
+
+void KWTextParag::saveOasis( KoXmlWriter& writer, KoSavingContext& context,
+ int from, int to, bool saveAnchorsFramesets ) const
+{
+ // Special case for inline tables that are alone in their paragraph:
+ // save <table> instead of <p>.
+ if ( string()->length() == 2 /*&& saveAnchorsFramesets*/ ) {
+ KoTextStringChar &ch = string()->at( 0 );
+ if ( ch.isCustom() && dynamic_cast<KWAnchor*>( ch.customItem() )) {
+ KWFrameSet* fs = static_cast<KWAnchor *>( ch.customItem() )->frameSet();
+ if ( fs->type() == FT_TABLE ) {
+ // TODO maybe save parag style? extract a common method out of KoTextStringChar::saveOasis
+ fs->saveOasis( writer, context, true );
+ return;
+ }
+ }
+ }
+ KoTextParag::saveOasis( writer, context, from, to, saveAnchorsFramesets );
+}
diff --git a/kword/KWTextParag.h b/kword/KWTextParag.h
new file mode 100644
index 00000000..9e3ffe27
--- /dev/null
+++ b/kword/KWTextParag.h
@@ -0,0 +1,98 @@
+/* This file is part of the KDE project
+ Copyright (C) 2001 David Faure <faure@kde.org>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+*/
+
+#ifndef kwtextparag_h
+#define kwtextparag_h
+
+#include "KoTextParag.h"
+
+class KoStyleCollection;
+class QDomDocument;
+class KWTextFrameSet;
+class KWTextDocument;
+class KWDocument;
+class KWTextParag;
+class KoParagStyle;
+
+// At the moment those are the same - to be discussed
+typedef KoParagLayout KWParagLayout;
+
+/**
+ * This class extends KoTextParag for KWord-specific formatting stuff,
+ * custom items, loading and saving.
+ */
+class KWTextParag : public KoTextParag
+{
+public:
+ KWTextParag( KoTextDocument *d, KoTextParag *pr = 0, KoTextParag *nx = 0, bool updateIds = TRUE )
+ : KoTextParag( d, pr, nx, updateIds ) { }
+ ~KWTextParag() { }
+
+ KWTextDocument * kwTextDocument() const;
+
+ virtual void setParagLayout( const KoParagLayout &layout, int flags = KoParagLayout::All, int marginIndex = -1 );
+
+ /** The type of page-breaking behaviour */
+ void setPageBreaking( int pb ); // warning this sets all the flags!
+ int pageBreaking() const { return m_layout.pageBreaking; }
+ bool linesTogether() const { return m_layout.pageBreaking & KoParagLayout::KeepLinesTogether; }
+ bool hardFrameBreakBefore() const { return m_layout.pageBreaking & KoParagLayout::HardFrameBreakBefore; }
+ bool hardFrameBreakAfter() const { return m_layout.pageBreaking & KoParagLayout::HardFrameBreakAfter; }
+
+ /** Public for loading a style (KWord-1.3 XML) */
+ static KoTextFormat loadFormat( QDomElement &formatElem, KoTextFormat *refFormat, const QFont &defaultFont, const QString & defaultLanguage, bool hyphanation );
+ /** Public for saving a style (KWord-1.3 XML) */
+ static QDomElement saveFormat( QDomDocument &doc, KoTextFormat *curFormat, KoTextFormat *refFormat, int pos, int len );
+
+
+ /** Save (to KWord-1.3 XML) the whole paragraph */
+ void save( QDomElement &parentElem, bool saveAnchorsFramesets = false );
+
+ /** Save (to KWord-1.3 XML) a portion of the paragraph */
+ void save( QDomElement &parentElem, int from, int to, bool saveAnchorsFramesets = false );
+
+ /** Load (from KWord-1.3 XML) the paragraph */
+ void load( QDomElement &attributes );
+
+ /** Load (from KWord-1.3 XML) and apply \<FORMAT\> tags (used by KWTextParag::load and by KWPasteCommand) */
+ void loadFormatting( QDomElement &attributes, int offset = 0, bool loadFootNote=true );
+
+ /** Load (from KWord-1.3 XML) and apply paragraph layout */
+ void loadLayout( QDomElement & attributes );
+
+ /** Load (from KWord-1.3 XML), optionally using styles from document. */
+ static KoParagLayout loadParagLayout( QDomElement & parentElem, KWDocument *doc, bool useRefStyle );
+
+ virtual void loadOasis( const QDomElement& e, KoOasisContext& context, KoStyleCollection *styleCollection, uint& pos );
+ virtual void saveOasis( KoXmlWriter& writer, KoSavingContext& context,
+ int from, int to, bool saveAnchorsFramesets = false ) const;
+
+ virtual void join( KoTextParag *parag );
+protected:
+ virtual void drawFormattingChars( QPainter &painter, int start, int len,
+ int lastY_pix, int baseLine_pix, int h_pix, // in pixels
+ bool drawSelections,
+ KoTextFormat *lastFormat, const QMemArray<int> &selectionStarts,
+ const QMemArray<int> &selectionEnds, const QColorGroup &cg,
+ bool rightToLeft, int line, KoTextZoomHandler* zh,
+ int whichFormattingChars );
+
+};
+
+#endif
diff --git a/kword/KWVariable.cpp b/kword/KWVariable.cpp
new file mode 100644
index 00000000..675f22b1
--- /dev/null
+++ b/kword/KWVariable.cpp
@@ -0,0 +1,739 @@
+/* This file is part of the KDE project
+ Copyright (C) 1998, 1999 Reginald Stadlbauer <reggie@kde.org>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+*/
+
+#include "KWVariable.h"
+
+#include "KWTextFrameSet.h"
+#include "KWTextDocument.h"
+#include "KWMailMergeDataBase.h"
+#include "KWDocument.h"
+#include "KWCommand.h"
+#include "KWViewMode.h"
+#include "KWPageManager.h"
+
+#include <KoVariable.h>
+#include <KoXmlWriter.h>
+#include <KoXmlNS.h>
+#include <KoDom.h>
+
+#include <klocale.h>
+#include <kdebug.h>
+
+KWVariableSettings::KWVariableSettings() : KoVariableSettings()
+{
+ m_footNoteCounter.setSuffix( QString::null );
+ m_endNoteCounter.setSuffix( QString::null );
+ // By default endnotes are numbered in lowercase roman numbers, in other WPs.
+ m_endNoteCounter.setStyle( KoParagCounter::STYLE_ROM_NUM_L );
+}
+
+void KWVariableSettings::changeFootNoteCounter( KoParagCounter _c )
+{
+ m_footNoteCounter = _c;
+}
+
+void KWVariableSettings::changeEndNoteCounter( KoParagCounter _c )
+{
+ m_endNoteCounter = _c;
+}
+
+void KWVariableSettings::saveNoteConfiguration( KoXmlWriter& writer ) const
+{
+ writer.startElement( "text:notes-configuration" );
+ writer.addAttribute( "text:note-class", "footnote" );
+ // let the counter save: num-prefix num-suffix num-format start-value
+ m_footNoteCounter.saveOasisListLevel( writer, false );
+ writer.addAttribute( "text:footnotes-position", "page" ); // tell OO what we do
+ writer.addAttribute( "text:start-numbering-at", "document" ); // tell OO what we do
+ writer.endElement();
+ writer.startElement( "text:notes-configuration" );
+ writer.addAttribute( "text:note-class", "endnote" );
+ // let the counter save: num-prefix num-suffix num-format start-value
+ m_endNoteCounter.saveOasisListLevel( writer, false );
+ writer.addAttribute( "text:start-numbering-at", "document" ); // tell OO what we do
+ writer.endElement();
+}
+
+void KWVariableSettings::loadNoteConfiguration( const QDomElement& parent )
+{
+ QDomElement e;
+ forEachElement( e, parent )
+ {
+ if ( e.localName() == "notes-configuration" && e.namespaceURI() == KoXmlNS::text )
+ {
+ const QString noteClass = e.attributeNS( KoXmlNS::text, "note-class", QString::null );
+ if ( noteClass == "footnote" ) {
+ m_footNoteCounter.loadOasisListStyle( e, QDomElement(), QDomElement(), -1, true, false, 1, false );
+ m_footNoteCounter.setNumbering( KoParagCounter::NUM_FOOTNOTE );
+ m_footNoteCounter.setRestartCounter( false );
+ }
+ else if ( noteClass == "endnote" ) {
+ m_endNoteCounter.loadOasisListStyle( e, QDomElement(), QDomElement(), -1, true, false, 1, false );
+ m_endNoteCounter.setNumbering( KoParagCounter::NUM_FOOTNOTE );
+ m_endNoteCounter.setRestartCounter( false );
+ }
+ }
+ }
+}
+
+void KWVariableSettings::save( QDomElement &parentElem )
+{
+ KoVariableSettings::save( parentElem );
+ QDomDocument doc = parentElem.ownerDocument();
+ QDomElement footNoteSettingElem = doc.createElement( "FOOTNOTESETTING" );
+ parentElem.appendChild( footNoteSettingElem );
+ m_footNoteCounter.save( footNoteSettingElem );
+ QDomElement endNoteSettingElem = doc.createElement( "ENDNOTESETTING" );
+ parentElem.appendChild( endNoteSettingElem );
+ m_endNoteCounter.save( endNoteSettingElem );
+}
+
+void KWVariableSettings::load( QDomElement &elem )
+{
+ KoVariableSettings::load( elem );
+ QDomElement footNoteSettings = elem.namedItem( "FOOTNOTESETTING" ).toElement();
+ if ( !footNoteSettings.isNull() )
+ m_footNoteCounter.load( footNoteSettings );
+ QDomElement endNoteSettings = elem.namedItem( "ENDNOTESETTING" ).toElement();
+ if ( !endNoteSettings.isNull() )
+ m_endNoteCounter.load( endNoteSettings );
+}
+
+KWVariableCollection::KWVariableCollection(KWVariableSettings *_setting, KoVariableFormatCollection* coll)
+ : KoVariableCollection(_setting, coll)
+{
+}
+
+KoVariable* KWVariableCollection::loadOasisField( KoTextDocument* textdoc, const QDomElement& tag, KoOasisContext& context )
+{
+ const QString localName( tag.localName() );
+ const bool isTextNS = tag.namespaceURI() == KoXmlNS::text;
+ if ( isTextNS )
+ {
+ //kdDebug()<<" localName :"<<localName<<endl;
+ if ( localName == "note" )
+ {
+ QString key = "STRING";
+ int type = VT_FOOTNOTE;
+ return loadOasisFieldCreateVariable( textdoc, tag, context, key, type );
+ }
+ else if ( localName == "table-count" ||
+ localName == "object-count" ||
+ localName == "picture-count" ||
+ localName == "paragraph-count" ||
+ localName == "word-count" ||
+ localName == "character-count" ||
+ localName == "sentence-count" ||
+ localName == "line-count" ||
+ localName == "frame-count" ||
+ localName == "non-whitespace-character-count" ||
+ localName == "syllable-count")
+ {
+ QString key = "NUMBER";
+ int type = VT_STATISTIC;
+ return loadOasisFieldCreateVariable( textdoc, tag, context, key, type );
+ }
+ else
+ return KoVariableCollection::loadOasisField( textdoc, tag, context );
+ }
+ else
+ return KoVariableCollection::loadOasisField( textdoc, tag, context );
+}
+
+KoVariable *KWVariableCollection::createVariable( int type, short int subtype, KoVariableFormatCollection * coll, KoVariableFormat *varFormat,KoTextDocument *textdoc, KoDocument * doc, int _correct,bool _forceDefaultFormat, bool loadFootNote )
+{
+ KWDocument *m_doc = static_cast<KWDocument *>(doc);
+ KoVariable * var = 0L;
+ switch(type) {
+ case VT_PGNUM:
+ if ( !varFormat )
+ varFormat = (subtype == KoPageVariable::VST_CURRENT_SECTION) ? coll->format("STRING") : coll->format("NUMBER");
+ var = new KWPgNumVariable( textdoc, subtype, varFormat, this, m_doc );
+ break;
+ case VT_MAILMERGE:
+ var = new KWMailMergeVariable( textdoc, QString::null, coll->format("STRING"), this, m_doc );
+ break;
+ case VT_FOOTNOTE:
+ if ( !loadFootNote )
+ return 0L;
+ if ( !varFormat )
+ varFormat = coll->format("STRING");
+ var = new KWFootNoteVariable( textdoc, varFormat, this, m_doc );
+ break;
+ case VT_STATISTIC:
+ if ( !varFormat )
+ varFormat = coll->format("NUMBER");
+ var = new KWStatisticVariable( textdoc, subtype, varFormat, this, m_doc );
+ break;
+ default:
+ return KoVariableCollection::createVariable( type, subtype, coll, varFormat, textdoc, doc, _correct, _forceDefaultFormat );
+ }
+ return var;
+}
+
+/******************************************************************/
+/* Class: KWPgNumVariable */
+/******************************************************************/
+KWPgNumVariable::KWPgNumVariable( KoTextDocument *textdoc, int subtype, KoVariableFormat *varFormat ,KoVariableCollection *_varColl, KWDocument *doc )
+ : KoPageVariable( textdoc, subtype, varFormat ,_varColl ), m_doc(doc)
+{
+}
+
+void KWPgNumVariable::recalc()
+{
+ if ( !m_doc->layoutViewMode()->hasPages() ) // ModeText
+ {
+ //necessary to resize it in this mode because in this mode
+ //we don't call KWTextFrameSet::drawFrame()
+ resize();
+ return;
+ }
+
+ if ( m_subtype == VST_PGNUM_TOTAL )
+ {
+ m_varValue = QVariant(m_doc->pageCount()+m_varColl->variableSetting()->startingPageNumber()-1);
+ resize();
+ }
+ // The other cases are handled by the more dynamic code in KWTextFrameSet::drawFrame()
+ // But we don't want to keep a width of -1 ...
+ if ( width == -1 )
+ width = 0;
+}
+
+QString KWPgNumVariable::text(bool realValue)
+{
+ if (m_varColl->variableSetting()->displayFieldCode()&& !realValue)
+ return fieldCode();
+ // #### ??? What?
+ else if ( m_subtype != VST_CURRENT_SECTION && !m_doc->layoutViewMode()->hasPages() && !realValue)
+ return fieldCode();
+ else
+ return m_varFormat->convert( m_varValue );
+}
+
+/******************************************************************/
+/* Class: KWMailMergeVariable */
+/******************************************************************/
+KWMailMergeVariable::KWMailMergeVariable( KoTextDocument *textdoc, const QString &name, KoVariableFormat *varFormat,KoVariableCollection *_varColl, KWDocument *doc )
+ : KoMailMergeVariable( textdoc, name, varFormat,_varColl ), m_doc(doc)
+{
+}
+
+QString KWMailMergeVariable::value() const
+{
+ return m_doc->mailMergeDataBase()->getValue( m_varValue.toString() );
+}
+
+QString KWMailMergeVariable::text(bool realValue)
+{
+ if (m_varColl->variableSetting()->displayFieldCode()&& !realValue)
+ return fieldCode();
+ // ## should use a format maybe
+ QString v = value();
+ if ( m_doc->mailMergeDataBase()->isSampleRecord() )
+ return "<" + v + ">";
+ return v;
+}
+
+void KWMailMergeVariable::recalc()
+{
+ resize();
+}
+
+/////////////
+
+KWFootNoteVariable::KWFootNoteVariable( KoTextDocument *textdoc, KoVariableFormat *varFormat, KoVariableCollection *varColl, KWDocument *doc )
+ : KoVariable( textdoc, varFormat, varColl ),
+ m_doc(doc),
+ m_frameset( 0L ),
+ m_numberingType( Auto ),
+ m_num( -1 ),
+ m_numDisplay( -1 )
+{
+ m_varValue = QVariant( QString::null );
+}
+
+void KWFootNoteVariable::setNumberingType( Numbering _type )
+{
+ m_numberingType = _type;
+ //delete m_varFormat;
+ setVariableFormat(m_doc->variableFormatCollection()->format("STRING"));
+}
+
+void KWFootNoteVariable::loadOasis( const QDomElement& footNoteTag, KoOasisContext& context )
+{
+ /*<text:note text:id="ftn0" text:note-class="footnote"><text:note-citation>1</text:note-citation><text:note-body>
+ <text:p text:style-name="Footnote"></text:p></text:note-body></text:note> */
+ const QString id = footNoteTag.attributeNS( KoXmlNS::text, "id", QString::null );
+
+ if ( footNoteTag.hasAttributeNS( KoXmlNS::text, "note-class" ) )
+ {
+ const QString str = footNoteTag.attributeNS( KoXmlNS::text, "note-class", QString::null );
+ if ( str == "footnote" )
+ m_noteType = FootNote;
+ else if ( str == "endnote" )
+ m_noteType = EndNote;
+ else {
+ kdWarning()<<" Unknown footnote type: '" << str << "'" << endl;
+ m_noteType = FootNote;
+ }
+ }
+
+ QDomElement element;
+ QDomElement bodyElement;
+ forEachElement( element, footNoteTag )
+ {
+ if ( element.namespaceURI() != KoXmlNS::text )
+ continue;
+
+ const QString localName = element.localName();
+ if( localName == "note-citation" )
+ {
+ if ( element.hasAttributeNS( KoXmlNS::text, "label" ) )
+ m_numberingType = Manual;
+ else
+ m_numberingType = Auto;
+ if ( m_numberingType == Auto )
+ {
+ //kdDebug()<<" automatic \n";
+ m_numDisplay = element.text().toInt();
+ formatedNote();
+ }
+ else
+ {
+ // kdDebug()<<" manual \n";
+ m_varValue = QVariant( element.text() );
+ }
+ } else if ( localName == "note-body" ) {
+ bodyElement = element;
+ }
+ }
+ Q_ASSERT( !bodyElement.isNull() );
+
+ Q_ASSERT( !m_frameset );
+ m_frameset = new KWFootNoteFrameSet( m_doc, id );
+ m_frameset->setFrameSetInfo( KWFrameSet::FI_FOOTNOTE );
+
+ m_frameset->setFootNoteVariable( this );
+ m_frameset->createInitialFrame( 0 );
+ m_doc->addFrameSet( m_frameset );
+
+ // Load the body of the footnote
+ m_frameset->loadOasisContent( bodyElement, context );
+}
+
+void KWFootNoteVariable::saveOasis( KoXmlWriter& writer, KoSavingContext& context ) const
+{
+ if(! m_frameset) return; // see bug #126007
+
+ //<text:note text:id="ftn0" text:note-class="footnote"><text:note-citation>1</text:note-citation><text:note-body><text:p text:style-name="Footnote"/></text:note-body></text:note>
+ //<text:note text:id="ftn1" text:note-class="endnote"><text:note-citation>i</text:note-citation><text:note-body><text:p text:style-name="Endnote"/></text:note-body></text:note>
+ //<text:note text:id="ftn2" text:note-class="footnote"><text:note-citation text:label="vv">vv</text:note-citation><text:note-body><text:p text:style-name="Footnote"/></text:note-body></text:note>
+ writer.startElement( "text:note" );
+ writer.addAttribute( "text:id",m_frameset->name() );
+ writer.addAttribute( "text:note-class", m_noteType == FootNote ? "footnote" : "endnote" );
+
+ writer.startElement( "text:note-citation" );
+ if ( m_numberingType == Auto )
+ writer.addTextNode( QString( "%1" ).arg( m_numDisplay ) );
+ else
+ {
+ writer.addAttribute( "text:label", m_varValue.toString() );
+ writer.addTextNode(m_varValue.toString() );
+ }
+ writer.endElement();
+
+ writer.startElement( "text:note-body" );
+ //save text from end/footnote
+ m_frameset->saveOasisContent( writer, context );
+ writer.endElement();
+
+ writer.endElement();
+}
+
+void KWFootNoteVariable::saveVariable( QDomElement &parentElem )
+{
+ QDomElement footnoteElem = parentElem.ownerDocument().createElement( "FOOTNOTE" );
+ parentElem.appendChild( footnoteElem );
+ //footnoteElem.setAttribute( "subtype", 0 );
+ if ( m_numberingType == Auto )
+ footnoteElem.setAttribute( "value", m_numDisplay );
+ else
+ footnoteElem.setAttribute( "value", m_varValue.toString() );
+ footnoteElem.setAttribute( "notetype", m_noteType == FootNote ? "footnote" : "endnote" );
+ footnoteElem.setAttribute( "numberingtype", m_numberingType == Auto ? "auto" : "manual" );
+ Q_ASSERT( m_frameset );
+ if( m_frameset )
+ footnoteElem.setAttribute( "frameset", m_frameset->name() );
+}
+
+void KWFootNoteVariable::load( QDomElement &elem )
+{
+ KoVariable::load( elem );
+ QDomElement footnoteElem = elem.namedItem( "FOOTNOTE" ).toElement();
+ if (!footnoteElem.isNull())
+ {
+ //m_subtype = footnoteElem.attribute("subtype").toInt();
+ QString str = footnoteElem.attribute("notetype").lower();
+ if ( str == "footnote" )
+ m_noteType = FootNote;
+ else if ( str == "endnote" )
+ m_noteType = EndNote;
+ else
+ kdWarning() << "Unknown footnote type: '" << str << "'" << endl;
+
+ str = footnoteElem.attribute("numberingtype").lower();
+ if ( str == "auto" )
+ m_numberingType = Auto;
+ else if ( str == "manual")
+ m_numberingType = Manual;
+ else
+ kdWarning() << "Unknown footnote numbering: '" << str << "'" << endl;
+
+ if ( m_numberingType == Auto )
+ {
+ m_numDisplay = footnoteElem.attribute("value").toInt();
+ formatedNote();
+ }
+ else
+ m_varValue = QVariant(footnoteElem.attribute("value"));
+
+ str = footnoteElem.attribute("frameset");
+ m_doc->addFootNoteRequest( str, this );
+ }
+}
+
+void KWFootNoteVariable::formatedNote()
+{
+ if ( m_numberingType == Auto )
+ {
+ m_varValue = QVariant(applyStyle());
+ }
+}
+
+QString KWFootNoteVariable::applyStyle()
+{
+ KWVariableSettings* settings = static_cast<KWVariableSettings*>(m_varColl->variableSetting());
+ KoParagCounter tmpCounter = (m_noteType == FootNote) ? settings->footNoteCounter() : settings->endNoteCounter();
+
+ QString tmp;
+ int val = m_numDisplay + tmpCounter.startNumber()-1;
+ Q_ASSERT( val >= 0 );
+ if ( val < 0 ) // let's not go into makeRomanNumber with a negative number :}
+ return i18n("ERROR");
+ switch ( tmpCounter.style() )
+ {
+ case KoParagCounter::STYLE_NUM:
+ tmp.setNum( val );
+ break;
+ case KoParagCounter::STYLE_ALPHAB_L:
+ tmp=KoParagCounter::makeAlphaLowerNumber( val );
+ break;
+ case KoParagCounter::STYLE_ALPHAB_U:
+ tmp=KoParagCounter::makeAlphaUpperNumber( val );
+ break;
+ case KoParagCounter::STYLE_ROM_NUM_L:
+ tmp = KoParagCounter::makeRomanNumber( val ).lower();
+ break;
+ case KoParagCounter::STYLE_ROM_NUM_U:
+ tmp = KoParagCounter::makeRomanNumber( val ).upper();
+ break;
+ case KoParagCounter::STYLE_CUSTOMBULLET:
+ //todo change font
+ tmp = tmpCounter.customBulletCharacter();
+ break;
+ default:
+ tmp.setNum( val );
+ break;
+ }
+
+ tmp.prepend( tmpCounter.prefix() );
+ tmp.append( tmpCounter.suffix() );
+ return tmp;
+}
+
+QString KWFootNoteVariable::text(bool realValue)
+{
+ if (m_varColl->variableSetting()->displayFieldCode()&& !realValue)
+ return fieldCode();
+ return m_varFormat->convert( m_varValue );
+}
+
+void KWFootNoteVariable::setNumDisplay( int val )
+{
+ m_numDisplay = val;
+ if ( val != -1 ) // -1 is used to 'invalidate so that renumberFootNotes recalcs'
+ formatedNote();
+}
+
+QString KWFootNoteVariable::fieldCode()
+{
+ return (noteType()==FootNote) ?i18n("Footnote"):i18n("Endnote");
+}
+
+void KWFootNoteVariable::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 )
+{
+ KoTextFormat * fmt = format();
+ KoTextZoomHandler * zh = textDocument()->paintingZoomHandler();
+
+ // Force drawing as "superscript" - hmm, the formatting will use too big font metrics though.
+ QFont font( fmt->screenFont( zh ) );
+ int pointSize = ( ( font.pointSize() * 2 ) / 3 );
+ font.setPointSize( pointSize );
+
+ int offset = _offset;
+ if ( offset == 0 )
+ {
+ int h = zh->layoutUnitToPixelY( /*_y HACK,*/ height );
+ offset = -( h - QFontMetrics(font).height() );
+ }
+
+ QColor textColor( fmt->color() );
+ drawCustomItemHelper( p, x, y, wpix, hpix, ascentpix, cg, selected, offset, fmt, font, textColor, drawingShadow );
+}
+
+void KWFootNoteVariable::finalize()
+{
+ Q_ASSERT( m_frameset );
+ if (!m_frameset )
+ return;
+ Q_ASSERT( !m_frameset->isDeleted() );
+ if ( m_frameset->isDeleted() )
+ return;
+
+ //kdDebug(32001) << "KWFootNoteVariable::finalize" << endl;
+
+ int pageNum = this->pageNum();
+ if ( pageNum == -1 )
+ return;
+
+ KWFrame* footNoteFrame = m_frameset->frame( 0 );
+ int framePage = footNoteFrame->pageNumber();
+ if ( framePage != pageNum )
+ {
+ //kdDebug(32001) << "Footnote var '" << text() << "' at page " << pageNum << ", footnote frame at page " << framePage << " -> abortFormatting() and recalcFrames()" << endl;
+ KWTextFrameSet * fs = static_cast<KWTextDocument *>(textDocument())->textFrameSet();
+ fs->textObject()->abortFormatting();
+
+ // abortFormatting is a bool in kotextobject. So we need to return there before
+ // starting text layout again.
+ m_doc->delayedRecalcFrames( QMIN( pageNum, framePage ) );
+ m_doc->delayedRepaintAllViews();
+ }
+}
+
+void KWFootNoteVariable::resize()
+{
+ if ( m_deleted )
+ return;
+ KoTextFormat *fmt = format();
+ QFont font( fmt->refFont() ); // LU font
+ if ( fmt->vAlign() == KoTextFormat::AlignNormal ) // if it's still normal...
+ {
+ int pointSize = ( ( font.pointSize() * 2 ) / 3 ); // ...force superscript
+ font.setPointSize( pointSize );
+ }
+ QFontMetrics fm( font );
+ QString txt = text();
+ width = 0;
+ for ( int i = 0 ; i < (int)txt.length() ; ++i )
+ width += fm.charWidth( txt, i ); // size at 100%
+ // zoom to LU
+ width = qRound( KoTextZoomHandler::ptToLayoutUnitPt( width ) );
+ height = fmt->height();
+ m_ascent = fmt->ascent();
+ //kdDebug() << "KWFootNoteVariable::resize text=" << txt << " width=" << width << " height=" << height << endl;
+}
+
+void KWFootNoteVariable::setDeleted( bool del )
+{
+ kdDebug() << "KWFootNoteVariable::setDeleted " << del << endl;
+ if ( del )
+ {
+ Q_ASSERT( m_frameset );
+ if ( m_frameset ) {
+ m_frameset->deleteAllFrames(); // Important, because we don't want to save it!
+ m_frameset->setVisible( false );
+ }
+ }
+ else
+ {
+ Q_ASSERT( m_frameset );
+ if ( m_frameset ) {
+ kdDebug() << "Making frameset " << m_frameset << " visible" << endl;
+ m_frameset->setVisible( true );
+ if ( m_frameset->isDeleted() )
+ m_frameset->createInitialFrame( 0 ); // Page number shouldn't matter (see recalcFrames below).
+ Q_ASSERT( m_frameset->isVisible() );
+ }
+ }
+
+ // hmm, maybe compress all the stuff below and do only once
+ // (e.g. when deleting multiple footnotes)?
+ // (but we can't really delay it with a sst, the formatMore after undo/redo
+ // needs this to be done already, I think). Bah.
+
+ // Re-number footnote variables
+ KWTextFrameSet * textfs = static_cast<KWTextDocument *>(textDocument())->textFrameSet();
+ textfs->renumberFootNotes();
+
+ m_doc->recalcFrames();
+
+ if (!del)
+ m_frameset->layout(); // format its text, so that it resizes the frame
+ KoVariable::setDeleted( del );
+ // Does this compress? Probably not.
+ m_doc->delayedRepaintAllViews();
+}
+
+int KWFootNoteVariable::pageNum() const
+{
+ int page = m_doc->pageManager()->pageNumber(varY());
+ Q_ASSERT( page <= m_doc->lastPage() );
+ return page;
+}
+
+double KWFootNoteVariable::varY() const
+{
+ // Find out the position of the footnote variable in document coordinates.
+ int paragy = paragraph()->rect().y();
+ KWTextFrameSet * fs = static_cast<KWTextDocument *>(textDocument())->textFrameSet();
+ if ( !fs->hasFramesInPageArray() ) // we need it for internalToDocument
+ {
+ kdDebug(32001) << "KWFootNoteVariable::varY too early, no updateFrames yet" << endl;
+ return 0; // this happens on loading - frame layout is done before text layout
+ }
+ // What we need is "has never been formatted". Not "has just been invalidated"...
+ //if ( !paragraph()->isValid() )
+ //{
+ // kdDebug(32001) << "KWFootNoteVariable::varY called but paragraph " << paragraph()->paragId() << " not valid" << endl;
+ // return 0;
+ //}
+ KoPoint dPoint;
+ //kdDebug(32001) << "KWFootNoteVariable::pageNum position of variable (LU): " << QPoint( x(), paragy + y() + height ) << endl;
+ KWFrame* containingFrame = fs->internalToDocument( QPoint( x(), paragy + y() + height ), dPoint );
+ if ( containingFrame )
+ {
+ // Ok, the (bottom of the) footnote variable is at dPoint.
+ double varY = dPoint.y();
+ //kdDebug(32001) << " found containingFrame " << containingFrame << " page:" << containingFrame->pageNumber() << " varY=" << varY << endl;
+ //int pageNum = containingFrame->pageNumber(); // and at page pageNum
+ return varY;
+ } else
+ {
+ // This can happen if the page hasn't been created yet
+ //kdDebug(32001) << "KWFootNoteVariable::pageNum internalToDocument returned 0L for " << x << ", " << y+paragy << endl;
+ return 0;
+ }
+}
+
+
+KWStatisticVariable::KWStatisticVariable( KoTextDocument *textdoc, int subtype, KoVariableFormat *varFormat,KoVariableCollection *_varColl, KWDocument *doc )
+ : KoStatisticVariable( textdoc, subtype, varFormat, _varColl ),
+ m_doc(doc)
+{
+}
+
+void KWStatisticVariable::recalc()
+{
+ int nb = 0;
+ ulong charsWithSpace = 0L;
+ ulong charsWithoutSpace = 0L;
+ ulong words = 0L;
+ ulong sentences = 0L;
+ ulong lines = 0L;
+ ulong syllables = 0L;
+ bool frameInfo = ( m_subtype == VST_STATISTIC_NB_WORD ||
+ m_subtype == VST_STATISTIC_NB_SENTENCE ||
+ m_subtype == VST_STATISTIC_NB_LINES ||
+ m_subtype == VST_STATISTIC_NB_CHARACTERE);
+ QPtrListIterator<KWFrameSet> framesetIt( m_doc->framesetsIterator() );
+ //TODO change int to ulong
+ for ( framesetIt.toFirst(); framesetIt.current(); ++framesetIt )
+ {
+ KWFrameSet *frameSet = framesetIt.current();
+ if ( frameSet->isVisible() )
+ {
+ if ( m_subtype == VST_STATISTIC_NB_FRAME )
+ {
+ ++nb;
+ }
+ else if( m_subtype == VST_STATISTIC_NB_PICTURE && frameSet->type() == FT_PICTURE )
+ {
+ ++nb;
+ }
+ else if( m_subtype == VST_STATISTIC_NB_TABLE && frameSet->type() == FT_TABLE )
+ {
+ ++nb;
+ }
+ else if( m_subtype == VST_STATISTIC_NB_EMBEDDED && frameSet->type() == FT_PART )
+ {
+ ++nb;
+ }
+ if ( frameInfo
+ && (frameSet->frameSetInfo() == KWFrameSet::FI_FOOTNOTE || frameSet->frameSetInfo() == KWFrameSet::FI_BODY)
+ && frameSet->isVisible() )
+ {
+ frameSet->statistics( 0L, charsWithSpace, charsWithoutSpace,
+ words, sentences, syllables, lines, false );
+ }
+ }
+ if ( frameInfo )
+ {
+ if( m_subtype == VST_STATISTIC_NB_WORD )
+ {
+ nb = words;
+ }
+ else if( m_subtype == VST_STATISTIC_NB_SENTENCE )
+ {
+ nb = sentences;
+ }
+ else if( m_subtype == VST_STATISTIC_NB_LINES )
+ {
+ nb = lines;
+ }
+ else if ( m_subtype == VST_STATISTIC_NB_CHARACTERE )
+ {
+ nb = charsWithSpace;
+ }
+ else if ( m_subtype == VST_STATISTIC_NB_NON_WHITESPACE_CHARACTERE )
+ {
+ nb = charsWithoutSpace;
+ }
+ else if ( m_subtype == VST_STATISTIC_NB_SYLLABLE )
+ {
+ nb = syllables;
+ }
+ else
+ nb = 0;
+ }
+ }
+ m_varValue = QVariant(nb);
+ resize();
+ if ( width == -1 )
+ width = 0;
+}
+
+QString KWStatisticVariable::text(bool realValue)
+{
+ if ( m_varColl->variableSetting()->displayFieldCode() && !realValue )
+ return fieldCode();
+ else
+ return m_varFormat->convert( m_varValue );
+}
diff --git a/kword/KWVariable.h b/kword/KWVariable.h
new file mode 100644
index 00000000..545bea90
--- /dev/null
+++ b/kword/KWVariable.h
@@ -0,0 +1,183 @@
+/* This file is part of the KDE project
+ Copyright (C) 1998, 1999 Reginald Stadlbauer <reggie@kde.org>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+*/
+
+#ifndef variable_h
+#define variable_h
+
+#include <qstring.h>
+#include <qdatetime.h>
+#include <qasciidict.h>
+
+#include "defs.h"
+
+#include <KoVariable.h>
+#include <KoParagCounter.h>
+
+class KWDocument;
+class KWTextFrameSet;
+class KWFootNoteFrameSet;
+class KoVariable;
+class KoPageVariable;
+class KoMailMergeVariable;
+class QDomElement;
+class KoTextFormat;
+
+
+class KWVariableSettings : public KoVariableSettings
+{
+ public:
+ KWVariableSettings();
+ virtual ~KWVariableSettings() {}
+ virtual void save( QDomElement &parentElem );
+ virtual void load( QDomElement &elem );
+ void saveNoteConfiguration( KoXmlWriter& writer ) const;
+ void loadNoteConfiguration( const QDomElement& parent );
+ void changeFootNoteCounter( KoParagCounter _c );
+ void changeEndNoteCounter( KoParagCounter _c );
+ KoParagCounter endNoteCounter() const { return m_endNoteCounter;}
+ KoParagCounter footNoteCounter() const { return m_footNoteCounter;}
+ private:
+ KoParagCounter m_footNoteCounter;
+ KoParagCounter m_endNoteCounter;
+};
+
+class KWVariableCollection : public KoVariableCollection
+{
+ public:
+ KWVariableCollection(KWVariableSettings *_settings, KoVariableFormatCollection* coll);
+ virtual KoVariable *createVariable( int type, short int subtype, KoVariableFormatCollection * coll, KoVariableFormat *varFormat,KoTextDocument *textdoc, KoDocument * doc, int _correct, bool _forceDefaultFormat=false, bool loadFootNote= true );
+ virtual KoVariable* loadOasisField( KoTextDocument* textdoc, const QDomElement& tag, KoOasisContext& context );
+
+ private:
+ KWDocument *m_doc;
+};
+
+/**
+ * "current page number" and "number of pages" variables
+ */
+class KWPgNumVariable : public KoPageVariable
+{
+public:
+ KWPgNumVariable( KoTextDocument *textdoc, int subtype, KoVariableFormat *varFormat ,KoVariableCollection *_varColl, KWDocument *doc );
+
+ virtual void recalc();
+ virtual QString text(bool realValue=false);
+
+private:
+ KWDocument *m_doc;
+};
+
+
+/**
+ * Mail Merge variable
+ */
+class KWMailMergeVariable : public KoMailMergeVariable
+{
+public:
+ KWMailMergeVariable( KoTextDocument *textdoc, const QString &name, KoVariableFormat *varFormat,KoVariableCollection *_varColl, KWDocument *doc );
+
+ virtual QString text(bool realValue=false);
+ virtual QString value() const;
+ virtual void recalc();
+ private:
+ KWDocument *m_doc;
+};
+
+/**
+ * The variable showing the footnote number in superscript, in the text.
+ */
+class KWFootNoteVariable : public KoVariable
+{
+public:
+ KWFootNoteVariable( KoTextDocument *textdoc, KoVariableFormat *varFormat, KoVariableCollection *varColl, KWDocument *doc );
+ virtual VariableType type() const
+ { return VT_FOOTNOTE; }
+ enum Numbering {Auto, Manual};
+
+ void setNoteType( NoteType _noteType ) { m_noteType = _noteType;}
+ NoteType noteType() const {return m_noteType; }
+
+ void setNumberingType( Numbering _type );
+ Numbering numberingType() const { return m_numberingType;}
+
+ void setManualString( const QString & _str ) { m_varValue=QVariant(_str);}
+ QString manualString() const { return m_varValue.toString();}
+
+ virtual void resize();
+ virtual void 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 );
+
+ /** The frameset that contains the text for this footnote */
+ KWFootNoteFrameSet * frameSet() const { return m_frameset; }
+ void setFrameSet( KWFootNoteFrameSet* fs ) { Q_ASSERT( !m_frameset ); m_frameset = fs; }
+
+ virtual void saveVariable( QDomElement &parentElem );
+ virtual void load( QDomElement &elem );
+
+ virtual void loadOasis( const QDomElement &footNoteTag, KoOasisContext& context );
+ virtual void saveOasis( KoXmlWriter& writer, KoSavingContext& context ) const;
+
+
+ virtual QString text(bool realValue=false);
+ // Nothing to do here. Numbering done by KWTextFrameSet::renumberFootNotes
+ virtual void recalc() { }
+
+ // This is a sequence number, to order footnotes. It is always set, and different for all footnotes.
+ void setNum( int _num ) { m_num = _num; }
+ int num() const { return m_num; }
+
+ // The number being displayed - for auto-numbered footnotes only.
+ void setNumDisplay( int val );
+ int numDisplay() const { return m_numDisplay; }
+
+ virtual void finalize();
+
+ // The page this var is on
+ int pageNum() const;
+ // The current Y position of the var (in doc pt)
+ double varY() const;
+
+ virtual void setDeleted( bool del );
+
+ void formatedNote();
+ virtual QString fieldCode();
+protected:
+ QString applyStyle();
+
+private:
+ KWDocument *m_doc;
+ NoteType m_noteType;
+ KWFootNoteFrameSet* m_frameset;
+ Numbering m_numberingType;
+ int m_num;
+ int m_numDisplay;
+};
+
+
+class KWStatisticVariable : public KoStatisticVariable
+{
+public:
+ KWStatisticVariable( KoTextDocument *textdoc, int subtype, KoVariableFormat *varFormat,KoVariableCollection *_varColl, KWDocument *doc );
+ virtual void recalc();
+ virtual QString text(bool realValue=false);
+
+protected:
+ KWDocument *m_doc;
+};
+
+#endif
diff --git a/kword/KWView.cpp b/kword/KWView.cpp
new file mode 100644
index 00000000..ec7be88b
--- /dev/null
+++ b/kword/KWView.cpp
@@ -0,0 +1,7756 @@
+/* This file is part of the KDE project
+ Copyright (C) 1998, 1999 Reginald Stadlbauer <reggie@kde.org>
+ Copyright (C) 2001 David Faure <faure@kde.org>
+ Copyright (C) 2005 Thomas Zander <zander@kde.org>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA
+*/
+
+#undef Unsorted
+
+#include "KWView.h"
+
+#include "KWordViewIface.h"
+#include "KWConfigFootNoteDia.h"
+#include "defs.h"
+#include "KWDeleteDia.h"
+#include "KWDocStruct.h"
+#include "KWFootNoteDia.h"
+#include "KWInsertDia.h"
+#include "KWAnchor.h"
+#include "KoTextBookmark.h"
+#include "KWCanvas.h"
+#include "KWCommand.h"
+#include "KWConfig.h"
+#include "KWCreateBookmarkDia.h"
+#include "KWDocument.h"
+#include "KWEditPersonnalExpression.h"
+#include "KWFormulaFrameSet.h"
+#include "KWFrame.h"
+#include "KWPictureFrameSet.h"
+#include "KWFrameStyle.h"
+#include "KWFrameStyleManager.h"
+#include "KWImportStyleDia.h"
+#include "KWInsertPageDia.h"
+#include "KWInsertPicDia.h"
+#include "KWPartFrameSet.h"
+#include "KWStyleManager.h"
+#include "KWTableFrameSet.h"
+#include "KWTableStyle.h"
+#include "KWTableStyleManager.h"
+#include "KWTextDocument.h"
+#include "KWVariable.h"
+#include "KWViewMode.h"
+#include "KWMailMergeDataBase.h"
+#include "KWMailMergeLabelAction.h"
+#include "KWResizeTableDia.h"
+#include "KWFindReplace.h"
+#include "KWSortDia.h"
+#include "KWSplitCellDia.h"
+#include "KWTableDia.h"
+#include "KWCollectFramesetsVisitor.h"
+#include "KWOasisLoader.h"
+#include "KWOasisSaver.h"
+#include "KWFrameList.h"
+#include "KWPageManager.h"
+#include "KWPage.h"
+#include "KWFrameViewManager.h"
+#include "KWFrameView.h"
+#include "KWStatisticsDialog.h"
+
+#include <kformuladocument.h>
+#include <kformulamimesource.h>
+
+#include <KoRichText.h>
+#include <KoAutoFormat.h>
+#include <KoAutoFormatDia.h>
+#include <KoChangeCaseDia.h>
+#include <KoCharSelectDia.h>
+#include <KoCommentDia.h>
+#include <KoCreateStyleDia.h>
+#include <KoDocumentInfo.h>
+#include <KoFontDia.h>
+#include <KoFrame.h>
+#include <KoInsertLink.h>
+#include <KoMainWindow.h>
+#include <KoParagDia.h>
+#include <KoPartSelectAction.h>
+#include <KoPictureFilePreview.h>
+#include <KoSearchDia.h>
+#include <KoStore.h>
+#include <KoStoreDrag.h>
+#include <KoTemplateCreateDia.h>
+#include <KoCompletionDia.h>
+#include <KoVariable.h>
+#include <KoCustomVariablesDia.h>
+#include <KoTextObject.h>
+#include <tkcoloractions.h>
+#include <KoSpeaker.h>
+
+#include <kparts/partmanager.h>
+#include <kaccelgen.h>
+#include <kcolordialog.h>
+#include <kdebug.h>
+#include <kfiledialog.h>
+#include <kimageio.h>
+#include <kinputdialog.h>
+#include <kio/netaccess.h>
+#include <kmessagebox.h>
+#include <kparts/event.h>
+#include <kstandarddirs.h>
+#include <kstatusbar.h>
+#include <kstdaccel.h>
+#include <kstdaction.h>
+#include <ktempfile.h>
+#include <kurldrag.h>
+#include <kdeversion.h>
+#include <kiconloader.h>
+
+#include <qclipboard.h>
+#include <qapplication.h>
+#include <qgroupbox.h>
+#include <qlayout.h>
+#include <qpaintdevicemetrics.h>
+#include <qprogressdialog.h>
+#include <qregexp.h>
+#include <qtimer.h>
+#include <qbuffer.h>
+
+#include <stdlib.h>
+
+#include <kspell2/dialog.h>
+#include <kspell2/defaultdictionary.h>
+#include "KoSpell.h"
+
+using namespace KSpell2;
+
+/******************************************************************/
+/* Class: TableInfo */
+/******************************************************************/
+class TableInfo {
+ public:
+ TableInfo( const QValueList<KWFrameView*>& selectedFrames ) {
+ m_protectContent = false;
+ //m_views = selectedFrames;
+ int amountSelected = 0;
+ m_cell = 0;
+ QMap<KWTableFrameSet*, QValueList<unsigned int> > tableRows, tableCols;
+
+ QValueList<KWFrameView*>::const_iterator framesIterator = selectedFrames.begin();
+ for(;framesIterator != selectedFrames.end(); ++framesIterator) {
+ KWFrameView *view = *framesIterator;
+ if(!view->selected()) continue;
+ KWFrameSet *fs = view->frame()->frameSet();
+ Q_ASSERT(fs);
+ KWTableFrameSet::Cell *cell = dynamic_cast<KWTableFrameSet::Cell*>(fs);
+ if(cell == 0) continue;
+ amountSelected++;
+ if(cell->protectContent())
+ m_protectContent=true;
+
+ if(! tableRows.contains(fs->groupmanager())) { // create empty lists.
+ QValueList<unsigned int> rows;
+ for(unsigned int i=fs->groupmanager()->getRows(); i != 0; i--)
+ rows.append(0);
+ tableRows.insert(fs->groupmanager(), rows);
+ QValueList<unsigned int> cols;
+ for(unsigned int i=fs->groupmanager()->getColumns(); i != 0; i--)
+ cols.append(0);
+ tableCols.insert(fs->groupmanager(), cols);
+ }
+ QValueList<unsigned int> rows = tableRows[fs->groupmanager()];
+ for(unsigned int r=cell->firstRow(); r <= cell->lastRow(); r++)
+ rows[r] = rows[r] + 1;
+ tableRows[fs->groupmanager()] = rows;
+ QValueList<unsigned int> columns = tableCols[fs->groupmanager()];
+ for(unsigned int c=cell->firstColumn(); c <= cell->lastColumn(); c++)
+ columns[c] = columns[c] + 1;
+ tableCols[fs->groupmanager()] = columns;
+
+ if(m_cell == 0 || m_cell->firstRow() > cell->firstRow() ||
+ m_cell->firstRow() == cell->firstRow() &&
+ m_cell->firstColumn() > cell->firstColumn())
+ m_cell = cell;
+ }
+
+ m_selected = amountSelected != 0;
+ m_oneCellSelected = amountSelected == 1;
+ if(amountSelected == 0) return;
+
+ for(QMapIterator<KWTableFrameSet*, QValueList<unsigned int> > iter = tableRows.begin();
+ iter != tableRows.end(); ++iter) {
+ QValueList<unsigned int> rows = iter.data();
+ QValueListIterator<unsigned int> rowsIter = rows.begin();
+ for(int x=0;rowsIter != rows.end(); ++rowsIter, x++)
+ if(*rowsIter == iter.key()->getColumns())
+ m_rows.append(x);
+
+ QValueList<unsigned int> columns = tableCols[iter.key()];
+ QValueListIterator<unsigned int> colsIter = columns.begin();
+ for(int x=0;colsIter != columns.end(); ++colsIter, x++)
+ if(*colsIter == iter.key()->getRows())
+ m_columns.append(x);
+ }
+ }
+
+ int tableCellsSelected() { return m_selected; }
+ int amountRowsSelected() { return m_rows.count(); }
+ int amountColumnsSelected() { return m_columns.count(); }
+ bool oneCellSelected() { return m_oneCellSelected; }
+ bool protectContentEnabled() { return m_protectContent; }
+ QValueList<uint> selectedRows() { return m_rows; }
+ QValueList<uint> selectedColumns() { return m_columns; }
+ KWTableFrameSet::Cell *firstSelectedCell() { return m_cell; }
+ private:
+ //QValueList<KWFrameView*> m_views;
+ bool m_oneCellSelected, m_selected, m_protectContent;
+ QValueList<uint> m_rows, m_columns;
+ KWTableFrameSet::Cell *m_cell;
+};
+
+/******************************************************************/
+/* Class: KWView */
+/******************************************************************/
+KWView::KWView( const QString& viewMode, QWidget *parent, const char *name, KWDocument* doc )
+ : KoView( doc, parent, name )
+{
+ m_doc = doc;
+ m_gui = 0;
+
+ m_dcop = 0;
+ dcopObject(); // build it
+ m_fsInline=0;
+ m_spell.kospell = 0;
+ m_spell.dlg = 0;
+ m_broker = Broker::openBroker( KSharedConfig::openConfig( "kwordrc" ) );
+ m_spell.macroCmdSpellCheck=0L;
+ m_spell.textIterator = 0L;
+ m_currentPage = m_doc->pageManager()->page(m_doc->startPage());
+ m_specialCharDlg=0L;
+ m_searchEntry = 0L;
+ m_replaceEntry = 0L;
+ m_findReplace = 0L;
+ m_fontDlg = 0L;
+ m_paragDlg = 0L;
+ m_tableSplit.columns = 1;
+ m_tableSplit.rows = 1;
+
+ m_actionList.setAutoDelete( true );
+ m_variableActionList.setAutoDelete( true );
+ // Default values.
+ m_zoomViewModeNormal.m_zoom = m_doc->zoom();
+ m_zoomViewModeNormal.m_zoomMode = m_doc->zoomMode();
+ m_zoomViewModePreview.m_zoom = 33; // TODO: bad to leave hardcoded...
+ m_zoomViewModePreview.m_zoomMode = KoZoomMode::ZOOM_CONSTANT;
+
+ m_viewFrameBorders = m_doc->viewFrameBorders();
+ KoView::setZoom( m_doc->zoomedResolutionY() /* KoView only supports one zoom */ ); // initial value
+ //m_viewTableGrid = true;
+
+ setInstance( KWFactory::instance() );
+ if ( !m_doc->isReadWrite() )
+ setXMLFile( "kword_readonly.rc" );
+ else
+ setXMLFile( "kword.rc" );
+
+
+ QObject::connect( this, SIGNAL( embeddImage( const QString & ) ),
+ this, SLOT( slotEmbedImage( const QString & ) ) );
+
+ setKeyCompression( TRUE );
+ setAcceptDrops( TRUE );
+
+ setupActions();
+
+ m_gui = new KWGUI( viewMode, this, this );
+ m_gui->setGeometry( 0, 0, width(), height() );
+ m_gui->show();
+
+ m_sbPageLabel = 0;
+ m_sbModifiedLabel = 0;
+ m_sbFramesLabel = 0;
+ m_sbOverwriteLabel = 0;
+ m_sbZoomLabel = 0;
+ m_sbUnitLabel = 0;
+ if ( KStatusBar* sb = statusBar() ) // No statusbar in e.g. konqueror
+ {
+ m_sbPageLabel = new KStatusBarLabel( QString::null, 0, sb );
+ m_sbPageLabel->setAlignment( AlignLeft | AlignVCenter );
+ addStatusBarItem( m_sbPageLabel, 0 );
+
+ m_sbModifiedLabel = new KStatusBarLabel( " ", 0, sb );
+ m_sbModifiedLabel->setAlignment( AlignLeft | AlignVCenter );
+ addStatusBarItem( m_sbModifiedLabel, 0 );
+
+ m_sbFramesLabel = new KStatusBarLabel( QString::null, 0, sb );
+ m_sbFramesLabel->setAlignment( AlignLeft | AlignVCenter );
+ addStatusBarItem( m_sbFramesLabel, 1 );
+
+ m_sbOverwriteLabel = new KStatusBarLabel( ' ' + i18n( "INSRT" ) + ' ', 0, sb );
+ m_sbOverwriteLabel->setAlignment( AlignHCenter | AlignVCenter );
+ addStatusBarItem( m_sbOverwriteLabel, 0 );
+
+ m_sbZoomLabel = new KStatusBarLabel( ' ' + QString::number( m_doc->zoom() ) + "% ", 0, sb );
+ m_sbZoomLabel->setAlignment( AlignHCenter | AlignVCenter );
+ addStatusBarItem( m_sbZoomLabel, 0 );
+
+ m_sbUnitLabel = new KStatusBarLabel( ' ' + KoUnit::unitDescription( m_doc->unit() ) + ' ', 0, sb );
+ m_sbUnitLabel->setAlignment( AlignHCenter | AlignVCenter );
+ addStatusBarItem( m_sbUnitLabel, 0 );
+ }
+
+ connect( m_doc, SIGNAL( modified( bool ) ),
+ this, SLOT( documentModified( bool )) );
+
+ connect( m_doc, SIGNAL( numPagesChanged() ),
+ this, SLOT( numPagesChanged()) );
+
+ connect( m_doc, SIGNAL( pageLayoutChanged( const KoPageLayout& ) ),
+ this, SLOT( slotPageLayoutChanged( const KoPageLayout& )) );
+
+ connect( m_doc, SIGNAL( docStructureChanged(int) ),
+ this, SLOT( docStructChanged(int)) );
+
+ connect( m_doc, SIGNAL( unitChanged(KoUnit::Unit) ),
+ this, SLOT( slotUnitChanged(KoUnit::Unit) ) );
+
+ connect( m_doc, SIGNAL( sig_refreshMenuCustomVariable()),
+ this, SLOT( refreshCustomMenu()));
+
+ connect( m_doc, SIGNAL( completed() ),
+ this, SLOT( slotDocumentLoadingCompleted() ) );
+
+ connect( frameViewManager(), SIGNAL(sigFrameSelectionChanged()),
+ this, SLOT( frameSelectedChanged()));
+
+ connect( frameViewManager(), SIGNAL(sigFrameSetRenamed()),
+ this, SLOT( updateFrameStatusBarItem()));
+
+ connect( QApplication::clipboard(), SIGNAL( dataChanged() ),
+ this, SLOT( clipboardDataChanged() ) );
+
+ connect( m_gui->canvasWidget(), SIGNAL(currentFrameSetEditChanged()),
+ this, SLOT(slotFrameSetEditChanged()) );
+
+ connect( m_gui->canvasWidget(), SIGNAL( currentMouseModeChanged(int) ),
+ this, SLOT( showMouseMode(int) ) );
+
+ connect( m_gui->canvasWidget(), SIGNAL( overwriteModeChanged( bool ) ),
+ this, SLOT( changeOverwriteMode( bool ) ) );
+
+ // Cut and copy are directly connected to the selectionChanged signal
+ if ( m_doc->isReadWrite() )
+ {
+ connect( m_gui->canvasWidget(), SIGNAL(selectionChanged(bool)),
+ this, SLOT(slotChangeCutState(bool )) );
+ connect (m_gui->canvasWidget(), SIGNAL(selectionChanged(bool)),
+ this, SLOT(slotChangeCaseState(bool )));
+ }
+ else
+ {
+ m_actionEditCut->setEnabled( false );
+ m_actionChangeCase->setEnabled( false );
+ }
+
+ connect( m_gui->canvasWidget(), SIGNAL(selectionChanged(bool)),
+ m_actionEditCopy, SLOT(setEnabled(bool)) );
+
+ //connect (m_gui->canvasWidget(), SIGNAL(selectionChanged(bool)),
+ // m_actionCreateStyleFromSelection, SLOT(setEnabled(bool)));
+
+ connect (m_gui->canvasWidget(), SIGNAL(selectionChanged(bool)),
+ m_actionConvertToTextBox, SLOT(setEnabled(bool)));
+ connect (m_gui->canvasWidget(), SIGNAL(selectionChanged(bool)),
+ m_actionAddPersonalExpression, SLOT(setEnabled(bool )));
+ connect (m_gui->canvasWidget(), SIGNAL(selectionChanged(bool)),
+ m_actionSortText, SLOT(setEnabled(bool )));
+
+ connect( m_gui->canvasWidget(), SIGNAL(docStructChanged(int)),
+ this, SLOT(docStructChanged(int)));
+
+ connect( m_gui->canvasWidget(), SIGNAL(updateRuler()),
+ this, SLOT(slotUpdateRuler()));
+
+ if ( shell() )
+ {
+ connect( shell(), SIGNAL( documentSaved()), m_doc,SLOT(slotDocumentInfoModifed() ) );
+ changeNbOfRecentFiles( m_doc->maxRecentFiles() );
+ }
+
+ m_gui->canvasWidget()->updateCurrentFormat();
+ setFocusProxy( m_gui->canvasWidget() );
+
+ //when kword is embedded into konqueror apply a zoom=100
+ //in konqueror we can't change zoom -- ### TODO ?
+ if(!m_doc->isReadWrite())
+ {
+ setZoom( 100, true );
+ slotUpdateRuler();
+ initGui();
+ }
+
+ // Determine initial scroll position
+ // We do this delayed, so that the GUI has been fully constructed
+ // (and e.g. the statusbar can repaint).
+ QTimer::singleShot( 0, this, SLOT( slotSetInitialPosition() ) );
+ QTimer::singleShot( 0, this, SLOT( updateZoom() ) );
+}
+
+KWView::~KWView()
+{
+ delete m_tableActionList.first(); // the first one is the separator.
+ clearSpellChecker();
+
+ delete m_searchEntry;
+ m_searchEntry = 0L;
+ delete m_replaceEntry;
+ m_replaceEntry = 0L;
+ if ( m_specialCharDlg )
+ m_specialCharDlg->closeDialog(); // will call slotSpecialCharDlgClosed
+
+ // Abort any find/replace
+ delete m_findReplace;
+ // Delete gui while we still exist ( it needs documentDeleted() )
+ delete m_gui;
+ delete m_sbPageLabel;
+ delete m_sbFramesLabel;
+ delete m_fsInline;
+ delete m_dcop;
+ delete m_fontDlg;
+ delete m_paragDlg;
+}
+
+DCOPObject* KWView::dcopObject()
+{
+ if ( !m_dcop )
+ m_dcop = new KWordViewIface( this );
+
+ return m_dcop;
+}
+
+void KWView::slotChangeCutState(bool b)
+{
+ KWTextFrameSetEdit * edit = currentTextEdit();
+ if ( edit && edit->textFrameSet()->protectContent())
+ m_actionEditCut->setEnabled( false );
+ else
+ m_actionEditCut->setEnabled( b );
+}
+
+void KWView::slotChangeCaseState(bool b)
+{
+ KWTextFrameSetEdit * edit = currentTextEdit();
+ if ( edit && edit->textFrameSet()->protectContent())
+ m_actionChangeCase->setEnabled( false );
+ else
+ m_actionChangeCase->setEnabled( b );
+}
+
+void KWView::slotSetInitialPosition()
+{
+ KWTextFrameSetEdit* textedit = dynamic_cast<KWTextFrameSetEdit *>(m_gui->canvasWidget()->currentFrameSetEdit());
+ if ( textedit )
+ textedit->ensureCursorVisible();
+ else
+ m_gui->canvasWidget()->setContentsPos( 0, 0 );
+}
+
+void KWView::changeNbOfRecentFiles(int nb)
+{
+ if ( shell() ) // 0 when embedded into konq !
+ shell()->setMaxRecentItems( nb );
+}
+
+KWViewMode* KWView::viewMode() const
+{
+ return m_gui->canvasWidget()->viewMode();
+}
+
+void KWView::initGui()
+{
+ clipboardDataChanged();
+ if ( m_gui )
+ m_gui->showGUI();
+ showMouseMode( KWCanvas::MM_EDIT );
+ initGUIButton();
+ m_actionFormatDecreaseIndent->setEnabled(false);
+ //setNoteType(m_doc->getNoteType(), false);
+
+ m_actionFormatColor->setCurrentColor( Qt::black );
+
+ updateGridButton();
+
+ //refresh zoom combobox
+ updateZoomControls();
+
+
+ // This is probably to emit currentMouseModeChanged and set the cursor
+ m_gui->canvasWidget()->setMouseMode( m_gui->canvasWidget()->mouseMode() );
+
+ bool editingFormula = dynamic_cast<KWFormulaFrameSetEdit *>( m_gui->canvasWidget()->currentFrameSetEdit() ) != 0;
+ //showFormulaToolbar( FALSE ); // not called, to avoid creating the formula-document if not necessary
+ if(shell())
+ shell()->showToolbar( "formula_toolbar", editingFormula );
+
+ if ( !editingFormula )
+ {
+ kWordDocument()->formulaDocumentWrapper()->setEnabled(false);
+ kWordDocument()->formulaDocumentWrapper()->enableMatrixActions(false);
+ kWordDocument()->formulaDocumentWrapper()->getSyntaxHighlightingAction()->setEnabled(false);
+ }
+
+ // Prevention against applyMainWindowSettings hiding the statusbar
+ if ( KStatusBar* sb = statusBar() )
+ sb->show();
+
+ updatePageInfo();
+ slotFrameSetEditChanged();
+ frameSelectedChanged();
+ updateTocActionText(m_doc->tocPresent());
+ //at the beginning m_actionBackgroundColor should be active
+ m_actionBackgroundColor->setEnabled(true);
+ updateBgSpellCheckingState();
+ updateDirectCursorButton();
+ m_actionCreateFrameStyle->setEnabled(false);
+}
+
+
+void KWView::updateBgSpellCheckingState()
+{
+ m_actionAllowBgSpellCheck->setChecked( m_doc->backgroundSpellCheckEnabled() );
+}
+
+
+void KWView::initGUIButton()
+{
+ m_actionViewFrameBorders->setChecked( viewFrameBorders() );
+ m_actionViewFormattingChars->setChecked( m_doc->viewFormattingChars() );
+ m_actionShowDocStruct->setChecked(m_doc->showdocStruct());
+ m_actionShowRuler->setChecked(m_doc->showRuler());
+
+ updateHeaderFooterButton();
+ m_actionAllowAutoFormat->setChecked( m_doc->allowAutoFormat() );
+
+ if ( !m_doc->isEmbedded() ) {
+ QString mode = viewMode()->type();
+ if (mode=="ModePreview")
+ m_actionViewPreviewMode->setChecked(true);
+ else if (mode=="ModeText")
+ m_actionViewTextMode->setChecked(true);
+ else //if (mode=="ModeNormal")
+ m_actionViewPageMode->setChecked(true);
+ switchModeView();
+ }
+}
+
+void KWView::setupActions()
+{
+ // The actions here are grouped by menu, because this helps noticing
+ // accelerator clashes.
+
+ // -------------- File menu
+ m_actionExtraCreateTemplate = new KAction( i18n( "&Create Template From Document..." ), 0,
+ this, SLOT( extraCreateTemplate() ),
+ actionCollection(), "extra_template" );
+ m_actionExtraCreateTemplate->setToolTip( i18n( "Save this document and use it later as a template" ) );
+ m_actionExtraCreateTemplate->setWhatsThis( i18n( "You can save this document as a template.<br><br>You can use this new template as a starting point for another document." ) );
+
+ m_actionFileStatistics = new KAction( i18n( "Statistics" ), 0, this, SLOT( fileStatistics() ), actionCollection(), "file_statistics" );
+ m_actionFileStatistics->setToolTip( i18n( "Sentence, word and letter counts for this document" ) );
+ m_actionFileStatistics->setWhatsThis( i18n( "Information on the number of letters, words, syllables and sentences for this document.<p>Evaluates readability using the Flesch reading score." ) );
+ // -------------- Edit actions
+ m_actionEditCut = KStdAction::cut( this, SLOT( editCut() ), actionCollection(), "edit_cut" );
+ m_actionEditCopy = KStdAction::copy( this, SLOT( editCopy() ), actionCollection(), "edit_copy" );
+ m_actionEditPaste = KStdAction::paste( this, SLOT( editPaste() ), actionCollection(), "edit_paste" );
+ m_actionEditFind = KStdAction::find( this, SLOT( editFind() ), actionCollection(), "edit_find" );
+ m_actionEditFindNext = KStdAction::findNext( this, SLOT( editFindNext() ), actionCollection(), "edit_findnext" );
+ m_actionEditFindPrevious = KStdAction::findPrev( this, SLOT( editFindPrevious() ), actionCollection(), "edit_findprevious" );
+ m_actionEditReplace = KStdAction::replace( this, SLOT( editReplace() ), actionCollection(), "edit_replace" );
+ m_actionEditSelectAll = KStdAction::selectAll( this, SLOT( editSelectAll() ), actionCollection(), "edit_selectall" );
+ new KAction( i18n( "Select All Frames" ), 0, this, SLOT( editSelectAllFrames() ), actionCollection(), "edit_selectallframes" );
+ m_actionEditSelectCurrentFrame = new KAction( i18n( "Select Frame" ), 0,
+ 0, this, SLOT( editSelectCurrentFrame() ),
+ actionCollection(), "edit_selectcurrentframe" );
+ m_actionSpellCheck = KStdAction::spelling( this, SLOT( slotSpellCheck() ), actionCollection(), "extra_spellcheck" );
+ m_actionDeletePage = new KAction( i18n( "Delete Page" ), "delslide", 0,
+ this, SLOT( deletePage() ),
+ actionCollection(), "delete_page" );
+ kdDebug() << m_doc->pageCount() << " " << (m_doc->processingType() == KWDocument::DTP) << endl;
+
+ (void) new KAction( i18n( "Configure Mai&l Merge..." ), "configure",0,
+ this, SLOT( editMailMergeDataBase() ),
+ actionCollection(), "edit_sldatabase" );
+
+
+ (void) new KWMailMergeLabelAction::KWMailMergeLabelAction( i18n("Drag Mail Merge Variable"), 0,
+ this, SLOT(editMailMergeDataBase()), actionCollection(), "mailmerge_draglabel" );
+
+// (void) new KWMailMergeComboAction::KWMailMergeComboAction(i18n("Insert Mailmerge Var"),0,this,SLOT(JWJWJW()),actionCollection(),"mailmerge_varchooser");
+
+ // -------------- Frame menu
+ m_actionEditDelFrame = new KAction( i18n( "&Delete Frame" ), 0,
+ this, SLOT( editDeleteFrame() ),
+ actionCollection(), "edit_delframe" );
+ m_actionEditDelFrame->setToolTip( i18n( "Delete the currently selected frame(s)." ) );
+ m_actionEditDelFrame->setWhatsThis( i18n( "Delete the currently selected frame(s)." ) );
+
+ m_actionCreateLinkedFrame = new KAction( i18n( "Create Linked Copy" ), 0, this, SLOT( createLinkedFrame() ), actionCollection(), "create_linked_frame" );
+ m_actionCreateLinkedFrame->setToolTip( i18n( "Create a copy of the current frame, always showing the same contents" ) );
+ m_actionCreateLinkedFrame->setWhatsThis( i18n("Create a copy of the current frame, that remains linked to it. This means they always show the same contents: modifying the contents in such a frame will update all its linked copies.") );
+
+ m_actionRaiseFrame = new KAction( i18n( "Ra&ise Frame" ), "raise",
+ Qt::CTRL +Qt::SHIFT+ Qt::Key_R, this, SLOT( raiseFrame() ),
+ actionCollection(), "raiseframe" );
+ m_actionRaiseFrame->setToolTip( i18n( "Raise the currently selected frame so that it appears above all the other frames" ) );
+ m_actionRaiseFrame->setWhatsThis( i18n( "Raise the currently selected frame so that it appears above all the other frames. This is only useful if frames overlap each other. If multiple frames are selected they are all raised in turn." ) );
+
+ m_actionLowerFrame = new KAction( i18n( "&Lower Frame" ), "lower",
+ Qt::CTRL +Qt::SHIFT+ Qt::Key_L, this, SLOT( lowerFrame() ),
+ actionCollection(), "lowerframe" );
+ m_actionLowerFrame->setToolTip( i18n( "Lower the currently selected frame so that it disappears under any frame that overlaps it" ) );
+ m_actionLowerFrame->setWhatsThis( i18n( "Lower the currently selected frame so that it disappears under any frame that overlaps it. If multiple frames are selected they are all lowered in turn." ) );
+
+ m_actionBringToFront= new KAction( i18n( "Bring to Front" ), "bring_forward",
+ 0, this, SLOT( bringToFront() ),
+ actionCollection(), "bring_tofront_frame" );
+
+ m_actionSendBackward= new KAction( i18n( "Send to Back" ), "send_backward",
+ 0, this, SLOT( sendToBack() ),
+ actionCollection(), "send_toback_frame" );
+
+
+ // -------------- View menu
+
+ if ( !m_doc->isEmbedded() ) {
+
+ m_actionViewTextMode = new KToggleAction( i18n( "Text Mode" ), 0,
+ this, SLOT( viewTextMode() ),
+ actionCollection(), "view_textmode" );
+ m_actionViewTextMode->setToolTip( i18n( "Only show the text of the document." ) );
+ m_actionViewTextMode->setWhatsThis( i18n( "Do not show any pictures, formatting or layout. KWord will display only the text for editing." ) );
+
+ m_actionViewTextMode->setExclusiveGroup( "viewmodes" );
+ m_actionViewPageMode = new KToggleAction( i18n( "&Page Mode" ), 0,
+ this, SLOT( viewPageMode() ),
+ actionCollection(), "view_pagemode" );
+ m_actionViewPageMode->setWhatsThis( i18n( "Switch to page mode.<br><br> Page mode is designed to make editing your text easy.<br><br>This function is most frequently used to return to text editing after switching to preview mode." ) );
+ m_actionViewPageMode->setToolTip( i18n( "Switch to page editing mode." ) );
+
+ m_actionViewPageMode->setExclusiveGroup( "viewmodes" );
+ m_actionViewPageMode->setChecked( true );
+ m_actionViewPreviewMode = new KToggleAction( i18n( "Pre&view Mode" ), 0,
+ this, SLOT( viewPreviewMode() ),
+ actionCollection(), "view_previewmode" );
+ m_actionViewPreviewMode->setWhatsThis( i18n( "Zoom out from your document to get a look at several pages of your document.<br><br>The number of pages per line can be customized." ) );
+ m_actionViewPreviewMode->setToolTip( i18n( "Zoom out to a multiple page view." ) );
+
+ m_actionViewPreviewMode->setExclusiveGroup( "viewmodes" );
+ }
+ else // no viewmode switching when embedded; at least "Page" makes no sense
+ {
+ m_actionViewTextMode = 0;
+ m_actionViewPageMode = 0;
+ m_actionViewPreviewMode = 0;
+ }
+
+ m_actionViewFormattingChars = new KToggleAction( i18n( "&Formatting Characters" ), 0,
+ this, SLOT( slotViewFormattingChars() ),
+ actionCollection(), "view_formattingchars" );
+ m_actionViewFormattingChars->setToolTip( i18n( "Toggle the display of non-printing characters." ) );
+ m_actionViewFormattingChars->setWhatsThis( i18n( "Toggle the display of non-printing characters.<br><br>When this is enabled, KWord shows you tabs, spaces, carriage returns and other non-printing characters." ) );
+
+ m_actionViewFrameBorders = new KToggleAction( i18n( "Frame &Borders" ), 0,
+ this, SLOT( slotViewFrameBorders() ),
+ actionCollection(), "view_frameborders" );
+ m_actionViewFrameBorders->setToolTip( i18n( "Turns the border display on and off." ) );
+ m_actionViewFrameBorders->setWhatsThis( i18n( "Turns the border display on and off.<br><br>The borders are never printed. This option is useful to see how the document will appear on the printed page." ) );
+
+ m_actionViewHeader = new KToggleAction( i18n( "Enable Document &Headers" ), 0,
+ this, SLOT( viewHeader() ),
+ actionCollection(), "format_header" );
+ m_actionViewHeader->setCheckedState(i18n("Disable Document &Headers"));
+ m_actionViewHeader->setToolTip( i18n( "Shows and hides header display." ) );
+ m_actionViewHeader->setWhatsThis( i18n( "Selecting this option toggles the display of headers in KWord.<br><br>Headers are special frames at the top of each page which can contain page numbers or other information." ) );
+
+ m_actionViewFooter = new KToggleAction( i18n( "Enable Document Foo&ters" ), 0,
+ this, SLOT( viewFooter() ),
+ actionCollection(), "format_footer" );
+ m_actionViewFooter->setCheckedState(i18n("Disable Document Foo&ters"));
+ m_actionViewFooter->setToolTip( i18n( "Shows and hides footer display." ) );
+ m_actionViewFooter->setWhatsThis( i18n( "Selecting this option toggles the display of footers in KWord. <br><br>Footers are special frames at the bottom of each page which can contain page numbers or other information." ) );
+
+ m_actionViewZoom = new KSelectAction( i18n( "Zoom" ), "viewmag", 0,
+ actionCollection(), "view_zoom" );
+
+ connect( m_actionViewZoom, SIGNAL( activated( const QString & ) ),
+ this, SLOT( viewZoom( const QString & ) ) );
+ m_actionViewZoom->setEditable(true);
+ changeZoomMenu( );
+
+ // -------------- Insert menu
+ m_actionInsertSpecialChar = new KAction( i18n( "Sp&ecial Character..." ), "char",
+ Qt::ALT + Qt::SHIFT + Qt::Key_C,
+ this, SLOT( insertSpecialChar() ),
+ actionCollection(), "insert_specialchar" );
+ m_actionInsertSpecialChar->setToolTip( i18n( "Insert one or more symbols or letters not found on the keyboard." ) );
+ m_actionInsertSpecialChar->setWhatsThis( i18n( "Insert one or more symbols or letters not found on the keyboard." ) );
+
+ m_actionInsertFrameBreak = new KAction( QString::null, Qt::CTRL + Qt::Key_Return,
+ this, SLOT( insertFrameBreak() ),
+ actionCollection(), "insert_framebreak" );
+ if ( m_doc->processingType() == KWDocument::WP ) {
+ m_actionInsertFrameBreak->setText( i18n( "Page Break" ) );
+ m_actionInsertFrameBreak->setToolTip( i18n( "Force the remainder of the text into the next page." ) );
+ m_actionInsertFrameBreak->setWhatsThis( i18n( "This inserts a non-printing character at the current cursor position. All text after this point will be moved into the next page." ) );
+ } else {
+ m_actionInsertFrameBreak->setText( i18n( "&Hard Frame Break" ) );
+ m_actionInsertFrameBreak->setToolTip( i18n( "Force the remainder of the text into the next frame." ) );
+ m_actionInsertFrameBreak->setWhatsThis( i18n( "This inserts a non-printing character at the current cursor position. All text after this point will be moved into the next frame in the frameset." ) );
+ }
+
+ /*actionInsertPage =*/ new KAction( m_doc->processingType() == KWDocument::WP ? i18n( "Page" ) : i18n( "Page..." ), "page", 0,
+ this, SLOT( insertPage() ),
+ actionCollection(), "insert_page" );
+
+ m_actionInsertLink = new KAction( i18n( "Link..." ), 0,
+ this, SLOT( insertLink() ),
+ actionCollection(), "insert_link" );
+ m_actionInsertLink->setToolTip( i18n( "Insert a Web address, email address or hyperlink to a file." ) );
+ m_actionInsertLink->setWhatsThis( i18n( "Insert a Web address, email address or hyperlink to a file." ) );
+
+ m_actionInsertComment = new KAction( i18n( "Comment..." ), 0,
+ this, SLOT( insertComment() ),
+ actionCollection(), "insert_comment" );
+ m_actionInsertComment->setToolTip( i18n( "Insert a comment about the selected text." ) );
+ m_actionInsertComment->setWhatsThis( i18n( "Insert a comment about the selected text. These comments are not designed to appear on the final page." ) );
+
+ m_actionEditComment = new KAction( i18n("Edit Comment..."), 0,
+ this,SLOT(editComment()),
+ actionCollection(), "edit_comment");
+ m_actionEditComment->setToolTip( i18n( "Change the content of a comment." ) );
+ m_actionEditComment->setWhatsThis( i18n( "Change the content of a comment." ) );
+
+ m_actionRemoveComment = new KAction( i18n("Remove Comment"), 0,
+ this,SLOT(removeComment()),
+ actionCollection(), "remove_comment");
+ m_actionRemoveComment->setToolTip( i18n( "Remove the selected document comment." ) );
+ m_actionRemoveComment->setWhatsThis( i18n( "Remove the selected document comment." ) );
+ m_actionCopyTextOfComment = new KAction( i18n("Copy Text of Comment..."), 0,
+ this,SLOT(copyTextOfComment()),
+ actionCollection(), "copy_text_comment");
+
+
+ m_actionInsertFootEndNote = new KAction( i18n( "&Footnote/Endnote..." ), 0,
+ this, SLOT( insertFootNote() ),
+ actionCollection(), "insert_footendnote" );
+ m_actionInsertFootEndNote->setToolTip( i18n( "Insert a footnote referencing the selected text." ) );
+ m_actionInsertFootEndNote->setWhatsThis( i18n( "Insert a footnote referencing the selected text." ) );
+
+ m_actionInsertContents = new KAction( i18n( "Table of &Contents" ), 0,
+ this, SLOT( insertContents() ),
+ actionCollection(), "insert_contents" );
+ m_actionInsertContents->setToolTip( i18n( "Insert table of contents at the current cursor position." ) );
+ m_actionInsertContents->setWhatsThis( i18n( "Insert table of contents at the current cursor position." ) );
+
+ m_variableDefMap.clear();
+ actionInsertVariable = new KActionMenu( i18n( "&Variable" ),
+ actionCollection(), "insert_variable" );
+
+ // The last argument is only needed if a submenu is to be created
+ addVariableActions( VT_FIELD, KoFieldVariable::actionTexts(), actionInsertVariable, i18n("Document &Information") );
+ addVariableActions( VT_DATE, KoDateVariable::actionTexts(), actionInsertVariable, i18n("&Date") );
+ addVariableActions( VT_TIME, KoTimeVariable::actionTexts(), actionInsertVariable, i18n("&Time") );
+ addVariableActions( VT_PGNUM, KoPageVariable::actionTexts(), actionInsertVariable, i18n("&Page") );
+ addVariableActions( VT_STATISTIC, KWStatisticVariable::actionTexts(), actionInsertVariable, i18n("&Statistic") );
+
+ m_actionInsertCustom = new KActionMenu( i18n( "&Custom" ),
+ actionCollection(), "insert_custom" );
+ actionInsertVariable->insert(m_actionInsertCustom);
+
+ //addVariableActions( VT_CUSTOM, KWCustomVariable::actionTexts(), actionInsertVariable, QString::null );
+
+ addVariableActions( VT_MAILMERGE, KoMailMergeVariable::actionTexts(), actionInsertVariable, QString::null );
+
+ actionInsertVariable->popupMenu()->insertSeparator();
+ m_actionRefreshAllVariable = new KAction( i18n( "&Refresh All Variables" ), 0,
+ this, SLOT( refreshAllVariable() ),
+ actionCollection(), "refresh_all_variable" );
+ m_actionRefreshAllVariable->setToolTip( i18n( "Update all variables to current values." ) );
+ m_actionRefreshAllVariable->setWhatsThis( i18n( "Update all variables in the document to current values.<br><br>This will update page numbers, dates or any other variables that need updating." ) );
+
+ actionInsertVariable->insert(m_actionRefreshAllVariable);
+
+ m_actionInsertExpression = new KActionMenu( i18n( "&Expression" ),
+ actionCollection(), "insert_expression" );
+ loadexpressionActions( m_actionInsertExpression);
+
+ m_actionToolsCreateText = new KToggleAction( i18n( "Te&xt Frame" ), "frame_text", Qt::Key_F10 /*same as kpr*/,
+ this, SLOT( toolsCreateText() ),
+ actionCollection(), "tools_createtext" );
+ m_actionToolsCreateText->setToolTip( i18n( "Create a new text frame." ) );
+ m_actionToolsCreateText->setWhatsThis( i18n( "Create a new text frame." ) );
+
+ m_actionToolsCreateText->setExclusiveGroup( "tools" );
+ m_actionInsertFormula = new KAction( i18n( "For&mula" ), "frame_formula", Qt::Key_F4,
+ this, SLOT( insertFormula() ),
+ actionCollection(), "tools_formula" );
+ m_actionInsertFormula->setToolTip( i18n( "Insert a formula into a new frame." ) );
+ m_actionInsertFormula->setWhatsThis( i18n( "Insert a formula into a new frame." ) );
+
+ m_actionInsertTable = new KAction( i18n( "&Table..." ), "inline_table",
+ Qt::Key_F5,
+ this, SLOT( insertTable() ),
+ actionCollection(), "insert_table" );
+ m_actionInsertTable->setToolTip( i18n( "Create a table." ) );
+ m_actionInsertTable->setWhatsThis( i18n( "Create a table.<br><br>The table can either exist in a frame of its own or inline." ) );
+
+ m_actionToolsCreatePix = new KToggleAction( i18n( "P&icture..." ), "frame_image", // or inline_image ?
+ Qt::SHIFT + Qt::Key_F5 /*same as kpr*/,
+ this, SLOT( insertPicture() ),
+ actionCollection(), "insert_picture" );
+ m_actionToolsCreatePix->setToolTip( i18n( "Create a new frame for a picture." ) );
+ m_actionToolsCreatePix->setWhatsThis( i18n( "Create a new frame for a picture or diagram." ) );
+ m_actionToolsCreatePix->setExclusiveGroup( "tools" );
+
+ m_actionToolsCreatePart = new KoPartSelectAction( i18n( "&Object Frame" ), "frame_query",
+ this, SLOT( toolsPart() ),
+ actionCollection(), "tools_part" );
+ m_actionToolsCreatePart->setToolTip( i18n( "Insert an object into a new frame." ) );
+ m_actionToolsCreatePart->setWhatsThis( i18n( "Insert an object into a new frame." ) );
+
+ m_actionInsertFile = new KAction( i18n( "Fi&le..." ), 0,
+ this, SLOT( insertFile() ),
+ actionCollection(), "insert_file" );
+
+
+ // ------------------------- Format menu
+ m_actionFormatFont = new KAction( i18n( "&Font..." ), Qt::ALT + Qt::CTRL + Qt::Key_F,
+ this, SLOT( formatFont() ),
+ actionCollection(), "format_font" );
+ m_actionFormatFont->setToolTip( i18n( "Change character size, font, boldface, italics etc." ) );
+ m_actionFormatFont->setWhatsThis( i18n( "Change the attributes of the currently selected characters." ) );
+
+ m_actionFormatParag = new KAction( i18n( "&Paragraph..." ), Qt::ALT + Qt::CTRL + Qt::Key_P,
+ this, SLOT( formatParagraph() ),
+ actionCollection(), "format_paragraph" );
+ m_actionFormatParag->setToolTip( i18n( "Change paragraph margins, text flow, borders, bullets, numbering etc." ) );
+ m_actionFormatParag->setWhatsThis( i18n( "Change paragraph margins, text flow, borders, bullets, numbering etc.<p>Select text in multiple paragraphs to change the formatting of all selected paragraphs.<p>If no text is selected, the paragraph where the cursor is located will be changed." ) );
+
+ m_actionFormatFrameSet = new KAction( i18n( "F&rame/Frameset Properties" ), 0,
+ this, SLOT( formatFrameSet() ),
+ actionCollection(), "format_frameset" );
+ m_actionFormatFrameSet->setToolTip( i18n( "Alter frameset properties." ) );
+ m_actionFormatFrameSet->setWhatsThis( i18n( "Alter frameset properties.<p>Currently you can change the frame background." ) );
+
+ m_actionFormatPage = new KAction( i18n( "Page &Layout..." ), 0,
+ this, SLOT( formatPage() ),
+ actionCollection(), "format_page" );
+ m_actionFormatPage->setToolTip( i18n( "Change properties of entire page." ) );
+ m_actionFormatPage->setWhatsThis( i18n( "Change properties of the entire page.<p>Currently you can change paper size, paper orientation, header and footer sizes, and column settings." ) );
+
+
+ m_actionFormatFrameStylist = new KAction( i18n( "&Frame Style Manager" ), 0 /*shortcut?*/,
+ this, SLOT( extraFrameStylist() ),
+ actionCollection(), "frame_stylist" );
+ m_actionFormatFrameStylist->setToolTip( i18n( "Change attributes of framestyles." ) );
+ m_actionFormatFrameStylist->setWhatsThis( i18n( "Change background and borders of framestyles.<p>Multiple framestyles can be changed using the dialog box." ) );
+
+
+ m_actionFormatStylist = new KAction( i18n( "&Style Manager" ), Qt::ALT + Qt::CTRL + Qt::Key_S,
+ this, SLOT( extraStylist() ),
+ actionCollection(), "format_stylist" );
+ m_actionFormatStylist->setToolTip( i18n( "Change attributes of styles." ) );
+ m_actionFormatStylist->setWhatsThis( i18n( "Change font and paragraph attributes of styles.<p>Multiple styles can be changed using the dialog box." ) );
+
+ m_actionFormatFontSize = new KFontSizeAction( i18n( "Font Size" ), 0,
+ actionCollection(), "format_fontsize" );
+ connect( m_actionFormatFontSize, SIGNAL( fontSizeChanged( int ) ),
+ this, SLOT( textSizeSelected( int ) ) );
+
+ m_actionFontSizeIncrease = new KAction( i18n("Increase Font Size"), "fontsizeup", Qt::CTRL + Qt::Key_Greater, this, SLOT( increaseFontSize() ), actionCollection(), "increase_fontsize" );
+ m_actionFontSizeDecrease = new KAction( i18n("Decrease Font Size"), "fontsizedown", Qt::CTRL + Qt::Key_Less, this, SLOT( decreaseFontSize() ), actionCollection(), "decrease_fontsize" );
+
+#ifdef KFONTACTION_HAS_CRITERIA_ARG
+ m_actionFormatFontFamily = new KFontAction( KFontChooser::SmoothScalableFonts,
+ i18n( "Font Family" ), 0,
+ actionCollection(), "format_fontfamily" );
+#else
+ m_actionFormatFontFamily = new KFontAction( i18n( "Font Family" ), 0,
+ actionCollection(), "format_fontfamily" );
+#endif
+ connect( m_actionFormatFontFamily, SIGNAL( activated( const QString & ) ),
+ this, SLOT( textFontSelected( const QString & ) ) );
+
+ m_actionFormatStyleMenu = new KActionMenu( i18n( "St&yle" ), 0,
+ actionCollection(), "format_stylemenu" );
+ m_actionFormatStyle = new KSelectAction( i18n( "St&yle" ), 0,
+ actionCollection(), "format_style" );
+ // In fact, binding a key to this action will simply re-apply the current style. Why not.
+ //m_actionFormatStyle->setShortcutConfigurable( false );
+ connect( m_actionFormatStyle, SIGNAL( activated( int ) ),
+ this, SLOT( textStyleSelected( int ) ) );
+ updateStyleList();
+
+ m_actionFormatDefault=new KAction( i18n( "Default Format" ), 0,
+ this, SLOT( textDefaultFormat() ),
+ actionCollection(), "text_default" );
+ m_actionFormatDefault->setToolTip( i18n( "Change font and paragraph attributes to their default values." ) );
+ m_actionFormatDefault->setWhatsThis( i18n( "Change font and paragraph attributes to their default values." ) );
+
+ // ----------------------- More format actions, for the toolbar only
+
+ m_actionFormatBold = new KToggleAction( i18n( "&Bold" ), "text_bold", Qt::CTRL + Qt::Key_B,
+ this, SLOT( textBold() ),
+ actionCollection(), "format_bold" );
+ m_actionFormatItalic = new KToggleAction( i18n( "&Italic" ), "text_italic", Qt::CTRL + Qt::Key_I,
+ this, SLOT( textItalic() ),
+ actionCollection(), "format_italic" );
+ m_actionFormatUnderline = new KToggleAction( i18n( "&Underline" ), "text_under", Qt::CTRL + Qt::Key_U,
+ this, SLOT( textUnderline() ),
+ actionCollection(), "format_underline" );
+ m_actionFormatStrikeOut = new KToggleAction( i18n( "&Strike Out" ), "text_strike", 0 ,
+ this, SLOT( textStrikeOut() ),
+ actionCollection(), "format_strike" );
+
+ m_actionFormatAlignLeft = new KToggleAction( i18n( "Align &Left" ), "text_left", Qt::CTRL + Qt::Key_L,
+ this, SLOT( textAlignLeft() ),
+ actionCollection(), "format_alignleft" );
+ m_actionFormatAlignLeft->setExclusiveGroup( "align" );
+ m_actionFormatAlignLeft->setChecked( TRUE );
+ m_actionFormatAlignCenter = new KToggleAction( i18n( "Align &Center" ), "text_center", Qt::CTRL + Qt::ALT + Qt::Key_C,
+ this, SLOT( textAlignCenter() ),
+ actionCollection(), "format_aligncenter" );
+ m_actionFormatAlignCenter->setExclusiveGroup( "align" );
+ m_actionFormatAlignRight = new KToggleAction( i18n( "Align &Right" ), "text_right", Qt::CTRL + Qt::ALT + Qt::Key_R,
+ this, SLOT( textAlignRight() ),
+ actionCollection(), "format_alignright" );
+ m_actionFormatAlignRight->setExclusiveGroup( "align" );
+ m_actionFormatAlignBlock = new KToggleAction( i18n( "Align &Block" ), "text_block", Qt::CTRL + Qt::Key_J,
+ this, SLOT( textAlignBlock() ),
+ actionCollection(), "format_alignblock" );
+ m_actionFormatAlignBlock->setExclusiveGroup( "align" );
+
+ m_actionFormatSpacingSingle = new KToggleAction( i18n( "Line Spacing &1" ), "spacesimple", Qt::CTRL + Qt::Key_1,
+ this, SLOT( textSpacingSingle() ),
+ actionCollection(), "format_spacingsingle" );
+ m_actionFormatSpacingSingle->setExclusiveGroup( "spacing" );
+ m_actionFormatSpacingOneAndHalf = new KToggleAction( i18n( "Line Spacing 1.&5" ), "spacedouble", Qt::CTRL + Qt::Key_5,
+ this, SLOT( textSpacingOneAndHalf() ),
+ actionCollection(), "format_spacing15" );
+ m_actionFormatSpacingOneAndHalf->setExclusiveGroup( "spacing" );
+ m_actionFormatSpacingDouble = new KToggleAction( i18n( "Line Spacing &2" ), "spacetriple", Qt::CTRL + Qt::Key_2,
+ this, SLOT( textSpacingDouble() ),
+ actionCollection(), "format_spacingdouble" );
+ m_actionFormatSpacingDouble->setExclusiveGroup( "spacing" );
+
+ m_actionFormatSuper = new KToggleAction( i18n( "Superscript" ), "super", 0,
+ this, SLOT( textSuperScript() ),
+ actionCollection(), "format_super" );
+ //m_actionFormatSuper->setExclusiveGroup( "valign" );
+ m_actionFormatSub = new KToggleAction( i18n( "Subscript" ), "sub", 0,
+ this, SLOT( textSubScript() ),
+ actionCollection(), "format_sub" );
+ //m_actionFormatSub->setExclusiveGroup( "valign" );
+
+ m_actionFormatIncreaseIndent= new KAction( i18n( "Increase Indent" ),
+ QApplication::reverseLayout() ? "format_decreaseindent" : "format_increaseindent", 0,
+ this, SLOT( textIncreaseIndent() ),
+ actionCollection(), "format_increaseindent" );
+
+ m_actionFormatDecreaseIndent= new KAction( i18n( "Decrease Indent" ),
+ QApplication::reverseLayout() ? "format_increaseindent" :"format_decreaseindent", 0,
+ this, SLOT( textDecreaseIndent() ),
+ actionCollection(), "format_decreaseindent" );
+
+ m_actionFormatColor = new TKSelectColorAction( i18n( "Text Color..." ), TKSelectColorAction::TextColor,
+ this, SLOT( textColor() ),
+ actionCollection(), "format_color", true );
+ m_actionFormatColor->setDefaultColor(QColor());
+
+
+ //actionFormatList = new KToggleAction( i18n( "List" ), "enumList", 0,
+ // this, SLOT( textList() ),
+ // actionCollection(), "format_list" );
+ //actionFormatList->setExclusiveGroup( "style" );
+
+ m_actionFormatNumber = new KActionMenu( i18n( "Number" ),
+ "enumList", actionCollection(), "format_number" );
+ m_actionFormatNumber->setDelayed( false );
+ m_actionFormatBullet = new KActionMenu( i18n( "Bullet" ),
+ "unsortedList", actionCollection(), "format_bullet" );
+ m_actionFormatBullet->setDelayed( false );
+ QPtrList<KoCounterStyleWidget::StyleRepresenter> stylesList;
+ KoCounterStyleWidget::makeCounterRepresenterList( stylesList );
+ QPtrListIterator<KoCounterStyleWidget::StyleRepresenter> styleIt( stylesList );
+ for ( ; styleIt.current() ; ++styleIt ) {
+ // Dynamically create toggle-actions for each list style.
+ // This approach allows to edit toolbars and extract separate actions from this menu
+ KToggleAction* act = new KToggleAction( styleIt.current()->name(), /*TODO icon,*/
+ 0, this, SLOT( slotCounterStyleSelected() ),
+ actionCollection(), QString("counterstyle_%1").arg( styleIt.current()->style() ).latin1() );
+ act->setExclusiveGroup( "counterstyle" );
+ // Add to the right menu: both for "none", bullet for bullets, numbers otherwise
+ if ( styleIt.current()->style() == KoParagCounter::STYLE_NONE ) {
+ m_actionFormatBullet->insert( act );
+ m_actionFormatNumber->insert( act );
+ } else if ( styleIt.current()->isBullet() )
+ m_actionFormatBullet->insert( act );
+ else
+ m_actionFormatNumber->insert( act );
+ }
+
+ // ---------------------------- frame toolbar actions
+
+ m_actionFrameStyleMenu = new KActionMenu( i18n( "Fra&mestyle" ), 0,
+ actionCollection(), "frame_stylemenu" );
+ m_actionFrameStyle = new KSelectAction( i18n( "Framest&yle" ), 0,
+ actionCollection(), "frame_style" );
+ connect( m_actionFrameStyle, SIGNAL( activated( int ) ),
+ this, SLOT( frameStyleSelected( int ) ) );
+ updateFrameStyleList();
+ m_actionBorderOutline = new KToggleAction( i18n( "Border Outline" ), "borderoutline",
+ 0, this, SLOT( borderOutline() ), actionCollection(), "border_outline" );
+ m_actionBorderLeft = new KToggleAction( i18n( "Border Left" ), "borderleft",
+ 0, this, SLOT( borderLeft() ), actionCollection(), "border_left" );
+ m_actionBorderRight = new KToggleAction( i18n( "Border Right" ), "borderright",
+ 0, this, SLOT( borderRight() ), actionCollection(), "border_right" );
+ m_actionBorderTop = new KToggleAction( i18n( "Border Top" ), "bordertop",
+ 0, this, SLOT( borderTop() ), actionCollection(), "border_top" );
+ m_actionBorderBottom = new KToggleAction( i18n( "Border Bottom" ), "borderbottom",
+ 0, this, SLOT( borderBottom() ), actionCollection(), "border_bottom" );
+ m_actionBorderStyle = new KSelectAction( i18n( "Border Style" ),
+ 0, actionCollection(), "border_style" );
+
+ QStringList lst;
+ lst << KoBorder::getStyle( KoBorder::SOLID );
+ lst << KoBorder::getStyle( KoBorder::DASH );
+ lst << KoBorder::getStyle( KoBorder::DOT );
+ lst << KoBorder::getStyle( KoBorder::DASH_DOT );
+ lst << KoBorder::getStyle( KoBorder::DASH_DOT_DOT );
+ lst << KoBorder::getStyle( KoBorder::DOUBLE_LINE );
+ m_actionBorderStyle->setItems( lst );
+ m_actionBorderWidth = new KSelectAction( i18n( "Border Width" ), 0,
+ actionCollection(), "border_width" );
+ lst.clear();
+ for ( unsigned int i = 1; i < 10; i++ )
+ lst << QString::number( i );
+ m_actionBorderWidth->setItems( lst );
+ m_actionBorderWidth->setCurrentItem( 0 );
+
+ m_actionBorderColor = new TKSelectColorAction( i18n("Border Color"), TKSelectColorAction::LineColor, actionCollection(), "border_color", true );
+ m_actionBorderColor->setDefaultColor(QColor());
+
+
+ m_actionBackgroundColor = new TKSelectColorAction( i18n( "Text Background Color..." ), TKSelectColorAction::FillColor, actionCollection(),"border_backgroundcolor", true);
+ m_actionBackgroundColor->setToolTip( i18n( "Change background color for currently selected text." ) );
+ m_actionBackgroundColor->setWhatsThis( i18n( "Change background color for currently selected text." ) );
+
+ connect(m_actionBackgroundColor,SIGNAL(activated()),SLOT(backgroundColor() ));
+ m_actionBackgroundColor->setDefaultColor(QColor());
+
+ // ---------------------- Table menu
+ m_actionTablePropertiesMenu = new KAction( i18n( "&Properties" ), 0,
+ this, SLOT( tableProperties() ),
+ actionCollection(), "table_propertiesmenu" );
+ m_actionTablePropertiesMenu->setToolTip( i18n( "Adjust properties of the current table." ) );
+ m_actionTablePropertiesMenu->setWhatsThis( i18n( "Adjust properties of the current table." ) );
+
+ m_actionTableInsertRow = new KAction( i18n( "&Insert Row..." ), "insert_table_row", 0,
+ this, SLOT( tableInsertRow() ),
+ actionCollection(), "table_insrow" );
+ m_actionTableInsertRow->setToolTip( i18n( "Insert one or more rows at cursor location." ) );
+ m_actionTableInsertRow->setWhatsThis( i18n( "Insert one or more rows at current cursor location." ) );
+
+ m_actionTableInsertCol = new KAction( i18n( "I&nsert Column..." ), "insert_table_col", 0,
+ this, SLOT( tableInsertCol() ),
+ actionCollection(), "table_inscol" );
+ m_actionTableInsertCol->setToolTip( i18n( "Insert one or more columns into the current table." ) );
+ m_actionTableInsertCol->setWhatsThis( i18n( "Insert one or more columns into the current table." ) );
+
+ m_actionTableDelRow = new KAction( 0, "delete_table_row", 0,
+ this, SLOT( tableDeleteRow() ),
+ actionCollection(), "table_delrow" );
+ m_actionTableDelRow->setToolTip( i18n( "Delete selected rows from the current table." ) );
+ m_actionTableDelRow->setWhatsThis( i18n( "Delete selected rows from the current table." ) );
+
+ m_actionTableDelCol = new KAction( 0, "delete_table_col", 0,
+ this, SLOT( tableDeleteCol() ),
+ actionCollection(), "table_delcol" );
+ m_actionTableDelCol->setToolTip( i18n( "Delete selected columns from the current table." ) );
+ m_actionTableDelCol->setWhatsThis( i18n( "Delete selected columns from the current table." ) );
+
+ m_actionTableResizeCol = new KAction( i18n( "Resize Column..." ), 0,
+ this, SLOT( tableResizeCol() ),
+ actionCollection(), "table_resizecol" );
+ m_actionTableResizeCol->setToolTip( i18n( "Change the width of the currently selected column." ) );
+ m_actionTableResizeCol->setWhatsThis( i18n( "Change the width of the currently selected column." ) );
+
+
+ m_actionTableJoinCells = new KAction( i18n( "&Join Cells" ), 0,
+ this, SLOT( tableJoinCells() ),
+ actionCollection(), "table_joincells" );
+ m_actionTableJoinCells->setToolTip( i18n( "Join two or more cells into one large cell." ) );
+ m_actionTableJoinCells->setWhatsThis( i18n( "Join two or more cells into one large cell.<p>This is a good way to create titles and labels within a table." ) );
+
+ m_actionTableSplitCells= new KAction( i18n( "&Split Cell..." ), 0,
+ this, SLOT( tableSplitCells() ),
+ actionCollection(), "table_splitcells" );
+ m_actionTableSplitCells->setToolTip( i18n( "Split one cell into two or more cells." ) );
+ m_actionTableSplitCells->setWhatsThis( i18n( "Split one cell into two or more cells.<p>Cells can be split horizontally, vertically or both directions at once." ) );
+
+ m_actionTableProtectCells= new KToggleAction( i18n( "Protect Cells" ), 0, 0, 0,
+ actionCollection(), "table_protectcells" );
+ m_actionTableProtectCells->setToolTip( i18n( "Prevent changes to content of selected cells." ) );
+ connect (m_actionTableProtectCells, SIGNAL( toggled(bool) ), this,
+ SLOT( tableProtectCells(bool) ));
+
+ m_actionTableProtectCells->setWhatsThis( i18n( "Toggles cell protection on and off.<br><br>When cell protection is on, the user can not alter the content or formatting of the text within the cell." ) );
+
+ m_actionTableUngroup = new KAction( i18n( "&Ungroup Table" ), 0,
+ this, SLOT( tableUngroupTable() ),
+ actionCollection(), "table_ungroup" );
+ m_actionTableUngroup->setToolTip( i18n( "Break a table into individual frames." ) );
+ m_actionTableUngroup->setWhatsThis( i18n( "Break a table into individual frames<p>Each frame can be moved independently around the page." ) );
+
+ m_actionTableDelete = new KAction( i18n( "Delete &Table" ), 0,
+ this, SLOT( tableDelete() ),
+ actionCollection(), "table_delete" );
+ m_actionTableDelete->setToolTip( i18n( "Delete the entire table." ) );
+ m_actionTableDelete->setWhatsThis( i18n( "Deletes all cells and the content within the cells of the currently selected table." ) );
+
+
+ m_actionTableStylist = new KAction( i18n( "T&able Style Manager" ), 0,
+ this, SLOT( tableStylist() ),
+ actionCollection(), "table_stylist" );
+ m_actionTableStylist->setToolTip( i18n( "Change attributes of tablestyles." ) );
+ m_actionTableStylist->setWhatsThis( i18n( "Change textstyle and framestyle of the tablestyles.<p>Multiple tablestyles can be changed using the dialog box." ) );
+
+ m_actionTableStyleMenu = new KActionMenu( i18n( "Table&style" ), 0,
+ actionCollection(), "table_stylemenu" );
+ m_actionTableStyle = new KSelectAction( i18n( "Table&style" ), 0,
+ actionCollection(), "table_style" );
+ connect( m_actionTableStyle, SIGNAL( activated( int ) ),
+ this, SLOT( tableStyleSelected( int ) ) );
+ updateTableStyleList();
+
+ m_actionConvertTableToText = new KAction( i18n( "Convert Table to Text" ), 0,
+ this, SLOT( convertTableToText() ),
+ actionCollection(), "convert_table_to_text" );
+ m_actionSortText= new KAction( i18n( "Sort Text..." ), 0,
+ this, SLOT( sortText() ),
+ actionCollection(), "sort_text" );
+
+ m_actionAddPersonalExpression= new KAction( i18n( "Add Expression" ), 0,
+ this, SLOT( addPersonalExpression() ),
+ actionCollection(), "add_personal_expression" );
+
+
+ // ---------------------- Tools menu
+
+
+ m_actionAllowAutoFormat = new KToggleAction( i18n( "Enable Autocorrection" ), 0,
+ this, SLOT( slotAllowAutoFormat() ),
+ actionCollection(), "enable_autocorrection" );
+ m_actionAllowAutoFormat->setCheckedState(i18n("Disable Autocorrection"));
+ m_actionAllowAutoFormat->setToolTip( i18n( "Toggle autocorrection on and off." ) );
+ m_actionAllowAutoFormat->setWhatsThis( i18n( "Toggle autocorrection on and off." ) );
+
+ m_actionAutoFormat = new KAction( i18n( "Configure &Autocorrection..." ), 0,
+ this, SLOT( extraAutoFormat() ),
+ actionCollection(), "configure_autocorrection" );
+ m_actionAutoFormat->setToolTip( i18n( "Change autocorrection options." ) );
+ m_actionAutoFormat->setWhatsThis( i18n( "Change autocorrection options including:<p> <UL><LI><P>exceptions to autocorrection</P> <LI><P>add/remove autocorrection replacement text</P> <LI><P>and basic autocorrection options</P>." ) );
+
+ m_actionEditCustomVarsEdit = new KAction( i18n( "Custom &Variables..." ), 0,
+ this, SLOT( editCustomVars() ), // TODO: new dialog w add etc.
+ actionCollection(), "custom_vars" );
+
+ m_actionEditPersonnalExpr=new KAction( i18n( "Edit &Personal Expressions..." ), 0,
+ this, SLOT( editPersonalExpr() ),
+ actionCollection(), "personal_expr" );
+ m_actionEditPersonnalExpr->setToolTip( i18n( "Add or change one or more personal expressions." ) );
+ m_actionEditPersonnalExpr->setWhatsThis( i18n( "Add or change one or more personal expressions.<p>Personal expressions are a way to quickly insert commonly used phrases or text into your document." ) );
+
+ m_actionChangeCase=new KAction( i18n( "Change Case..." ), 0,
+ this, SLOT( changeCaseOfText() ),
+ actionCollection(), "change_case" );
+ m_actionChangeCase->setToolTip( i18n( "Alter the capitalization of selected text." ) );
+ m_actionChangeCase->setWhatsThis( i18n( "Alter the capitalization of selected text to one of five pre-defined patterns.<p>You can also switch all letters from upper case to lower case and from lower case to upper case in one move." ) );
+
+ //------------------------ Settings menu
+ m_actionConfigure = KStdAction::preferences(this, SLOT(configure()), actionCollection(), "configure" );
+
+ //------------------------ Menu frameSet
+ KAction *actionChangePicture=new KAction( i18n( "Change Picture..." ),"frame_image",0,
+ this, SLOT( changePicture() ),
+ actionCollection(), "change_picture" );
+ actionChangePicture->setToolTip( i18n( "Change the picture in the currently selected frame." ) );
+ actionChangePicture->setWhatsThis( i18n( "You can specify a different picture in the current frame.<br><br>KWord automatically resizes the new picture to fit within the old frame." ) );
+
+ m_actionConfigureHeaderFooter=new KAction( i18n( "Configure Header/Footer..." ), 0,
+ this, SLOT( configureHeaderFooter() ),
+ actionCollection(), "configure_headerfooter" );
+ m_actionConfigureHeaderFooter->setToolTip( i18n( "Configure the currently selected header or footer." ) );
+ m_actionConfigureHeaderFooter->setWhatsThis( i18n( "Configure the currently selected header or footer." ) );
+
+ m_actionInlineFrame = new KToggleAction( i18n( "Inline Frame" ), 0,
+ this, SLOT( inlineFrame() ),
+ actionCollection(), "inline_frame" );
+ m_actionInlineFrame->setToolTip( i18n( "Convert current frame to an inline frame." ) );
+ m_actionInlineFrame->setWhatsThis( i18n( "Convert the current frame to an inline frame.<br><br>Place the inline frame within the text at the point nearest to the frames current position." ) );
+
+ m_actionOpenLink = new KAction( i18n( "Open Link" ), 0,
+ this, SLOT( openLink() ),
+ actionCollection(), "open_link" );
+ m_actionOpenLink->setToolTip( i18n( "Open the link with the appropriate application." ) );
+ m_actionOpenLink->setWhatsThis( i18n( "Open the link with the appropriate application.<br><br>Web addresses are opened in a browser.<br>Email addresses begin a new message addressed to the link.<br>File links are opened by the appropriate viewer or editor." ) );
+
+ m_actionChangeLink=new KAction( i18n("Change Link..."), 0,
+ this,SLOT(changeLink()),
+ actionCollection(), "change_link");
+ m_actionChangeLink->setToolTip( i18n( "Change the content of the currently selected link." ) );
+ m_actionChangeLink->setWhatsThis( i18n( "Change the details of the currently selected link." ) );
+
+ m_actionCopyLink = new KAction( i18n( "Copy Link" ), 0,
+ this, SLOT( copyLink() ),
+ actionCollection(), "copy_link" );
+
+ m_actionAddLinkToBookmak = new KAction( i18n( "Add to Bookmark" ), 0,
+ this, SLOT( addToBookmark() ),
+ actionCollection(), "add_to_bookmark" );
+
+ m_actionRemoveLink = new KAction( i18n( "Remove Link" ), 0,
+ this, SLOT( removeLink() ),
+ actionCollection(), "remove_link" );
+
+ m_actionShowDocStruct = new KToggleAction( i18n( "Show Doc Structure" ), 0,
+ this, SLOT( showDocStructure() ),
+ actionCollection(), "show_docstruct" );
+ m_actionShowDocStruct->setCheckedState(i18n("Hide Doc Structure"));
+ m_actionShowDocStruct->setToolTip( i18n( "Open document structure sidebar." ) );
+ m_actionShowDocStruct->setWhatsThis( i18n( "Open document structure sidebar.<p>This sidebar helps you organize your document and quickly find pictures, tables etc." ) );
+
+ m_actionShowRuler = new KToggleAction( i18n( "Show Rulers" ), 0,
+ this, SLOT( showRuler() ),
+ actionCollection(), "show_ruler" );
+ m_actionShowRuler->setCheckedState(i18n("Hide Rulers"));
+ m_actionShowRuler->setToolTip( i18n( "Shows or hides rulers." ) );
+ m_actionShowRuler->setWhatsThis( i18n("The rulers are the white measuring spaces top and left of the "
+ "document. The rulers show the position and width of pages and of frames and can "
+ "be used to position tabulators among others.<p>Uncheck this to disable "
+ "the rulers from being displayed." ) );
+
+ m_actionViewShowGrid = new KToggleAction( i18n( "Show Grid" ), 0,
+ this, SLOT( viewGrid() ),
+ actionCollection(), "view_grid" );
+ m_actionViewShowGrid->setCheckedState(i18n("Hide Grid"));
+
+ m_actionViewSnapToGrid= new KToggleAction( i18n( "Snap to Grid" ), 0,
+ this, SLOT(viewSnapToGrid() ),
+ actionCollection(), "view_snaptogrid" );
+
+ m_actionConfigureCompletion = new KAction( i18n( "Configure C&ompletion..." ), 0,
+ this, SLOT( configureCompletion() ),
+ actionCollection(), "configure_completion" );
+ m_actionConfigureCompletion->setToolTip( i18n( "Change the words and options for autocompletion." ) );
+ m_actionConfigureCompletion->setWhatsThis( i18n( "Add words or change the options for autocompletion." ) );
+
+
+ // ------------------- Actions with a key binding and no GUI item
+ new KAction( i18n( "Insert Non-Breaking Space" ), Qt::CTRL+Qt::Key_Space,
+ this, SLOT( slotNonbreakingSpace() ), actionCollection(), "nonbreaking_space" );
+ new KAction( i18n( "Insert Non-Breaking Hyphen" ), Qt::CTRL+Qt::SHIFT+Qt::Key_Minus,
+ this, SLOT( slotNonbreakingHyphen() ), actionCollection(), "nonbreaking_hyphen" );
+ new KAction( i18n( "Insert Soft Hyphen" ), Qt::CTRL+Qt::Key_Minus,
+ this, SLOT( slotSoftHyphen() ), actionCollection(), "soft_hyphen" );
+ new KAction( i18n( "Line Break" ), Qt::SHIFT+Qt::Key_Return,
+ this, SLOT( slotLineBreak() ), actionCollection(), "line_break" );
+
+ new KAction( i18n( "Completion" ), KStdAccel::shortcut(KStdAccel::TextCompletion), this, SLOT( slotCompletion() ), actionCollection(), "completion" );
+
+ new KAction( i18n( "Increase Numbering Level" ), Qt::ALT+Qt::Key_Right,
+ this, SLOT( slotIncreaseNumberingLevel() ), actionCollection(), "increase_numbering_level" );
+ new KAction( i18n( "Decrease Numbering Level" ), Qt::ALT+Qt::Key_Left,
+ this, SLOT( slotDecreaseNumberingLevel() ), actionCollection(), "decrease_numbering_level" );
+
+
+ // --------
+ m_actionEditCustomVars = new KAction( i18n( "Edit Variable..." ), 0,
+ this, SLOT( editCustomVariable() ),
+ actionCollection(), "edit_customvars" );
+ m_actionApplyAutoFormat= new KAction( i18n( "Apply Autocorrection" ), 0,
+ this, SLOT( applyAutoFormat() ),
+ actionCollection(), "apply_autoformat" );
+ m_actionApplyAutoFormat->setToolTip( i18n( "Manually force KWord to scan the entire document and apply autocorrection." ) );
+ m_actionApplyAutoFormat->setWhatsThis( i18n( "Manually force KWord to scan the entire document and apply autocorrection." ) );
+
+ m_actionCreateStyleFromSelection = new KAction( i18n( "Create Style From Selection..." ), 0,
+ this, SLOT( createStyleFromSelection()),
+ actionCollection(), "create_style" );
+ m_actionCreateStyleFromSelection->setToolTip( i18n( "Create a new style based on the currently selected text." ) );
+ m_actionCreateStyleFromSelection->setWhatsThis( i18n( "Create a new style based on the currently selected text." ) ); // ## "on the current paragraph, taking the formatting from where the cursor is. Selecting text isn't even needed."
+
+ m_actionConfigureFootEndNote = new KAction( i18n( "&Footnote..." ), 0,
+ this, SLOT( configureFootEndNote()),
+ actionCollection(), "format_footendnote" );
+ m_actionConfigureFootEndNote->setToolTip( i18n( "Change the look of footnotes." ) );
+ m_actionConfigureFootEndNote->setWhatsThis( i18n( "Change the look of footnotes." ) );
+
+ m_actionEditFootEndNote= new KAction( i18n("Edit Footnote"), 0,
+ this, SLOT( editFootEndNote()),
+ actionCollection(), "edit_footendnote" );
+ m_actionEditFootEndNote->setToolTip( i18n( "Change the content of the currently selected footnote." ) );
+ m_actionEditFootEndNote->setWhatsThis( i18n( "Change the content of the currently selected footnote." ) );
+
+
+ m_actionChangeFootNoteType = new KAction( i18n("Change Footnote/Endnote Parameter"), 0,
+ this, SLOT( changeFootNoteType() ),
+ actionCollection(), "change_footendtype");
+
+ m_actionSavePicture= new KAction( i18n("Save Picture As..."), 0,
+ this, SLOT( savePicture() ),
+ actionCollection(), "save_picture");
+ m_actionSavePicture->setToolTip( i18n( "Save the picture in a separate file." ) );
+ m_actionSavePicture->setWhatsThis( i18n( "Save the picture in the currently selected frame in a separate file, outside the KWord document." ) );
+
+ m_actionAllowBgSpellCheck = new KToggleAction( i18n( "Autospellcheck" ), 0,
+ this, SLOT( autoSpellCheck() ),
+ actionCollection(), "tool_auto_spellcheck" );
+
+
+ m_actionGoToFootEndNote = new KAction( QString::null /*set dynamically*/, 0,
+ this, SLOT( goToFootEndNote() ),
+ actionCollection(), "goto_footendnote" );
+
+ // Document Structure Area popup menu.
+ m_actionDocStructEdit = new KAction( i18n( "Edit Text" ), 0,
+ this, SLOT( docStructEdit() ),
+ actionCollection(), "docstruct_edit" );
+ m_actionDocStructSpeak = new KAction( i18n("Speak Text" ), 0,
+ this, SLOT( docStructSpeak() ),
+ actionCollection(), "docstruct_speak" );
+ m_actionDocStructSelect = new KAction( i18n( "Show" ), 0,
+ this, SLOT( docStructSelect() ),
+ actionCollection(), "docstruct_select" );
+ m_actionDocStructDelete = new KAction( i18n( "Delete Frame" ), 0,
+ this, SLOT( docStructDelete() ),
+ actionCollection(), "docstruct_delete" );
+ m_actionDocStructProperties = new KAction( i18n( "Properties" ), 0,
+ this, SLOT( docStructProperties() ),
+ actionCollection(), "docstruct_properties" );
+
+ m_actionAddBookmark= new KAction( i18n( "&Bookmark..." ), 0,
+ this, SLOT( addBookmark() ),
+ actionCollection(), "add_bookmark" );
+ m_actionSelectBookmark= new KAction( i18n( "Select &Bookmark..." ), 0,
+ this, SLOT( selectBookmark() ),
+ actionCollection(), "select_bookmark" );
+
+ m_actionImportStyle= new KAction( i18n( "Import Styles..." ), 0,
+ this, SLOT( importStyle() ),
+ actionCollection(), "import_style" );
+
+ m_actionCreateFrameStyle = new KAction( i18n( "&Create Framestyle From Frame..." ), 0,
+ this, SLOT( createFrameStyle()),
+ actionCollection(), "create_framestyle" );
+ m_actionCreateFrameStyle->setToolTip( i18n( "Create a new style based on the currently selected frame." ) );
+ m_actionCreateFrameStyle->setWhatsThis( i18n( "Create a new framestyle based on the currently selected frame." ) );
+
+#if 0 // re-enable after fixing
+ m_actionInsertDirectCursor = new KToggleAction( i18n( "Type Anywhere Cursor" ), 0,
+ this, SLOT( insertDirectCursor() ),
+ actionCollection(), "direct_cursor" );
+#endif
+
+ m_actionConvertToTextBox = new KAction( i18n( "Convert to Text Box" ), 0,
+ this, SLOT( convertToTextBox() ),
+ actionCollection(), "convert_to_text_box" );
+
+
+ m_actionSpellIgnoreAll = new KAction( i18n( "Ignore All" ), 0,
+ this, SLOT( slotAddIgnoreAllWord() ),
+ actionCollection(), "ignore_all" );
+
+ m_actionAddWordToPersonalDictionary=new KAction( i18n( "Add Word to Dictionary" ),0,
+ this, SLOT( addWordToDictionary() ),
+ actionCollection(), "add_word_to_dictionary" );
+
+ m_actionEmbeddedStoreInternal=new KToggleAction( i18n( "Store Document Internally" ),0,
+ this, SLOT( embeddedStoreInternal() ),
+ actionCollection(), "embedded_store_internal" );
+
+ m_actionGoToDocumentStructure=new KAction( i18n( "Go to Document Structure" ), KShortcut("Alt+1"),
+ this, SLOT( goToDocumentStructure() ),
+ actionCollection(), "goto_document_structure" );
+ m_actionGoToDocument=new KAction( i18n( "Go to Document" ), KShortcut("Alt+2"),
+ this, SLOT( goToDocument() ),
+ actionCollection(), "goto_document" );
+
+ // For RMB inside a cell, see KWFrameView::showPopup
+ // This isn't a dynamic list; it's only plugged/unplugged depending on the context.
+ // If you change the contents of that list, check ~KWView.
+ m_tableActionList.append( new KActionSeparator(actionCollection()) );
+ m_tableActionList.append( m_actionTableInsertRow );
+ m_tableActionList.append( m_actionTableDelRow );
+ m_tableActionList.append( m_actionTableInsertCol );
+ m_tableActionList.append( m_actionTableDelCol );
+}
+
+void KWView::refreshMenuExpression()
+{
+ loadexpressionActions( m_actionInsertExpression);
+}
+
+void KWView::updateGridButton()
+{
+ m_actionViewShowGrid->setChecked( m_doc->showGrid() );
+ m_actionViewSnapToGrid->setChecked ( m_doc->snapToGrid() );
+}
+
+void KWView::loadexpressionActions( KActionMenu * parentMenu)
+{
+ KActionPtrList lst = actionCollection()->actions("expression-action");
+ QValueList<KAction *> actions = lst;
+ QValueList<KAction *>::ConstIterator it = lst.begin();
+ QValueList<KAction *>::ConstIterator end = lst.end();
+ // Delete all actions but keep their shortcuts in mind
+ QMap<QString, KShortcut> personalShortCuts;
+ for (; it != end; ++it )
+ {
+ personalShortCuts.insert( (*it)->text(), (*it)->shortcut() );
+ delete *it;
+ }
+
+ parentMenu->popupMenu()->clear();
+ QStringList path = m_doc->personalExpressionPath();
+ QStringList files;
+ for ( QStringList::Iterator it = path.begin(); it != path.end(); ++it )
+ {
+ QDir dir( *it );
+ if ( dir.exists() )
+ {
+ QStringList tmp = dir.entryList("*.xml");
+ for ( QStringList::Iterator it2 = tmp.begin(); it2 != tmp.end(); ++it2 )
+ files.append( QString( (*it) + (*it2) ));
+ }
+ }
+
+ //QStringList files = KWFactory::instance()->dirs()->findAllResources( "expression", "*.xml", TRUE );
+ int i = 0;
+ int nbFile = 0;
+ for( QStringList::Iterator it = files.begin(); it != files.end(); ++it,nbFile++ )
+ createExpressionActions( parentMenu,*it, i,(nbFile<(int)files.count()-1), personalShortCuts );
+}
+
+void KWView::createExpressionActions( KActionMenu * parentMenu,const QString& filename,int &i, bool insertSepar, const QMap<QString, KShortcut>& personalShortCut )
+{
+ QFile file( filename );
+ if ( !file.exists() || !file.open( IO_ReadOnly ) )
+ return;
+
+ QDomDocument doc;
+ doc.setContent( &file );
+ file.close();
+
+ bool expressionExist =false;
+ QDomNode n = doc.documentElement().firstChild();
+ for( ; !n.isNull(); n = n.nextSibling() )
+ {
+ if ( n.isElement() )
+ {
+ QDomElement e = n.toElement();
+ if ( e.tagName() == "Type" )
+ {
+ expressionExist =true;
+ QString group = i18n( e.namedItem( "TypeName" ).toElement().text().utf8() );
+ KActionMenu * subMenu = new KActionMenu( group, actionCollection() );
+ parentMenu->insert( subMenu );
+
+ QDomNode n2 = e.firstChild();
+ for( ; !n2.isNull(); n2 = n2.nextSibling() )
+ {
+
+ if ( n2.isElement() )
+ {
+ QDomElement e2 = n2.toElement();
+ if ( e2.tagName() == "Expression" )
+ {
+ QString text = i18n( e2.namedItem( "Text" ).toElement().text().utf8() );
+ KAction * act = new KAction( text, 0, this, SLOT( insertExpression() ),
+ actionCollection(),
+ QString("expression-action_%1").arg(i).latin1() );
+ if ( personalShortCut.contains(text) )
+ act->setShortcut( personalShortCut[text] );
+ i++;
+ act->setGroup("expression-action");
+ subMenu->insert( act );
+ }
+ }
+ }
+ }
+ }
+ }
+ if(expressionExist && insertSepar)
+ parentMenu->popupMenu()->insertSeparator();
+}
+
+void KWView::insertExpression()
+{
+ KWTextFrameSetEdit * edit = currentTextEdit();
+ if ( edit )
+ {
+ KAction * act = (KAction *)(sender());
+ edit->insertExpression(act->text());
+ }
+}
+
+
+void KWView::addVariableActions( int type, const QStringList & texts,
+ KActionMenu * parentMenu, const QString & menuText )
+{
+ // Single items go directly into parentMenu.
+ // For multiple items we create a submenu.
+ if ( texts.count() > 1 && !menuText.isEmpty() )
+ {
+ KActionMenu * subMenu = new KActionMenu( menuText, actionCollection() );
+ parentMenu->insert( subMenu );
+ parentMenu = subMenu;
+ }
+ QStringList::ConstIterator it = texts.begin();
+ for ( int i = 0; it != texts.end() ; ++it, ++i )
+ {
+ if ( !(*it).isEmpty() ) // in case of removed subtypes or placeholders
+ {
+ VariableDef v;
+ v.type = type;
+ v.subtype = i;
+ QCString actionName;
+ actionName.sprintf( "var-action-%d-%d", type, i );
+ KAction * act = new KAction( (*it), 0, this, SLOT( insertVariable() ),
+ actionCollection(), actionName );
+ // Mainly for KEditToolbar
+ act->setToolTip( i18n( "Insert variable \"%1\" into the text" ).arg( *it ) );
+ m_variableDefMap.insert( act, v );
+ parentMenu->insert( act );
+ }
+ }
+}
+
+void KWView::refreshCustomMenu()
+{
+ KActionPtrList lst2 = actionCollection()->actions("custom-variable-action");
+ QValueList<KAction *> actions = lst2;
+ QValueList<KAction *>::ConstIterator it2 = lst2.begin();
+ QValueList<KAction *>::ConstIterator end = lst2.end();
+ QMap<QString, KShortcut> shortCuts;
+
+ for (; it2 != end; ++it2 )
+ {
+ shortCuts.insert((*it2)->text(), (*it2)->shortcut());
+ delete *it2;
+ }
+
+ delete m_actionInsertCustom;
+ m_actionInsertCustom = new KActionMenu( i18n( "&Custom" ),
+ actionCollection(), "insert_custom" );
+ actionInsertVariable->insert(m_actionInsertCustom, 0);
+
+ m_actionInsertCustom->popupMenu()->clear();
+ QPtrListIterator<KoVariable> it( m_doc->variableCollection()->getVariables() );
+ KAction * act=0;
+ QStringList lst;
+ QString varName;
+ int i = 0;
+ for ( ; it.current() ; ++it )
+ {
+ KoVariable *var = it.current();
+ if ( var->type() == VT_CUSTOM )
+ {
+ varName=( (KoCustomVariable*) var )->name();
+ if ( !lst.contains( varName) )
+ {
+ lst.append( varName );
+ QCString name = QString("custom-action_%1").arg(i).latin1();
+ act = new KAction( varName, shortCuts[varName], this, SLOT( insertCustomVariable() ),actionCollection(), name );
+ act->setGroup( "custom-variable-action" );
+ m_actionInsertCustom->insert( act );
+ i++;
+ }
+ }
+ }
+ bool state=!lst.isEmpty();
+ if(state)
+ m_actionInsertCustom->popupMenu()->insertSeparator();
+
+ act = new KAction( i18n("New..."), 0, this, SLOT( insertNewCustomVariable() ), actionCollection(),QString("custom-action_%1").arg(i).latin1());
+ act->setGroup( "custom-variable-action" );
+
+
+ m_actionEditCustomVarsEdit->setEnabled( state );
+
+ m_actionInsertCustom->insert( act );
+
+}
+
+
+void KWView::insertCustomVariable()
+{
+ KWTextFrameSetEdit * edit = currentTextEdit();
+ if ( edit )
+ {
+ KAction * act = (KAction *)(sender());
+ edit->insertCustomVariable(act->text());
+ }
+}
+
+void KWView::insertNewCustomVariable()
+{
+ KWTextFrameSetEdit * edit = currentTextEdit();
+ if ( edit )
+ edit->insertVariable( VT_CUSTOM, 0 );
+}
+
+void KWView::showFormulaToolbar( bool show )
+{
+ m_doc->formulaDocument()->setEnabled( show );
+ m_doc->formulaDocumentWrapper()->enableMatrixActions( show );
+ m_doc->formulaDocumentWrapper()->getSyntaxHighlightingAction()->setEnabled( true );
+ if(shell())
+ shell()->showToolbar( "formula_toolbar", show );
+}
+
+void KWView::updatePageInfo()
+{
+ if ( m_sbPageLabel )
+ {
+ KWFrameSetEdit * edit = m_gui->canvasWidget()->currentFrameSetEdit();
+ if ( edit && edit->currentFrame() )
+ m_currentPage = m_doc->pageManager()->page(edit->currentFrame());
+ else {
+ KWFrameView *view = frameViewManager()->selectedFrame();
+ if(view)
+ m_currentPage = m_doc->pageManager()->page(view->frame());
+ }
+ /*kdDebug() << (void*)this << " KWView::updatePageInfo "
+ << " edit: " << edit << " " << ( edit?edit->frameSet()->name():QString::null)
+ << " currentFrame: " << (edit?edit->currentFrame():0L)
+ << " m_currentPage=" << currentPage() << " m_sbPageLabel=" << m_sbPageLabel
+ << endl;*/
+
+ QString oldText = m_sbPageLabel->text();
+ QString newText;
+ if ( viewMode()->hasPages() )
+ newText = ' ' + i18n( "Page %1 of %2" ).arg(m_currentPage->pageNumber())
+ .arg(m_doc->pageCount()) + ' ';
+
+ if ( newText != oldText )
+ {
+ m_sbPageLabel->setText( newText );
+ // Need to repaint immediately. Otherwise when deleting 100 pages
+ // at once, there's no feedback.
+ m_sbPageLabel->repaint();
+ }
+ }
+ slotUpdateRuler();
+}
+
+void KWView::numPagesChanged()
+{
+ docStructChanged(TextFrames);
+ updatePageInfo();
+ int pages = m_doc->pageCount();
+ kdDebug() << pages << " " << (m_doc->processingType() == KWDocument::DTP) << endl;
+ refreshDeletePageAction();
+}
+
+void KWView::updateFrameStatusBarItem()
+{
+ KStatusBar * sb = statusBar();
+ int nbFrame=frameViewManager()->selectedFrames().count();
+ if ( m_doc->showStatusBar() && sb && nbFrame > 0 )
+ {
+ if ( nbFrame == 1 )
+ {
+ KoUnit::Unit unit = m_doc->unit();
+ QString unitName = m_doc->unitName();
+ KWFrame * frame = frameViewManager()->selectedFrames()[0]->frame();
+ m_sbFramesLabel->setText( ' ' + i18n( "Statusbar info", "%1: %2, %3 - %4, %5 (width: %6, height: %7)" )
+ .arg( frame->frameSet()->name() )
+ .arg( KoUnit::toUserStringValue( frame->left(), unit ) )
+ .arg( KoUnit::toUserStringValue( frame->top() - m_doc->pageManager()->topOfPage(
+ m_doc->pageManager()->pageNumber(frame->rect()) ), unit) )
+ .arg( KoUnit::toUserStringValue( frame->right(), unit ) )
+ .arg( KoUnit::toUserStringValue( frame->bottom(), unit ) )
+ .arg( KoUnit::toUserStringValue( frame->width(), unit ) )
+ .arg( KoUnit::toUserStringValue( frame->height(), unit ) ) );
+ } else
+ m_sbFramesLabel->setText( ' ' + i18n( "%1 frames selected" ).arg( nbFrame ) );
+ }
+ else if ( sb && m_sbFramesLabel )
+ m_sbFramesLabel->setText( QString::null );
+}
+
+void KWView::setTemporaryStatusBarText(const QString &text)
+{
+ if ( statusBar() && m_sbFramesLabel )
+ m_sbFramesLabel->setText( text );
+}
+
+void KWView::clipboardDataChanged()
+{
+ if ( !m_gui || !m_doc->isReadWrite() )
+ {
+ m_actionEditPaste->setEnabled(false);
+ return;
+ }
+ KWFrameSetEdit * edit = m_gui->canvasWidget()->currentFrameSetEdit();
+ // Is there plain text in the clipboard ?
+ if ( edit && !QApplication::clipboard()->text().isEmpty() )
+ {
+ m_actionEditPaste->setEnabled(true);
+ return;
+ }
+ QMimeSource *data = QApplication::clipboard()->data();
+ const int provides = checkClipboard( data );
+ if ( provides & ( ProvidesImage | ProvidesOasis | ProvidesFormula ) )
+ m_actionEditPaste->setEnabled( true );
+ else
+ {
+ // Plain text requires a framesetedit
+ m_actionEditPaste->setEnabled( edit && ( provides & ProvidesPlainText ) );
+ }
+}
+
+int KWView::checkClipboard( QMimeSource *data )
+{
+ int provides = 0;
+ QValueList<QCString> formats;
+ const char* fmt;
+ for (int i=0; (fmt = data->format(i)); i++)
+ formats.append( QCString( fmt ) );
+
+ if ( QImageDrag::canDecode( data ) )
+ provides |= ProvidesImage;
+ if ( formats.findIndex( KFormula::MimeSource::selectionMimeType() ) != -1 )
+ provides |= ProvidesFormula;
+ if ( formats.findIndex( "text/plain" ) != -1 )
+ provides |= ProvidesPlainText;
+ QCString returnedTypeMime = KoTextObject::providesOasis( data );
+ if ( !returnedTypeMime.isEmpty() )
+ provides |= ProvidesOasis;
+ //kdDebug(32001) << "KWView::checkClipboard provides=" << provides << endl;
+ return provides;
+}
+
+/*=========================== file print =======================*/
+void KWView::setupPrinter( KPrinter &prt )
+{
+ //recalc time and date variable before to print
+ //it's necessary otherwise we print a document
+ //with a bad date and time
+ //TODO call once this function
+ m_doc->recalcVariables( VT_TIME );
+ m_doc->recalcVariables( VT_DATE );
+ m_doc->recalcVariables( VT_STATISTIC );
+
+ prt.setPageSelection( KPrinter::ApplicationSide );
+ prt.setCurrentPage( currentPage() );
+ prt.setMinMax( m_doc->startPage(), m_doc->lastPage() );
+
+ KoPageLayout pgLayout = m_doc->pageLayout();
+
+ prt.setPageSize( static_cast<KPrinter::PageSize>( KoPageFormat::printerPageSize( pgLayout.format ) ) );
+
+ if ( pgLayout.orientation == PG_LANDSCAPE || pgLayout.format == PG_SCREEN )
+ prt.setOrientation( KPrinter::Landscape );
+ else
+ prt.setOrientation( KPrinter::Portrait );
+}
+
+void KWView::print( KPrinter &prt )
+{
+ bool displayFieldCode = m_doc->variableCollection()->variableSetting()->displayFieldCode();
+ if ( displayFieldCode )
+ {
+ m_doc->variableCollection()->variableSetting()->setDisplayFieldCode(false);
+ m_doc->recalcVariables( VT_ALL );
+ }
+
+// Don't repaint behind the print dialog until we're done zooming/unzooming the doc
+ m_gui->canvasWidget()->setUpdatesEnabled(false);
+ m_gui->canvasWidget()->viewport()->setCursor( waitCursor );
+
+ prt.setFullPage( true );
+
+ // ### HACK: disable zooming-when-printing if embedded parts are used.
+ // No koffice app supports zooming in paintContent currently.
+ // Disable in ALL cases now
+ bool doZoom = false;
+ /*QPtrListIterator<KWFrameSet> fit = m_doc->framesetsIterator();
+ for ( ; fit.current() && doZoom ; ++fit )
+ if ( fit.current()->type() == FT_PART )
+ doZoom = false;*/
+
+ int oldZoom = m_doc->zoom();
+ // We don't get valid metrics from the printer - and we want a better resolution
+ // anyway (it's the PS driver that takes care of the printer resolution).
+ QPaintDeviceMetrics metrics( &prt );
+
+ //int dpiX = metrics.logicalDpiX();
+ //int dpiY = metrics.logicalDpiY();
+ int dpiX = doZoom ? 300 : KoGlobal::dpiX();
+ int dpiY = doZoom ? 300 : KoGlobal::dpiY();
+ ///////// Changing the dpiX/dpiY is very wrong nowadays. This has no effect on the font size
+ ///////// that we give Qt, anymore, so it leads to minuscule fonts in the printout => doZoom==false.
+ m_doc->setZoomAndResolution( 100, dpiX, dpiY );
+ m_doc->newZoomAndResolution( false, true /* for printing*/ );
+ //kdDebug() << "KWView::print metrics: " << metrics.logicalDpiX() << "," << metrics.logicalDpiY() << endl;
+ //kdDebug() << "x11AppDPI: " << KoGlobal::dpiX() << "," << KoGlobal::dpiY() << endl;
+
+ bool serialLetter = FALSE;
+
+ QPtrList<KoVariable> vars = m_doc->variableCollection()->getVariables();
+ KoVariable *v = 0;
+ for ( v = vars.first(); v; v = vars.next() ) {
+ if ( v->type() == VT_MAILMERGE ) {
+ serialLetter = TRUE;
+ break;
+ }
+ }
+
+ if ( !m_doc->mailMergeDataBase() ) serialLetter=FALSE;
+ else
+ {
+ m_doc->mailMergeDataBase()->refresh(false);
+ if (m_doc->mailMergeDataBase()->getNumRecords() == 0 ) serialLetter = FALSE;
+ }
+
+ //float left_margin = 0.0;
+ //float top_margin = 0.0;
+
+ KoPageLayout pgLayout;
+ KoColumns cl;
+ KoKWHeaderFooter hf;
+ m_doc->getPageLayout( pgLayout, cl, hf );
+ KoPageLayout oldPGLayout = pgLayout;
+
+ if ( pgLayout.format == PG_SCREEN )
+ {
+ //left_margin = 25.8;
+ //top_margin = 15.0;
+ pgLayout.ptLeft += 25.8; // Not sure why we need this....
+ pgLayout.ptRight += 15.0;
+ m_doc->setPageLayout( pgLayout, cl, hf, false );
+ }
+
+ QPainter painter;
+ painter.begin( &prt );
+
+ kdDebug(32001) << "KWView::print scaling by " << (double)metrics.logicalDpiX() / (double)dpiX
+ << "," << (double)metrics.logicalDpiY() / (double)dpiY << endl;
+ painter.scale( (double)metrics.logicalDpiX() / (double)dpiX,
+ (double)metrics.logicalDpiY() / (double)dpiY );
+
+ bool canceled = false;
+ // Breaks wysiwyg, obviously - trying without
+//#define KW_PASS_PAINTER_TO_QRT
+#ifdef KW_PASS_PAINTER_TO_QRT
+ int paragraphs = 0;
+ fit.toFirst();
+ for ( ; fit.current() ; ++fit )
+ if ( fit.current()->isVisible() )
+ paragraphs += fit.current()->paragraphs();
+ kdDebug() << "KWView::print total paragraphs: " << paragraphs << endl;
+
+ // This can take a lot of time (reformatting everything), so a progress dialog is needed
+ QProgressDialog progress( i18n( "Printing..." ), i18n( "Cancel" ), paragraphs, this );
+ progress.setProgress( 0 );
+ int processedParags = 0;
+ fit.toFirst();
+ for ( ; fit.current() ; ++fit )
+ if ( fit.current()->isVisible() )
+ {
+ qApp->processEvents();
+ if ( progress.wasCancelled() ) {
+ canceled = true;
+ break;
+ }
+
+ kdDebug() << "KWView::print preparePrinting " << fit.current()->name() << endl;
+ fit.current()->preparePrinting( &painter, &progress, processedParags );
+ }
+#endif
+
+ if ( !canceled )
+ {
+ if ( !serialLetter )
+ m_gui->canvasWidget()->print( &painter, &prt );
+ else
+ {
+ for ( int i = 0; i < m_doc->mailMergeDataBase()->getNumRecords(); ++i ) {
+ m_doc->setMailMergeRecord( i );
+ m_doc->variableCollection()->recalcVariables(VT_MAILMERGE);
+ m_gui->canvasWidget()->print( &painter, &prt );
+ if ( i < m_doc->mailMergeDataBase()->getNumRecords() - 1 )
+ prt.newPage();
+ }
+ m_doc->setMailMergeRecord( -1 );
+ }
+ }
+
+ if ( pgLayout.format == PG_SCREEN )
+ m_doc->setPageLayout( oldPGLayout, cl, hf, false );
+
+#ifdef KW_PASS_PAINTER_TO_QRT
+ fit.toFirst();
+ for ( ; fit.current() ; ++fit )
+ if ( fit.current()->isVisible() )
+ fit.current()->preparePrinting( 0L, 0L, processedParags );
+#endif
+
+ m_doc->setZoomAndResolution( oldZoom, KoGlobal::dpiX(), KoGlobal::dpiY() );
+ m_doc->newZoomAndResolution( false, false );
+ kdDebug() << "KWView::print zoom&res reset" << endl;
+
+ m_gui->canvasWidget()->setUpdatesEnabled(true);
+ m_gui->canvasWidget()->viewport()->setCursor( ibeamCursor );
+ m_doc->repaintAllViews();
+
+ if ( displayFieldCode )
+ {
+ m_doc->variableCollection()->variableSetting()->setDisplayFieldCode(true);
+ m_doc->recalcVariables( VT_ALL );
+ }
+ else
+ m_doc->variableCollection()->recalcVariables(VT_MAILMERGE);
+
+ painter.end(); // this is what triggers the printing
+ m_doc->variableCollection()->variableSetting()->setLastPrintingDate(QDateTime::currentDateTime());
+ m_doc->recalcVariables( VT_DATE );
+}
+
+void KWView::showFormat( const KoTextFormat &currentFormat )
+{
+ // update the gui with the current format.
+ //kdDebug() << "KWView::setFormat font family=" << currentFormat.font().family() << endl;
+ if (m_actionFormatFontFamily->font() != currentFormat.font().family())
+ m_actionFormatFontFamily->setFont( currentFormat.font().family() );
+ if (m_actionFormatFontSize->fontSize() != currentFormat.pointSize())
+ m_actionFormatFontSize->setFontSize( currentFormat.pointSize() );
+ m_actionFormatBold->setChecked( currentFormat.font().bold());
+ m_actionFormatItalic->setChecked( currentFormat.font().italic() );
+ m_actionFormatUnderline->setChecked( currentFormat.underline());
+ m_actionFormatStrikeOut->setChecked( currentFormat.strikeOut());
+ QColor col=currentFormat.textBackgroundColor();
+ //m_actionBackgroundColor->setEnabled(true);
+ m_actionBackgroundColor->setCurrentColor( col.isValid() ? col : QApplication::palette().color( QPalette::Active, QColorGroup::Base ));
+
+ if ( m_gui /* if not in constructor */ && frameViewManager()->selectedFrames().count() > 0)
+ m_actionBackgroundColor->setText(i18n("Frame Background Color..."));
+ else
+ m_actionBackgroundColor->setText(i18n("Text Background Color..."));
+ switch(currentFormat.vAlign())
+ {
+ case KoTextFormat::AlignSuperScript:
+ {
+ m_actionFormatSub->setChecked( false );
+ m_actionFormatSuper->setChecked( true );
+ break;
+ }
+ case KoTextFormat::AlignSubScript:
+ {
+ m_actionFormatSub->setChecked( true );
+ m_actionFormatSuper->setChecked( false );
+ break;
+ }
+ case KoTextFormat::AlignNormal:
+ default:
+ {
+ m_actionFormatSub->setChecked( false );
+ m_actionFormatSuper->setChecked( false );
+ break;
+ }
+ }
+
+}
+
+void KWView::showRulerIndent( double leftMargin, double firstLine, double rightMargin, bool rtl )
+{
+ KoRuler * hRuler = m_gui ? m_gui->getHorzRuler() : 0;
+ if ( hRuler )
+ {
+ hRuler->setFirstIndent( KoUnit::toUserValue( firstLine, m_doc->unit() ) );
+ hRuler->setLeftIndent( KoUnit::toUserValue( leftMargin, m_doc->unit() ) );
+ hRuler->setRightIndent( KoUnit::toUserValue( rightMargin, m_doc->unit() ) );
+ hRuler->setDirection( rtl );
+ m_actionFormatDecreaseIndent->setEnabled( leftMargin>0);
+ }
+}
+
+void KWView::showAlign( int align ) {
+ switch ( align ) {
+ case Qt::AlignAuto: // In left-to-right mode it's align left. TODO: alignright if text->isRightToLeft()
+ kdWarning() << k_funcinfo << "shouldn't be called with AlignAuto" << endl;
+ // fallthrough
+ case Qt::AlignLeft:
+ m_actionFormatAlignLeft->setChecked( TRUE );
+ break;
+ case Qt::AlignHCenter:
+ m_actionFormatAlignCenter->setChecked( TRUE );
+ break;
+ case Qt::AlignRight:
+ m_actionFormatAlignRight->setChecked( TRUE );
+ break;
+ case Qt::AlignJustify:
+ m_actionFormatAlignBlock->setChecked( TRUE );
+ break;
+ }
+}
+
+void KWView::showSpacing( int spacing ) {
+ switch ( spacing )
+ {
+ case KoParagLayout::LS_SINGLE:
+ m_actionFormatSpacingSingle->setChecked( TRUE );
+ break;
+ case KoParagLayout::LS_ONEANDHALF:
+ m_actionFormatSpacingOneAndHalf->setChecked( TRUE );
+ break;
+ case KoParagLayout::LS_DOUBLE:
+ m_actionFormatSpacingDouble->setChecked( TRUE );
+ break;
+ default:
+ m_actionFormatSpacingSingle->setChecked( FALSE );
+ m_actionFormatSpacingOneAndHalf->setChecked( FALSE );
+ m_actionFormatSpacingDouble->setChecked( FALSE );
+ }
+}
+
+void KWView::showCounter( KoParagCounter &c )
+{
+ QString styleStr("counterstyle_");
+ styleStr += QString::number( c.style() );
+ //kdDebug() << "KWView::showCounter styleStr=" << styleStr << endl;
+ KToggleAction* act = static_cast<KToggleAction *>( actionCollection()->action( styleStr.latin1() ) );
+ Q_ASSERT( act );
+ if ( act )
+ act->setChecked( true );
+}
+
+void KWView::updateBorderButtons( const KoBorder& left, const KoBorder& right,
+ const KoBorder& top, const KoBorder& bottom )
+{
+ m_actionBorderLeft->setChecked( left.penWidth() > 0 );
+ m_actionBorderRight->setChecked( right.penWidth() > 0 );
+ m_actionBorderTop->setChecked( top.penWidth() > 0 );
+ m_actionBorderBottom->setChecked( bottom.penWidth() > 0 );
+ m_actionBorderOutline->setChecked(
+ m_actionBorderLeft->isChecked() &&
+ m_actionBorderRight->isChecked() &&
+ m_actionBorderTop->isChecked() &&
+ m_actionBorderBottom->isChecked());
+
+ KoBorder border = left;
+ if(left.penWidth() > 0)
+ border = left;
+ else if(right.penWidth() > 0)
+ border = right;
+ else if(top.penWidth() > 0)
+ border = top;
+ else if(bottom.penWidth() > 0)
+ border = bottom;
+ else
+ return;// then don't update since they are all empty.
+
+ m_actionBorderWidth->setCurrentItem( (int)border.penWidth() - 1 );
+ m_actionBorderStyle->setCurrentItem( (int)border.getStyle() );
+ m_actionBorderColor->setCurrentColor( border.color );
+}
+
+void KWView::updateReadWrite( bool readwrite )
+{
+ // First disable or enable everything
+ QValueList<KAction*> actions = actionCollection()->actions();
+ // Also grab actions from the document
+ actions += m_doc->actionCollection()->actions();
+ QValueList<KAction*>::ConstIterator aIt = actions.begin();
+ QValueList<KAction*>::ConstIterator aEnd = actions.end();
+ for (; aIt != aEnd; ++aIt )
+ (*aIt)->setEnabled( readwrite );
+
+ if ( !readwrite )
+ {
+ // Readonly -> re-enable a few harmless actions
+ m_actionFileStatistics->setEnabled( true );
+ m_actionExtraCreateTemplate->setEnabled( true );
+ m_actionViewPageMode->setEnabled( true );
+ m_actionViewPreviewMode->setEnabled( true );
+
+ m_actionViewTextMode->setEnabled( true );
+ m_actionShowRuler->setEnabled( true );
+ m_actionEditFind->setEnabled( true );
+ m_actionViewFormattingChars->setEnabled( true );
+ m_actionViewFrameBorders->setEnabled( true );
+ // that's not readonly, in fact, it modifies the doc
+ //m_actionViewHeader->setEnabled( true );
+ //m_actionViewFooter->setEnabled( true );
+ m_actionViewZoom->setEnabled( true );
+ m_actionInsertComment->setEnabled( true );
+ m_actionAllowAutoFormat->setEnabled( true );
+ m_actionShowDocStruct->setEnabled( true );
+ m_actionConfigureCompletion->setEnabled( true );
+ m_actionFormatBullet->setEnabled(true);
+ m_actionFormatNumber->setEnabled( true);
+ m_actionSelectBookmark->setEnabled( true );
+ KAction* act = actionCollection()->action("edit_sldatabase");
+ if (act)
+ act->setEnabled( true );
+
+ // In fact the new view could be readwrite, so this is too dangerous
+ // (e.g. during spellchecking or during search-n-replace)
+ //act = actionCollection()->action("view_newview");
+ //if (act)
+ // act->setEnabled( true );
+ }
+ else
+ {
+ frameSelectedChanged();
+ slotFrameSetEditChanged();
+ refreshCustomMenu();
+ refreshDeletePageAction();
+ // Correctly enable or disable undo/redo actions again
+ m_doc->commandHistory()->updateActions();
+ }
+}
+
+void KWView::refreshDeletePageAction()
+{
+ m_actionDeletePage->setEnabled( m_doc->pageCount() > 1 && m_doc->processingType() == KWDocument::DTP );
+}
+
+void KWView::showMouseMode( int mouseMode )
+{
+ switch ( mouseMode ) {
+ case KWCanvas::MM_EDIT:
+ case KWCanvas::MM_CREATE_TABLE:
+ case KWCanvas::MM_CREATE_FORMULA:
+ case KWCanvas::MM_CREATE_PART:
+ // No tool to activate for this mode -> deselect all the others
+ m_actionToolsCreateText->setChecked( false );
+ m_actionToolsCreatePix->setChecked( false );
+ //m_actionToolsCreatePart->setChecked( false );
+ break;
+ case KWCanvas::MM_CREATE_TEXT:
+ m_actionToolsCreateText->setChecked( true );
+ break;
+ case KWCanvas::MM_CREATE_PIX:
+ m_actionToolsCreatePix->setChecked( true );
+ break;
+ //case KWCanvas::MM_CREATE_PART:
+ //m_actionToolsCreatePart->setChecked( true );
+ break;
+ }
+
+ m_actionTableJoinCells->setEnabled( FALSE );
+ m_actionTableSplitCells->setEnabled( FALSE );
+ m_actionTableProtectCells->setEnabled( false );
+ m_actionFormatFrameSet->setEnabled(FALSE);
+ m_actionTablePropertiesMenu->setEnabled( false );
+ m_actionConvertTableToText->setEnabled( false );
+}
+
+void KWView::showStyle( const QString & styleName )
+{
+ KoParagStyle* style = m_doc->styleCollection()->findStyle( styleName );
+ if ( style ) {
+ int pos = m_doc->styleCollection()->indexOf( style );
+ // Select style in combo
+ m_actionFormatStyle->setCurrentItem( pos );
+ // Check the appropriate action among the m_actionFormatStyleMenu actions
+ KToggleAction* act = dynamic_cast<KToggleAction *>(actionCollection()->action(style->name().utf8()));
+ if ( act )
+ act->setChecked( true );
+ }
+}
+
+// used to avoid action naming conflicts
+static const char* PARAGSTYLE_ACTION_PREFIX = "paragstyle_";
+static const char* FRAMESTYLE_ACTION_PREFIX = "framestyle_";
+static const char* TABLESTYLE_ACTION_PREFIX = "tablestyle_";
+
+void KWView::updateStyleList()
+{
+ QString currentStyle = m_actionFormatStyle->currentText();
+ // Generate list of styles
+ const QStringList lst = m_doc->styleCollection()->displayNameList();
+ const int pos = lst.findIndex( currentStyle );
+ // Fill the combo - using a KSelectAction
+ m_actionFormatStyle->setItems( lst );
+ if ( pos > -1 )
+ m_actionFormatStyle->setCurrentItem( pos );
+
+ // Fill the menu - using a KActionMenu, so that it's possible to bind keys
+ // to individual actions
+ QStringList lstWithAccels;
+ // Generate unique accelerators for the menu items
+ KAccelGen::generate( lst, lstWithAccels );
+ QMap<QString, KShortcut> shortCuts;
+
+ KActionPtrList lst2 = actionCollection()->actions("styleList");
+ QValueList<KAction *> actions = lst2;
+ QValueList<KAction *>::ConstIterator it = lst2.begin();
+ const QValueList<KAction *>::ConstIterator end = lst2.end();
+ for (; it != end; ++it )
+ {
+ shortCuts.insert( QString::fromUtf8( (*it)->name() ), (*it)->shortcut() );
+ m_actionFormatStyleMenu->remove( *it );
+ delete *it;
+ }
+ uint i = 0;
+ for ( QStringList::Iterator it = lstWithAccels.begin(); it != lstWithAccels.end(); ++it, ++i )
+ {
+ // The list lst was created (unsorted) from the style collection, so we have still the same order.
+ KoParagStyle *style = m_doc->styleCollection()->styleAt( i );
+ if ( style )
+ {
+ QString name = PARAGSTYLE_ACTION_PREFIX + style->name();
+ KToggleAction* act = new KToggleAction( (*it),
+ shortCuts[name], this, SLOT( slotStyleSelected() ),
+ actionCollection(), name.utf8() );
+ act->setGroup( "styleList" );
+ act->setExclusiveGroup( "styleListAction" );
+ act->setToolTip( i18n( "Apply a paragraph style" ) );
+ m_actionFormatStyleMenu->insert( act );
+ }
+ else
+ kdWarning() << "No style found for " << *it << endl;
+ }
+}
+
+// Called when selecting a style in the Format / Style menu
+void KWView::slotStyleSelected()
+{
+ QString actionName = QString::fromUtf8(sender()->name());
+ const QString prefix = PARAGSTYLE_ACTION_PREFIX;
+ if ( actionName.startsWith( prefix ) ) {
+ actionName = actionName.mid( prefix.length() );
+ kdDebug(32001) << "KWView::slotStyleSelected " << actionName << endl;
+ textStyleSelected( m_doc->styleCollection()->findStyle( actionName ) );
+ }
+}
+
+void KWView::updateFrameStyleList()
+{
+ // Remember selected style (by name; better would be by pointer, but what if it got deleted?)
+ // This is all in case the index of the selected style has changed.
+ const QString currentStyle = m_actionFrameStyle->currentText();
+ // Generate list of styles
+ const QStringList lst = m_doc->frameStyleCollection()->displayNameList();
+ const int pos = lst.findIndex( currentStyle );
+ // Fill the combo
+ m_actionFrameStyle->setItems( lst );
+ if ( pos > -1 )
+ m_actionFrameStyle->setCurrentItem( pos );
+
+ // Fill the menu - using a KActionMenu, so that it's possible to bind keys
+ // to individual actions
+ QStringList lstWithAccels;
+ // Generate unique accelerators for the menu items
+ KAccelGen::generate( lst, lstWithAccels );
+ QMap<QString, KShortcut> shortCuts; // style (internal) name -> shortcut
+
+
+ KActionPtrList lst2 = actionCollection()->actions("frameStyleList");
+ QValueList<KAction *> actions = lst2;
+ QValueList<KAction *>::ConstIterator it = lst2.begin();
+ QValueList<KAction *>::ConstIterator end = lst2.end();
+ for (; it != end; ++it )
+ {
+ shortCuts.insert( QString::fromUtf8( (*it)->name() ), (*it)->shortcut() );
+ m_actionFrameStyleMenu->remove( *it );
+ delete *it;
+ }
+
+ uint i = 0;
+ for ( QStringList::Iterator it = lstWithAccels.begin(); it != lstWithAccels.end(); ++it, ++i )
+ {
+ // The list lst was created (unsorted) from the frame style collection, so we have still the same order.
+ KWFrameStyle *style = m_doc->frameStyleCollection()->frameStyleAt( i );
+ if ( style )
+ {
+ QString name = FRAMESTYLE_ACTION_PREFIX + style->name();
+ KToggleAction* act = new KToggleAction( (*it),
+ shortCuts[name], // KDE4: use value()
+ this, SLOT( slotFrameStyleSelected() ),
+ actionCollection(), name.utf8() /*KDE4: remove conversion*/ );
+ act->setGroup( "frameStyleList" );
+ act->setExclusiveGroup( "frameStyleList" );
+ act->setToolTip( i18n( "Apply a frame style" ) );
+ m_actionFrameStyleMenu->insert( act );
+ }
+ else
+ kdWarning() << "No frame style found for " << *it << endl;
+ }
+}
+
+
+void KWView::updateTableStyleList()
+{
+ const QString currentStyle = m_actionTableStyle->currentText();
+ // Generate list of styles
+ const QStringList lst = m_doc->tableStyleCollection()->displayNameList();
+ const int pos = lst.findIndex( currentStyle );
+ // Fill the combo
+ m_actionTableStyle->setItems( lst );
+ if ( pos > -1 )
+ m_actionTableStyle->setCurrentItem( pos );
+
+ // Fill the menu - using a KActionMenu, so that it's possible to bind keys
+ // to individual actions
+ QStringList lstWithAccels;
+ // Generate unique accelerators for the menu items
+ KAccelGen::generate( lst, lstWithAccels );
+ QMap<QString, KShortcut> shortCuts;
+
+ QValueList<KAction *> actions = actionCollection()->actions("tableStyleList");
+ QValueList<KAction *>::ConstIterator it = actions.begin();
+ const QValueList<KAction *>::ConstIterator end = actions.end();
+ for (; it != end; ++it )
+ {
+ shortCuts.insert( QString::fromUtf8( (*it)->name() ), (*it)->shortcut() );
+ m_actionTableStyleMenu->remove( *it );
+ delete *it;
+ }
+
+ uint i = 0;
+ for ( QStringList::Iterator it = lstWithAccels.begin(); it != lstWithAccels.end(); ++it, ++i )
+ {
+ // The list lst was created (unsorted) from the table style collection, so we have still the same order.
+ KWTableStyle *style = m_doc->tableStyleCollection()->tableStyleAt( i );
+ if ( style )
+ {
+ QString name = TABLESTYLE_ACTION_PREFIX + style->name();
+ KToggleAction* act = new KToggleAction( (*it),
+ shortCuts[name], this, SLOT( slotTableStyleSelected() ),
+ actionCollection(), name.utf8() );
+ act->setExclusiveGroup( "tableStyleList" );
+ act->setGroup( "tableStyleList" );
+ act->setToolTip( i18n( "Apply a table style" ) );
+ m_actionTableStyleMenu->insert( act );
+ }
+ else
+ kdWarning() << "No table style found for " << *it << endl;
+ }
+}
+
+void KWView::editCut()
+{
+ KWFrameSetEdit * edit = currentTextEdit();
+ if ( edit )
+ edit->cut();
+ else {
+ QDragObject *drag = m_doc->dragSelected( frameViewManager()->selectedFrames() );
+ QApplication::clipboard()->setData( drag );
+ deleteFrame(false);
+ }
+}
+
+void KWView::editCopy()
+{
+ KWTextFrameSetEdit * edit = currentTextEdit();
+ if ( edit )
+ edit->copy();
+ else {
+ QDragObject *drag = m_doc->dragSelected( frameViewManager()->selectedFrames() );
+ QApplication::clipboard()->setData( drag );
+ }
+}
+
+void KWView::editPaste()
+{
+ QMimeSource *data = QApplication::clipboard()->data();
+ pasteData( data, false );
+}
+
+// paste or drop
+void KWView::pasteData( QMimeSource* data, bool drop )
+{
+ int provides = checkClipboard( data );
+ Q_ASSERT( provides != 0 );
+
+ // formula must be the first as a formula is also available as image
+ if ( provides & ProvidesFormula ) {
+ KWFrameSetEdit * edit = m_gui->canvasWidget()->currentFrameSetEdit();
+ if ( edit && edit->frameSet()->type() == FT_FORMULA ) {
+ edit->pasteData( data, ProvidesFormula, drop );
+ }
+ else {
+ insertFormula( data );
+ }
+ }
+ else // pasting text and/or frames
+ {
+ deselectAllFrames();
+ // let the user select paste format if the clipboard contains an image URL
+ if ( (provides & ProvidesImage) && (provides & ProvidesPlainText) && !( provides & ProvidesOasis ) )
+ {
+ QStringList list;
+ list.append( i18n("Image") );
+ list.append( i18n("Plain text") );
+ bool ok;
+ QString result = KInputDialog::getItem( i18n("Paste"), i18n("Select paste format:"), list, 0, false, &ok );
+ if (!ok)
+ return;
+ if ( result == list.first() )
+ {
+ provides = ProvidesImage;
+ } else {
+ provides = ProvidesPlainText;
+ }
+ if ( !drop ) // get it again, to avoid crashes
+ data = QApplication::clipboard()->data();
+ }
+ KWTextFrameSetEdit * edit = currentTextEdit();
+ if ( edit && ( provides & ProvidesPlainText ) ) {
+ edit->pasteData( data, provides, drop );
+ } else if ( provides & ProvidesOasis ) {
+ // Not editing a frameset? We can't paste plain text then... only entire frames.
+ QCString returnedTypeMime = KoTextObject::providesOasis( data );
+ if ( !returnedTypeMime.isEmpty() )
+ {
+ const QByteArray arr = data->encodedData( returnedTypeMime );
+ if( !arr.isEmpty() )
+ {
+ QBuffer buffer( arr );
+ KoStore * store = KoStore::createStore( &buffer, KoStore::Read );
+ KWOasisLoader oasisLoader( m_doc );
+ QValueList<KWFrame *> frames = oasisLoader.insertOasisData( store, 0 /* no cursor */ );
+ delete store;
+ QValueList<KWFrame *>::ConstIterator it = frames.begin();
+ KMacroCommand* macroCmd = 0L;
+ for ( ; it != frames.end() ; ++it )
+ {
+ if ( !macroCmd )
+ macroCmd = new KMacroCommand( i18n( "Paste" ) );
+
+ KWCreateFrameCommand *cmd = new KWCreateFrameCommand( i18n( "Paste" ), *it );
+ macroCmd->addCommand( cmd );
+
+ frameViewManager()->view(*it)->setSelected(true);
+ (*it)->frameSet()->updateFrames();
+ }
+
+ if ( macroCmd ) {
+ m_doc->addCommand( macroCmd );
+ KWFrameList::recalcAllFrames(m_doc);
+ return;
+ }
+ }
+ }
+ }
+ if ( provides & ProvidesImage )
+ { // providesImage, must be after providesOasis
+ KoPoint docPoint( m_currentPage->leftMargin(),
+ m_currentPage->offsetInDocument() + m_currentPage->topMargin());
+ m_gui->canvasWidget()->pasteImage( data, docPoint );
+ }
+ }
+}
+
+void KWView::editSelectAll()
+{
+ KWFrameSetEdit * edit = m_gui->canvasWidget()->currentFrameSetEdit();
+ if ( edit )
+ edit->selectAll();
+}
+
+void KWView::editSelectAllFrames()
+{
+ m_gui->canvasWidget()->selectAllFrames( true );
+}
+
+void KWView::editSelectCurrentFrame()
+{
+ if (!m_gui) return;
+ KWFrameSetEdit* edit = m_gui->canvasWidget()->currentFrameSetEdit();
+ KWFrame* frame = edit->currentFrame();
+ if (!frame) return;
+ KWFrameView *view = frameViewManager()->view(frame);
+ if (!view) return;
+ view->setSelected(true);
+}
+
+void KWView::editFind()
+{
+ if (!m_searchEntry)
+ m_searchEntry = new KoSearchContext();
+ KWTextFrameSetEdit * edit = currentTextEdit();
+ bool hasSelection = edit && edit->textFrameSet()->hasSelection();
+ bool hasCursor = edit != 0L;
+
+ KoSearchDia dialog( m_gui->canvasWidget(), "find", m_searchEntry, hasSelection, hasCursor );
+ if ( dialog.exec() == QDialog::Accepted )
+ {
+ delete m_findReplace;
+ m_findReplace = new KWFindReplace( m_gui->canvasWidget(), &dialog, m_gui->canvasWidget()->kWordDocument()->visibleTextObjects(viewMode()), edit);
+ editFindNext();
+ }
+}
+
+void KWView::editReplace()
+{
+ if (!m_searchEntry)
+ m_searchEntry = new KoSearchContext();
+ if (!m_replaceEntry)
+ m_replaceEntry = new KoSearchContext();
+
+ KWTextFrameSetEdit * edit = currentTextEdit();
+ bool hasSelection = edit && edit->textFrameSet()->hasSelection();
+ bool hasCursor = edit != 0L;
+
+ KoReplaceDia dialog( m_gui->canvasWidget(), "replace", m_searchEntry, m_replaceEntry, hasSelection, hasCursor );
+ if ( dialog.exec() == QDialog::Accepted )
+ {
+ delete m_findReplace;
+ m_findReplace = new KWFindReplace( m_gui->canvasWidget(), &dialog, m_gui->canvasWidget()->kWordDocument()->visibleTextObjects(viewMode()), edit);
+ editFindNext();
+ }
+}
+
+void KWView::editFindNext()
+{
+ if ( !m_findReplace ) // shouldn't be called before find or replace is activated
+ {
+ editFind();
+ return;
+ }
+ (void) m_findReplace->findNext();
+}
+
+void KWView::editFindPrevious()
+{
+ if ( !m_findReplace ) // shouldn't be called before find or replace is activated
+ {
+ editFind();
+ return;
+ }
+ (void) m_findReplace->findPrevious();
+}
+
+void KWView::adjustZOrderOfSelectedFrames(MoveFrameType moveType) {
+ KMacroCommand* macroCmd = 0L;
+ // For each selected frame...
+ QValueList<KWFrameView*> selectedFrames = frameViewManager()->selectedFrames();
+ if(selectedFrames.count()==0) return;
+
+ KWPage *page = m_doc->pageManager()->page(selectedFrames[0]->frame());
+ QPtrList<KWFrame> frames;
+ QValueListIterator<KWFrameView*> framesIterator = selectedFrames.begin();
+ while(framesIterator != selectedFrames.end()) {
+ // include all frames in case of table.
+ frames.append((*framesIterator)->frame());
+ KWFrameSet *table = (*framesIterator)->frame()->frameSet()->groupmanager();
+ if(table) {
+ for (QPtrListIterator<KWFrame> cellIt(table->frameIterator() ); cellIt.current() ; ++cellIt ) {
+ KWFrame *frame = cellIt.current();
+ if(page->rect().contains(*frame) && !frames.contains(frame))
+ frames.append(frame);
+ }
+ }
+ ++framesIterator;
+ }
+
+ int lowestZOrder=10000;
+ QString actionName;
+ framesIterator = selectedFrames.begin();
+ while(framesIterator != selectedFrames.end()) {
+ KWFrame* frame = (*framesIterator)->frame();
+ int newZOrder=0;
+ switch(moveType) {
+ case RaiseFrame:
+ newZOrder=raiseFrame(frames,frame);
+ actionName=i18n("Raise Frame");
+ break;
+ case LowerFrame:
+ newZOrder=lowerFrame(frames,frame);
+ actionName=i18n("Lower Frame");
+ break;
+ case BringToFront:
+ newZOrder=bringToFront(frames,frame);
+ actionName=i18n("Bring to Front");
+ break;
+ case SendToBack:
+ newZOrder=sendToBack(frames,frame);
+ actionName=i18n("Send to Back");
+ break;
+ }
+
+ if ( newZOrder != frame->zOrder() ) { // only if changed.
+ lowestZOrder=QMIN(lowestZOrder, newZOrder);
+
+ KWFrame* frameCopy = frame->getCopy();
+ frame->setZOrder( newZOrder );
+ frame->frameStack()->update();
+
+ KWFramePropertiesCommand* cmd = new KWFramePropertiesCommand( QString::null, frameCopy, frame);
+ if(!macroCmd)
+ macroCmd = new KMacroCommand( actionName );
+ macroCmd->addCommand(cmd);
+
+ frameCopy = frame->getCopy();
+ frame->setZOrder( newZOrder );
+
+ cmd = new KWFramePropertiesCommand( QString::null, frameCopy, frame );
+ if(!macroCmd)
+ macroCmd = new KMacroCommand( actionName );
+ macroCmd->addCommand(cmd);
+ }
+ ++framesIterator;
+ }
+
+ if ( macroCmd )
+ {
+ m_doc->addCommand(macroCmd);
+ // Calling updateFrames() on the selected frames' framesets isn't enough,
+ // we also need other framesets to notice the new frames on top.
+ m_doc->updateAllFrames();
+ m_doc->layout();
+ m_doc->repaintAllViews();
+ }
+
+ if(lowestZOrder != 10000 && m_doc->processingType() == KWDocument::WP) {
+ m_doc->lowerMainFrames( page->pageNumber(), lowestZOrder );
+ }
+}
+
+// Make room for refZOrder, by raising all z-orders above it by 1
+void KWView::increaseAllZOrdersAbove(int refZOrder, int pageNum, const QPtrList<KWFrame>& frameSelection) {
+ QPtrList<KWFrame> framesInPage = m_doc->framesInPage( pageNum, false );
+ for ( QPtrListIterator<KWFrame> frameIt( framesInPage ); frameIt.current(); ++frameIt ) {
+ if(frameSelection.contains(frameIt.current()) > 0) continue; // ignore frames we selected.
+ if(frameIt.current()->zOrder() >= refZOrder) {
+ frameIt.current()->setZOrder( frameIt.current()->zOrder() + 1 );
+ }
+ }
+}
+
+// Make room for refZOrder, by lowering all z-orders below it by 1
+void KWView::decreaseAllZOrdersUnder(int refZOrder, int pageNum, const QPtrList<KWFrame>& frameSelection) {
+ QPtrList<KWFrame> framesInPage = m_doc->framesInPage( pageNum, false );
+ for ( QPtrListIterator<KWFrame> frameIt( framesInPage ); frameIt.current(); ++frameIt ) {
+ if(frameSelection.contains(frameIt.current()) > 0) continue; // ignore frames we selected.
+ if(frameIt.current()->zOrder() <= refZOrder) {
+ frameIt.current()->setZOrder( frameIt.current()->zOrder() - 1 );
+ }
+ }
+}
+
+int KWView::raiseFrame(const QPtrList<KWFrame>& frameSelection, const KWFrame *frame) {
+ int newZOrder = 10000;
+ QValueList<int> zorders;
+ QPtrList<KWFrame> framesInPage = m_doc->framesInPage( frame->pageNumber(), false );
+ for ( QPtrListIterator<KWFrame> frameIt( framesInPage ); frameIt.current(); ++frameIt ) {
+ if(frameSelection.contains(frameIt.current()) > 0) continue; // ignore other frames we selected.
+ if(! frameIt.current()->intersects(*frame)) continue; // only frames that I intersect with.
+ int z = frameIt.current()->zOrder();
+ if(z > frame->zOrder()) {
+ newZOrder=QMIN(newZOrder, z + 1);
+ }
+ zorders.append( z );
+ }
+ if(newZOrder==10000) return frame->zOrder();
+ // Ensure that newZOrder is "free"
+ if ( zorders.find( newZOrder ) != zorders.end() )
+ increaseAllZOrdersAbove( newZOrder, frame->pageNumber(), frameSelection );
+ return newZOrder;
+}
+
+int KWView::lowerFrame(const QPtrList<KWFrame>& frameSelection, const KWFrame *frame) {
+ int newZOrder = -10000;
+ QValueList<int> zorders;
+ QPtrList<KWFrame> framesInPage = m_doc->framesInPage( frame->pageNumber(), false );
+ for ( QPtrListIterator<KWFrame> frameIt( framesInPage ); frameIt.current(); ++frameIt ) {
+ if(frameSelection.contains(frameIt.current()) > 0) continue; // ignore other frames we selected.
+ if(frameIt.current()->frameSet()->isMainFrameset()) continue; // ignore main frameset.
+ if(! frameIt.current()->intersects(*frame)) continue; // only frames that I intersect with.
+ int z = frameIt.current()->zOrder();
+ if(z < frame->zOrder()) {
+ newZOrder=QMAX(newZOrder, z -1);
+ }
+ zorders.append( z );
+ }
+ if(newZOrder==-10000) return frame->zOrder();
+ // Ensure that newZOrder is "free"
+ if ( zorders.find( newZOrder ) != zorders.end() )
+ decreaseAllZOrdersUnder( newZOrder, frame->pageNumber(), frameSelection );
+ return newZOrder;
+}
+
+int KWView::bringToFront(const QPtrList<KWFrame>& frameSelection, const KWFrame *frame) {
+ int newZOrder = frame->zOrder();
+ QPtrList<KWFrame> framesInPage = m_doc->framesInPage( frame->pageNumber(), false );
+ for ( QPtrListIterator<KWFrame> frameIt( framesInPage ); frameIt.current(); ++frameIt ) {
+ if(frameSelection.contains(frameIt.current()) > 0) continue; // ignore other frames we selected.
+ if(! frameIt.current()->intersects(*frame)) continue; // only frames that I intersect with.
+ newZOrder=QMAX(newZOrder, frameIt.current()->zOrder()+1);
+ }
+ return newZOrder;
+}
+
+int KWView::sendToBack(const QPtrList<KWFrame>& frameSelection, const KWFrame *frame) {
+ int newZOrder = frame->zOrder();
+ QPtrList<KWFrame> framesInPage = m_doc->framesInPage( frame->pageNumber(), false );
+ for ( QPtrListIterator<KWFrame> frameIt( framesInPage ); frameIt.current(); ++frameIt ) {
+ if(frameSelection.contains(frameIt.current()) > 0) continue; // ignore other frames we selected.
+ if(frameIt.current()->frameSet()->isMainFrameset()) continue; // ignore main frameset.
+ if(! frameIt.current()->intersects(*frame)) continue; // only frames that I intersect with.
+ newZOrder=QMIN(newZOrder, frameIt.current()->zOrder()-1);
+ }
+ return newZOrder;
+}
+
+void KWView::editDeleteFrame()
+{
+ deleteFrame();
+}
+
+void KWView::deleteFrame( bool warning )
+{
+ if ( !m_doc->isReadWrite() )
+ return;
+
+ QValueList<KWFrameView*> frames = frameViewManager()->selectedFrames();
+ if( frames.count() < 1) {
+ kdWarning() << "KWView::deleteFrame: no frame selected" << endl;
+ return;
+ }
+ if(frames.count()==1)
+ {
+ KWFrame *theFrame = frames[0]->frame();
+ KWFrameSet *fs = theFrame->frameSet();
+
+ Q_ASSERT( !fs->isAHeader() ); // the action is disabled for such cases
+ Q_ASSERT( !fs->isAFooter() );
+ if ( fs->isMainFrameset() || fs->isAFooter() || fs->isAHeader() || fs->isFootEndNote())
+ return;
+
+ // frame is part of a table?
+ if ( fs->groupmanager() )
+ {
+ int result = KMessageBox::warningContinueCancel(
+ this,
+ i18n( "You are about to delete a table.\n"
+ "Doing so will delete all the text in the table.\n"
+ "Are you sure you want to do that?"),
+ i18n("Delete Table"), KStdGuiItem::del(),
+ "DeleteTableConfirmation",
+ true );
+ if (result != KMessageBox::Continue)
+ return;
+ m_doc->deleteTable( fs->groupmanager() );
+ return;
+ }
+
+ if ( fs->frameCount() == 1 && fs->type() == FT_TEXT) {
+ if ( fs->isMainFrameset())
+ return; // if primairy FS, we can't delete it :)
+
+ KWTextFrameSet * textfs = dynamic_cast<KWTextFrameSet *>(fs);
+ Q_ASSERT(textfs);
+ if ( !textfs )
+ return;
+
+ KoTextDocument * textdoc = textfs->textDocument();
+ if ( textdoc->length() > 0 )
+ {
+ int result = KMessageBox::warningContinueCancel(
+ this,
+ i18n( "You are about to delete the last Frame of the "
+ "Frameset '%1'. "
+ "The contents of this Frameset will not appear "
+ "anymore!\n"
+ "Are you sure you want to do that?").arg(fs->name()),
+ i18n("Delete Frame"), KStdGuiItem::del());
+
+ if (result != KMessageBox::Continue)
+ return;
+
+ m_doc->deleteFrame( theFrame );
+ return;
+ }
+
+ }
+
+ if(warning)
+ {
+ int result = KMessageBox::warningContinueCancel(
+ this,
+ i18n("Do you want to delete this frame?"),
+ i18n("Delete Frame"),
+ KGuiItem(i18n("&Delete"),"editdelete"),
+ "DeleteLastFrameConfirmation",
+ true );
+ if (result != KMessageBox::Continue)
+ return;
+ }
+ m_doc->deleteFrame( theFrame );
+ }
+ else
+ {
+ //several frame
+ if(warning)
+ {
+ int result = KMessageBox::warningContinueCancel(
+ this,
+ i18n("Do you want to delete this frame?"),
+ i18n("Delete Frame"),
+ KGuiItem(i18n("&Delete"),"editdelete"),
+ "DeleteLastFrameConfirmation",
+ true );
+ if (result != KMessageBox::Continue)
+ return;
+ }
+
+ deleteSelectedFrames();
+ }
+}
+
+void KWView::createLinkedFrame()
+{
+ QValueList<KWFrameView*> selectedFrames = frameViewManager()->selectedFrames();
+ if (selectedFrames.count() != 1)
+ return; // action is disabled in such a case
+ KWFrame* frame = selectedFrames[0]->frame();
+ KWFrame* newFrame = new KWFrame(0L, frame->x() + m_gui->getVertRuler()->minimumSizeHint().width(), frame->y() + m_gui->getHorzRuler()->minimumSizeHint().height(), frame->width(), frame->height() );
+ newFrame->setZOrder( m_doc->maxZOrder( newFrame->pageNumber(m_doc) ) + 1 ); // make sure it's on top
+ newFrame->setCopy(true);
+ newFrame->setNewFrameBehavior( KWFrame::Copy );
+ frame->frameSet()->addFrame( newFrame );
+
+ frameViewManager()->view(newFrame)->setSelected(true);
+
+ KWCreateFrameCommand *cmd = new KWCreateFrameCommand( i18n("Create Linked Copy"), newFrame );
+ m_doc->addCommand( cmd );
+
+ m_doc->frameChanged( newFrame );
+}
+
+void KWView::editCustomVariable()
+{
+ KWTextFrameSetEdit * edit = currentTextEdit();
+ if (edit)
+ {
+ KoCustomVariable *var = static_cast<KoCustomVariable *>(edit->variable());
+ if (var)
+ {
+ QString oldvalue = var->value();
+ KoCustomVarDialog dia( this, var );
+ if ( dia.exec() )
+ {
+ m_doc->recalcVariables( VT_CUSTOM );
+ if( var->value() != oldvalue )
+ {
+ KWChangeCustomVariableValue *cmd=new KWChangeCustomVariableValue(i18n( "Change Custom Variable" ),m_doc, oldvalue, var->value(), var );
+ m_doc->addCommand(cmd);
+ }
+ }
+ }
+ }
+}
+
+void KWView::editCustomVars()
+{
+ KoCustomVariablesDia dia( this, m_doc->variableCollection()->getVariables() );
+ QStringList listOldCustomValue;
+ QPtrListIterator<KoVariable> oldIt( m_doc->variableCollection()->getVariables() );
+ for ( ; oldIt.current() ; ++oldIt )
+ {
+ if(oldIt.current()->type()==VT_CUSTOM)
+ listOldCustomValue.append(((KoCustomVariable*)oldIt.current())->value());
+ }
+ if(dia.exec())
+ {
+ m_doc->recalcVariables( VT_CUSTOM );
+ //temporaly hack, for the moment we can't undo/redo change custom variables
+ QPtrListIterator<KoVariable> it( m_doc->variableCollection()->getVariables() );
+ KMacroCommand * macroCommand = 0L;
+ int i=0;
+ for ( ; it.current() ; ++it )
+ {
+ if(it.current()->type() == VT_CUSTOM )
+ {
+ if(((KoCustomVariable*)it.current())->value()!=*(listOldCustomValue.at(i)))
+ {
+ if(!macroCommand)
+ macroCommand = new KMacroCommand( i18n( "Change Custom Variable" ) );
+ KWChangeCustomVariableValue *cmd=new KWChangeCustomVariableValue(i18n( "Change Custom Variable" ),m_doc,*(listOldCustomValue.at(i)), ((KoCustomVariable*)it.current())->value() ,((KoCustomVariable*)it.current()));
+ macroCommand->addCommand(cmd);
+ }
+ i++;
+ }
+ }
+ if(macroCommand)
+ m_doc->addCommand(macroCommand);
+ }
+}
+
+void KWView::editMailMergeDataBase()
+{
+ m_doc->mailMergeDataBase()->showConfigDialog(this);
+#if 0
+ KWMailMergeEditor *dia = new KWMailMergeEditor( this, m_doc->mailMergeDataBase() );
+ dia->exec();
+ // Don't know if we really need this so it's commented out (SL)
+ // m_gui->canvasWidget()->repaintAll( FALSE );
+ delete dia;
+#endif
+}
+
+void KWView::viewTextMode()
+{
+ if ( m_actionViewTextMode->isChecked() )
+ {
+ KWTextFrameSet* fs = KWViewModeText::determineTextFrameSet( m_doc );
+ if ( fs ) { // TODO: disable the action when there is no text frameset available
+ if ( dynamic_cast<KWViewModePreview *>(viewMode()) )
+ {
+ m_zoomViewModePreview.m_zoom = m_doc->zoom();
+ m_zoomViewModePreview.m_zoomMode = m_doc->zoomMode();
+ }
+ else
+ {
+ m_zoomViewModeNormal.m_zoom = m_doc->zoom();
+ m_zoomViewModeNormal.m_zoomMode = m_doc->zoomMode();
+ }
+ // we don't know ZOOM_PAGE in the new view. so
+ // we use ZOOM_CONSTANT in that case
+ switch(m_zoomViewModeNormal.m_zoomMode)
+ {
+ case KoZoomMode::ZOOM_WIDTH:
+ m_doc->setZoomMode(KoZoomMode::ZOOM_WIDTH);
+ QTimer::singleShot( 0, this, SLOT( updateZoom() ) );
+ break;
+ case KoZoomMode::ZOOM_PAGE: // no break
+ m_zoomViewModeNormal.m_zoomMode = KoZoomMode::ZOOM_CONSTANT;
+ case KoZoomMode::ZOOM_CONSTANT:
+ m_doc->setZoomMode(KoZoomMode::ZOOM_CONSTANT);
+ showZoom( m_zoomViewModeNormal.m_zoom );
+ setZoom( m_zoomViewModeNormal.m_zoom, false );
+ break;
+ }
+ m_doc->switchViewMode( "ModeText" );
+ } else
+ initGUIButton(); // ensure we show the current viewmode
+ }
+ else
+ m_actionViewTextMode->setChecked( true ); // always one has to be checked !
+}
+
+void KWView::viewPageMode()
+{
+ if ( m_actionViewPageMode->isChecked() )
+ {
+ if ( dynamic_cast<KWViewModePreview *>(viewMode()) )
+ {
+ m_zoomViewModePreview.m_zoom = m_doc->zoom();
+ m_zoomViewModePreview.m_zoomMode = m_doc->zoomMode();
+ }
+ else
+ {
+ m_zoomViewModeNormal.m_zoom = m_doc->zoom();
+ m_zoomViewModeNormal.m_zoomMode = m_doc->zoomMode();
+ }
+ switch(m_zoomViewModeNormal.m_zoomMode)
+ {
+ case KoZoomMode::ZOOM_WIDTH:
+ m_doc->setZoomMode(KoZoomMode::ZOOM_WIDTH);
+ QTimer::singleShot( 0, this, SLOT( updateZoom() ) );
+ break;
+ case KoZoomMode::ZOOM_PAGE:
+ m_doc->setZoomMode(KoZoomMode::ZOOM_PAGE);
+ QTimer::singleShot( 0, this, SLOT( updateZoom() ) );
+ break;
+ case KoZoomMode::ZOOM_CONSTANT:
+ m_doc->setZoomMode(KoZoomMode::ZOOM_CONSTANT);
+ showZoom( m_zoomViewModeNormal.m_zoom );
+ setZoom( m_zoomViewModeNormal.m_zoom, false );
+ break;
+ }
+ m_doc->switchViewMode( "ModeNormal" );
+ }
+ else
+ m_actionViewPageMode->setChecked( true ); // always one has to be checked !
+}
+
+void KWView::viewPreviewMode()
+{
+ if ( m_actionViewPreviewMode->isChecked() )
+ {
+ m_zoomViewModeNormal.m_zoom = m_doc->zoom();
+ m_zoomViewModeNormal.m_zoomMode = m_doc->zoomMode();
+ switch(m_zoomViewModePreview.m_zoomMode)
+ {
+ case KoZoomMode::ZOOM_WIDTH:
+ m_doc->setZoomMode(KoZoomMode::ZOOM_WIDTH);
+ QTimer::singleShot( 0, this, SLOT( updateZoom() ) );
+ break;
+ case KoZoomMode::ZOOM_PAGE:
+ m_doc->setZoomMode(KoZoomMode::ZOOM_PAGE);
+ QTimer::singleShot( 0, this, SLOT( updateZoom() ) );
+ break;
+ case KoZoomMode::ZOOM_CONSTANT:
+ m_doc->setZoomMode(KoZoomMode::ZOOM_CONSTANT);
+ showZoom( m_zoomViewModePreview.m_zoom );
+ setZoom( m_zoomViewModePreview.m_zoom, false );
+ break;
+ }
+ m_doc->switchViewMode( "ModePreview" );
+ }
+ else
+ m_actionViewPreviewMode->setChecked( true ); // always one has to be checked !
+}
+
+void KWView::updateZoomControls()
+{
+ switch(m_doc->zoomMode())
+ {
+ case KoZoomMode::ZOOM_WIDTH:
+ case KoZoomMode::ZOOM_PAGE:
+ showZoom( KoZoomMode::toString(m_doc->zoomMode()) );
+ break;
+ case KoZoomMode::ZOOM_CONSTANT:
+ changeZoomMenu( m_doc->zoom() );
+ showZoom( m_doc->zoom() );
+ break;
+ }
+}
+
+void KWView::changeZoomMenu( int zoom )
+{
+ QString mode;
+ if ( m_gui && m_gui->canvasWidget() && viewMode())
+ mode = viewMode()->type();
+
+ QStringList lst;
+ lst << KoZoomMode::toString(KoZoomMode::ZOOM_WIDTH);
+ if ( mode!="ModeText" )
+ lst << KoZoomMode::toString(KoZoomMode::ZOOM_PAGE);
+
+ if(zoom>0)
+ {
+ QValueList<int> list;
+ bool ok;
+ const QStringList itemsList ( m_actionViewZoom->items() );
+ QRegExp regexp("(\\d+)"); // "Captured" non-empty sequence of digits
+
+ for (QStringList::ConstIterator it = itemsList.begin() ; it != itemsList.end() ; ++it)
+ {
+ regexp.search(*it);
+ const int val=regexp.cap(1).toInt(&ok);
+ //zoom : limit inferior=10
+ if(ok && val>9 && list.contains(val)==0)
+ list.append( val );
+ }
+ //necessary at the beginning when we read config
+ //this value is not in combo list
+ if(list.contains(zoom)==0)
+ list.append( zoom );
+
+ qHeapSort( list );
+
+ for (QValueList<int>::Iterator it = list.begin() ; it != list.end() ; ++it)
+ lst.append( i18n("%1%").arg(*it) );
+ }
+ else
+ {
+ lst << i18n("%1%").arg("33");
+ lst << i18n("%1%").arg("50");
+ lst << i18n("%1%").arg("75");
+ lst << i18n("%1%").arg("100");
+ lst << i18n("%1%").arg("125");
+ lst << i18n("%1%").arg("150");
+ lst << i18n("%1%").arg("200");
+ lst << i18n("%1%").arg("250");
+ lst << i18n("%1%").arg("350");
+ lst << i18n("%1%").arg("400");
+ lst << i18n("%1%").arg("450");
+ lst << i18n("%1%").arg("500");
+ }
+ m_actionViewZoom->setItems( lst );
+}
+
+void KWView::showZoom( int zoom )
+{
+ QStringList list = m_actionViewZoom->items();
+ QString zoomStr( i18n("%1%").arg( zoom ) );
+ m_actionViewZoom->setCurrentItem( list.findIndex(zoomStr) );
+}
+
+void KWView::showZoom( const QString& zoom )
+{
+ QStringList list = m_actionViewZoom->items();
+ m_actionViewZoom->setCurrentItem( list.findIndex( zoom ) );
+}
+
+void KWView::slotViewFormattingChars()
+{
+ m_doc->setViewFormattingChars(m_actionViewFormattingChars->isChecked());
+ m_doc->layout(); // Due to the different formatting when this option is activated
+ m_doc->repaintAllViews();
+}
+
+void KWView::slotViewFrameBorders()
+{
+ setViewFrameBorders(m_actionViewFrameBorders->isChecked());
+ m_gui->canvasWidget()->repaintAll();
+}
+
+void KWView::viewHeader()
+{
+ bool state = m_actionViewHeader->isChecked();
+ m_doc->setHeaderVisible( state );
+ KWHideShowHeader *cmd=new KWHideShowHeader( state ? i18n("Enable Document Headers"):i18n("Disable Document Headers"), m_doc, state);
+ m_doc->addCommand(cmd);
+ updateHeader();
+}
+
+void KWView::updateHeader()
+{
+ KWTextFrameSetEdit * edit = currentTextEdit();
+ bool state = m_actionViewHeader->isChecked();
+ if(!state )
+ {
+ KWFrameSet *frameSet=0L;
+ if(edit)
+ {
+ frameSet=edit->frameSet();
+ if (frameSet->isAHeader())
+ m_doc->terminateEditing( frameSet );
+ else
+ {
+ KWTableFrameSet *table = frameSet->frame(0)->frameSet()->groupmanager();
+ if (table)
+ {
+ if (table->isFloating() && table->anchorFrameset()->isAHeader())
+ m_doc->terminateEditing( table );
+ }
+ }
+
+ }
+ else
+ {
+ KWFormulaFrameSetEdit * editFormula = dynamic_cast<KWFormulaFrameSetEdit *>(m_gui->canvasWidget()->currentFrameSetEdit());
+ if(editFormula)
+ {
+ frameSet= editFormula->frameSet();
+ if(frameSet->type()==FT_FORMULA && frameSet->isFloating())
+ m_doc->terminateEditing( frameSet );
+ }
+
+ }
+ }
+}
+
+
+void KWView::viewFooter()
+{
+ bool state=m_actionViewFooter->isChecked();
+ m_doc->setFooterVisible( state );
+ KWHideShowFooter *cmd=new KWHideShowFooter( state ? i18n("Enable Document Footers"):i18n("Disable Document Footers"), m_doc, state);
+ m_doc->addCommand(cmd);
+ updateFooter();
+}
+
+void KWView::updateFooter()
+{
+ bool state=m_actionViewFooter->isChecked();
+ KWTextFrameSetEdit * edit = currentTextEdit();
+ if(!state )
+ {
+ KWFrameSet *frameSet=0L;
+ if(edit)
+ {
+ frameSet=edit->frameSet();
+ if (frameSet->isAFooter())
+ m_doc->terminateEditing( frameSet );
+ else
+ {
+ KWTableFrameSet *table = frameSet->frame(0)->frameSet()->groupmanager();
+ if (table)
+ {
+ if (table->isFloating() && table->anchorFrameset()->isAFooter())
+ m_doc->terminateEditing( table );
+ }
+ }
+ }
+ else
+ {
+ KWFormulaFrameSetEdit * editFormula = dynamic_cast<KWFormulaFrameSetEdit *>(m_gui->canvasWidget()->currentFrameSetEdit());
+ if(editFormula)
+ {
+ frameSet= editFormula->frameSet();
+ if(frameSet->type()==FT_FORMULA && frameSet->isFloating())
+ m_doc->terminateEditing( frameSet );
+
+ }
+
+ }
+ }
+
+}
+
+void KWView::updateZoom( ) {
+ viewZoom(m_actionViewZoom->currentText());
+}
+
+void KWView::viewZoom( const QString &s )
+{
+ bool ok=false;
+ KWCanvas * canvas = m_gui->canvasWidget();
+ int zoom = 0;
+
+ if ( s == KoZoomMode::toString(KoZoomMode::ZOOM_WIDTH) )
+ {
+ m_doc->setZoomMode(KoZoomMode::ZOOM_WIDTH);
+ zoom = qRound( static_cast<double>(canvas->visibleWidth() * 100 ) / (m_doc->resolutionX() * m_currentPage->width() ) ) - 1;
+
+ if(zoom != m_doc->zoom() && !canvas->verticalScrollBar() ||
+ !canvas->verticalScrollBar()->isVisible()) { // has no vertical scrollbar
+ // we have to do this twice to take into account a possibly appearing vertical scrollbar
+ QTimer::singleShot( 0, this, SLOT( updateZoom() ) );
+ }
+ ok = true;
+ }
+ else if ( s == KoZoomMode::toString(KoZoomMode::ZOOM_PAGE) )
+ {
+ m_doc->setZoomMode(KoZoomMode::ZOOM_PAGE);
+ double height = m_doc->resolutionY() * m_currentPage->height();
+ double width = m_doc->resolutionX() * m_currentPage->width();
+ zoom = QMIN( qRound( static_cast<double>(canvas->visibleHeight() * 100 ) / height ),
+ qRound( static_cast<double>(canvas->visibleWidth() * 100 ) / width ) ) - 1;
+
+ ok = true;
+ }
+ else
+ {
+ m_doc->setZoomMode(KoZoomMode::ZOOM_CONSTANT);
+ QRegExp regexp("(\\d+)"); // "Captured" non-empty sequence of digits
+ regexp.search(s);
+ zoom=regexp.cap(1).toInt(&ok);
+ }
+
+ if( !ok || zoom<10 ) //zoom should be valid and >10
+ zoom = m_doc->zoom();
+ if ( !KoZoomMode::isConstant(s) )
+ showZoom( s ); //set current menu item
+ else
+ {
+ changeZoomMenu( zoom ); //add current zoom value to the menu
+ showZoom( zoom ); //set current menu item
+ }
+
+ //apply zoom if zoom!=m_doc->zoom()
+ if( zoom != m_doc->zoom() )
+ {
+ setZoom( zoom, true );
+
+ KWTextFrameSetEdit * edit = currentTextEdit();
+ if ( edit )
+ edit->ensureCursorVisible();
+ }
+
+ m_gui->canvasWidget()->setFocus();
+
+}
+
+void KWView::setZoom( int zoom, bool updateViews )
+{
+ m_doc->setZoomAndResolution( zoom, KoGlobal::dpiX(), KoGlobal::dpiY());
+ m_doc->newZoomAndResolution( updateViews, false );
+ m_doc->updateZoomRuler();
+
+ if ( statusBar() )
+ m_sbZoomLabel->setText( ' ' + QString::number( zoom ) + "% " );
+
+ // Also set the zoom in KoView (for embedded views)
+ kdDebug() << "KWView::setZoom " << zoom << " setting koview zoom to " << m_doc->zoomedResolutionY() << endl;
+ KoView::setZoom( m_doc->zoomedResolutionY() /* KoView only supports one zoom */ );
+}
+
+void KWView::insertPicture()
+{
+ if ( m_actionToolsCreatePix->isChecked() )
+ {
+ KWInsertPicDia dia( this,m_gui->canvasWidget()->pictureInline(),m_gui->canvasWidget()->pictureKeepRatio(),m_doc );
+ if ( dia.exec() == QDialog::Accepted && !dia.picture().isNull() )
+ {
+ insertPicture( dia.picture(), dia.makeInline(), dia.keepRatio(), 0, 0 );
+ m_gui->canvasWidget()->setPictureInline( dia.makeInline());
+ m_gui->canvasWidget()->setPictureKeepRatio( dia.keepRatio() );
+ }
+ else
+ m_gui->canvasWidget()->setMouseMode( KWCanvas::MM_EDIT );
+ }
+ else
+ {
+ // clicked on the already active tool -> abort
+ m_gui->canvasWidget()->setMouseMode( KWCanvas::MM_EDIT );
+ }
+}
+
+
+void KWView::slotEmbedImage( const QString &filename )
+{
+ KoPicture picture;
+ KoPictureKey key;
+ key.setKeyFromFile( filename );
+ picture.setKey( key );
+ picture.loadFromFile( filename );
+ insertPicture( picture, false, true, 0, 0 );
+}
+
+void KWView::insertPicture( const KoPicture& picture, const bool makeInline, const bool keepRatio, int suggestedWidth, int suggestedHeight )
+{
+ QSize pixmapSize( picture.getOriginalSize() );
+ if ( suggestedWidth > 0 && suggestedHeight > 0 )
+ pixmapSize = QSize( suggestedWidth, suggestedHeight );
+
+ if ( makeInline )
+ {
+ const double widthLimit = m_currentPage->width() - m_currentPage->leftMargin() -
+ m_currentPage->rightMargin() - 10;
+ const double heightLimit = m_currentPage->height() - m_currentPage->topMargin() -
+ m_currentPage->bottomMargin() - 10;
+ m_fsInline = 0;
+ KWPictureFrameSet *frameset = new KWPictureFrameSet( m_doc, QString::null );
+
+ frameset->insertPicture( picture );
+
+ // This ensures 1-1 at 100% on screen, but allows zooming and printing with correct DPI values
+ // ### TODO/FIXME: is the qRound really necessary?
+ double width = m_doc->unzoomItX( qRound( (double)pixmapSize.width() * m_doc->zoomedResolutionX() / POINT_TO_INCH( KoGlobal::dpiX() ) ) );
+ double height = m_doc->unzoomItY( qRound( (double)pixmapSize.height() * m_doc->zoomedResolutionY() / POINT_TO_INCH( KoGlobal::dpiY() ) ) );
+
+ frameset->setKeepAspectRatio( keepRatio);
+
+
+ if ( keepRatio && ((width > widthLimit) || (height > heightLimit)) )
+ {
+ // size too big => adjust the size and keep ratio
+ const double ratioX = width / widthLimit;
+ const double ratioY = height / heightLimit;
+ const double ratioPicture = width / height;
+
+ if ( ratioPicture == 0 ) // unlikely
+ {
+ width = widthLimit;
+ height = heightLimit;
+ }
+ else
+ if ( ratioX > ratioY ) // restrict width and calculate height
+ {
+ width = widthLimit;
+ height = widthLimit/ratioPicture;
+ }
+ else // restrict height and calculate width
+ {
+ width = heightLimit*ratioPicture;
+ height = heightLimit;
+ }
+ }
+ else
+ {
+ // Apply reasonable limits
+ width = kMin( width, widthLimit );
+ height = kMin( height, heightLimit );
+ }
+
+ m_fsInline = frameset;
+ KWFrame *frame = new KWFrame ( m_fsInline, 0, 0, width, height );
+ m_fsInline->addFrame( frame, false );
+ m_gui->canvasWidget()->inlinePictureStarted();
+ showMouseMode( KWCanvas::MM_EDIT );
+
+ displayFrameInlineInfo();
+
+#if 0
+ edit->insertFloatingFrameSet( fs, i18n("Insert Picture Inline") );
+ fs->finalize(); // done last since it triggers a redraw
+ showMouseMode( KWCanvas::MM_EDIT );
+ m_doc->refreshDocStructure(Pictures);
+#endif
+ }
+ else
+ {
+ m_gui->canvasWidget()->insertPicture( picture, pixmapSize, keepRatio );
+ }
+}
+
+bool KWView::insertInlinePicture()
+{
+ Q_ASSERT( m_fsInline );
+ KWTextFrameSetEdit * edit = currentTextEdit();
+ if(edit)
+ {
+ if ( edit->textFrameSet()->textObject()->protectContent() )
+ return false;
+
+ m_doc->addFrameSet( m_fsInline, false ); // done first since the frame number is stored in the undo/redo
+#if 0
+ KWFrame *frame = new KWFrame( m_fsInline, 0, 0, m_doc->unzoomItX( width ), m_doc->unzoomItY( height ) );
+ m_fsInline->addFrame( frame, false );
+#endif
+ edit->insertFloatingFrameSet( m_fsInline, i18n("Insert Picture Inline") );
+ m_fsInline->finalize(); // done last since it triggers a redraw
+ showMouseMode( KWCanvas::MM_EDIT );
+ m_doc->refreshDocStructure(Pictures);
+ m_fsInline=0;
+ updateFrameStatusBarItem();
+ }
+ else
+ {
+ delete m_fsInline;
+ m_fsInline=0;
+ updateFrameStatusBarItem();
+ }
+ return true;
+}
+
+void KWView::displayFrameInlineInfo()
+{
+ KMessageBox::information(this,
+ i18n("Set cursor where you want to insert inline frame."),
+ i18n("Insert Inline Frame"),
+ "SetCursorInsertInlineFrame",true);
+
+ if ( statusBar() && m_sbFramesLabel )
+ m_sbFramesLabel->setText( ' ' + i18n("Set cursor where you want to insert inline frame." ) );
+}
+
+void KWView::insertSpecialChar()
+{
+ KWTextFrameSetEdit *edit=currentTextEdit();
+ if ( !edit )
+ return;
+ QString f = edit->textFontFamily();
+ QChar c=' ';
+ if (m_specialCharDlg==0)
+ {
+ m_specialCharDlg = new KoCharSelectDia( this, "insert special char", f, c, false );
+ connect( m_specialCharDlg, SIGNAL(insertChar(QChar,const QString &)),
+ this, SLOT(slotSpecialChar(QChar,const QString &)));
+ connect( m_specialCharDlg, SIGNAL( finished() ),
+ this, SLOT( slotSpecialCharDlgClosed() ) );
+ }
+ m_specialCharDlg->show();
+}
+
+void KWView::slotSpecialCharDlgClosed()
+{
+ if ( m_specialCharDlg )
+ {
+ disconnect( m_specialCharDlg, SIGNAL(insertChar(QChar,const QString &)),
+ this, SLOT(slotSpecialChar(QChar,const QString &)));
+ disconnect( m_specialCharDlg, SIGNAL( finished() ),
+ this, SLOT( slotSpecialCharDlgClosed() ) );
+ m_specialCharDlg->deleteLater();
+ m_specialCharDlg = 0L;
+ }
+}
+
+void KWView::slotSpecialChar(QChar c, const QString &font)
+{
+ KWTextFrameSetEdit *edit=currentTextEdit();
+ if ( !edit )
+ return;
+ edit->insertSpecialChar(c, font);
+}
+
+void KWView::insertFrameBreak()
+{
+ KWTextFrameSetEdit *edit=currentTextEdit();
+ if ( !edit )
+ return;
+ edit->insertFrameBreak();
+}
+
+void KWView::insertPage()
+{
+ if ( m_doc->processingType() == KWDocument::WP )
+ {
+ m_gui->canvasWidget()->editFrameSet( m_doc->frameSet(0) );
+ KWTextFrameSetEdit *edit = currentTextEdit();
+ Q_ASSERT(edit);
+ if ( edit )
+ edit->insertWPPage();
+ } else {
+ KWInsertPageDia dlg( this, "insertpage");
+ if ( dlg.exec())
+ {
+ // If 'before', subtract 1 to the page number
+ int page = m_currentPage->pageNumber();
+ KCommand* cmd = new KWInsertRemovePageCommand( m_doc, KWInsertRemovePageCommand::Insert, dlg.insertPagePos()==KW_INSERTPAGEAFTER ? page : (page -1));
+ cmd->execute();
+ m_doc->addCommand( cmd );
+ }
+ }
+}
+
+void KWView::deletePage()
+{
+ KCommand* cmd = new KWInsertRemovePageCommand( m_doc, KWInsertRemovePageCommand::Remove, m_currentPage->pageNumber() );
+ cmd->execute();
+ m_doc->addCommand( cmd );
+ if(m_doc->lastPage() > m_currentPage->pageNumber())
+ m_currentPage = m_doc->pageManager()->page( m_doc->lastPage() );
+}
+
+void KWView::insertLink()
+{
+ KWTextFrameSetEdit *edit=currentTextEdit();
+ if ( !edit )
+ return;
+ QString link;
+ QString ref;
+ if ( edit->textFrameSet()->hasSelection() )
+ {
+ QString selectedText = edit->textFrameSet()->textObject()->selectedText();
+ if ( edit->textFrameSet()->textObject()->selectionHasCustomItems() || selectedText.contains('\n') )
+ return;
+ if ( selectedText.startsWith( "mailto:/" ) ||
+ selectedText.startsWith( "ftp:/" ) ||
+ selectedText.startsWith( "http:/" ) )
+ {
+ link=selectedText;
+ ref = selectedText;
+ }
+ else
+ {
+ //Just add text as link name and not url
+ link = selectedText;
+ }
+ }
+
+ if(KoInsertLinkDia::createLinkDia(link, ref, m_doc->listOfBookmarkName(0), true, this))
+ {
+ if(!link.isEmpty() && !ref.isEmpty())
+ edit->insertLink(link, ref);
+ }
+}
+
+void KWView::insertComment()
+{
+ KWTextFrameSetEdit *edit=currentTextEdit();
+ if ( !edit )
+ return;
+ QString authorName;
+ KoDocumentInfo * info = m_doc->documentInfo();
+ KoDocumentInfoAuthor * authorPage = static_cast<KoDocumentInfoAuthor *>(info->page( "author" ));
+ if ( !authorPage )
+ kdWarning() << "Author information not found in documentInfo !" << endl;
+ else
+ authorName = authorPage->fullName();
+
+ KoCommentDia *commentDia = new KoCommentDia( this, QString::null,authorName );
+ if( commentDia->exec() )
+ {
+ edit->insertComment(commentDia->commentText());
+ }
+ delete commentDia;
+}
+
+
+void KWView::insertVariable()
+{
+ KWTextFrameSetEdit * edit = currentTextEdit();
+ if ( edit )
+ {
+ KAction * act = (KAction *)(sender());
+ VariableDefMap::Iterator it = m_variableDefMap.find( act );
+ if ( it == m_variableDefMap.end() )
+ kdWarning() << "Action not found in m_variableDefMap." << endl;
+ else
+ {
+ if ( (*it).type == VT_FIELD )
+ edit->insertVariable( (*it).type, KoFieldVariable::fieldSubType( (*it).subtype ) );
+ else
+ edit->insertVariable( (*it).type, (*it).subtype );
+ }
+ }
+}
+
+void KWView::insertFootNote()
+{
+ KWTextFrameSetEdit * edit = currentTextEdit();
+ //Q_ASSERT( edit ); // the action should be disabled if we're not editing a textframeset...
+ if ( edit ) // test for dcop call !
+ {
+ if ( edit->frameSet() != m_doc->frameSet(0) )
+ {
+ KMessageBox::sorry( this,
+ i18n( "You can only insert footnotes or "
+ "endnotes into the first frameset."),
+ i18n("Insert Footnote"));
+ } else {
+ KWFootNoteDia dia( m_gui->canvasWidget()->footNoteType(), m_gui->canvasWidget()->numberingFootNoteType(), QString::null, this, m_doc, 0 );
+ QPtrListIterator<KoTextCustomItem> it( edit->textDocument()->allCustomItems() );
+ for ( ; it.current() ; ++it )
+ {
+ KWFootNoteVariable *fnv = dynamic_cast<KWFootNoteVariable *>( it.current() );
+ if (fnv && !fnv->isDeleted() && fnv->frameSet() && !fnv->frameSet()->isDeleted() &&
+ fnv->numberingType()==KWFootNoteVariable::Manual )
+ dia.appendManualFootNote( fnv->text() );
+ }
+ if ( dia.exec() ) {
+ edit->insertFootNote( dia.noteType(), dia.numberingType(), dia.manualString() );
+ m_gui->canvasWidget()->setFootNoteType( dia.noteType() );
+ m_gui->canvasWidget()->setNumberingFootNoteType( dia.numberingType() );
+ }
+ }
+ }
+}
+
+void KWView::updateTocActionText(bool hasToc)
+{
+ KActionCollection * coll = actionCollection();
+ QString name= hasToc ? i18n("Update Table of &Contents"):i18n("Table of &Contents");
+ coll->action("insert_contents")->setText(name);
+}
+
+void KWView::insertContents()
+{
+ KWTextFrameSetEdit *edit = currentTextEdit();
+ if (edit)
+ edit->insertTOC();
+}
+
+void KWView::formatFont()
+{
+ KoTextFormatInterface* textIface = applicableTextInterfaces().first();
+
+ if ( !textIface || !textIface->currentFormat() )
+ return;
+
+ delete m_fontDlg;
+ m_fontDlg = new KoFontDia( *textIface->currentFormat()
+ , m_broker
+ , this, "" );
+
+ connect( m_fontDlg, SIGNAL( applyFont() ),
+ this, SLOT( slotApplyFont() ) );
+
+ m_fontDlg->exec();
+ delete m_fontDlg;
+ m_fontDlg=0L;
+
+ //m_gui->canvasWidget()->setFocus();
+}
+
+void KWView::slotApplyFont()
+{
+ int flags = m_fontDlg->changedFlags();
+ if ( flags )
+ {
+ KMacroCommand *globalCmd = new KMacroCommand(i18n("Change Font"));
+ QPtrList<KoTextFormatInterface> lst = applicableTextInterfaces();
+ QPtrListIterator<KoTextFormatInterface> it( lst );
+ for ( ; it.current() ; ++it )
+ {
+ KoTextFormat newFormat = m_fontDlg->newFormat();
+ KCommand *cmd = it.current()->setFormatCommand( &newFormat, flags, true);
+ if (cmd)
+ globalCmd->addCommand(cmd);
+ }
+ m_doc->addCommand(globalCmd);
+ m_gui->canvasWidget()->setFocus(); // the combo keeps focus...
+ }
+
+}
+
+void KWView::formatParagraph()
+{
+ showParagraphDialog();
+}
+
+void KWView::showParagraphDialog( int initialPage, double initialTabPos )
+{
+ KWTextFrameSetEdit *edit = currentTextEdit();
+ if (edit)
+ {
+ delete m_paragDlg;
+ bool showFrameEndOptions = !edit->frameSet()->isHeaderOrFooter() &&
+ !edit->frameSet()->groupmanager();
+ m_paragDlg = new KoParagDia( this, "",
+ KoParagDia::PD_SPACING | KoParagDia::PD_ALIGN |
+ KoParagDia::PD_DECORATION | KoParagDia::PD_NUMBERING |
+ KoParagDia::PD_TABS,
+ m_doc->unit(),
+ edit->textFrameSet()->frame(0)->width(),
+ showFrameEndOptions,
+ edit->frameSet()->isFootEndNote());
+ m_paragDlg->setCaption( i18n( "Paragraph Settings" ) );
+
+ // Initialize the dialog from the current paragraph's settings
+ m_paragDlg->setParagLayout( edit->cursor()->parag()->paragLayout() );
+
+ // Set initial page and initial tabpos if necessary
+ if ( initialPage != -1 )
+ {
+ m_paragDlg->setCurrentPage( initialPage );
+ if ( initialPage == KoParagDia::PD_TABS )
+ m_paragDlg->tabulatorsWidget()->setCurrentTab( initialTabPos );
+ }
+ connect( m_paragDlg, SIGNAL( applyParagStyle() ), this, SLOT( slotApplyParag()));
+
+ m_paragDlg->exec();
+ delete m_paragDlg;
+ m_paragDlg=0L;
+ }
+
+}
+
+void KWView::slotApplyParag()
+{
+ KWTextFrameSetEdit *edit = currentTextEdit();
+ if( !edit)
+ return;
+ KMacroCommand * macroCommand = 0L;
+ KCommand *cmd=0L;
+ if(m_paragDlg->isLeftMarginChanged())
+ {
+ cmd=edit->setMarginCommand( QStyleSheetItem::MarginLeft, m_paragDlg->leftIndent() );
+ if(cmd)
+ {
+ if ( !macroCommand )
+ macroCommand = new KMacroCommand( i18n( "Paragraph Settings" ) );
+ macroCommand->addCommand(cmd);
+ }
+ m_gui->getHorzRuler()->setLeftIndent( KoUnit::toUserValue( m_paragDlg->leftIndent(), m_doc->unit() ) );
+
+ }
+
+ if(m_paragDlg->isRightMarginChanged())
+ {
+ cmd=edit->setMarginCommand( QStyleSheetItem::MarginRight, m_paragDlg->rightIndent() );
+ if(cmd)
+ {
+ if ( !macroCommand )
+ macroCommand = new KMacroCommand( i18n( "Paragraph Settings" ) );
+ macroCommand->addCommand(cmd);
+ }
+ m_gui->getHorzRuler()->setRightIndent( KoUnit::toUserValue( m_paragDlg->rightIndent(), m_doc->unit() ) );
+ }
+ if(m_paragDlg->isSpaceBeforeChanged())
+ {
+ cmd=edit->setMarginCommand( QStyleSheetItem::MarginTop, m_paragDlg->spaceBeforeParag() );
+ if(cmd)
+ {
+ if ( !macroCommand )
+ macroCommand = new KMacroCommand( i18n( "Paragraph Settings" ) );
+ macroCommand->addCommand(cmd);
+ }
+ }
+ if(m_paragDlg->isSpaceAfterChanged())
+ {
+ cmd=edit->setMarginCommand( QStyleSheetItem::MarginBottom, m_paragDlg->spaceAfterParag() );
+ if(cmd)
+ {
+ if ( !macroCommand )
+ macroCommand = new KMacroCommand( i18n( "Paragraph Settings" ) );
+ macroCommand->addCommand(cmd);
+ }
+ }
+ if(m_paragDlg->isFirstLineChanged())
+ {
+ cmd=edit->setMarginCommand( QStyleSheetItem::MarginFirstLine, m_paragDlg->firstLineIndent());
+ if(cmd)
+ {
+ if ( !macroCommand )
+ macroCommand = new KMacroCommand( i18n( "Paragraph Settings" ) );
+ macroCommand->addCommand(cmd);
+ }
+ m_gui->getHorzRuler()->setFirstIndent(
+ KoUnit::toUserValue( m_paragDlg->firstLineIndent(), m_doc->unit() ) );
+ }
+
+ if(m_paragDlg->isAlignChanged())
+ {
+ cmd=edit->setAlignCommand( m_paragDlg->align() );
+ if(cmd)
+ {
+ if ( !macroCommand )
+ macroCommand = new KMacroCommand( i18n( "Paragraph Settings" ) );
+ macroCommand->addCommand(cmd);
+ }
+ }
+ if(m_paragDlg->isCounterChanged())
+ {
+ cmd=edit->setCounterCommand( m_paragDlg->counter() );
+ if(cmd)
+ {
+ if ( !macroCommand )
+ macroCommand = new KMacroCommand( i18n( "Paragraph Settings" ) );
+ macroCommand->addCommand(cmd);
+ }
+ }
+ if(m_paragDlg->listTabulatorChanged())
+ {
+ cmd=edit->setTabListCommand( m_paragDlg->tabListTabulator() );
+ if(cmd)
+ {
+ if ( !macroCommand )
+ macroCommand = new KMacroCommand( i18n( "Paragraph Settings" ) );
+ macroCommand->addCommand(cmd);
+ }
+ }
+
+ if(m_paragDlg->isLineSpacingChanged())
+ {
+ cmd=edit->setLineSpacingCommand( m_paragDlg->lineSpacing(),m_paragDlg->lineSpacingType() );
+ if(cmd)
+ {
+ if ( !macroCommand )
+ macroCommand = new KMacroCommand( i18n( "Paragraph Settings" ) );
+
+ macroCommand->addCommand(cmd);
+ }
+ }
+ if(m_paragDlg->isBorderChanged())
+ {
+ cmd=edit->setBordersCommand( m_paragDlg->leftBorder(),
+ m_paragDlg->rightBorder(),
+ m_paragDlg->topBorder(),
+ m_paragDlg->bottomBorder() );
+ if(cmd)
+ {
+ if ( !macroCommand )
+ macroCommand = new KMacroCommand( i18n( "Paragraph Settings" ) );
+
+ macroCommand->addCommand(cmd);
+ }
+ }
+ if( m_paragDlg->isJoinBorderChanged() )
+ {
+ cmd=edit->setJoinBordersCommand( m_paragDlg->joinBorder() );
+ if(cmd)
+ {
+ if ( !macroCommand )
+ macroCommand = new KMacroCommand( i18n( "Paragraph Settings" ) );
+
+ macroCommand->addCommand(cmd);
+ }
+ }
+ if ( m_paragDlg->isPageBreakingChanged() )
+ {
+ cmd=edit->setPageBreakingCommand( m_paragDlg->pageBreaking() );
+ if(cmd)
+ {
+ if ( !macroCommand )
+ macroCommand = new KMacroCommand( i18n( "Paragraph Settings" ) );
+
+ macroCommand->addCommand(cmd);
+ }
+ }
+
+ if ( m_paragDlg->isBackgroundColorChanged() )
+ {
+ cmd=edit->setBackgroundColorCommand( m_paragDlg->backgroundColor() );
+ if(cmd)
+ {
+ if ( !macroCommand )
+ macroCommand = new KMacroCommand( i18n( "Paragraph Settings" ) );
+
+ macroCommand->addCommand(cmd);
+ }
+ }
+
+ if(macroCommand)
+ m_doc->addCommand(macroCommand);
+ // Set "oldLayout" in KoParagDia from the current paragraph's settings
+ // Otherwise "isBlahChanged" will return wrong things when doing A -> B -> A
+ m_paragDlg->setParagLayout( edit->cursor()->parag()->paragLayout() );
+}
+
+// This handles Tabulators _only_
+void KWView::slotHRulerDoubleClicked( double ptpos )
+{
+ showParagraphDialog( KoParagDia::PD_TABS, ptpos );
+}
+
+// This handles either:
+// - Indents
+// - Page Layout
+//
+// This does _not_ handle Tabulators!
+void KWView::slotHRulerDoubleClicked()
+{
+ QString mode = viewMode()->type();
+ bool state = (mode!="ModeText");
+ if ( !state )
+ return;
+
+ KoRuler *ruler = m_gui->getHorzRuler ();
+ if ( (ruler->flags() & KoRuler::F_INDENTS) && currentTextEdit() ) {
+ if ( ruler->doubleClickedIndent () ) {
+ formatParagraph();
+ return;
+ }
+ }
+
+ formatPage();
+}
+
+void KWView::formatPage()
+{
+ if( !m_doc->isReadWrite())
+ return;
+ QString mode = viewMode()->type();
+ bool state = (mode!="ModeText");
+ if ( !state )
+ return;
+
+ KoPageLayout pgLayout;
+ KoColumns cl;
+ KoKWHeaderFooter kwhf;
+ m_doc->getPageLayout( pgLayout, cl, kwhf );
+
+ KWPageLayoutStruct oldLayout( pgLayout, cl, kwhf );
+
+ KoHeadFoot hf;
+ int flags = FORMAT_AND_BORDERS | DISABLE_UNIT;
+ if ( m_doc->processingType() == KWDocument::WP )
+ flags |= KW_HEADER_AND_FOOTER | COLUMNS;
+ else
+ flags |= DISABLE_BORDERS;
+
+ KoUnit::Unit unit = m_doc->unit();
+ KoUnit::Unit oldUnit = unit;
+
+ if ( KoPageLayoutDia::pageLayout( pgLayout, hf, cl, kwhf, flags, unit, this ) )
+ {
+ if( !(oldLayout._pgLayout==pgLayout) ||
+ oldLayout._cl != cl ||
+ oldLayout._hf != kwhf )
+ {
+ KWPageLayoutStruct newLayout( pgLayout, cl, kwhf );
+
+ KWTextFrameSetEdit *edit = currentTextEdit();
+ if (edit)
+ edit->textFrameSet()->clearUndoRedoInfo();
+ KCommand *cmd =new KWPageLayoutCommand( i18n("Change Layout"),
+ m_doc, oldLayout, newLayout );
+ m_doc->addCommand(cmd);
+
+ m_doc->setPageLayout( pgLayout, cl, kwhf );
+ }
+ if ( unit != oldUnit )
+ m_doc->setUnit( unit ); // ##### needs undo/redo support
+ }
+}
+
+void KWView::formatFrameSet()
+{
+ if ( frameViewManager()->selectedFrame() )
+ {
+ m_gui->canvasWidget()->editFrameProperties();
+ }
+ else // Should never happen, the action is disabled
+ KMessageBox::sorry( this,
+ i18n("You must select a frame first."),
+ i18n("Format Frameset"));
+}
+
+void KWView::slotSpellCheck()
+{
+ if (m_spell.kospell) return; // Already in progress
+ //m_doc->setReadWrite(false); // prevent editing text - not anymore
+ m_spell.macroCmdSpellCheck = 0L;
+ m_spell.replaceAll.clear();
+ QValueList<KoTextObject *> objects;
+ KWTextFrameSetEdit * edit = currentTextEdit();
+ if (!edit)
+ return;
+ int options = 0;
+ if ( edit && edit->textFrameSet()->hasSelection() )
+ {
+ objects.append(edit->textFrameSet()->textObject());
+ options = KFindDialog::SelectedText;
+ }
+ else
+ {
+ objects = m_gui->canvasWidget()->kWordDocument()->visibleTextObjects(viewMode());
+ }
+ m_spell.textIterator = new KoTextIterator( objects, edit, options );
+ kdDebug()<<"Created iterator with "<< objects.count() <<endl;
+ startKSpell();
+}
+
+void KWView::extraAutoFormat()
+{
+ m_doc->autoFormat()->readConfig();
+ KoAutoFormatDia dia( this, 0, m_doc->autoFormat() );
+ dia.exec();
+ m_doc->startBackgroundSpellCheck(); // will do so if enabled
+}
+
+void KWView::extraFrameStylist()
+{
+ KWTextFrameSetEdit * edit = currentTextEdit();
+ if ( edit )
+ edit->hideCursor();
+ KWFrameStyleManager * frameStyleManager = new KWFrameStyleManager( this, m_doc, QString::null );
+ frameStyleManager->exec();
+ delete frameStyleManager;
+ if ( edit )
+ edit->showCursor();
+}
+
+void KWView::createFrameStyle()
+{
+
+ QValueList<KWFrameView*> selectedFrames = frameViewManager()->selectedFrames();
+ if (selectedFrames.count() != 1)
+ return;
+
+ KWFrame* frame = selectedFrames[0]->frame();
+
+ KoCreateStyleDia *dia = new KoCreateStyleDia( m_doc->frameStyleCollection()->displayNameList(), this, 0 );
+ if ( dia->exec() )
+ {
+ KWFrameStyle *style= new KWFrameStyle( dia->nameOfNewStyle(), frame );
+ m_doc->frameStyleCollection()->addStyle( style );
+ m_doc->updateAllFrameStyleLists();
+ }
+ delete dia;
+}
+
+void KWView::extraStylist()
+{
+ KWTextFrameSetEdit * edit = currentTextEdit();
+ QString activeStyleName = QString::null;
+ if ( edit )
+ {
+ edit->hideCursor();
+ if (edit->cursor() && edit->cursor()->parag() && edit->cursor()->parag()->style())
+ activeStyleName = edit->cursor()->parag()->style()->displayName();
+ }
+ KWStyleManager * styleManager = new KWStyleManager( this, m_doc->unit(),m_doc, *m_doc->styleCollection(), activeStyleName );
+ styleManager->exec();
+ delete styleManager;
+ if ( edit )
+ edit->showCursor();
+}
+
+void KWView::extraCreateTemplate()
+{
+ int width = 60;
+ int height = 60;
+ QPixmap pix = m_doc->generatePreview(QSize(width, height));
+
+ KTempFile tempFile( QString::null, ".odt" );
+ tempFile.setAutoDelete(true);
+
+ m_doc->saveNativeFormat( tempFile.name() );
+
+ KoTemplateCreateDia::createTemplate( "kword_template", KWFactory::instance(),
+ tempFile.name(), pix, this );
+
+ KWFactory::instance()->dirs()->addResourceType("kword_template",
+ KStandardDirs::kde_default( "data" ) +
+ "kword/templates/");
+}
+
+void KWView::toolsCreateText()
+{
+ if ( m_actionToolsCreateText->isChecked() )
+ m_gui->canvasWidget()->setMouseMode( KWCanvas::MM_CREATE_TEXT );
+ else
+ {
+ // clicked on the already active tool -> abort
+ m_gui->canvasWidget()->setMouseMode( KWCanvas::MM_EDIT );
+ }
+}
+
+void KWView::insertTable()
+{
+ KWCanvas * canvas = m_gui->canvasWidget();
+ canvas->setMouseMode( KWCanvas::MM_EDIT );
+ KWTableDia *tableDia = new KWTableDia( this, 0, KWTableDia::NEW, canvas, m_doc,
+ canvas->tableRows(),
+ canvas->tableCols(),
+ canvas->tableWidthMode(),
+ canvas->tableHeightMode(),
+ canvas->tableIsFloating(),
+ canvas->tableTemplateName(),
+ canvas->tableFormat());
+ tableDia->setCaption( i18n( "Insert Table" ) );
+ if ( tableDia->exec() == QDialog::Rejected )
+ canvas->setMouseMode( KWCanvas::MM_EDIT );
+ delete tableDia;
+}
+
+void KWView::insertFormula( QMimeSource* source )
+{
+ KWTextFrameSetEdit *edit = currentTextEdit();
+ if (edit)
+ {
+ KWFormulaFrameSet *frameset = new KWFormulaFrameSet( m_doc, QString::null );
+ m_doc->addFrameSet( frameset, false ); // done first since the frame number is stored in the undo/redo
+ if ( source ) {
+ QByteArray data = source->encodedData( KFormula::MimeSource::selectionMimeType() );
+ QDomDocument formula;
+ formula.setContent( data );
+ QDomElement formulaElem = formula.namedItem("math").toElement();
+ frameset->paste( formulaElem );
+ }
+ KWFrame *frame = new KWFrame(frameset, 0, 0, 10, 10 );
+ frame->setZOrder( m_doc->maxZOrder( frame->pageNumber(m_doc) ) + 1 ); // make sure it's on top
+ frameset->addFrame( frame, false );
+ edit->insertFloatingFrameSet( frameset, i18n("Insert Formula") );
+ frameset->finalize(); // done last since it triggers a redraw
+ m_doc->refreshDocStructure(FT_FORMULA);
+
+ m_gui->canvasWidget()->editFrameSet( frameset );
+ frameset->setChanged();
+ m_gui->canvasWidget()->repaintChanged( frameset, true );
+ }
+}
+
+void KWView::toolsPart()
+{
+ m_gui->canvasWidget()->insertPart( m_actionToolsCreatePart->documentEntry() );
+}
+
+
+int KWView::tableSelectCell(const QString &tableName, uint row, uint col)
+{
+ if(!m_doc || !m_gui)
+ return -1;
+ KWFrameSet *fs = m_doc->frameSetByName(tableName);
+ if(!fs)
+ return -1;
+ KWTableFrameSet *table = dynamic_cast<KWTableFrameSet*>(fs);
+ if(!table)
+ return -1;
+ if (row >= table->getRows() || col >= table->getColumns())
+ return -1;
+
+ KWTableFrameSet::Cell *cell = table->cell(row, col);
+
+ KWCanvas *canvas = m_gui->canvasWidget();
+ if(!canvas)
+ return -1;
+ canvas->tableSelectCell(table, cell);
+ return 0;
+}
+
+int KWView::tableDeleteRow(const QValueList<uint>& rows, KWTableFrameSet *table )
+{
+ if(!table)
+ table = m_gui->canvasWidget()->getCurrentTable();
+
+ if (!m_doc || !table)
+ return -1;
+
+ if(rows.count() >= table->getRows()) {
+ m_doc->deleteTable(table);
+ return 0;
+ }
+
+ KMacroCommand *macro = new KMacroCommand(i18n("Remove Rows"));
+
+ for (int i = rows.count() - 1; i >= 0 ; i--) {
+ KWRemoveRowCommand *cmd = new KWRemoveRowCommand( i18n("Remove Row"),
+ table, rows[i] );
+ macro->addCommand(cmd);
+ }
+
+ macro->execute();
+ m_doc->addCommand(macro);
+ return 0;
+}
+
+int KWView::tableDeleteCol(const QValueList<uint>& cols, KWTableFrameSet *table)
+{
+ if(!table)
+ table = m_gui->canvasWidget()->getCurrentTable();
+
+ if (!m_doc || !table)
+ return -1;
+
+ if(cols.count() >= table->getColumns()) {
+ m_doc->deleteTable(table);
+ return 0;
+ }
+
+ KMacroCommand *macro = new KMacroCommand(i18n("Remove Columns"));
+
+ for (int i = cols.count() - 1; i >= 0; i--) {
+ KWRemoveColumnCommand *cmd = new KWRemoveColumnCommand( i18n("Remove Column"),
+ table, cols[i] );
+ macro->addCommand(cmd);
+ }
+
+ macro->execute();
+ m_doc->addCommand(macro);
+ return 0;
+}
+
+void KWView::tableProperties()
+{
+ KWCanvas * canvas = m_gui->canvasWidget();
+ KWTableFrameSet *table = canvas->getCurrentTable();
+ if (table)
+ {
+ canvas->setMouseMode( KWCanvas::MM_EDIT );
+ KWTableDia *tableDia = new KWTableDia( this, 0, KWTableDia::EDIT, canvas, m_doc,
+ table->getRows(),
+ table->getColumns(),
+ canvas->tableWidthMode(),
+ canvas->tableHeightMode(),
+ canvas->tableIsFloating(),
+ canvas->tableTemplateName(),
+ canvas->tableFormat());
+ tableDia->setCaption( i18n( "Adjust Table" ) );
+ if ( tableDia->exec() == QDialog::Rejected )
+ canvas->setMouseMode( KWCanvas::MM_EDIT );
+ delete tableDia;
+ }
+}
+
+void KWView::tableInsertRow()
+{
+ TableInfo ti(frameViewManager()->selectedFrames());
+ KWTableFrameSet::Cell *cell = ti.firstSelectedCell();
+ if(! cell) return;
+
+ KWInsertDia dia( this, cell->groupmanager(), KWInsertDia::insertRow, cell->firstRow());
+ dia.exec();
+}
+
+void KWView::tableInsertRow(uint row, KWTableFrameSet *table)
+{
+ if(!table)
+ table = m_gui->canvasWidget()->getCurrentTable();
+
+ if (!m_doc || !table)
+ return;
+
+ if(row > table->getRows())
+ return;
+
+ KWInsertRowCommand *cmd = new KWInsertRowCommand( i18n("Insert Row"), table, row);
+ cmd->execute();
+ m_doc->addCommand(cmd);
+}
+
+
+void KWView::tableInsertCol()
+{
+ TableInfo ti(frameViewManager()->selectedFrames());
+ KWTableFrameSet::Cell *cell = ti.firstSelectedCell();
+ if(! cell) return;
+
+ KWInsertDia dia( this, cell->groupmanager(), KWInsertDia::insertColumn, cell->firstColumn());
+ dia.exec();
+}
+
+void KWView::tableInsertCol(uint col, KWTableFrameSet *table )
+{
+ if(!table)
+ table = m_gui->canvasWidget()->getCurrentTable();
+
+ if (!m_doc || !table)
+ return;
+
+ if(col > table->getColumns())
+ return;
+
+ // we pass as last parameter the maximum offset that the table can use.
+ // this offset is the max right offset of the containing frame in the case
+ // of an inline (floating) table, the size of the page for other tables.
+ double maxRightOffset;
+ if (table->isFloating()) // inline table: max offset of containing frame
+ maxRightOffset = table->anchorFrameset()->frame(0)->right();
+ else { // non inline table: max offset of the page
+ KWPage *page = m_doc->pageManager()->page( table->cell(0,0)->frame(0) );
+ maxRightOffset = page->width() - page->rightMargin();
+ }
+
+ KWInsertColumnCommand *cmd = new KWInsertColumnCommand( i18n("Insert Column"),
+ table, col, maxRightOffset);
+ cmd->execute();
+ m_doc->addCommand(cmd);
+}
+
+void KWView::tableDeleteRow()
+{
+ TableInfo ti( frameViewManager()->selectedFrames() );
+ if(ti.amountRowsSelected() == 0) return;
+
+ KWDeleteDia dia( this, ti.firstSelectedCell()->groupmanager(),
+ KWDeleteDia::deleteRow, ti.selectedRows() );
+ dia.exec();
+}
+
+void KWView::tableDeleteCol()
+{
+ TableInfo ti( frameViewManager()->selectedFrames() );
+ if(ti.amountColumnsSelected() == 0) return;
+
+ KWDeleteDia dia( this, ti.firstSelectedCell()->groupmanager(),
+ KWDeleteDia::deleteColumn, ti.selectedColumns() );
+ dia.exec();
+}
+
+void KWView::tableResizeCol()
+{
+ TableInfo ti( frameViewManager()->selectedFrames() );
+ KWTableFrameSet::Cell *cell = ti.firstSelectedCell();
+ if(cell == 0)
+ return;
+ KWResizeTableDia dia(this, cell->groupmanager(), m_doc, cell->firstColumn());
+ dia.exec();
+}
+
+void KWView::tableJoinCells()
+{
+ KWTableFrameSet *table = 0;
+ QValueList<KWFrameView*> selectedFrames = frameViewManager()->selectedFrames();
+ QValueListIterator<KWFrameView*> framesIterator = selectedFrames.begin();
+ unsigned int x1=10000, y1=10000, x2=0, y2=0;
+ for(;framesIterator != selectedFrames.end(); ++framesIterator) {
+ KWFrameView *view = *framesIterator;
+ if(!view->selected()) continue;
+ KWFrameSet *fs = view->frame()->frameSet();
+ Q_ASSERT(fs);
+ KWTableFrameSet::Cell *cell = dynamic_cast<KWTableFrameSet::Cell*>(fs);
+ if(cell == 0) continue;
+ if(!table)
+ table = cell->groupmanager();
+ else if(table != cell->groupmanager()) { // more then one table has selected cells
+ KMessageBox::sorry( this,
+ i18n( "More then one table has selected cells, please make sure "
+ "the selected cells are in one table and are connecting"),
+ i18n( "Join Cells Failed" ) );
+ return;
+ }
+
+ if(cell->firstRow() < y1) y1 = cell->firstRow();
+ if(cell->firstColumn() < x1) x1 = cell->firstColumn();
+ if(cell->lastRow() > y2) y2 = cell->lastRow();
+ if(cell->lastColumn() > x2) x2 = cell->lastColumn();
+ }
+
+ Q_ASSERT(table);
+ if (!table)
+ return;
+ KCommand * cmd=table->joinCells(x1, y1, x2, y2);
+ if ( !cmd )
+ {
+ KMessageBox::sorry( this,
+ i18n( "You have to select some cells which are next to each other "
+ "and are not already joined." ),
+ i18n( "Join Cells" ) );
+ return;
+ }
+ m_doc->addCommand(cmd);
+ m_doc->layout();
+}
+
+void KWView::tableSplitCells() {
+ KWSplitCellDia *splitDia=new KWSplitCellDia( this,"split cell",
+ m_tableSplit.columns, m_tableSplit.rows );
+ if(splitDia->exec()) {
+ m_tableSplit.rows = splitDia->rows();
+ m_tableSplit.columns = splitDia->columns();
+ tableSplitCells( m_tableSplit.columns, m_tableSplit.rows );
+ }
+ delete splitDia;
+}
+
+void KWView::tableSplitCells(int cols, int rows)
+{
+ TableInfo ti( frameViewManager()->selectedFrames() );
+ if(! ti.oneCellSelected()) {
+ KMessageBox::sorry( this,
+ i18n( "You have to put the cursor into a table "
+ "before splitting cells." ),
+ i18n( "Split Cells" ) );
+ return;
+ }
+
+ KWTableFrameSet::Cell *cell = ti.firstSelectedCell();
+ KCommand *cmd=cell->groupmanager()->splitCell(rows, cols, cell->firstColumn(), cell->firstRow());
+ if ( !cmd ) {
+ KMessageBox::sorry( this,
+ i18n("There is not enough space to split the cell into that many parts, make it bigger first"),
+ i18n("Split Cells") );
+ return;
+ }
+ m_doc->addCommand(cmd);
+ m_doc->updateAllFrames();
+ m_doc->layout();
+ frameViewManager()->view(cell->frame(0))->setSelected(true);
+}
+
+void KWView::tableUngroupTable()
+{
+ m_gui->canvasWidget()->setMouseMode( KWCanvas::MM_EDIT );
+
+ KWTableFrameSet *table = m_gui->canvasWidget()->getCurrentTable();
+ Q_ASSERT(table);
+ if (!table)
+ return;
+
+ // Use a macro command because we may have to make the table non-floating first
+ KMacroCommand * macroCmd = new KMacroCommand( i18n( "Ungroup Table" ) );
+
+ if ( table->isFloating() )
+ {
+ KWFrameSetInlineCommand *cmd = new KWFrameSetInlineCommand( QString::null, table, false );
+ macroCmd->addCommand(cmd);
+ }
+
+ KWUngroupTableCommand *cmd = new KWUngroupTableCommand( QString::null, table );
+ macroCmd->addCommand( cmd );
+ m_doc->addCommand( macroCmd );
+ macroCmd->execute(); // do it all
+}
+
+void KWView::tableDelete()
+{
+ KWTableFrameSet *table = m_gui->canvasWidget()->getCurrentTable();
+ Q_ASSERT(table);
+ if (!table)
+ return;
+ m_doc->deleteTable( table );
+}
+
+void KWView::tableStylist()
+{
+ KWTextFrameSetEdit * edit = currentTextEdit();
+ if ( edit )
+ edit->hideCursor();
+ KWTableStyleManager * tableStyleManager = new KWTableStyleManager( this, m_doc );
+ tableStyleManager->exec();
+ delete tableStyleManager;
+ if ( edit )
+ edit->showCursor();
+}
+
+void KWView::tableProtectCells(bool on)
+{
+ KMacroCommand *macro = 0;
+ QValueList<KWFrameView*> selectedFrames = frameViewManager()->selectedFrames();
+ QValueListIterator<KWFrameView*> framesIterator = selectedFrames.begin();
+ for(;framesIterator != selectedFrames.end(); ++framesIterator) {
+ KWFrameView *view = *framesIterator;
+ KWFrameSet *fs = view->frame()->frameSet();
+ Q_ASSERT(fs);
+ KWTableFrameSet::Cell *cell = dynamic_cast<KWTableFrameSet::Cell*>(fs);
+ if(cell == 0) continue;
+ if(cell->protectContent() != on) {
+ KWProtectContentCommand *cmd = new KWProtectContentCommand( i18n("Protect Content"), cell , on);
+ if ( !macro )
+ macro = new KMacroCommand( i18n("Protect Content"));
+ macro->addCommand( cmd );
+ }
+ }
+ if(macro) {
+ macro->execute();
+ m_doc->addCommand( macro );
+ }
+}
+
+void KWView::textStyleSelected( KoParagStyle *sty )
+{
+ if ( !sty )
+ return;
+
+ if ( m_gui->canvasWidget()->currentFrameSetEdit() )
+ {
+ KWTextFrameSetEdit * edit = dynamic_cast<KWTextFrameSetEdit *>(m_gui->canvasWidget()->currentFrameSetEdit()->currentTextEdit());
+ if ( edit )
+ edit->applyStyle( sty );
+ }
+ else
+ { // it might be that a frame (or several frames) are selected
+ QValueList<KWFrameView*> selectedFrames = frameViewManager()->selectedFrames();
+ if (selectedFrames.count() <= 0)
+ return; // nope, no frames are selected.
+ // yes, indeed frames are selected.
+
+ QValueListIterator<KWFrameView*> framesIterator = selectedFrames.begin();
+ KMacroCommand *globalCmd = 0L;
+ while(framesIterator != selectedFrames.end()) {
+ KWFrame *curFrame = (*framesIterator)->frame();
+ KWFrameSet *curFrameSet = curFrame->frameSet();
+ if (curFrameSet->type() == FT_TEXT)
+ {
+ KoTextObject *textObject = ((KWTextFrameSet*)curFrameSet)->textObject();
+ textObject->textDocument()->selectAll( KoTextDocument::Temp );
+ KCommand *cmd = textObject->applyStyleCommand( 0L, sty , KoTextDocument::Temp, KoParagLayout::All, KoTextFormat::Format, true, true );
+ textObject->textDocument()->removeSelection( KoTextDocument::Temp );
+ if (cmd)
+ {
+ if ( !globalCmd )
+ globalCmd = new KMacroCommand( selectedFrames.count() == 1 ? i18n("Apply Style to Frame") : i18n("Apply Style to Frames"));
+ globalCmd->addCommand( cmd );
+ }
+ }
+ ++framesIterator;
+ }
+ if ( globalCmd )
+ m_doc->addCommand( globalCmd );
+ }
+ m_gui->canvasWidget()->setFocus(); // the combo keeps focus...*/
+
+}
+
+// Called by the above, and when selecting a style in the style combobox
+void KWView::textStyleSelected( int index )
+{
+ textStyleSelected( m_doc->styleCollection()->styleAt( index ) );
+}
+
+// Slot is called when selecting a framestyle in the Frames / Framestyle menu
+void KWView::slotFrameStyleSelected()
+{
+ QString actionName = QString::fromUtf8(sender()->name());
+ const QString prefix = FRAMESTYLE_ACTION_PREFIX;
+ if ( actionName.startsWith( prefix ) ) {
+ actionName = actionName.mid( prefix.length() );
+ frameStyleSelected( m_doc->frameStyleCollection()->findStyle( actionName ) );
+ }
+}
+
+void KWView::frameStyleSelected( int index )
+{
+ frameStyleSelected( m_doc->frameStyleCollection()->frameStyleAt( index ) );
+}
+
+
+// Called by the above, and when selecting a style in the framestyle combobox
+void KWView::frameStyleSelected( KWFrameStyle *sty )
+{
+ if ( !sty )
+ return;
+
+ if ( m_gui->canvasWidget()->currentFrameSetEdit() )
+ {
+ KWFrame * single = m_gui->canvasWidget()->currentFrameSetEdit()->currentFrame();
+ if ( single ) {
+
+ KCommand *cmd = new KWFrameStyleCommand( i18n("Apply Framestyle to Frame"), single, sty );
+ if (cmd) {
+ m_doc->addCommand( cmd );
+ cmd->execute();
+ }
+ }
+ }
+ else
+ { // it might be that a frame (or several frames) are selected
+ QValueList<KWFrameView*> selectedFrames = frameViewManager()->selectedFrames();
+ if (selectedFrames.count() <= 0)
+ return; // nope, no frames are selected.
+ // yes, indeed frames are selected.
+
+ KMacroCommand *globalCmd = new KMacroCommand( selectedFrames.count() == 1 ? i18n("Apply Framestyle to Frame") : i18n("Apply Framestyle to Frames"));
+
+ QValueListIterator<KWFrameView*> framesIterator = selectedFrames.begin();
+ while(framesIterator != selectedFrames.end()) {
+ KWFrame *curFrame = (*framesIterator)->frame();
+ KCommand *cmd = new KWFrameStyleCommand( i18n("Apply Framestyle"), curFrame, sty );
+ if (cmd)
+ globalCmd->addCommand( cmd );
+ ++framesIterator;
+ }
+ m_doc->addCommand( globalCmd );
+ globalCmd->execute();
+ }
+
+ m_gui->canvasWidget()->repaintAll();
+ m_gui->canvasWidget()->setFocus(); // the combo keeps focus...*/
+
+ // Adjust GUI
+ const int pos = m_doc->frameStyleCollection()->indexOf( sty );
+ Q_ASSERT( pos >= 0 );
+ m_actionFrameStyle->setCurrentItem( pos );
+ KToggleAction* act = dynamic_cast<KToggleAction *>(actionCollection()->action( sty->name().utf8() ));
+ if ( act )
+ act->setChecked( true );
+}
+
+
+// Called when selecting a tablestyle in the Table / Tablestyle menu
+void KWView::slotTableStyleSelected()
+{
+ QString actionName = QString::fromUtf8(sender()->name());
+ const QString prefix = TABLESTYLE_ACTION_PREFIX;
+ if ( actionName.startsWith( prefix ) ) {
+ actionName = actionName.mid( prefix.length() );
+ tableStyleSelected( m_doc->tableStyleCollection()->findStyle( actionName ) );
+ }
+}
+
+void KWView::tableStyleSelected( int index )
+{
+ tableStyleSelected( m_doc->tableStyleCollection()->tableStyleAt( index ) );
+}
+
+// Called by the above, and when selecting a style in the framestyle combobox
+void KWView::tableStyleSelected( KWTableStyle *sty )
+{
+ if ( !sty )
+ return;
+
+ if ( m_gui->canvasWidget()->currentFrameSetEdit() )
+ {
+ KWFrame * single = m_gui->canvasWidget()->currentFrameSetEdit()->currentFrame();
+ if ( (single) && ( single->frameSet()->type() == FT_TEXT ) )
+ {
+ KCommand *cmd = new KWTableStyleCommand( i18n("Apply Tablestyle to Frame"), single, sty );
+ if (cmd) {
+ m_doc->addCommand( cmd );
+ cmd->execute();
+ }
+ }
+ }
+ else
+ {
+ QValueList<KWFrameView*> selectedFrames = frameViewManager()->selectedFrames();
+ if (selectedFrames.count() <= 0)
+ return; // nope, no frames are selected.
+
+ KMacroCommand *globalCmd = new KMacroCommand( selectedFrames.count() == 1 ? i18n("Apply Tablestyle to Frame") : i18n("Apply Tablestyle to Frames"));
+
+ QValueListIterator<KWFrameView*> framesIterator = selectedFrames.begin();
+ while(framesIterator != selectedFrames.end() ) {
+ KWFrame *curFrame = (*framesIterator)->frame();
+ if(dynamic_cast<KWTextFrameSet*>(curFrame->frameSet())) {
+ KCommand *cmd = new KWTableStyleCommand( i18n("Apply Tablestyle to Frame"),
+ curFrame, sty );
+ if (cmd)
+ globalCmd->addCommand( cmd );
+ }
+ ++framesIterator;
+ }
+ m_doc->addCommand( globalCmd );
+ globalCmd->execute();
+ }
+
+ m_gui->canvasWidget()->repaintAll();
+ m_gui->canvasWidget()->setFocus(); // the combo keeps focus...*/
+
+ // Adjust GUI
+ int pos = m_doc->tableStyleCollection()->indexOf( sty );
+ m_actionTableStyle->setCurrentItem( pos );
+ KToggleAction* act = dynamic_cast<KToggleAction *>(actionCollection()->action( sty->name().utf8() ));
+ if ( act )
+ act->setChecked( true );
+}
+
+void KWView::increaseFontSize()
+{
+ KWTextFrameSetEdit * edit = currentTextEdit();
+ KoTextFormat *format = edit->currentFormat();
+ if ( edit )
+ textSizeSelected( edit->textFrameSet()->textObject()->docFontSize( format ) + 1 );
+}
+
+void KWView::decreaseFontSize()
+{
+ KWTextFrameSetEdit * edit = currentTextEdit();
+ KoTextFormat *format = edit->currentFormat();
+ if ( edit )
+ textSizeSelected( edit->textFrameSet()->textObject()->docFontSize( format ) - 1 );
+}
+
+void KWView::textSizeSelected( int size )
+{
+ QPtrList<KoTextFormatInterface> lst = applicableTextInterfaces();
+ QPtrListIterator<KoTextFormatInterface> it( lst );
+ KMacroCommand *globalCmd = new KMacroCommand(i18n("Change Text Size"));
+ for ( ; it.current() ; ++it )
+ {
+ KCommand *cmd = it.current()->setPointSizeCommand( size );
+ if (cmd)
+ globalCmd->addCommand(cmd);
+ }
+ m_doc->addCommand(globalCmd);
+ m_gui->canvasWidget()->setFocus(); // the combo keeps focus...
+}
+
+void KWView::textFontSelected( const QString & font )
+{
+ QPtrList<KoTextFormatInterface> lst = applicableTextInterfaces();
+ if ( lst.isEmpty() ) return;
+ QPtrListIterator<KoTextFormatInterface> it( lst );
+ KMacroCommand* macroCmd = 0L;
+ for ( ; it.current() ; ++it )
+ {
+ KCommand *cmd = it.current()->setFamilyCommand( font );
+ if (cmd)
+ {
+ if ( !macroCmd )
+ macroCmd = new KMacroCommand( i18n("Change Text Font") );
+ macroCmd->addCommand( cmd );
+ }
+ }
+ if ( macroCmd )
+ m_doc->addCommand( macroCmd );
+ m_gui->canvasWidget()->setFocus(); // the combo keeps focus...
+}
+
+QPtrList<KoTextFormatInterface> KWView::applicableTextInterfaces() const
+{
+ QPtrList<KoTextFormatInterface> lst;
+ if (currentTextEdit())
+ {
+ if ( !currentTextEdit()->textObject()->protectContent())
+ {
+ // simply return the current textEdit
+ lst.append( currentTextEdit() );
+ //kdDebug() << "text frame name: " << currentTextEdit()->textFrameSet()->name() << endl;
+ KWCollectFramesetsVisitor visitor;
+ currentTextEdit()->textDocument()->visitSelection( KoTextDocument::Standard, &visitor ); //find all framesets in the selection
+ const QValueList<KWFrameSet *>& frameset = visitor.frameSets();
+ for ( QValueList<KWFrameSet *>::ConstIterator it = frameset.begin(); it != frameset.end(); ++it )
+ {
+ if ( (*it)->type() == FT_TABLE )
+ {
+ KWTableFrameSet* kwtableframeset = static_cast<KWTableFrameSet *>( *it );
+ //kdDebug() << "table found: " << kwtableframeset->frameCount() << endl;
+ int const rows = kwtableframeset->getRows();
+ int const cols = kwtableframeset->getColumns();
+ //finding all cells and add them to the interface list
+ for (int r=0; r<rows; ++r)
+ {
+ for (int c=0; c<cols; ++c)
+ {
+ KWTableFrameSet::Cell *cell = kwtableframeset->cell(r,c);
+ if (cell)
+ {
+ kdDebug() << "adding (" << r << "," << c << ")" << endl;
+ lst.append(cell);
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ else
+ { // it might be that a frame (or several frames) are selected
+ // in that case, list the text framesets behind them
+ QValueList<KWFrameView*> selectedFrames = frameViewManager()->selectedFrames();
+ QValueListIterator<KWFrameView*> framesIterator = selectedFrames.begin();
+ while(framesIterator != selectedFrames.end()) {
+ KWTextFrameSet* fs = dynamic_cast<KWTextFrameSet *>( (*framesIterator)->frame()->frameSet() );
+ if ( fs && !lst.contains( fs )&& !fs->protectContent() )
+ lst.append( fs );
+ ++framesIterator;
+ }
+ }
+ return lst;
+}
+
+void KWView::textBold()
+{
+ QPtrList<KoTextFormatInterface> lst = applicableTextInterfaces();
+ if ( lst.isEmpty() ) return;
+ QPtrListIterator<KoTextFormatInterface> it( lst );
+ KMacroCommand* macroCmd = 0L;
+ for ( ; it.current() ; ++it )
+ {
+ KCommand *cmd = it.current()->setBoldCommand( m_actionFormatBold->isChecked() );
+ if (cmd)
+ {
+ if ( !macroCmd )
+ macroCmd = new KMacroCommand( i18n("Make Text Bold") );
+ macroCmd->addCommand(cmd);
+ }
+ }
+ if(macroCmd)
+ m_doc->addCommand(macroCmd);
+
+}
+
+void KWView::textItalic()
+{
+ QPtrList<KoTextFormatInterface> lst = applicableTextInterfaces();
+ QPtrListIterator<KoTextFormatInterface> it( lst );
+ KMacroCommand* macroCmd = 0L;
+ for ( ; it.current() ; ++it )
+ {
+ KCommand *cmd = it.current()->setItalicCommand( m_actionFormatItalic->isChecked() );
+ if (cmd)
+ {
+ if ( !macroCmd )
+ macroCmd = new KMacroCommand( i18n("Make Text Italic") );
+ macroCmd->addCommand( cmd );
+ }
+ }
+ if( macroCmd)
+ m_doc->addCommand( macroCmd );
+}
+
+void KWView::textUnderline()
+{
+ QPtrList<KoTextFormatInterface> lst = applicableTextInterfaces();
+ QPtrListIterator<KoTextFormatInterface> it( lst );
+ KMacroCommand* macroCmd = 0L;
+
+ for ( ; it.current() ; ++it )
+ {
+ KCommand *cmd = it.current()->setUnderlineCommand( m_actionFormatUnderline->isChecked() );
+ if ( cmd )
+ {
+ if ( !macroCmd )
+ macroCmd = new KMacroCommand( i18n("Underline Text") );
+ macroCmd->addCommand( cmd );
+ }
+ }
+ if(macroCmd)
+ m_doc->addCommand( macroCmd );
+}
+
+void KWView::textStrikeOut()
+{
+ QPtrList<KoTextFormatInterface> lst = applicableTextInterfaces();
+ QPtrListIterator<KoTextFormatInterface> it( lst );
+ KMacroCommand* macroCmd = 0L;
+ for ( ; it.current() ; ++it )
+ {
+ KCommand *cmd = it.current()->setStrikeOutCommand( m_actionFormatStrikeOut->isChecked() );
+ if ( cmd )
+ {
+ if ( !macroCmd )
+ macroCmd = new KMacroCommand( i18n("Strike Out Text") );
+ macroCmd->addCommand( cmd );
+ }
+ }
+ if( macroCmd)
+ m_doc->addCommand( macroCmd );
+}
+
+void KWView::textColor()
+{
+ /* QColor color = edit->textColor();
+ if ( KColorDialog::getColor( color ) ) {
+ m_actionFormatColor->setColor( color );
+ edit->setTextColor( color );
+ }
+ */
+ QPtrList<KoTextFormatInterface> lst = applicableTextInterfaces();
+ if ( lst.isEmpty() ) return;
+ QPtrListIterator<KoTextFormatInterface> it( lst );
+ KMacroCommand* macroCmd = 0L;
+ for ( ; it.current() ; ++it )
+ {
+ KCommand *cmd = it.current()->setTextColorCommand( m_actionFormatColor->color() );
+ if ( cmd )
+ {
+ if ( !macroCmd )
+ macroCmd = new KMacroCommand( i18n("Set Text Color") );
+ macroCmd->addCommand( cmd );
+ }
+ }
+ if( macroCmd)
+ m_doc->addCommand( macroCmd );
+}
+
+void KWView::textAlignLeft()
+{
+ if ( m_actionFormatAlignLeft->isChecked() )
+ {
+ QPtrList<KoTextFormatInterface> lst = applicableTextInterfaces();
+ QPtrListIterator<KoTextFormatInterface> it( lst );
+ KMacroCommand* macroCmd = 0L;
+ for ( ; it.current() ; ++it )
+ {
+ KCommand *cmd = it.current()->setAlignCommand( Qt::AlignLeft );
+ if (cmd)
+ {
+ if ( !macroCmd)
+ macroCmd = new KMacroCommand( i18n("Left-Align Text") );
+ macroCmd->addCommand( cmd );
+ }
+ }
+ if( macroCmd )
+ m_doc->addCommand( macroCmd );
+ }
+ else
+ m_actionFormatAlignLeft->setChecked( true );
+}
+
+void KWView::textAlignCenter()
+{
+ if ( m_actionFormatAlignCenter->isChecked() )
+ {
+ QPtrList<KoTextFormatInterface> lst = applicableTextInterfaces();
+ QPtrListIterator<KoTextFormatInterface> it( lst );
+ KMacroCommand* macroCmd = 0L;
+ for ( ; it.current() ; ++it )
+ {
+ KCommand *cmd = it.current()->setAlignCommand( Qt::AlignHCenter );
+ if (cmd)
+ {
+ if ( !macroCmd )
+ macroCmd = new KMacroCommand( i18n("Center Text") );
+ macroCmd->addCommand( cmd );
+ }
+ }
+ if( macroCmd )
+ m_doc->addCommand( macroCmd );
+ }
+ else
+ m_actionFormatAlignCenter->setChecked( true );
+}
+
+void KWView::textAlignRight()
+{
+ if ( m_actionFormatAlignRight->isChecked() )
+ {
+ QPtrList<KoTextFormatInterface> lst = applicableTextInterfaces();
+ QPtrListIterator<KoTextFormatInterface> it( lst );
+ KMacroCommand* macroCmd = 0L;
+ for ( ; it.current() ; ++it )
+ {
+ KCommand *cmd = it.current()->setAlignCommand( Qt::AlignRight );
+ if ( cmd )
+ {
+ if (!macroCmd )
+ macroCmd = new KMacroCommand( i18n("Right-Align Text") );
+ macroCmd->addCommand( cmd );
+ }
+ }
+ if( macroCmd)
+ m_doc->addCommand( macroCmd );
+ }
+ else
+ m_actionFormatAlignRight->setChecked( true );
+}
+
+void KWView::textAlignBlock()
+{
+ if ( m_actionFormatAlignBlock->isChecked() )
+ {
+ QPtrList<KoTextFormatInterface> lst = applicableTextInterfaces();
+ QPtrListIterator<KoTextFormatInterface> it( lst );
+ KMacroCommand* macroCmd = 0L;
+ for ( ; it.current() ; ++it )
+ {
+ KCommand *cmd = it.current()->setAlignCommand( Qt::AlignJustify );
+ if ( cmd )
+ {
+ if ( !macroCmd )
+ macroCmd = new KMacroCommand( i18n("Justify Text") );
+ macroCmd->addCommand( cmd );
+ }
+ }
+ if( macroCmd)
+ m_doc->addCommand( macroCmd );
+ }
+ else
+ m_actionFormatAlignBlock->setChecked( true );
+}
+
+void KWView::setSpacing( KoParagLayout::SpacingType spacing, const QString& commandName)
+{
+ QPtrList<KoTextFormatInterface> lst = applicableTextInterfaces();
+ if ( lst.isEmpty() ) return;
+ QPtrListIterator<KoTextFormatInterface> it( lst );
+ KMacroCommand* macroCmd = 0L;
+ for ( ; it.current() ; ++it )
+ {
+ KoParagLayout layout( *it.current()->currentParagLayoutFormat() );
+ layout.lineSpacingType = spacing;
+
+ KCommand *cmd = it.current()->setParagLayoutFormatCommand( &layout, KoParagLayout::LineSpacing );
+ if (cmd)
+ {
+ if ( !macroCmd )
+ macroCmd = new KMacroCommand( commandName );
+ macroCmd->addCommand(cmd);
+ }
+ }
+ if( macroCmd)
+ m_doc->addCommand(macroCmd);
+}
+
+void KWView::textSpacingSingle()
+{
+ if ( m_actionFormatSpacingSingle->isChecked() )
+ setSpacing( KoParagLayout::LS_SINGLE, i18n("Set Single Line Spacing") );
+ else
+ m_actionFormatSpacingSingle->setChecked( true );
+}
+
+void KWView::textSpacingOneAndHalf()
+{
+ if ( m_actionFormatSpacingOneAndHalf->isChecked() )
+ setSpacing( KoParagLayout::LS_ONEANDHALF, i18n("Set One and a Half Line Spacing") );
+ else
+ m_actionFormatSpacingOneAndHalf->setChecked( true );
+}
+
+void KWView::textSpacingDouble()
+{
+ if ( m_actionFormatSpacingDouble->isChecked() )
+ setSpacing( KoParagLayout::LS_DOUBLE, i18n("Set Double Line Spacing") );
+ else
+ m_actionFormatSpacingDouble->setChecked( true );
+}
+
+void KWView::slotCounterStyleSelected()
+{
+ QString actionName = QString::fromLatin1(sender()->name());
+ QString styleStr = actionName.mid(13);
+ //kdDebug() << "KWView::slotCounterStyleSelected styleStr=" << styleStr << endl;
+ KoParagCounter::Style style = (KoParagCounter::Style)(styleStr.toInt());
+ KoParagCounter c;
+ if ( style == KoParagCounter::STYLE_NONE )
+ c.setNumbering( KoParagCounter::NUM_NONE );
+ else {
+ c.setNumbering( KoParagCounter::NUM_LIST );
+ c.setStyle( style );
+ if ( c.isBullet() )
+ c.setSuffix( QString::null );
+ else
+ c.setSuffix( "." );
+ // TODO save this setting, to use the last one selected in the dialog?
+ // (same for custom bullet char etc.)
+
+ // 68927: restart numbering, by default, if last parag wasn't numbered
+ // (and if we're not applying this to a selection)
+ if ( currentTextEdit() && !currentTextEdit()->textFrameSet()->hasSelection() ) {
+ KoTextParag* parag = currentTextEdit()->cursor()->parag();
+ if ( parag->prev() && !parag->prev()->counter() )
+ c.setRestartCounter(true);
+ }
+ }
+
+ QPtrList<KoTextFormatInterface> lst = applicableTextInterfaces();
+ QPtrListIterator<KoTextFormatInterface> it( lst );
+ KMacroCommand* macroCmd = 0L;
+ for ( ; it.current() ; ++it )
+ {
+ KCommand *cmd = it.current()->setCounterCommand( c );
+ if ( cmd )
+ {
+ if ( !macroCmd )
+ macroCmd=new KMacroCommand( i18n("Change List Type") );
+ macroCmd->addCommand( cmd );
+ }
+ }
+ if( macroCmd)
+ m_doc->addCommand( macroCmd );
+}
+
+void KWView::textSuperScript()
+{
+ QPtrList<KoTextFormatInterface> lst = applicableTextInterfaces();
+ if ( lst.isEmpty() ) return;
+ QPtrListIterator<KoTextFormatInterface> it( lst );
+ KMacroCommand* macroCmd = 0L;
+ for ( ; it.current() ; ++it )
+ {
+ KCommand *cmd = it.current()->setTextSuperScriptCommand(m_actionFormatSuper->isChecked());
+ if (cmd)
+ {
+ if ( !macroCmd )
+ macroCmd = new KMacroCommand( i18n("Make Text Superscript") );
+ macroCmd->addCommand(cmd);
+ }
+ }
+ if( macroCmd)
+ m_doc->addCommand(macroCmd);
+ if (m_actionFormatSuper->isChecked() )
+ m_actionFormatSub->setChecked( false );
+}
+
+void KWView::textSubScript()
+{
+ QPtrList<KoTextFormatInterface> lst = applicableTextInterfaces();
+ if ( lst.isEmpty() ) return;
+ QPtrListIterator<KoTextFormatInterface> it( lst );
+ KMacroCommand* macroCmd = 0L;
+ for ( ; it.current() ; ++it )
+ {
+ KCommand *cmd = it.current()->setTextSubScriptCommand(m_actionFormatSub->isChecked());
+ if (cmd)
+ {
+ if ( !macroCmd )
+ macroCmd = new KMacroCommand( i18n("Make Text Subscript") );
+ macroCmd->addCommand(cmd);
+ }
+ }
+ if( macroCmd )
+ m_doc->addCommand(macroCmd);
+ if (m_actionFormatSub->isChecked() )
+ m_actionFormatSuper->setChecked( false );
+}
+
+void KWView::changeCaseOfText()
+{
+ QPtrList<KoTextFormatInterface> lst = applicableTextInterfaces();
+ if ( lst.isEmpty() ) return;
+ QPtrListIterator<KoTextFormatInterface> it( lst );
+ KoChangeCaseDia *caseDia=new KoChangeCaseDia( this,"change case" );
+ if(caseDia->exec())
+ {
+ KMacroCommand* macroCmd = 0L;
+ for ( ; it.current() ; ++it )
+ {
+ KCommand *cmd = it.current()->setChangeCaseOfTextCommand(caseDia->getTypeOfCase());
+ if (cmd)
+ {
+ if ( !macroCmd )
+ macroCmd = new KMacroCommand( i18n("Change Case of Text") );
+ macroCmd->addCommand(cmd);
+ }
+ }
+ if( macroCmd )
+ m_doc->addCommand(macroCmd);
+ }
+ delete caseDia;
+}
+
+void KWView::editPersonalExpr()
+{
+ KWEditPersonnalExpression *personalDia=new KWEditPersonnalExpression( this );
+ if(personalDia->exec())
+ m_doc->refreshMenuExpression();
+ delete personalDia;
+}
+
+
+void KWView::textIncreaseIndent()
+{
+ QPtrList<KoTextFormatInterface> lst = applicableTextInterfaces();
+ if ( lst.isEmpty() ) return;
+ QPtrListIterator<KoTextFormatInterface> it( lst );
+ double leftMargin=0.0;
+ if(!lst.isEmpty())
+ leftMargin=lst.first()->currentParagLayoutFormat()->margins[QStyleSheetItem::MarginLeft];
+ double indent = m_doc->indentValue();
+ double newVal = leftMargin + indent;
+ KMacroCommand* macroCmd = 0L;
+ for ( ; it.current() ; ++it )
+ {
+ KCommand *cmd = it.current()->setMarginCommand( QStyleSheetItem::MarginLeft, newVal );
+ if (cmd)
+ {
+ if ( !macroCmd )
+ macroCmd = new KMacroCommand( i18n("Increase Paragraph Depth") );
+ macroCmd->addCommand(cmd);
+ }
+ }
+ if( macroCmd)
+ m_doc->addCommand(macroCmd);
+ if(!lst.isEmpty())
+ {
+ const KoParagLayout *layout=lst.first()->currentParagLayoutFormat();
+ showRulerIndent( layout->margins[QStyleSheetItem::MarginLeft], layout->margins[QStyleSheetItem::MarginFirstLine], layout->margins[QStyleSheetItem::MarginRight], lst.first()->rtl());
+ }
+#if 0
+
+
+ KWTextFrameSetEdit * edit = currentTextEdit();
+ if ( edit )
+ {
+ double leftMargin = edit->currentLeftMargin();
+ double indent = m_doc->indentValue();
+ double newVal = leftMargin + indent;
+ // Test commented out. This breaks with the DTP case... The user can put
+ // a frame anywhere, even closer to the edges than left/right border allows (DF).
+ //if( newVal <= (m_doc->ptPaperWidth()-m_doc->ptRightBorder()-m_doc->ptLeftBorder()))
+ {
+ KCommand *cmd=edit->setMarginCommand( QStyleSheetItem::MarginLeft, newVal );
+ if(cmd)
+ m_doc->addCommand(cmd);
+ }
+ }
+#endif
+}
+
+void KWView::textDecreaseIndent()
+{
+ QPtrList<KoTextFormatInterface> lst = applicableTextInterfaces();
+ if ( lst.isEmpty() ) return;
+ QPtrListIterator<KoTextFormatInterface> it( lst );
+ double leftMargin=0.0;
+ if(!lst.isEmpty())
+ leftMargin=lst.first()->currentParagLayoutFormat()->margins[QStyleSheetItem::MarginLeft];
+ double indent = m_doc->indentValue();
+ double newVal = leftMargin - indent;
+ KMacroCommand* macroCmd = 0L;
+ for ( ; it.current() ; ++it )
+ {
+ KCommand *cmd = it.current()->setMarginCommand( QStyleSheetItem::MarginLeft, QMAX( newVal, 0 ) );
+ if (cmd)
+ {
+ if ( !macroCmd )
+ macroCmd = new KMacroCommand( i18n("Decrease Paragraph Depth") );
+ macroCmd->addCommand(cmd);
+ }
+ }
+ if( macroCmd)
+ m_doc->addCommand(macroCmd);
+ if(!lst.isEmpty())
+ {
+ const KoParagLayout *layout=lst.first()->currentParagLayoutFormat();
+ showRulerIndent( layout->margins[QStyleSheetItem::MarginLeft], layout->margins[QStyleSheetItem::MarginFirstLine], layout->margins[QStyleSheetItem::MarginRight], lst.first()->rtl());
+ }
+
+
+#if 0
+ KWTextFrameSetEdit * edit = currentTextEdit();
+ if ( edit )
+ {
+ double leftMargin = edit->currentLeftMargin();
+ if ( leftMargin > 0 )
+ {
+ double indent = m_doc->indentValue();
+ double newVal = leftMargin - indent;
+ KCommand *cmd=edit->setMarginCommand( QStyleSheetItem::MarginLeft, QMAX( newVal, 0 ) );
+ if(cmd)
+ m_doc->addCommand(cmd);
+ }
+ }
+#endif
+}
+
+
+void KWView::textDefaultFormat()
+{
+ QPtrList<KoTextFormatInterface> lst = applicableTextInterfaces();
+ if ( lst.isEmpty() ) return;
+ QPtrListIterator<KoTextFormatInterface> it( lst );
+ KMacroCommand* macroCmd = 0L;
+ for ( ; it.current() ; ++it )
+ {
+ KCommand *cmd = it.current()->setDefaultFormatCommand();
+ if (cmd)
+ {
+ if ( !macroCmd )
+ macroCmd = new KMacroCommand( i18n("Default Format") );
+ macroCmd->addCommand(cmd);
+ }
+ }
+ if( macroCmd)
+ m_doc->addCommand(macroCmd);
+}
+
+
+void KWView::borderOutline()
+{
+ bool on = m_actionBorderOutline->isChecked();
+ if(m_actionBorderLeft->isChecked() != on) {
+ m_actionBorderLeft->setChecked(on);
+ borderLeft();
+ }
+ if(m_actionBorderRight->isChecked() != on) {
+ m_actionBorderRight->setChecked(on);
+ borderRight();
+ }
+ if(m_actionBorderTop->isChecked() != on) {
+ m_actionBorderTop->setChecked(on);
+ borderTop();
+ }
+ if(m_actionBorderBottom->isChecked() != on) {
+ m_actionBorderBottom->setChecked(on);
+ borderBottom();
+ }
+}
+
+void KWView::borderLeft() {
+ borderChanged(KoBorder::LeftBorder);
+}
+
+void KWView::borderRight() {
+ borderChanged(KoBorder::RightBorder);
+}
+
+void KWView::borderTop() {
+ borderChanged(KoBorder::TopBorder);
+}
+
+void KWView::borderBottom() {
+ borderChanged(KoBorder::BottomBorder);
+}
+
+void KWView::borderChanged(KoBorder::BorderType type) {
+ KoBorder border;
+ border.setPenWidth( m_actionBorderWidth->currentText().toInt() );
+ border.color = m_actionBorderColor->color();
+ border.setStyle( KoBorder::getStyle( m_actionBorderStyle->currentText() ) );
+ bool enabled = false;
+ QString comment;
+ switch(type) {
+ case KoBorder::LeftBorder:
+ enabled = m_actionBorderLeft->isChecked();
+ comment = i18n("Change Left Frame Border");
+ break;
+ case KoBorder::RightBorder:
+ enabled = m_actionBorderRight->isChecked();
+ comment = i18n("Change Right Frame Border");
+ break;
+ case KoBorder::TopBorder:
+ enabled = m_actionBorderTop->isChecked();
+ comment = i18n("Change Top Frame Border");
+ break;
+ case KoBorder::BottomBorder:
+ default:
+ enabled = m_actionBorderBottom->isChecked();
+ comment = i18n("Change Bottom Frame Border");
+ break;
+ }
+ if(!enabled)
+ border.setPenWidth(0);
+
+ KCommand *cmd = 0;
+ KWTextFrameSetEdit *edit = currentTextEdit();
+ if ( edit ) {
+ KoBorder left = edit->border(KoBorder::LeftBorder);
+ KoBorder right = edit->border(KoBorder::RightBorder);
+ KoBorder top = edit->border(KoBorder::TopBorder);
+ KoBorder bottom = edit->border(KoBorder::BottomBorder);
+ if(type == KoBorder::LeftBorder)
+ left = border;
+ else if(type == KoBorder::RightBorder)
+ right = border;
+ else if(type == KoBorder::TopBorder)
+ top = border;
+ else
+ bottom = border;
+ cmd=edit->setBordersCommand( left, right, top, bottom );
+ }
+ else {
+ QPtrList<FrameIndex> indexes;
+ QPtrList<KWFrameBorderCommand::FrameBorderTypeStruct> borders;
+ QValueList<KWFrameView*> selectedFrames = frameViewManager()->selectedFrames();
+ QValueListIterator<KWFrameView*> framesIterator = selectedFrames.begin();
+ for(;framesIterator != selectedFrames.end(); ++framesIterator) {
+ if( !(*framesIterator)->selected() ) continue;
+ KWFrame *frame = (*framesIterator)->frame();
+ indexes.append(new FrameIndex( frame ));
+ KWFrameBorderCommand::FrameBorderTypeStruct *bts =
+ new KWFrameBorderCommand::FrameBorderTypeStruct;
+ bts->m_EFrameType = type;
+ if(type == KoBorder::LeftBorder)
+ bts->m_OldBorder=frame->leftBorder();
+ else if(type == KoBorder::RightBorder)
+ bts->m_OldBorder=frame->rightBorder();
+ else if(type == KoBorder::TopBorder)
+ bts->m_OldBorder=frame->topBorder();
+ else
+ bts->m_OldBorder=frame->bottomBorder();
+ borders.append(bts);
+ }
+ if(indexes.count() > 0)
+ cmd=new KWFrameBorderCommand(comment, indexes, borders, border);
+ }
+ if(cmd) {
+ cmd->execute();
+ m_doc->addCommand( cmd );
+ }
+ // update actions.
+ m_actionBorderOutline->setChecked(
+ m_actionBorderLeft->isChecked() && m_actionBorderRight->isChecked() &&
+ m_actionBorderTop->isChecked() && m_actionBorderBottom->isChecked());
+}
+
+void KWView::backgroundColor()
+{
+ QColor backColor = m_actionBackgroundColor->color();
+ // ### TODO port to applicableTextInterfaces ? Hmm, careful with the "frame" case.
+ KWTextFrameSetEdit *edit = currentTextEdit();
+ if ( m_gui)
+ {
+ if(edit)
+ {
+ KCommand *cmd=edit->setTextBackgroundColorCommand(backColor);
+ if( cmd)
+ m_doc->addCommand( cmd );
+ }
+ else
+ m_gui->canvasWidget()->setFrameBackgroundColor( backColor );
+ }
+}
+
+void KWView::resizeEvent( QResizeEvent *e )
+{
+ QWidget::resizeEvent( e );
+ if ( m_gui )
+ {
+ m_gui->resize( width(), height() );
+ QString s = m_actionViewZoom->currentText();
+ if ( !KoZoomMode::isConstant(s) )
+ viewZoom( s );
+ }
+}
+
+void KWView::guiActivateEvent( KParts::GUIActivateEvent *ev )
+{
+ if ( ev->activated() )
+ {
+ initGui();
+ if (m_doc->isEmbedded() ) {
+ // Get zoom level from KoView, i.e. from the parent view
+ const int zoom = qRound( KoView::zoom() * 100 );
+ setZoom( zoom, true );
+ showZoom( zoom );
+ }
+ }
+ KoView::guiActivateEvent( ev );
+}
+
+void KWView::tabListChanged( const KoTabulatorList & tabList )
+{
+ if(!m_doc->isReadWrite())
+ return;
+ QPtrList<KoTextFormatInterface> lst = applicableTextInterfaces();
+ if ( lst.isEmpty() ) return;
+ QPtrListIterator<KoTextFormatInterface> it( lst );
+ KMacroCommand* macroCmd = 0L;
+ for ( ; it.current() ; ++it )
+ {
+ KCommand *cmd = it.current()->setTabListCommand( tabList );
+ if (cmd)
+ {
+ if ( !macroCmd )
+ macroCmd = new KMacroCommand(i18n("Change Tabulator") );
+ macroCmd->addCommand(cmd);
+ }
+ }
+ if(macroCmd)
+ m_doc->addCommand(macroCmd);
+}
+
+void KWView::newPageLayout( const KoPageLayout &layout )
+{
+ QString mode = viewMode()->type();
+ bool state = (mode!="ModeText");
+ if ( !state )
+ return;
+
+ KoPageLayout pgLayout;
+ KoColumns cl;
+ KoKWHeaderFooter hf;
+ m_doc->getPageLayout( pgLayout, cl, hf );
+
+ if(layout==pgLayout)
+ return;
+
+ KWPageLayoutStruct oldLayout( pgLayout, cl, hf );
+
+ m_doc->setPageLayout( layout, cl, hf );
+
+ KWPageLayoutStruct newLayout( layout, cl, hf );
+
+ KWTextFrameSetEdit *edit = currentTextEdit();
+ if (edit)
+ edit->textFrameSet()->clearUndoRedoInfo();
+ KCommand *cmd = new KWPageLayoutCommand( i18n("Change Layout"), m_doc, oldLayout, newLayout );
+ m_doc->addCommand(cmd);
+}
+
+void KWView::slotPageLayoutChanged( const KoPageLayout& layout )
+{
+ // This is connected to a signal of KWDocument, so that when the
+ // above method, or any other way of changing the page layout happens,
+ // the rulers are updated in all views.
+ viewMode()->setPageLayout( m_gui->getHorzRuler(), m_gui->getVertRuler(), layout );
+ m_gui->canvasWidget()->repaintAll();
+}
+
+void KWView::newFirstIndent( double firstIndent )
+{
+ QPtrList<KoTextFormatInterface> lst = applicableTextInterfaces();
+ if ( lst.isEmpty() ) return;
+ QPtrListIterator<KoTextFormatInterface> it( lst );
+ KMacroCommand* macroCmd = 0L;
+ for ( ; it.current() ; ++it )
+ {
+ KCommand *cmd = it.current()->setMarginCommand( QStyleSheetItem::MarginFirstLine, firstIndent );
+ if (cmd)
+ {
+ if ( !macroCmd )
+ macroCmd = new KMacroCommand(i18n("Change First Line Indent"));
+ macroCmd->addCommand(cmd);
+ }
+ }
+ if(macroCmd)
+ m_doc->addCommand(macroCmd);
+}
+
+void KWView::newLeftIndent( double leftIndent )
+{
+ QPtrList<KoTextFormatInterface> lst = applicableTextInterfaces();
+ if ( lst.isEmpty() ) return;
+ QPtrListIterator<KoTextFormatInterface> it( lst );
+ KMacroCommand* macroCmd = 0L;
+ for ( ; it.current() ; ++it )
+ {
+ KCommand *cmd = it.current()->setMarginCommand( QStyleSheetItem::MarginLeft, leftIndent );
+ if (cmd)
+ {
+ if ( !macroCmd )
+ macroCmd = new KMacroCommand(i18n("Change Indent") );
+ macroCmd->addCommand(cmd);
+ }
+ }
+ if(macroCmd)
+ m_doc->addCommand(macroCmd);
+
+}
+
+void KWView::newRightIndent( double rightIndent)
+{
+
+ QPtrList<KoTextFormatInterface> lst = applicableTextInterfaces();
+ if ( lst.isEmpty() ) return;
+ QPtrListIterator<KoTextFormatInterface> it( lst );
+ KMacroCommand* macroCmd = 0L;
+ for ( ; it.current() ; ++it )
+ {
+ KCommand *cmd = it.current()->setMarginCommand( QStyleSheetItem::MarginRight, rightIndent );
+ if (cmd)
+ {
+ if ( !macroCmd )
+ macroCmd = new KMacroCommand(i18n("Change Indent") );
+ macroCmd->addCommand(cmd);
+ }
+ }
+ if(macroCmd)
+ m_doc->addCommand(macroCmd);
+}
+
+QPopupMenu * KWView::popupMenu( const QString& name )
+{
+ // factory() is 0 when right-clicking on the kword document while
+ // an embedded object is active. KoPartManager lets the click through,
+ // without activating us - so let's do that first.
+ if ( !factory() )
+ partManager()->setActivePart( m_doc, this );
+ Q_ASSERT( factory() );
+ if ( factory() )
+ return ((QPopupMenu*)factory()->container( name, this ));
+ return 0;
+}
+
+void KWView::startKSpell()
+{
+ if ( !m_spell.kospell )
+ m_spell.kospell = new KoSpell( m_broker, this );
+
+ // Spell-check the next paragraph
+ Q_ASSERT( m_spell.textIterator );
+
+ m_spell.kospell->check( m_spell.textIterator, true );
+ delete m_spell.dlg;
+ m_spell.dlg = new KSpell2::Dialog( m_spell.kospell, this );
+ m_spell.dlg->activeAutoCorrect( true );
+
+ QObject::connect( m_spell.dlg, SIGNAL(misspelling(const QString&, int)),
+ this, SLOT(spellCheckerMisspelling(const QString&, int)) );
+ QObject::connect( m_spell.dlg, SIGNAL(replace(const QString&, int, const QString&)),
+ this, SLOT(spellCheckerCorrected(const QString&, int, const QString&)) );
+ QObject::connect( m_spell.dlg, SIGNAL(done(const QString&) ),
+ this, SLOT(spellCheckerDone(const QString&)) );
+ QObject::connect( m_spell.dlg, SIGNAL(cancel() ),
+ this, SLOT( spellCheckerCancel() ) );
+ QObject::connect( m_spell.dlg, SIGNAL(autoCorrect(const QString &, const QString & ) ),
+ this, SLOT( spellAddAutoCorrect (const QString &, const QString &) ) );
+
+ m_spell.dlg->show();
+ //clearSpellChecker();
+}
+
+void KWView::spellCheckerMisspelling( const QString &old, int pos )
+{
+ //kdDebug(32001) << "KWView::spellCheckerMisspelling old=" << old << " pos=" << pos << endl;
+ KoTextObject* textobj = m_spell.kospell->currentTextObject();
+ KoTextParag* parag = m_spell.kospell->currentParag();
+ Q_ASSERT( textobj );
+ Q_ASSERT( parag );
+ if ( !textobj || !parag ) return;
+ KWTextDocument *textdoc=static_cast<KWTextDocument *>( textobj->textDocument() );
+ Q_ASSERT( textdoc );
+ if ( !textdoc ) return;
+ pos += m_spell.kospell->currentStartIndex();
+ kdDebug(32001) << "KWView::spellCheckerMisspelling parag=" << parag->paragId() << " pos=" << pos << " length=" << old.length() << endl;
+ textdoc->textFrameSet()->highlightPortion( parag, pos, old.length(), m_gui->canvasWidget() );
+}
+
+void KWView::spellCheckerCorrected( const QString &old, int pos , const QString &corr )
+{
+ //kdDebug(32001) << "KWView::spellCheckerCorrected old=" << old << " corr=" << corr << " pos=" << pos << endl;
+ KoTextObject* textobj = m_spell.kospell->currentTextObject();
+ KoTextParag* parag = m_spell.kospell->currentParag();
+ Q_ASSERT( textobj );
+ Q_ASSERT( parag );
+ if ( !textobj || !parag ) return;
+ KWTextDocument *textdoc=static_cast<KWTextDocument *>( textobj->textDocument() );
+ Q_ASSERT( textdoc );
+ if ( !textdoc ) return;
+ pos += m_spell.kospell->currentStartIndex();
+ textdoc->textFrameSet()->highlightPortion( parag, pos, old.length(), m_gui->canvasWidget() );
+
+ KoTextCursor cursor( textdoc );
+ cursor.setParag( parag );
+ cursor.setIndex( pos );
+ if(!m_spell.macroCmdSpellCheck)
+ m_spell.macroCmdSpellCheck=new KMacroCommand(i18n("Correct Misspelled Word"));
+ m_spell.macroCmdSpellCheck->addCommand(textobj->replaceSelectionCommand(
+ &cursor, corr, QString::null, KoTextDocument::HighlightSelection));
+}
+
+void KWView::spellCheckerDone( const QString & )
+{
+ //kdDebug(32001) << "KWView::spellCheckerDone" << endl;
+ KWTextDocument *textdoc=static_cast<KWTextDocument *>( m_spell.kospell->textDocument() );
+ Q_ASSERT( textdoc );
+ if ( textdoc )
+ textdoc->textFrameSet()->removeHighlight();
+
+ clearSpellChecker();
+}
+
+void KWView::clearSpellChecker(bool cancelSpellCheck)
+{
+ kdDebug(32001) << "KWView::clearSpellChecker" << endl;
+
+ delete m_spell.textIterator;
+ m_spell.textIterator = 0L;
+ delete m_spell.kospell;
+ m_spell.kospell = 0;
+
+ if ( m_spell.macroCmdSpellCheck )
+ {
+ if ( !cancelSpellCheck )
+ m_doc->addCommand(m_spell.macroCmdSpellCheck);
+ else
+ {
+ //reverte all changes
+ m_spell.macroCmdSpellCheck->unexecute();
+ delete m_spell.macroCmdSpellCheck;
+ }
+ }
+ m_spell.macroCmdSpellCheck=0L;
+ m_spell.replaceAll.clear();
+ //m_doc->setReadWrite(true);
+}
+
+void KWView::spellCheckerCancel()
+{
+ kdDebug()<<"void KWView::spellCheckerCancel() \n";
+ spellCheckerRemoveHighlight();
+ //we add command :( => don't add command and reverte changes
+ clearSpellChecker(true);
+}
+
+
+void KWView::spellCheckerRemoveHighlight()
+{
+ KoTextObject* textobj = m_spell.kospell->currentTextObject();
+ if ( textobj ) {
+ KWTextDocument *textdoc=static_cast<KWTextDocument *>( textobj->textDocument() );
+ if ( textdoc )
+ textdoc->textFrameSet()->removeHighlight();
+ }
+ KWTextFrameSetEdit * edit = currentTextEdit();
+ if (edit)
+ edit->drawCursor( TRUE );
+}
+
+void KWView::spellAddAutoCorrect (const QString & originalword, const QString & newword)
+{
+ m_doc->autoFormat()->addAutoFormatEntry( originalword, newword );
+}
+
+void KWView::configure()
+{
+ KWConfig configDia( this );
+ configDia.exec();
+}
+
+KWTextFrameSetEdit *KWView::currentTextEdit() const
+{
+ if (!m_gui)
+ return 0L;
+ KWFrameSetEdit * edit = m_gui->canvasWidget()->currentFrameSetEdit();
+ if ( edit )
+ return dynamic_cast<KWTextFrameSetEdit *>(edit->currentTextEdit());
+ return 0L;
+}
+
+void KWView::slotFrameSetEditChanged()
+{
+ KWTextFrameSetEdit * edit = currentTextEdit();
+ bool rw = koDocument()->isReadWrite();
+ bool selectedFrames = frameViewManager()->selectedFrames().count() > 0;
+ bool hasSelection = false;
+ if ( edit ) {
+ hasSelection = edit->textFrameSet()->hasSelection();
+ if ( edit->textFrameSet()->textObject()->protectContent())
+ rw = false;
+ }
+ else {
+ KWFrameSetEdit * e = m_gui->canvasWidget()->currentFrameSetEdit();
+ if ( e && e->frameSet()->type() == FT_FORMULA ) {
+ hasSelection = true;
+ }
+ }
+ m_actionEditCut->setEnabled( hasSelection && rw );
+
+ m_actionEditCopy->setEnabled( hasSelection );
+ m_actionEditReplace->setEnabled( /*edit &&*/ rw );
+ clipboardDataChanged(); // for paste
+
+ bool state = (edit != 0 | selectedFrames) && rw;
+ m_actionEditSelectAll->setEnabled(state);
+ m_actionEditSelectCurrentFrame->setEnabled(state);
+ m_actionInsertComment->setEnabled( state );
+ m_actionFormatDefault->setEnabled( state );
+ m_actionFormatFont->setEnabled( state );
+ m_actionFormatFontSize->setEnabled( state );
+ m_actionFormatFontFamily->setEnabled( state );
+ m_actionAddBookmark->setEnabled(state);
+ m_actionBackgroundColor->setEnabled( state );
+ m_actionFormatStyleMenu->setEnabled( state );
+ m_actionFormatBold->setEnabled( state );
+ m_actionFormatItalic->setEnabled( state );
+ m_actionFormatUnderline->setEnabled( state );
+ m_actionFormatStrikeOut->setEnabled( state );
+ m_actionFormatColor->setEnabled( state );
+ m_actionFormatAlignLeft->setEnabled( state );
+ m_actionFormatAlignCenter->setEnabled( state );
+ m_actionFormatAlignRight->setEnabled( state );
+ m_actionFormatAlignBlock->setEnabled( state );
+
+ m_actionBorderLeft->setEnabled( state );
+ m_actionBorderRight->setEnabled( state );
+ m_actionBorderTop->setEnabled( state );
+ m_actionBorderBottom->setEnabled( state );
+ m_actionBorderOutline->setEnabled( state );
+ m_actionBorderColor->setEnabled( state );
+ m_actionBorderWidth->setEnabled( state );
+ m_actionBorderStyle->setEnabled( state );
+
+
+ //m_actionFormatIncreaseIndent->setEnabled(state);
+ m_actionInsertLink->setEnabled(state);
+ m_actionCreateStyleFromSelection->setEnabled( state /*&& hasSelection*/);
+ m_actionConvertToTextBox->setEnabled( state && hasSelection);
+ m_actionAddPersonalExpression->setEnabled( state && hasSelection);
+ m_actionSortText->setEnabled( state && hasSelection);
+ bool goodleftMargin=false;
+ if(state && edit)
+ goodleftMargin=(edit->currentLeftMargin()>0);
+
+ m_actionFormatDecreaseIndent->setEnabled(goodleftMargin);
+ const bool canChangeCounter = rw && ( !edit || !edit->textFrameSet()->isFootEndNote() );
+ m_actionFormatBullet->setEnabled(canChangeCounter);
+ m_actionFormatNumber->setEnabled(canChangeCounter);
+ m_actionFormatStyle->setEnabled(rw);
+ m_actionFormatSpacingSingle->setEnabled(rw);
+ m_actionFormatSpacingOneAndHalf->setEnabled(rw);
+ m_actionFormatSpacingDouble->setEnabled(rw);
+ m_actionFormatSuper->setEnabled(rw);
+ m_actionFormatSub->setEnabled(rw);
+ m_actionFormatParag->setEnabled(state);
+ m_actionInsertSpecialChar->setEnabled(state);
+ m_actionSpellCheck->setEnabled(state);
+
+ m_actionChangeCase->setEnabled( (rw && !edit)|| (state && hasSelection) );
+
+ if ( edit && edit->textFrameSet()->protectContent())
+ {
+ m_actionChangeCase->setEnabled( false );
+ m_actionEditCut->setEnabled( false );
+ }
+ else
+ m_actionChangeCase->setEnabled( true );
+
+ updateTableActions( frameViewManager()->selectedFrames() ) ;
+
+ m_actionInsertFormula->setEnabled(state && (viewMode()->type()!="ModeText"));
+ actionInsertVariable->setEnabled(state);
+ m_actionInsertExpression->setEnabled(state);
+
+ changeFootEndNoteState();
+ //frameset different of header/footer
+ state= state && edit && edit->frameSet() && !edit->frameSet()->isHeaderOrFooter() && !edit->frameSet()->groupmanager() && !edit->frameSet()->isFootEndNote();
+ m_actionInsertContents->setEnabled(state);
+ m_actionInsertFrameBreak->setEnabled( state );
+ updatePageInfo();
+}
+
+void KWView::changeFootEndNoteState()
+{
+ bool rw = koDocument()->isReadWrite();
+ KWTextFrameSetEdit * edit = currentTextEdit();
+ QString mode = viewMode()->type();
+
+ bool isEditableFrameset = edit && edit->frameSet() && edit->frameSet()->isMainFrameset();
+ bool ok = rw && isEditableFrameset && (mode!="ModeText");
+ m_actionInsertFootEndNote->setEnabled( ok );
+ m_actionEditFootEndNote->setEnabled( ok );
+}
+
+void KWView::changeFootNoteMenuItem( bool footnote)
+{
+ m_actionEditFootEndNote->setText( footnote? i18n("Edit Footnote"): i18n("Edit Endnote"));
+ m_actionChangeFootNoteType->setText( footnote? i18n("Change Footnote Parameter"):i18n("Change Endnote Parameter"));
+}
+
+void KWView::slotUpdateRuler()
+{
+ KWCanvas* canvas = m_gui->canvasWidget();
+ QRect r( canvas->viewMode()->rulerFrameRect() );
+ if ( !r.isNull() )
+ {
+ m_gui->getHorzRuler()->setFrameStartEnd( r.left(), r.right() );
+ m_gui->getVertRuler()->setFrameStartEnd( r.top(), r.bottom() );
+ }
+ canvas->updateRulerOffsets();
+}
+
+void KWView::frameSelectedChanged()
+{
+ bool rw = koDocument()->isReadWrite();
+ QValueList<KWFrameView*> selectedFrames = frameViewManager()->selectedFrames();
+
+ m_actionFormatFrameSet->setEnabled( selectedFrames.count() >= 1 );
+ if ( rw && selectedFrames.count() >= 1 )
+ {
+ bool okForDelete = true;
+ bool okForCopy = true;
+ bool okForLowerRaise = false;
+ bool okForChangeParagStyle = true;
+ bool okForChangeInline = true;
+ bool containsCellFrame = false;
+ bool containsMainFrame = false;
+
+ QValueListIterator<KWFrameView*> framesIterator = selectedFrames.begin();
+ while(framesIterator != selectedFrames.end() && (okForDelete || okForLowerRaise ||
+ okForChangeParagStyle || okForChangeInline) ) {
+ // Check we selected no footer nor header
+ bool isFootNote = (*framesIterator)->frame()->frameSet()->isFootEndNote();
+ bool headerFooterFootNote = isFootNote ||
+ (*framesIterator)->frame()->frameSet()->isHeaderOrFooter();
+ bool isMainWPFrame = (*framesIterator)->frame()->frameSet()->isMainFrameset();
+ okForChangeParagStyle &= !isFootNote;
+ okForCopy &= !headerFooterFootNote;
+
+ okForDelete &= !headerFooterFootNote;
+ okForDelete &= !isMainWPFrame;
+
+ // Check we selected a frame we can lower raise.
+ // The header, footer, main frameset, footnotes and inline frames can't be raised.
+ // As soon as we find one who we can lower/raise open the option.
+ okForLowerRaise |= !(isMainWPFrame || headerFooterFootNote || (*framesIterator)->frame()->frameSet()->isFloating());
+ okForChangeInline &= !(isMainWPFrame || headerFooterFootNote );
+
+ if ( (*framesIterator)->frame()->frameSet()->groupmanager() )
+ containsCellFrame = true;
+ if ( isMainWPFrame )
+ containsMainFrame = true;
+ ++framesIterator;
+ }
+ m_actionEditDelFrame->setEnabled( okForDelete );
+ m_actionEditCut->setEnabled( okForDelete && !containsCellFrame );
+ m_actionEditCopy->setEnabled( selectedFrames.count() >= 1 && okForCopy && !containsMainFrame && !containsCellFrame);
+
+ m_actionLowerFrame->setEnabled( okForLowerRaise );
+ m_actionRaiseFrame->setEnabled( okForLowerRaise );
+ m_actionSendBackward->setEnabled( okForLowerRaise );
+ m_actionBringToFront->setEnabled( okForLowerRaise );
+ m_actionFormatBullet->setEnabled( okForChangeParagStyle );
+ m_actionFormatNumber->setEnabled( okForChangeParagStyle );
+ m_actionFormatStyle->setEnabled( okForChangeParagStyle);
+ m_actionInlineFrame->setEnabled( okForChangeInline);
+
+ KWFrame *frame = selectedFrames[0]->frame();
+ updateBorderButtons(frame->leftBorder(), frame->rightBorder(), frame->topBorder(),
+ frame->bottomBorder());
+ } else
+ { // readonly document, or no frame selected -> disable
+ m_actionEditDelFrame->setEnabled( false );
+ m_actionInlineFrame->setEnabled(false);
+ m_actionEditCut->setEnabled( false );
+ m_actionLowerFrame->setEnabled( false );
+ m_actionRaiseFrame->setEnabled( false );
+ m_actionSendBackward->setEnabled( false );
+ m_actionBringToFront->setEnabled( false );
+
+ }
+ bool frameDifferentOfPart=false;
+ if(selectedFrames.count() >= 1)
+ {
+ QValueListIterator<KWFrameView*> framesIterator = selectedFrames.begin();
+ while(framesIterator != selectedFrames.end()) {
+ if ( (*framesIterator)->frame()->frameSet()->type()!=FT_PART &&
+ (*framesIterator)->frame()->frameSet()->type()!= FT_PICTURE) {
+ frameDifferentOfPart=true;
+ break;
+ }
+ ++framesIterator;
+ }
+ }
+
+ m_actionBackgroundColor->setEnabled( (selectedFrames.count() >= 1) && frameDifferentOfPart);
+ m_actionBackgroundColor->setText(i18n("Frame Background Color..."));
+
+ if ( frameDifferentOfPart ) {
+ KWFrame *frame = selectedFrames[0]->frame();
+ QColor frameCol=frame->backgroundColor().color();
+ //m_actionBackgroundColor->setText(i18n("Frame Background Color..."));
+ m_actionBackgroundColor->setCurrentColor( frameCol.isValid()? frame->backgroundColor().color() : QApplication::palette().color( QPalette::Active, QColorGroup::Base ));
+ }
+
+ m_actionCreateFrameStyle->setEnabled( selectedFrames.count()==1 );
+ m_actionCreateLinkedFrame->setEnabled( selectedFrames.count()==1 );
+
+ updateTableActions( selectedFrames );
+ updatePageInfo(); // takes care of slotUpdateRuler()
+ updateFrameStatusBarItem();
+
+ QPtrList<KoTextFormatInterface> lst = applicableTextInterfaces();
+ if ( !lst.isEmpty() )
+ {
+ QPtrListIterator<KoTextFormatInterface> it( lst );
+ KoTextFormat format=*(lst.first()->currentFormat());
+ showFormat( format );
+
+ const KoParagLayout * paragLayout=lst.first()->currentParagLayoutFormat();
+ KoParagCounter counter;
+ if(paragLayout->counter)
+ counter = *(paragLayout->counter);
+ showCounter( counter );
+ int align = paragLayout->alignment;
+ if ( align == Qt::AlignAuto )
+ align = Qt::AlignLeft; // ## seems hard to detect RTL here
+ showAlign( align );
+ KoParagLayout::SpacingType spacing=paragLayout->lineSpacingType;
+ showSpacing( spacing );
+ }
+
+ m_gui->canvasWidget()->repaintAll(false);
+}
+
+
+void KWView::updateTableActions( QValueList<KWFrameView*> selectedFrames)
+{
+ TableInfo ti(selectedFrames);
+ KWTableFrameSet *table = m_gui->canvasWidget()->getCurrentTable();
+ m_actionTableJoinCells->setEnabled( ti.tableCellsSelected());
+ m_actionConvertTableToText->setEnabled( table && table->isFloating() );
+
+ m_actionTableSplitCells->setEnabled( ti.oneCellSelected() );
+
+ m_actionTableInsertRow->setEnabled( ti.amountRowsSelected() );
+ m_actionTableDelRow->setEnabled( ti.amountRowsSelected() );
+ m_actionTableInsertCol->setEnabled( ti.amountColumnsSelected() );
+
+ if(ti.amountColumnsSelected() == 1)
+ m_actionTableDelCol->setText(i18n("D&elete Current Column..."));
+ else
+ m_actionTableDelCol->setText(i18n("D&elete Selected Columns..."));
+ m_actionTableDelCol->setEnabled( ti.amountColumnsSelected() > 0 );
+ if(ti.amountRowsSelected() == 1)
+ m_actionTableDelRow->setText(i18n("&Delete Current Row..."));
+ else
+ m_actionTableDelRow->setText(i18n("&Delete Selected Rows..."));
+ m_actionTableDelRow->setEnabled( ti.amountRowsSelected() > 0 );
+
+ m_actionTableResizeCol->setEnabled( ti.tableCellsSelected() );
+ m_actionTableDelete->setEnabled( ti.tableCellsSelected() );
+ m_actionTablePropertiesMenu->setEnabled( ti.tableCellsSelected() );
+
+ m_actionTableUngroup->setEnabled( ti.tableCellsSelected() );
+ m_actionTableProtectCells->setEnabled( ti.tableCellsSelected() );
+ m_actionTableProtectCells->setChecked( ti.protectContentEnabled() );
+}
+
+void KWView::docStructChanged(int type)
+{
+ KWDocStruct *m_pDocStruct=m_gui->getDocStruct();
+ if(m_pDocStruct)
+ m_pDocStruct->refreshTree(type);
+ m_doc->recalcVariables( VT_STATISTIC );
+}
+
+void KWView::documentModified( bool b )
+{
+ if ( !statusBar() )
+ return;
+
+ if ( b )
+ m_sbModifiedLabel->setPixmap( KGlobal::iconLoader()->loadIcon( "action-modified", KIcon::Small ) );
+ else
+ m_sbModifiedLabel->setText( " " );
+}
+
+void KWView::changeOverwriteMode( bool b )
+{
+ if ( !statusBar() )
+ return;
+
+ if ( b )
+ m_sbOverwriteLabel->setText( ' ' + i18n( "OVER" ) + ' ' );
+ else
+ m_sbOverwriteLabel->setText( ' ' + i18n( "INSRT" ) + ' ' );
+}
+
+void KWView::setViewFrameBorders(bool b)
+{
+ m_viewFrameBorders = b;
+ // Store setting in doc, for further views and for saving
+ m_doc->setViewFrameBorders( b );
+}
+
+bool KWView::doubleClickActivation() const
+{
+ return TRUE;
+}
+
+QWidget* KWView::canvas() const
+{
+ // used to be ->viewport(), but this makes no sense.
+ // active embedded objects must be positioned relative to the real view,
+ // to scroll around with it, instead of being children of the fixed viewport.
+ return m_gui->canvasWidget();
+}
+
+int KWView::canvasXOffset() const
+{
+ return m_gui->canvasWidget()->contentsX();
+}
+
+int KWView::canvasYOffset() const
+{
+ return m_gui->canvasWidget()->contentsY();
+}
+
+void KWView::canvasAddChild( KoViewChild * child )
+{
+ connect( m_gui->canvasWidget(), SIGNAL( viewTransformationsChanged() ),
+ child, SLOT( reposition() ) );
+ // Not necessary anymore
+ //m_gui->canvasWidget()->addChild( child->frame() );
+}
+
+void KWView::changePicture()
+{
+ KWFrameView *view = frameViewManager()->selectedFrame();
+ KWFrame *frame = view == 0 ? 0 : view->frame();
+ if( !frame )
+ return;
+ KWPictureFrameSet *frameset = static_cast<KWPictureFrameSet *>(frame->frameSet());
+ KoPictureKey oldKey ( frameset->picture().getKey() );
+ QString oldFile ( oldKey.filename() );
+ KURL url;
+ url.setPath( oldFile );
+ if (!QDir(url.directory()).exists())
+ oldFile = url.fileName();
+
+ KoPicture picture ( KWInsertPicDia::selectPictureDia( oldFile, this ) );
+ if ( !picture.isNull() )
+ {
+ KWFrameChangePictureCommand *cmd= new KWFrameChangePictureCommand( i18n("Change Picture"), FrameIndex(frame), oldKey, picture.getKey() ) ;
+
+ frameset->insertPicture( picture );
+ m_doc->frameChanged( frame );
+ m_doc->refreshDocStructure( FT_PICTURE );
+ m_doc->addCommand(cmd);
+ }
+ else
+ kdDebug() << "KWView::changePicture cancelled" << endl;
+}
+
+void KWView::savePicture()
+{
+ KWFrameView *view = frameViewManager()->selectedFrame();
+ KWFrame *frame = view == 0 ? 0 : view->frame();
+ if ( frame )//test for dcop call
+ {
+ KWPictureFrameSet *frameset = static_cast<KWPictureFrameSet *>(frame->frameSet());
+ QString oldFile = frameset->picture().getKey().filename();
+ KURL url;
+ url.setPath( oldFile );
+ if ( !QDir(url.directory()).exists() )
+ oldFile = url.fileName();
+
+ KoPicture picture( frameset->picture() );
+ QString mimetype = picture.getMimeType();
+ kdDebug() << "Picture has mime type: " << mimetype << endl;
+ QStringList mimetypes;
+ mimetypes << mimetype;
+ KFileDialog fd( oldFile, QString::null, this, 0, TRUE );
+ fd.setMimeFilter( mimetypes );
+ fd.setCaption(i18n("Save Picture"));
+ fd.setOperationMode(KFileDialog::Saving);
+ if ( fd.exec() == QDialog::Accepted )
+ {
+ url = fd.selectedURL();
+ if ( url.isValid() )
+ {
+ if ( url.isLocalFile() )
+ {
+ QFile file( url.path() );
+ if ( file.open( IO_ReadWrite ) )
+ {
+ picture.save( &file );
+ file.close();
+ }
+ else
+ {
+ KMessageBox::error(this,
+ i18n("Error during saving. Could not open '%1' for writing").arg ( url.path() ),
+ i18n("Save Picture"));
+ }
+ }
+ else
+ {
+ KTempFile tempFile;
+ tempFile.setAutoDelete( true );
+ if ( tempFile.status() == 0 )
+ {
+ QFile file( tempFile.name() );
+ if ( file.open( IO_ReadWrite ) )
+ {
+ picture.save( &file );
+ file.close();
+ if ( !KIO::NetAccess::upload( tempFile.name(), url, this ) )
+ {
+ KMessageBox::sorry( this, i18n(
+ "Unable to save the file to '%1'. %2.").arg( url.prettyURL() ).arg( KIO::NetAccess::lastErrorString() ),
+ i18n("Save Failed") );
+ }
+ }
+ else
+ KMessageBox::error(this,
+ i18n("Error during saving. Could not open '%1' temporary file for writing").arg ( file.name() ),
+ i18n("Save Picture"));
+ }
+ else
+ KMessageBox::sorry( this, i18n(
+ "Error during saving. Could not create temporary file: %1.").arg( strerror( tempFile.status() ) ),
+ i18n("Save Picture") );
+ }
+ }
+ else
+ KMessageBox::sorry( this, i18n("URL %1 is invalid.").arg( url.prettyURL() ), i18n("Save Picture") );
+ }
+ }
+}
+
+void KWView::configureHeaderFooter()
+{
+ KoPageLayout pgLayout;
+ KoColumns cl;
+ KoKWHeaderFooter kwhf;
+ m_doc->getPageLayout( pgLayout, cl, kwhf );
+
+ KWPageLayoutStruct oldLayout( pgLayout, cl, kwhf );
+
+ KoHeadFoot hf;
+ int flags = KW_HEADER_AND_FOOTER;
+ KoUnit::Unit unit = m_doc->unit();
+ KoUnit::Unit oldUnit = unit;
+
+ if ( KoPageLayoutDia::pageLayout( pgLayout, hf, cl, kwhf, flags, unit ) ) {
+ if( oldLayout._hf != kwhf )
+ {
+ KWPageLayoutStruct newLayout( pgLayout, cl, kwhf );
+
+ KCommand *cmd = new KWPageLayoutCommand( i18n("Change Layout"), m_doc,
+ oldLayout, newLayout );
+ m_doc->addCommand(cmd);
+
+ m_doc->setPageLayout( pgLayout, cl, kwhf );
+ }
+ if ( unit != oldUnit )
+ m_doc->setUnit( unit ); // needs undo/redo support
+ }
+
+}
+
+void KWView::inlineFrame()
+{
+ KWFrameView *view = frameViewManager()->selectedFrame();
+ KWFrame *frame = view == 0 ? 0 : view->frame();
+ if( !frame)
+ return;
+ KWFrameSet * fs = frame->frameSet();
+ KWFrameSet * parentFs = fs->groupmanager() ? fs->groupmanager() : fs;
+
+ if(m_actionInlineFrame->isChecked())
+ {
+
+ KMacroCommand* macroCmd = new KMacroCommand( i18n("Make Frameset Inline") );
+ QValueList<FrameIndex> frameindexList;
+ QValueList<FrameMoveStruct> frameindexMove;
+
+ KoPoint initialPos = frame->topLeft();
+ // turn non-floating frame into floating frame
+ KWFrameSetInlineCommand *cmd = new KWFrameSetInlineCommand( i18n("Make Frameset Inline"), parentFs, true );
+ cmd->execute();
+
+ frameindexList.append( FrameIndex( frame ) );
+ frameindexMove.append( FrameMoveStruct( initialPos, frame->topLeft() ) );
+
+ KWFrameMoveCommand *cmdMoveFrame = new KWFrameMoveCommand( i18n("Move Frame"), frameindexList, frameindexMove );
+
+ macroCmd->addCommand(cmdMoveFrame);
+ macroCmd->addCommand(cmd);
+ m_doc->addCommand(macroCmd);
+ }
+ else
+ {
+ KWFrameSetInlineCommand *cmd = new KWFrameSetInlineCommand( i18n("Make Frameset Non-Inline"), parentFs, false );
+ m_doc->addCommand(cmd);
+ cmd->execute();
+ }
+}
+
+void KWView::openLink()
+{
+ KWTextFrameSetEdit * edit = currentTextEdit();
+ if ( edit )
+ edit->openLink();
+}
+
+void KWView::changeLink()
+{
+ KWTextFrameSetEdit * edit = currentTextEdit();
+ if ( edit )
+ {
+ KoLinkVariable * var=edit->linkVariable();
+ if(var)
+ {
+ QString oldhref= var->url();
+ QString oldLinkName=var->value();
+ QString link=oldLinkName;
+ QString ref=oldhref;
+ if(KoInsertLinkDia::createLinkDia(link, ref, m_doc->listOfBookmarkName(0), true, this))
+ {
+ if(!link.isEmpty() && !ref.isEmpty())
+ {
+ if( ref != oldhref || link!=oldLinkName)
+ {
+ KWChangeLinkVariable*cmd=new KWChangeLinkVariable( i18n("Change Link"), m_doc,oldhref, ref, oldLinkName,link, var);
+ cmd->execute();
+ m_doc->addCommand(cmd);
+ }
+ }
+ }
+ }
+ }
+}
+
+void KWView::copyLink()
+{
+ KWTextFrameSetEdit * edit = currentTextEdit();
+ if ( edit )
+ edit->copyLink();
+}
+
+void KWView::removeLink()
+{
+ KWTextFrameSetEdit * edit = currentTextEdit();
+ if ( edit )
+ edit->removeLink();
+}
+
+void KWView::addToBookmark()
+{
+ KWTextFrameSetEdit * edit = currentTextEdit();
+ if ( edit )
+ {
+ KoLinkVariable * var=edit->linkVariable();
+ if(var)
+ {
+ edit->addBookmarks(var->url());
+ }
+ }
+}
+
+void KWView::showDocStructure()
+{
+ m_doc->setShowDocStruct(m_actionShowDocStruct->isChecked());
+ m_doc->reorganizeGUI();
+ QTimer::singleShot( 0, this, SLOT( updateZoom() ) );
+}
+
+void KWView::showRuler()
+{
+ m_doc->setShowRuler( m_actionShowRuler->isChecked());
+ m_doc->reorganizeGUI();
+ QTimer::singleShot( 0, this, SLOT( updateZoom() ) );
+}
+
+void KWView::viewGrid()
+{
+ m_doc->setShowGrid( m_actionViewShowGrid->isChecked() );
+ m_doc->setModified( true );
+ m_doc->updateGridButton();
+ m_doc->repaintAllViews(false);
+}
+
+void KWView::viewSnapToGrid()
+{
+ m_doc->setSnapToGrid( m_actionViewSnapToGrid->isChecked() );
+ m_doc->setModified( true );
+ m_doc->updateGridButton();
+}
+
+void KWView::slotSoftHyphen()
+{
+ KWTextFrameSetEdit * edit = currentTextEdit();
+ if ( edit )
+ edit->insertSoftHyphen();
+}
+
+void KWView::slotNonbreakingSpace()
+{
+ KWTextFrameSetEdit * edit = currentTextEdit();
+ if ( edit )
+ edit->insertNonbreakingSpace();
+}
+
+void KWView::slotNonbreakingHyphen()
+{
+ KWTextFrameSetEdit * edit = currentTextEdit();
+ if ( edit )
+ edit->insertNonbreakingHyphen();
+}
+
+void KWView::slotLineBreak()
+{
+ KWTextFrameSetEdit * edit = currentTextEdit();
+ if ( edit )
+ edit->insertLineBreak();
+}
+
+void KWView::slotIncreaseNumberingLevel()
+{
+ KWTextFrameSetEdit * edit = currentTextEdit();
+ if ( edit )
+ edit->increaseNumberingLevel( m_doc->styleCollection() );
+}
+
+void KWView::slotDecreaseNumberingLevel()
+{
+ KWTextFrameSetEdit * edit = currentTextEdit();
+ if ( edit )
+ edit->decreaseNumberingLevel( m_doc->styleCollection() );
+}
+
+void KWView::refreshAllVariable()
+{
+ m_doc->recalcVariables( VT_ALL );
+}
+
+void KWView::slotAllowAutoFormat()
+{
+ bool state = m_actionAllowAutoFormat->isChecked();
+ m_doc->setAllowAutoFormat( state );
+}
+
+void KWView::slotCompletion()
+{
+ KWTextFrameSetEdit * edit = currentTextEdit();
+ if ( edit )
+ edit->completion();
+}
+
+void KWView::updateHeaderFooterButton()
+{
+ m_actionViewHeader->setChecked(m_doc->isHeaderVisible());
+ m_actionViewFooter->setChecked(m_doc->isFooterVisible());
+}
+
+void KWView::editComment()
+{
+ KWTextFrameSetEdit * edit = currentTextEdit();
+ if ( edit )
+ {
+ KoVariable * tmpVar=edit->variable();
+ KoNoteVariable * var = dynamic_cast<KoNoteVariable *>(tmpVar);
+ if(var)
+ {
+ QString authorName;
+ KoDocumentInfo * info = m_doc->documentInfo();
+ KoDocumentInfoAuthor * authorPage = static_cast<KoDocumentInfoAuthor *>(info->page( "author" ));
+ if ( !authorPage )
+ kdWarning() << "Author information not found in documentInfo !" << endl;
+ else
+ authorName = authorPage->fullName();
+ QString oldValue = var->note();
+ QString createDate = var->createdNote();
+ KoCommentDia *commentDia = new KoCommentDia( this, oldValue, authorName, createDate);
+ if( commentDia->exec() )
+ {
+ if ( oldValue != commentDia->commentText())
+ {
+ KWChangeVariableNoteText *cmd = new KWChangeVariableNoteText( i18n("Change Note Text"), m_doc, oldValue,commentDia->commentText(), var);
+ m_doc->addCommand( cmd );
+ cmd->execute();
+ }
+ }
+ delete commentDia;
+ }
+ }
+}
+
+void KWView::fileStatistics()
+{
+ KWStatisticsDialog *statisticsDialog = new KWStatisticsDialog( this, m_doc );
+ if ( !statisticsDialog->wasCanceled() )
+ statisticsDialog->exec();
+ delete statisticsDialog;
+}
+
+void KWView::removeComment()
+{
+ KWTextFrameSetEdit * edit = currentTextEdit();
+ if ( edit )
+ {
+ edit->removeComment();
+ }
+}
+
+void KWView::copyTextOfComment()
+{
+ KWTextFrameSetEdit * edit = currentTextEdit();
+ if ( edit )
+ {
+ edit->copyTextOfComment();
+ }
+}
+
+void KWView::configureCompletion()
+{
+ m_doc->autoFormat()->readConfig();
+ KoCompletionDia dia( this, 0, m_doc->autoFormat() );
+ dia.exec();
+}
+
+void KWView::applyAutoFormat()
+{
+ m_doc->autoFormat()->readConfig();
+ KMacroCommand *macro = 0L;
+ QValueList<KoTextObject *> list(m_doc->visibleTextObjects(viewMode()));
+ QValueList<KoTextObject *>::Iterator fit = list.begin();
+ for ( ; fit != list.end() ; ++fit )
+ {
+ KCommand *cmd = m_doc->autoFormat()->applyAutoFormat( *fit );
+ if ( cmd )
+ {
+ if ( !macro )
+ macro = new KMacroCommand( i18n("Apply Autoformat"));
+ macro->addCommand( cmd );
+ }
+ }
+ if ( macro )
+ m_doc->addCommand( macro );
+}
+
+void KWView::createStyleFromSelection()
+{
+ KWTextFrameSetEdit * edit = currentTextEdit();
+ if ( edit )
+ {
+ KoStyleCollection* coll = m_doc->styleCollection();
+ KoCreateStyleDia *dia = new KoCreateStyleDia( QStringList(), this, 0 );
+ if ( dia->exec() )
+ {
+ QString name = dia->nameOfNewStyle();
+ KoParagStyle* style = coll->findStyleByDisplayName( name );
+ if ( style ) // update existing style
+ {
+ // TODO confirmation message box
+ edit->updateStyleFromSelection( style );
+ }
+ else // create new style
+ {
+ style = edit->createStyleFromSelection( name );
+ m_doc->styleCollection()->addStyle( style );
+ m_doc->updateAllStyleLists();
+ }
+ showStyle( name );
+ }
+ delete dia;
+ }
+}
+
+// Initially called by initGUIButton
+void KWView::switchModeView()
+{
+ KWCanvas* canvas = m_gui->canvasWidget();
+ slotUpdateRuler();
+
+ // Now update the actions appropriately
+ QString mode = canvas->viewMode()->type();
+ bool isTextMode = mode == "ModeText";
+ bool state = !isTextMode;
+ m_actionToolsCreateText->setEnabled(state);
+ m_actionToolsCreatePix->setEnabled(state);
+ m_actionToolsCreatePart->setEnabled(state);
+ m_actionInsertFormula->setEnabled(state);
+ m_actionInsertTable->setEnabled(state);
+ changeFootEndNoteState();
+ m_actionViewFooter->setEnabled( state && m_doc->processingType() == KWDocument::WP );
+ m_actionViewHeader->setEnabled( state && m_doc->processingType() == KWDocument::WP );
+ //m_actionViewTextMode->setEnabled(m_doc->processingType()==KWDocument::WP);
+ m_actionShowDocStruct->setEnabled(state);
+ m_actionFormatPage->setEnabled(state);
+ m_actionInsertContents->setEnabled( state );
+ m_actionFrameStyle->setEnabled( state );
+ m_actionTableStyle->setEnabled ( state );
+ m_actionViewShowGrid->setEnabled( state );
+ m_actionViewSnapToGrid->setEnabled( mode == "ModeNormal" || mode == "ModeEmbedded" ); // TODO fix snapping in preview mode
+ if ( m_gui->getHorzRuler())
+ {
+ m_gui->getHorzRuler()->setPageLayoutMenuItemEnabled( state );
+ if ( !koDocument()->isReadWrite())
+ m_gui->getHorzRuler()->changeFlags( KoRuler::F_NORESIZE );
+ else
+ {
+ if ( state )
+ m_gui->getHorzRuler()->changeFlags( m_gui->getHorzRuler()->flags() & ~(KoRuler::F_NORESIZE) );
+ else
+ m_gui->getHorzRuler()->changeFlags( m_gui->getHorzRuler()->flags() | KoRuler::F_NORESIZE );
+ }
+ }
+ if ( m_gui->getVertRuler() )
+ {
+ m_gui->getVertRuler()->setPageLayoutMenuItemEnabled( state );
+ if ( !koDocument()->isReadWrite())
+ m_gui->getVertRuler()->changeFlags( KoRuler::F_NORESIZE );
+ else
+ {
+ if ( state )
+ m_gui->getVertRuler()->changeFlags( m_gui->getVertRuler()->flags() & ~(KoRuler::F_NORESIZE) );
+ else
+ m_gui->getVertRuler()->changeFlags( m_gui->getVertRuler()->flags() | KoRuler::F_NORESIZE );
+
+ }
+ }
+
+ if ( isTextMode )
+ {
+ if ( m_doc->showdocStruct() )
+ {
+ m_doc->setShowDocStruct(false);
+ m_doc->reorganizeGUI();
+ }
+ }
+ else
+ {
+ m_doc->setShowDocStruct(m_actionShowDocStruct->isChecked());
+ m_doc->reorganizeGUI();
+ }
+ //recalc pgnum variable when we swith viewmode
+ //because in text mode view we display field code and not value
+ //normal because we don't have real page in this mode
+ m_doc->recalcVariables( VT_PGNUM );
+ if ( isTextMode )
+ {
+ // Make sure we edit the same frameset as the one shown in the textview ;-)
+ canvas->editFrameSet( static_cast<KWViewModeText* >(canvas->viewMode())->textFrameSet() );
+
+ }
+ //remove/add "zoom to page". Not necessary in text mode view.
+ updateZoomControls();
+
+ updatePageInfo();
+ // set page layout in rulers
+ canvas->viewMode()->setPageLayout( m_gui->getHorzRuler(), m_gui->getVertRuler(), m_doc->pageLayout() );
+}
+
+void KWView::configureFootEndNote()
+{
+ KWConfigFootNoteDia *dia = new KWConfigFootNoteDia( this, "configfootnote", m_doc );
+ dia->exec();
+ delete dia;
+}
+
+void KWView::editFootEndNote()
+{
+ KWTextFrameSetEdit * edit = currentTextEdit();
+ if ( edit )
+ {
+ KWFootNoteVariable * var = dynamic_cast<KWFootNoteVariable *>( edit->variable() );
+ if ( var && var->frameSet() )
+ {
+ m_gui->canvasWidget()->editFrameSet( var->frameSet() );
+ KWTextFrameSetEdit* textedit = currentTextEdit();
+ if ( textedit )
+ textedit->ensureCursorVisible();
+ }
+ }
+}
+
+void KWView::changeFootNoteType()
+{
+ KWTextFrameSetEdit * edit = currentTextEdit();
+ if ( edit )
+ {
+ KoVariable * tmpVar=edit->variable();
+ KWFootNoteVariable * var = dynamic_cast<KWFootNoteVariable *>(tmpVar);
+ if(var && var->frameSet())
+ {
+ KWFootNoteDia dia( var->noteType(), var->numberingType(), (var->numberingType()==KWFootNoteVariable::Auto) ? QString::null : var->manualString(), this, m_doc, 0 );
+ QPtrListIterator<KoTextCustomItem> it( edit->textDocument()->allCustomItems() );
+ for ( ; it.current() ; ++it )
+ {
+ KWFootNoteVariable *fnv = dynamic_cast<KWFootNoteVariable *>( it.current() );
+ if (fnv && !fnv->isDeleted() && fnv->frameSet() && !fnv->frameSet()->isDeleted() &&
+ fnv->numberingType()==KWFootNoteVariable::Manual && fnv != var)
+ dia.appendManualFootNote( fnv->text() );
+ }
+ if ( dia.exec() )
+ {
+ FootNoteParameter oldParam( var );
+ FootNoteParameter newParam(dia.noteType(), dia.numberingType(), dia.manualString() );
+ KWChangeFootNoteParametersCommand * cmd = new KWChangeFootNoteParametersCommand( i18n("Change Footnote Parameters"), var , oldParam, newParam, m_doc);
+ cmd->execute();
+ m_doc->addCommand ( cmd );
+ }
+ }
+ }
+}
+
+
+void KWView::autoSpellCheck()
+{
+ autoSpellCheck( m_actionAllowBgSpellCheck->isChecked() );
+}
+
+void KWView::autoSpellCheck(bool b)
+{
+ m_doc->changeBgSpellCheckingState( b );
+}
+
+void KWView::goToFootEndNote()
+{
+ KWFrameView *view = frameViewManager()->selectedFrame();
+ KWFrame *frame = view == 0 ? 0 : view->frame();
+ if( !frame)
+ return;
+ KWFootNoteFrameSet *footNoteFrameSet = dynamic_cast<KWFootNoteFrameSet *>(frame->frameSet());
+ if ( footNoteFrameSet )
+ {
+ KWFootNoteVariable* var=footNoteFrameSet->footNoteVariable();
+ KoTextParag *parag = var->paragraph();
+ int index = var->index();
+ KWTextDocument *textDoc = static_cast<KWTextDocument *>(var->textDocument());
+ KWTextFrameSet *frameSet =textDoc->textFrameSet();
+ m_gui->canvasWidget()->editTextFrameSet( frameSet, parag, index );
+ }
+}
+
+void KWView::openDocStructurePopupMenu( const QPoint &p, KWFrameSet *frameset, KWTextParag *parag)
+{
+ bool rw = koDocument()->isReadWrite();
+ bool kttsdInstalled = KoSpeaker::isKttsdInstalled();
+ if (!rw && !kttsdInstalled)
+ return;
+ bool hasText = (frameset->type()==FT_TEXT || frameset->type()==FT_TABLE || frameset->type()==FT_FORMULA );
+
+ m_actionDocStructEdit->setEnabled( rw && hasText );
+ m_actionDocStructDelete->setEnabled( (rw && !parag && !frameset->isMainFrameset() &&
+ !frameset->isFootEndNote() && !frameset->isHeaderOrFooter()) );
+ m_actionDocStructSpeak->setEnabled( hasText && kttsdInstalled );
+
+ QPopupMenu* popup = static_cast<QPopupMenu *>(factory()->container("docstruct_popup",this));
+ if ( popup )
+ popup->exec(p);
+}
+
+void KWView::docStructSelect()
+{
+ if ( m_gui->getDocStruct() )
+ {
+ m_gui->getDocStruct()->selectItem();
+ }
+}
+
+void KWView::docStructEdit()
+{
+ if ( m_gui->getDocStruct() )
+ {
+ m_gui->getDocStruct()->editItem();
+ //return focus to canvas.
+ m_gui->canvasWidget()->setFocus();
+ }
+}
+
+void KWView::docStructProperties()
+{
+ if ( m_gui->getDocStruct() )
+ {
+ m_gui->getDocStruct()->editProperties();
+ }
+}
+
+void KWView::docStructDelete()
+{
+ if ( m_gui->getDocStruct() )
+ {
+ m_gui->getDocStruct()->deleteItem();
+ }
+}
+
+void KWView::docStructSpeak()
+{
+ if ( m_gui->getDocStruct() )
+ {
+ m_gui->getDocStruct()->speakItem();
+ }
+}
+
+void KWView::insertFile()
+{
+ KFileDialog fd( QString::null, QString::null, this, 0, TRUE );
+ fd.setMimeFilter( "application/x-kword" );
+ fd.setCaption(i18n("Insert File"));
+ KURL url;
+ if ( fd.exec() != QDialog::Accepted )
+ return;
+ url = fd.selectedURL();
+ if( url.isEmpty() )
+ {
+ KMessageBox::sorry( this,
+ i18n("File name is empty."),
+ i18n("Insert File"));
+ return;
+ }
+ insertFile( url );
+}
+
+void KWView::insertFile(const KURL& url)
+{
+ KMacroCommand* macroCmd = 0L;
+ bool hasFixedFramesets = false;
+ KoStore* store=KoStore::createStore( this, url, KoStore::Read );
+
+ // TODO: this code only supports KWord-1.3 stores, it needs to support OASIS too.
+
+ // ###### All of this should be ported to use the pasting code instead.
+
+ QString maindoc = "maindoc.xml";
+ if ( store )
+ {
+ // We need to load the pictures before we treat framesets
+ // because KWDocument::pasteFrames() calls processPictureRequests().
+ bool b = store->open(maindoc);
+ if ( !b )
+ {
+ KMessageBox::sorry( this,
+ i18n("This file is not a KWord file!"),
+ i18n("Insert File"));
+ delete store;
+ return;
+ }
+
+ QDomDocument doc;
+ doc.setContent( store->device() );
+ QDomElement word = doc.documentElement();
+
+ m_doc->loadPictureMap( word );
+ store->close();
+ m_doc->loadImagesFromStore( store );
+ }
+ if ( store )
+ {
+ bool b = store->open(maindoc);
+ if ( !b )
+ {
+ KMessageBox::sorry( this,
+ i18n("File name is not a KWord file!"),
+ i18n("Insert File"));
+ delete store;
+ return;
+ }
+ QDomDocument doc;
+ doc.setContent( store->device() );
+ QDomElement word = doc.documentElement();
+
+ QDomElement framesets = word.namedItem( "FRAMESETS" ).toElement();
+ if ( !framesets.isNull() )
+ {
+ QDomElement framesetElem = framesets.firstChild().toElement();
+ // just in case
+ while ( !framesetElem.isNull() && framesetElem.tagName() != "FRAMESET" )
+ framesetElem = framesetElem.nextSibling().toElement();
+
+ if ( !framesetElem.isNull() )
+ {
+ KWTextFrameSet *textFrameSet = dynamic_cast<KWTextFrameSet *>( m_doc->frameSet(0) );
+ KoTextCursor insertionCursor( textFrameSet->textDocument() );
+ KWTextFrameSetEdit* edit = currentTextEdit();
+ if ( edit && !edit->textFrameSet()->protectContent()) {
+ textFrameSet = edit->textFrameSet();
+ insertionCursor = *edit->cursor();
+ }
+ // Handle the main textframeset special - concatenate the text
+ QDomDocument domDoc( "PARAGRAPHS" );
+ QDomElement paragsElem = domDoc.createElement( "PARAGRAPHS" );
+ domDoc.appendChild( paragsElem );
+
+ // Need an intermediate list otherwise nextSibling doesn't work after moving the node
+ // to the other DOM tree ;)
+ QValueList<QDomElement> paragList;
+ QValueList<QString> inlineFsNames;
+ QDomElement fsElem;
+
+ QDomNode n = framesetElem.firstChild().toElement();
+ while( !n.isNull() )
+ {
+ QDomElement e = n.toElement(); // try to convert the node to an element.
+ if ( !e.isNull() && e.tagName() == "PARAGRAPH" )
+ {
+ paragList.append( e );
+ // Handle inline framesets
+ QDomElement formatsElem = e.namedItem( "FORMATS" ).toElement();
+ if ( !formatsElem.isNull() )
+ {
+ // Get references to inline framesets
+ QDomElement formatElem = formatsElem.firstChild().toElement();
+ for ( ; !formatElem.isNull() ; formatElem = formatElem.nextSibling().toElement() )
+ {
+ QDomElement anchorElem = formatElem.namedItem( "ANCHOR" ).toElement();
+ if ( !anchorElem.isNull() )
+ {
+ QString type = anchorElem.attribute( "type" );
+ if ( type == "grpMgr" /* old syntax */ || type == "frameset" )
+ {
+ QString iName = anchorElem.attribute( "instance" );
+ inlineFsNames.append( iName );
+ // inline framsets shall appear after the paragraph
+ QString tableName;
+ QDomElement table;
+ fsElem = framesetElem.nextSibling().toElement();
+ for ( ; !fsElem.isNull() ; fsElem = fsElem.nextSibling().toElement() )
+ {
+ if ( fsElem.tagName() == "FRAMESET" )
+ {
+ QString name = fsElem.attribute( "name" );
+ QString grpMgr = fsElem.attribute( "grpMgr" );
+ if ( name == iName )
+ {
+ paragList.append( fsElem );
+ //kdDebug()<<k_funcinfo<<" Inline frameset: "<<name<<" added"<<endl;
+ }
+ else if ( grpMgr == iName )
+ { // Table so we need to create table framset if it is new
+ if ( grpMgr != tableName )
+ {
+ tableName = grpMgr;
+ table = domDoc.createElement("FRAMESET");
+ table.setAttribute("frameType", FT_TABLE);
+ table.setAttribute("frameInfo", 0);
+ table.setAttribute("protectSize", fsElem.attribute("protectSize","0"));
+ table.setAttribute("name", tableName);
+ table.setAttribute("visible", fsElem.attribute("visible","1"));
+ paragList.append( table ); // same level as paragraphs, so it goes into the paragList
+ //kdDebug()<<k_funcinfo<<" paragList Added new table: "<<grpMgr<<endl;
+ }
+
+ table.appendChild( fsElem.cloneNode() ); // add the cell as child to the table frameset
+ //kdDebug()<<k_funcinfo<<" Inline table: "<<grpMgr<<" Added new cell: "<<name<<endl;
+ }
+ //else kdDebug()<<k_funcinfo<<" Fixed frameset: "<<name<<endl;
+ }
+ //else kdDebug()<<k_funcinfo<<" Not frameset: "<<fsElem.tagName()<<endl;
+ }
+ //kdDebug()<<k_funcinfo<<" Treated "<<i<<" frameset elements"<<endl;
+ }
+ }
+ }
+ }
+ }
+ n = n.nextSibling();
+ }
+
+ QValueList<QDomElement>::Iterator it = paragList.begin();
+ QValueList<QDomElement>::Iterator end = paragList.end();
+ for ( ; it!= end ; ++it )
+ {
+ //kdDebug()<<k_funcinfo<<" paragList tag: "<<(*it).tagName()<<" name: "<<(*it).attribute( "name" )<<" grpMgr: "<<(*it).attribute( "grpMgr" )<<endl;
+ paragsElem.appendChild( *it );
+ }
+ //kdDebug() << k_funcinfo << "Paragraphs:\n" << domDoc.toCString() << endl;
+
+ // The fixed framesets
+ // doctype SELECTION is used for fixed framesets
+ QDomDocument domDocFrames( "SELECTION" ); // see KWCanvas::copySelectedFrames
+ QDomElement topElem = domDocFrames.createElement( "SELECTION" );
+ domDocFrames.appendChild( topElem );
+ QString tableName;
+ QDomElement table;
+ QValueList<QString> fsInHeader;
+ QValueList<QDomElement> framesetsList;
+
+ framesetElem = framesetElem.nextSibling().toElement();
+ for ( ; !framesetElem.isNull() ; framesetElem = framesetElem.nextSibling().toElement() )
+ {
+ if ( framesetElem.tagName() == "FRAMESET" )
+ {
+ FrameSetType frameSetType = static_cast<FrameSetType>( KWDocument::getAttribute( framesetElem, "frameType", FT_BASE ) );
+ KWFrameSet::Info info = static_cast<KWFrameSet::Info>( framesetElem.attribute("frameInfo").toInt() );
+ if ( frameSetType == FT_TEXT &&
+ (info == KWFrameSet::FI_FIRST_HEADER ||
+ info == KWFrameSet::FI_EVEN_HEADER ||
+ info == KWFrameSet::FI_ODD_HEADER ||
+ info == KWFrameSet::FI_FIRST_FOOTER ||
+ info == KWFrameSet::FI_EVEN_FOOTER ||
+ info == KWFrameSet::FI_ODD_FOOTER)
+ )
+ fsInHeader += getInlineFramesets( framesetElem );
+
+ QString name = framesetElem.attribute( "name" );
+ QString grpMgr = framesetElem.attribute( "grpMgr" );
+ if ( !inlineFsNames.contains(name) && !inlineFsNames.contains(grpMgr) )
+ { // fixed frameset
+ if ( !grpMgr.isEmpty() )
+ { // Table cell
+ if ( grpMgr != tableName )
+ { // New table (first cell)
+ tableName = grpMgr;
+ table = domDocFrames.createElement("FRAMESET");
+ table.setAttribute("frameType", FT_TABLE);
+ table.setAttribute("frameInfo", 0);
+ table.setAttribute("protectSize", framesetElem.attribute("protectSize","0"));
+ table.setAttribute("name", tableName);
+ table.setAttribute("visible", framesetElem.attribute("visible","1"));
+ framesetsList.append( table );
+ //kdDebug()<<k_funcinfo<<" framesetsList Added new table: "<<grpMgr<<endl;
+ }
+ table.appendChild( framesetElem.cloneNode() ); // add the cell as child to the table frameset
+ //kdDebug()<<k_funcinfo<<" Fixed table '"<<grpMgr<<"': Added new cell: '"<<name<<"'"<<endl;
+ }
+ else // other frameset type
+ {
+ framesetsList.append( framesetElem );
+ //kdDebug()<<k_funcinfo<<" Fixed frameset: '"<<name<<"' added"<<endl;
+ }
+ }
+ //else kdDebug()<<k_funcinfo<<" Inline frameset, skipped: "<<name<<endl;
+ }
+ //else kdDebug()<<k_funcinfo<<" Not frameset element, skipped: "<<framesetElem.tagName()<<endl;
+ }
+ it = framesetsList.begin();
+ end = framesetsList.end();
+ for ( ; it != end ; ++it )
+ {
+ framesetElem = (*it);
+ FrameSetType frameSetType = static_cast<FrameSetType>( KWDocument::getAttribute( framesetElem, "frameType", FT_BASE ) );
+ KWFrameSet::Info info = static_cast<KWFrameSet::Info>( framesetElem.attribute("frameInfo").toInt() );
+ QString name = framesetElem.attribute("name");
+ QString grpMgr = framesetElem.attribute( "grpMgr" );
+ // We skip headers, footers and framsets/tables inside theese
+ if ( !fsInHeader.contains(name) && !fsInHeader.contains(grpMgr) &&
+ !( frameSetType == FT_TEXT &&
+ (info == KWFrameSet::FI_FIRST_HEADER ||
+ info == KWFrameSet::FI_EVEN_HEADER ||
+ info == KWFrameSet::FI_ODD_HEADER ||
+ info == KWFrameSet::FI_FIRST_FOOTER ||
+ info == KWFrameSet::FI_EVEN_FOOTER ||
+ info == KWFrameSet::FI_ODD_FOOTER) )
+ )
+ {
+ hasFixedFramesets = true;
+ topElem.appendChild( framesetElem );
+ }
+ }
+ // Embedded documents
+ QDomDocument embeddedDoc( "SELECTION" );
+ QDomElement selElem = embeddedDoc.createElement( "SELECTION" );
+ embeddedDoc.appendChild( selElem );
+
+ QValueList<QDomElement> embeddedList;
+ QDomElement embeddedElem = word.namedItem( "EMBEDDED" ).toElement();
+ for ( ; !embeddedElem.isNull() ; embeddedElem = embeddedElem.nextSibling().toElement() )
+ {
+ if ( embeddedElem.tagName() == "EMBEDDED" )
+ {
+ embeddedList.append( embeddedElem );
+ }
+ }
+ it = embeddedList.begin();
+ end = embeddedList.end();
+ bool hasEmbedded = false;
+ for ( ; it!= end ; ++it )
+ {
+ selElem.appendChild( *it );
+ hasEmbedded = true;
+ }
+ store->close();
+
+
+ // Now we do the insertion
+ if ( !macroCmd )
+ macroCmd = new KMacroCommand( i18n("Insert File") );
+
+ if ( hasFixedFramesets )
+ {
+ // insert fixed framesets
+ //kdDebug() << k_funcinfo << domDocFrames.toCString() << endl;
+ m_doc->pasteFrames( topElem, macroCmd, false, false, false /* don't select frames */ );
+ }
+ if ( hasEmbedded )
+ {
+ //kdDebug()<<k_funcinfo<<" Embedded: \n"<<embeddedDoc.toCString()<<endl;
+ if ( !macroCmd )
+ macroCmd = new KMacroCommand( i18n("Insert File") );
+ m_doc->insertEmbedded( store, selElem, macroCmd, 0 );
+ }
+
+ // insert paragraphs and inline framesets (we always have at least one paragraph)
+ KCommand *cmd = textFrameSet->pasteOasis( &insertionCursor, domDoc.toCString(), true );
+
+ if ( cmd ) {
+ macroCmd->addCommand( cmd );
+ }
+ m_doc->addCommand( macroCmd );
+
+ }
+ }
+
+ m_doc->loadImagesFromStore( store );
+ m_doc->completePasting();
+
+ }
+ delete store;
+}
+
+QValueList<QString> KWView::getInlineFramesets( const QDomNode &framesetElem)
+{
+ //kdDebug()<<k_funcinfo<<" Frameset: "<<framesetElem.toElement().attribute("name")<<endl;
+ QValueList<QString> list;
+ QDomNode n = framesetElem.firstChild().toElement();
+ for( ; !n.isNull(); n = n.nextSibling() )
+ {
+ QDomElement e = n.toElement(); // try to convert the node to an element.
+ if ( !e.isNull() && e.tagName() == "PARAGRAPH" )
+ {
+ QDomElement formatsElem = e.namedItem( "FORMATS" ).toElement();
+ if ( !formatsElem.isNull() )
+ {
+ // Get references to inline framesets
+ QDomElement formatElem = formatsElem.firstChild().toElement();
+ for ( ; !formatElem.isNull() ; formatElem = formatElem.nextSibling().toElement() )
+ {
+ QDomElement anchorElem = formatElem.namedItem( "ANCHOR" ).toElement();
+ if ( !anchorElem.isNull() )
+ {
+ QString type = anchorElem.attribute( "type" );
+ if ( type == "grpMgr" /* old syntax */ || type == "frameset" )
+ {
+ QString iName = anchorElem.attribute( "instance" );
+ list.append( iName );
+ //kdDebug()<<k_funcinfo<<" added: "<<iName<<endl;
+ }
+ }
+ }
+ }
+ }
+ }
+ return list;
+}
+
+void KWView::addBookmark()
+{
+ KWTextFrameSetEdit * edit = currentTextEdit();
+ if ( edit )
+ {
+ //don't create list against viewmode. We must list all bookmarks.
+ KWCreateBookmarkDia dia( m_doc->listOfBookmarkName(0L), this, 0 );
+ if ( dia.exec() ) {
+ QString bookName = dia.bookmarkName();
+ KoTextCursor start, end;
+ if ( edit->textDocument()->hasSelection( KoTextDocument::Standard ) ) {
+ start = edit->textDocument()->selectionStartCursor( KoTextDocument::Standard );
+ end = edit->textDocument()->selectionEndCursor( KoTextDocument::Standard );
+ } else {
+ start = *edit->cursor();
+ end = start;
+ }
+ int startSel = start.index();
+ int endSel = end.index();
+ m_doc->insertBookmark(bookName, start.parag(),end.parag(), startSel, endSel);
+ }
+ }
+}
+
+void KWView::selectBookmark()
+{
+ KWSelectBookmarkDia dia( m_doc->listOfBookmarkName(viewMode()), m_doc, this, 0 );
+ if ( dia.exec() ) {
+ QString bookName = dia.bookmarkSelected();
+ const KoTextBookmark * book = m_doc->bookmarkByName( bookName );
+ Q_ASSERT( book );
+ if ( book )
+ {
+ Q_ASSERT( book->startParag() );
+ Q_ASSERT( book->endParag() );
+ if ( !book->startParag() || !book->endParag() )
+ return;
+ KWTextFrameSet* textfs = static_cast<KWTextDocument *>( book->textDocument() )->textFrameSet();
+ m_gui->canvasWidget()->editTextFrameSet( textfs, book->startParag(), book->bookmarkStartIndex() );
+ KWTextFrameSetEdit * edit = currentTextEdit();
+ Q_ASSERT( edit );
+ if ( edit )
+ {
+ edit->textDocument()->removeSelection( KoTextDocument::Standard );
+ edit->textDocument()->setSelectionStart( KoTextDocument::Standard, edit->cursor() );
+ edit->cursor()->setParag( book->endParag());
+ edit->cursor()->setIndex(book->bookmarkEndIndex() );
+ edit->textDocument()->setSelectionEnd( KoTextDocument::Standard, edit->cursor() );
+ book->startParag()->setChanged( true );
+ book->endParag()->setChanged( true );
+ m_doc->slotRepaintChanged( edit->frameSet() );
+ }
+ }
+ }
+}
+
+void KWView::importStyle()
+{
+ KWImportStyleDia dia( m_doc, m_doc->styleCollection(), this );
+ if ( dia.exec() && !dia.importedStyles().isEmpty() ) {
+ m_doc->styleCollection()->importStyles( dia.importedStyles() );
+ m_doc->setModified( true );
+ m_doc->updateAllStyleLists();
+ }
+}
+
+void KWView::testAndCloseAllFrameSetProtectedContent()
+{
+ KWTextFrameSetEdit* edit = currentTextEdit();
+ if ( edit && edit->textFrameSet()->protectContent()) {
+ m_doc->terminateEditing( edit->frameSet());
+ }
+}
+
+void KWView::updateRulerInProtectContentMode()
+{
+ KWTextFrameSetEdit* edit = currentTextEdit();
+ KoRuler * hRuler = m_gui ? m_gui->getHorzRuler() : 0;
+
+ if ( edit && hRuler) {
+ if ( !edit->textFrameSet()->protectContent() )
+ hRuler->changeFlags(KoRuler::F_INDENTS | KoRuler::F_TABS);
+ else
+ hRuler->changeFlags(0);
+ hRuler->repaint();
+ }
+}
+
+void KWView::deselectAllFrames()
+{
+ m_gui->canvasWidget()->selectAllFrames( false );
+}
+
+void KWView::insertDirectCursor()
+{
+#if 0
+ insertDirectCursor( m_actionInsertDirectCursor->isChecked());
+#endif
+}
+
+void KWView::insertDirectCursor(bool b)
+{
+ m_doc->setInsertDirectCursor(b);
+}
+
+void KWView::updateDirectCursorButton()
+{
+#if 0
+ m_actionInsertDirectCursor->setChecked(m_doc->insertDirectCursor());
+#endif
+}
+
+void KWView::convertTableToText()
+{
+ KWCanvas * canvas = m_gui->canvasWidget();
+ KWTableFrameSet *table = canvas->getCurrentTable();
+ if ( table && table->isFloating() )
+ {
+ const QByteArray arr = table->convertTableToText();
+ KWAnchor * anchor = table->findAnchor( 0 );
+ if ( anchor && arr.size() )
+ {
+ KWTextFrameSet *frameset = table->anchorFrameset();
+ KoTextParag *parag = anchor->paragraph();
+ int pos = anchor->index();
+ KMacroCommand *macro = new KMacroCommand(i18n("Convert Table to Text"));
+ KCommand *cmd = table->anchorFrameset()->deleteAnchoredFrame( anchor );
+ if ( cmd )
+ macro->addCommand( cmd);
+
+ m_gui->canvasWidget()->editTextFrameSet( frameset, parag, pos );
+
+ KWTextFrameSetEdit* edit = currentTextEdit();
+ if ( edit && edit->textFrameSet())
+ {
+ cmd = edit->textFrameSet()->pasteOasis( edit->cursor(), arr, true );
+ if ( cmd )
+ macro->addCommand( cmd );
+ }
+ m_doc->addCommand(macro);
+ }
+ }
+}
+
+void KWView::convertToTextBox()
+{
+ KWTextFrameSetEdit* edit = currentTextEdit();
+ if ( !edit )
+ return;
+
+ KWTextFrameSet* textfs = edit->textFrameSet();
+ if( textfs->protectContent() || !textfs->textObject()->hasSelection() )
+ return;
+
+ KWOasisSaver oasisSaver( m_doc );
+ textfs->textDocument()->copySelection( oasisSaver.bodyWriter(), oasisSaver.savingContext(), KoTextDocument::Standard );
+ if ( !oasisSaver.finish() )
+ return;
+ const QByteArray arr = oasisSaver.data();
+ if ( !arr.size() )
+ return;
+
+ KCommand *cmd = textfs->textObject()->removeSelectedTextCommand( edit->textView()->cursor(), KoTextDocument::Standard );
+ Q_ASSERT( cmd );
+ KMacroCommand* macro = new KMacroCommand( i18n("Convert to Text Box"));
+ macro->addCommand( cmd );
+ // Where to place the resulting text box? Maybe it should be made inline?
+ cmd = m_gui->canvasWidget()->createTextBox( KoRect(30,30,300,300) );
+ Q_ASSERT( cmd );
+ if ( cmd )
+ macro->addCommand( cmd );
+
+ edit = currentTextEdit();
+ Q_ASSERT( edit ); // if it can really be 0, we need to undo the above...
+ if ( edit )
+ {
+ cmd = edit->textFrameSet()->pasteOasis( edit->textView()->cursor(), arr, true );
+ if ( cmd )
+ macro->addCommand( cmd );
+ // Auto-resize the frame from its contents
+ edit->textFrameSet()->layout();
+ }
+ m_doc->addCommand( macro );
+}
+
+void KWView::slotAddIgnoreAllWord()
+{
+ KWTextFrameSetEdit* edit = currentTextEdit();
+ if ( edit )
+ m_doc->addSpellCheckIgnoreWord( edit->currentWordOrSelection() );
+}
+
+void KWView::sortText()
+{
+ KWTextFrameSetEdit* edit = currentTextEdit();
+ if ( edit && edit->textFrameSet()->hasSelection() )
+ {
+ KWSortDia dlg( this, "sort dia" );
+ if ( dlg.exec() )
+ {
+ const QByteArray arr = edit->textFrameSet()->sortText(dlg.getSortType());
+ if ( arr.size() )
+ {
+ KCommand *cmd = edit->textFrameSet()->pasteOasis( edit->cursor(), arr, true );
+ if ( cmd )
+ m_doc->addCommand(cmd);
+ }
+ }
+ }
+}
+
+void KWView::addPersonalExpression()
+{
+ KWTextFrameSetEdit* edit = currentTextEdit();
+ if ( !(edit && edit->textFrameSet()->hasSelection()))
+ return;
+
+ QString newExpression = edit->textFrameSet()->textObject()->selectedText();
+ //load file !!!
+ QString tmp=locateLocal("data","kword/expression/perso.xml");
+ QFile file( tmp );
+ if ( !file.open( IO_ReadOnly ) )
+ return;
+ QDomDocument doc;
+ doc.setContent( &file );
+ file.close();
+
+ QString group;
+ QMap<QString, QStringList>lstOfPersonalExp;
+ QStringList list;
+ QDomNode n = doc.documentElement().firstChild();
+ for( ; !n.isNull(); n = n.nextSibling() )
+ {
+ if ( n.isElement() )
+ {
+ QDomElement e = n.toElement();
+ if ( e.tagName() == "Type" )
+ {
+ list.clear();
+ group = i18n( e.namedItem( "TypeName" ).toElement().text().utf8() );
+
+ QDomNode n2 = e.firstChild();
+ for( ; !n2.isNull(); n2 = n2.nextSibling() )
+ {
+
+ if ( n2.isElement() )
+ {
+ QDomElement e2 = n2.toElement();
+ if ( e2.tagName() == "Expression" )
+ {
+ QString text = i18n( e2.namedItem( "Text" ).toElement().text().utf8() );
+ list<<text;
+ }
+ }
+ }
+ lstOfPersonalExp.insert(group,list);
+ group = "";
+ }
+ }
+ }
+ //save
+ doc = QDomDocument( "KWordExpression" );
+ QDomElement begin = doc.createElement( "KWordExpression" );
+ doc.appendChild( begin );
+ QMapIterator<QString, QStringList> itPersonalExp = lstOfPersonalExp.find(i18n("Normal"));
+ if ( itPersonalExp != lstOfPersonalExp.end())
+ {
+ list = itPersonalExp.data();
+ list<<newExpression;
+ lstOfPersonalExp.replace( i18n("Normal"), list);
+ }
+ else
+ {
+ list.clear();
+ list<<newExpression;
+ lstOfPersonalExp.insert( i18n("Normal"), list);
+ }
+
+
+ itPersonalExp = lstOfPersonalExp.begin();
+ for ( ; itPersonalExp != lstOfPersonalExp.end(); ++itPersonalExp )
+ {
+ QDomElement type = doc.createElement( "Type" );
+ begin.appendChild( type );
+ QDomElement typeName = doc.createElement( "TypeName" );
+ type.appendChild( typeName );
+ typeName.appendChild( doc.createTextNode(itPersonalExp.key() ) );
+ list=itPersonalExp.data();
+ for( uint i=0;i<list.count();i++ )
+ {
+ QDomElement expr = doc.createElement( "Expression" );
+ type.appendChild( expr );
+ QDomElement text = doc.createElement( "Text" );
+ expr.appendChild( text );
+ text.appendChild( doc.createTextNode(list[i] ) );
+ }
+ }
+ QCString s = doc.toCString();
+
+ if ( !file.open( IO_WriteOnly ) )
+ {
+ kdDebug()<<"Error in addPersonalExpression()\n";
+ return;
+ }
+ file.writeBlock(s,s.length());
+ file.close();
+ m_doc->refreshMenuExpression();
+}
+
+void KWView::addWordToDictionary()
+{
+ KWTextFrameSetEdit* edit = currentTextEdit();
+ if ( edit )
+ {
+ QString word = edit->wordUnderCursor( *edit->cursor() );
+ if ( !word.isEmpty() )
+ m_doc->addWordToDictionary( word );
+ }
+}
+
+void KWView::embeddedStoreInternal()
+{
+ kdDebug(31001)<<k_funcinfo<<endl;
+ KWFrameView *view = frameViewManager()->selectedFrame();
+ KWFrame *frame = view == 0 ? 0 : view->frame();
+ if( !frame)
+ return;
+ KWPartFrameSet *part = static_cast<KWPartFrameSet *>(frame->frameSet());
+ part->storeInternal();
+}
+
+void KWView::goToDocumentStructure()
+{
+ KWDocStruct* docStruct = getGUI()->getDocStruct();
+ if (docStruct) docStruct->setFocusHere();
+}
+
+void KWView::goToDocument()
+{
+ KWCanvas* canvas = getGUI()->canvasWidget();
+ if (!canvas) return;
+ canvas->setFocus();
+}
+
+void KWView::deleteFrameSet( KWFrameSet * frameset)
+{
+ if ( frameset && frameset->frame(0))
+ {
+ frameViewManager()->view(frameset->frame(0))->setSelected( true );
+ deleteFrame();
+ }
+}
+
+QPtrList<KAction> KWView::listOfResultOfCheckWord( const QString &word )
+{
+ QPtrList<KAction> listAction;
+ DefaultDictionary *dict = m_broker->defaultDictionary();
+ const QStringList lst = dict->suggest( word );
+ if ( !lst.contains( word ) )
+ {
+ QStringList::ConstIterator it = lst.begin();
+ const QStringList::ConstIterator end = lst.end();
+ for ( ; it != end ; ++it )
+ {
+ if ( !(*it).isEmpty() ) // in case of removed subtypes or placeholders
+ {
+ KAction * act = new KAction( *it );
+ connect( act, SIGNAL(activated()), this, SLOT(slotCorrectWord()) );
+ listAction.append( act );
+ }
+ }
+ }
+ return listAction;
+}
+
+void KWView::slotCorrectWord()
+{
+ KAction * act = (KAction *)(sender());
+ KWTextFrameSetEdit* edit = currentTextEdit();
+ if ( edit )
+ {
+ edit->selectWordUnderCursor( *(edit->cursor()) );
+ m_doc->addCommand( edit->textObject()->replaceSelectionCommand( edit->cursor(), act->text(), i18n("Replace Word") ));
+ }
+}
+
+void KWView::slotChildActivated( bool a )
+{
+ // Same hack as in KoView
+ KoViewChild* ch = child( (KoView*)sender() );
+ if ( !ch )
+ return;
+ KWDocumentChild* kwchild = static_cast<KWDocumentChild *>( ch->documentChild() );
+ KWPartFrameSet* fs = kwchild->partFrameSet();
+ //kdDebug() << "KWView::slotChildActivated fs=" << fs << endl;
+ Q_ASSERT( fs );
+ if ( fs ) {
+ if ( a )
+ fs->startEditing();
+ else
+ fs->endEditing();
+ }
+ KoView::slotChildActivated( a );
+}
+
+Broker *KWView::broker() const
+{
+ return m_broker;
+}
+
+void KWView::slotUnitChanged( KoUnit::Unit unit )
+{
+ getGUI()->getHorzRuler()->setUnit( unit );
+ getGUI()->getVertRuler()->setUnit( unit );
+ if ( m_sbUnitLabel )
+ m_sbUnitLabel->setText( ' ' + KoUnit::unitDescription( unit ) + ' ' );
+}
+
+KWFrameViewManager* KWView::frameViewManager() const {
+ return getGUI()->canvasWidget()->frameViewManager();
+}
+
+void KWView::deleteSelectedFrames() {
+ int nbCommand=0;
+
+ int docItem=0; // bitmask for changed doc items.
+
+ KMacroCommand * macroCmd = new KMacroCommand( i18n("Delete Frames") );
+ KWFrameViewManager *fvMgr = frameViewManager();
+ while (KWFrameView *frameView = fvMgr->selectedFrame()) {
+ KWFrame *frame = frameView->frame();
+ KWFrameSet *fs = frame->frameSet();
+ if ( fs->isAFooter() || fs->isAHeader() )
+ continue;
+ KWTableFrameSet *table=fs->groupmanager();
+ if ( table ) {
+ docItem|=m_doc->typeItemDocStructure(table->type());
+
+ if ( table->isFloating() ) {
+ docItem|=m_doc->typeItemDocStructure(fs->type());
+
+ KWAnchor * anchor = table->findAnchor( 0 );
+ KCommand * cmd=table->anchorFrameset()->deleteAnchoredFrame( anchor );
+ macroCmd->addCommand(cmd);
+ nbCommand++;
+ }
+ else {
+ KWDeleteTableCommand *cmd = new KWDeleteTableCommand( i18n("Delete Table"), table );
+ cmd->execute();
+ macroCmd->addCommand(cmd);
+ nbCommand++;
+ }
+ }
+ else { // a simple frame
+ if ( fs->isMainFrameset() )
+ continue;
+
+ docItem|=m_doc->typeItemDocStructure(fs->type());
+
+ if ( fs->isFloating() ) {
+ KWAnchor * anchor = fs->findAnchor( 0 );
+ KCommand *cmd=fs->anchorFrameset()->deleteAnchoredFrame( anchor );
+ macroCmd->addCommand(cmd);
+ nbCommand++;
+ }
+ else {
+ KWDeleteFrameCommand *cmd = new KWDeleteFrameCommand( i18n("Delete Frame"), frame );
+ cmd->execute();
+ macroCmd->addCommand(cmd);
+ nbCommand++;
+ }
+ }
+ }
+ if( nbCommand ) {
+ m_doc->addCommand(macroCmd);
+ m_doc->refreshDocStructure(docItem);
+ }
+ else
+ delete macroCmd;
+}
+
+
+/******************************************************************/
+/* Class: KWViewWidget */
+/******************************************************************/
+KWViewWidget::KWViewWidget( QWidget *parent, KWView *view )
+ : QWidget( parent ),
+ m_view ( view )
+{
+}
+
+void KWViewWidget::resizeEvent( QResizeEvent *e )
+{
+ // Update zoom if width changes and fit width is used
+ if ( ( e->size().width() != e->oldSize().width() )
+ && ( m_view->kWordDocument()->zoomMode() == KoZoomMode::ZOOM_WIDTH ) )
+ {
+ QTimer::singleShot( 0, m_view, SLOT( updateZoom() ) );
+ }
+
+ QWidget::resizeEvent( e );
+}
+
+
+/******************************************************************/
+/* Class: KWGUI */
+/******************************************************************/
+KWGUI::KWGUI( const QString& viewMode, QWidget *parent, KWView *daView )
+ : QHBox( parent, "" ),
+ m_view ( daView )
+{
+
+ KWDocument * doc = m_view->kWordDocument();
+
+ m_horRuler = 0;
+ m_vertRuler = 0;
+
+ // The splitter
+ m_panner = new QSplitter( Qt::Horizontal, this );
+
+ // The left side
+ m_docStruct = new KWDocStruct( m_panner, doc, this );
+ m_docStruct->setMinimumWidth( 0 );
+
+ // The right side
+ m_right = new KWViewWidget( m_panner, m_view );
+ QGridLayout *gridLayout = new QGridLayout( m_right, 2, 2 );
+ m_canvas = new KWCanvas( viewMode, m_right, doc, this );
+ gridLayout->addWidget( m_canvas, 1, 1 );
+
+ QValueList<int> l;
+ l << 10;
+ l << 90;
+ m_panner->setSizes( l );
+
+ KoPageLayout layout = doc->pageLayout();
+
+ m_tabChooser = new KoTabChooser( m_right, KoTabChooser::TAB_ALL );
+ m_tabChooser->setReadWrite(doc->isReadWrite());
+ gridLayout->addWidget( m_tabChooser, 0, 0 );
+
+ m_horRuler = new KoRuler( m_right, m_canvas->viewport(), Qt::Horizontal, layout,
+ KoRuler::F_INDENTS | KoRuler::F_TABS,
+ doc->unit(), m_tabChooser );
+ m_horRuler->setReadWrite(doc->isReadWrite());
+ gridLayout->addWidget( m_horRuler, 0, 1 );
+
+ m_vertRuler = new KoRuler( m_right, m_canvas->viewport(), Qt::Vertical, layout,
+ 0, doc->unit() );
+ m_vertRuler->setReadWrite(doc->isReadWrite());
+ gridLayout->addWidget( m_vertRuler, 1, 0 );
+
+ m_horRuler->setZoom( doc->zoomedResolutionX() );
+ m_vertRuler->setZoom( doc->zoomedResolutionY() );
+
+ m_horRuler->setGridSize(doc->gridX());
+
+ connect( m_horRuler, SIGNAL( newPageLayout( const KoPageLayout & ) ), m_view, SLOT( newPageLayout( const KoPageLayout & ) ) );
+ connect( m_horRuler, SIGNAL( newLeftIndent( double ) ), m_view, SLOT( newLeftIndent( double ) ) );
+ connect( m_horRuler, SIGNAL( newFirstIndent( double ) ), m_view, SLOT( newFirstIndent( double ) ) );
+ connect( m_horRuler, SIGNAL( newRightIndent( double ) ), m_view, SLOT( newRightIndent( double ) ) );
+
+ connect( m_horRuler, SIGNAL( doubleClicked() ), m_view, SLOT( slotHRulerDoubleClicked() ) );
+ connect( m_horRuler, SIGNAL( doubleClicked(double) ), m_view, SLOT( slotHRulerDoubleClicked(double) ) );
+ connect( m_horRuler, SIGNAL( unitChanged( KoUnit::Unit ) ), this, SLOT( unitChanged( KoUnit::Unit ) ) );
+ connect( m_vertRuler, SIGNAL( newPageLayout( const KoPageLayout & ) ), m_view, SLOT( newPageLayout( const KoPageLayout & ) ) );
+ connect( m_vertRuler, SIGNAL( doubleClicked() ), m_view, SLOT( formatPage() ) );
+ connect( m_vertRuler, SIGNAL( unitChanged( KoUnit::Unit ) ), this, SLOT( unitChanged( KoUnit::Unit ) ) );
+
+ m_horRuler->hide();
+ m_vertRuler->hide();
+
+ m_canvas->show();
+
+ reorganize();
+
+ connect( m_horRuler, SIGNAL( tabListChanged( const KoTabulatorList & ) ), m_view,
+ SLOT( tabListChanged( const KoTabulatorList & ) ) );
+
+ setKeyCompression( TRUE );
+ setAcceptDrops( TRUE );
+ setFocusPolicy( QWidget::NoFocus );
+}
+
+void KWGUI::showGUI()
+{
+ reorganize();
+}
+
+void KWGUI::resizeEvent( QResizeEvent *e )
+{
+ QWidget::resizeEvent( e );
+ reorganize();
+}
+
+void KWGUI::reorganize()
+{
+ int hSpace = m_vertRuler->minimumSizeHint().width();
+ int vSpace = m_horRuler->minimumSizeHint().height();
+ if(m_view->kWordDocument()->showRuler())
+ {
+ m_vertRuler->show();
+ m_horRuler->show();
+ m_tabChooser->show();
+ m_tabChooser->setGeometry( 0, 0, hSpace, vSpace );
+ }
+ else
+ {
+ m_vertRuler->hide();
+ m_horRuler->hide();
+ m_tabChooser->hide();
+ hSpace = 0;
+ vSpace = 0;
+ }
+
+ if(m_view->kWordDocument()->showdocStruct()) {
+ if(m_docStruct->isHidden()) {
+ m_docStruct->show();
+ if(m_panner->sizes()[0] < 50) {
+ QValueList<int> l;
+ l << 100;
+ l << width()-100;
+ m_panner->setSizes( l );
+ }
+ }
+ } else
+ m_docStruct->hide();
+
+ if( m_view->statusBar())
+ {
+ if(m_view->kWordDocument()->showStatusBar())
+ m_view->statusBar()->show();
+ else
+ m_view->statusBar()->hide();
+ }
+
+ if ( m_view->kWordDocument()->showScrollBar())
+ {
+ m_canvas->setVScrollBarMode(QScrollView::Auto);
+ m_canvas->setHScrollBarMode(QScrollView::Auto);
+ }
+ else
+ {
+ m_canvas->setVScrollBarMode(QScrollView::AlwaysOff);
+ m_canvas->setHScrollBarMode(QScrollView::AlwaysOff);
+ }
+}
+
+void KWGUI::unitChanged( KoUnit::Unit u )
+{
+ m_view->kWordDocument()->setUnit( u );
+}
+
+QPoint KWView::applyViewTransformations( const QPoint& p ) const
+{
+ return viewMode()->normalToView( m_doc->zoomPoint( KoPoint( p ) ) );
+}
+
+QPoint KWView::reverseViewTransformations( const QPoint& p ) const
+{
+ return m_doc->unzoomPoint( viewMode()->viewToNormal( p ) ).toQPoint();
+}
+
+int KWView::currentPage() const {
+ return m_currentPage->pageNumber();
+}
+
+void KWView::slotDocumentLoadingCompleted()
+{
+ updateStyleList();
+}
+
+#include "KWView.moc"
diff --git a/kword/KWView.h b/kword/KWView.h
new file mode 100644
index 00000000..7463435a
--- /dev/null
+++ b/kword/KWView.h
@@ -0,0 +1,879 @@
+/* This file is part of the KDE project
+ Copyright (C) 1998, 1999 Reginald Stadlbauer <reggie@kde.org>
+ Copyright (C) 2005 Thomas Zander <zander@kde.org>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+
+#ifndef kwview_h
+#define kwview_h
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <kprinter.h>
+
+#include <KoBorder.h>
+#include "defs.h"
+#include "KWTextParag.h"
+
+#include <KoPageLayoutDia.h>
+#include <KoView.h>
+#include <KoPoint.h>
+#include <kshortcut.h>
+#include <KoZoomMode.h>
+
+#include <qbrush.h>
+#include <qhbox.h>
+
+class KWPage;
+class KWViewMode;
+class KWDocStruct;
+class KWCanvas;
+class KWDocument;
+class KWGUI;
+class KWFrame;
+class KWFrameView;
+class KWFrameViewManager;
+class KWTextFrameSetEdit;
+class KMacroCommand;
+class KWFrameSet;
+class KWFindReplace;
+class KWFrameStyle;
+class KWTableStyle;
+class KWTableFrameSet;
+
+class KoPicture;
+class KoSearchContext;
+class KoTextFormatInterface;
+class KoRuler;
+class TKSelectColorAction;
+class KoPartSelectAction;
+class KoCharSelectDia;
+class KoTextFormat;
+class KoFontDia;
+class KoParagDia;
+class KoTextIterator;
+
+class DCOPObject;
+class KStatusBarLabel;
+class KoSpell;
+class KURL;
+class KAction;
+class KActionMenu;
+class KSelectAction;
+class KToggleAction;
+class KFontSizeAction;
+class KFontAction;
+class QResizeEvent;
+class QSplitter;
+
+#include <kspell2/broker.h>
+namespace KSpell2 {
+ class Dialog;
+}
+
+
+/******************************************************************/
+/* Class: KWView */
+/******************************************************************/
+
+class KWView : public KoView
+{
+ Q_OBJECT
+
+public:
+ KWView( const QString& viewMode, QWidget *parent, const char *name, KWDocument *doc );
+ virtual ~KWView();
+
+ virtual DCOPObject* dcopObject();
+
+ // Those methods update the UI (from the given formatting info)
+ // They do NOT do anything to the text
+ void showFormat( const KoTextFormat &currentFormat );
+ void showAlign( int align );
+ void showCounter( KoParagCounter &c );
+ void showSpacing( int spacing );
+ /**
+ * Updates the checked state of the border buttons based on the parameters.
+ * @param left represents the left border being currently visible
+ * @param right represents the right border being currently visible
+ * @param top represents the top border being currently visible
+ * @param bottom represents the bottom border being currently visible
+ */
+ void updateBorderButtons( const KoBorder& left, const KoBorder& right,
+ const KoBorder& top, const KoBorder& bottom );
+
+ void showStyle( const QString & styleName );
+ void showRulerIndent( double leftMargin, double firstLine, double rightMargin, bool rtl );
+ void showZoom( int zoom ); // show a zoom value in the combo
+ void showZoom( const QString& zoom ); // show a zoom value in the combo
+ void setZoom( int zoom, bool updateViews ); // change the zoom value
+
+ bool viewFrameBorders() const { return m_viewFrameBorders; }
+ void setViewFrameBorders(bool b);
+
+ /**
+ * Returns the KWord global KSpell2 Broker object.
+ */
+ KSpell2::Broker *broker() const;
+
+ void setNoteType(NoteType nt, bool change=true);
+
+ KWDocument *kWordDocument()const { return m_doc; }
+ KWGUI *getGUI()const { return m_gui; }
+ KWViewMode* viewMode() const;
+
+ void updateStyleList();
+ void updateFrameStyleList();
+ void updateTableStyleList();
+
+ void initGui();
+
+ /// returns the current page number this view is looking at
+ int currentPage() const;
+
+ /**
+ * Overloaded from View
+ */
+ bool doubleClickActivation() const;
+ /**
+ * Overloaded from View
+ */
+ QWidget* canvas() const;
+ /**
+ * Overloaded from View
+ */
+ int canvasXOffset() const;
+ /**
+ * Overloaded from View
+ */
+ int canvasYOffset() const;
+ /**
+ * Overloaded vrom View
+ */
+ void canvasAddChild( KoViewChild *child );
+
+ virtual void setupPrinter( KPrinter &printer );
+ virtual void print( KPrinter &printer );
+
+ virtual QPoint applyViewTransformations( const QPoint& ) const;
+ virtual QPoint reverseViewTransformations( const QPoint& ) const;
+
+ void changeNbOfRecentFiles(int nb);
+
+ void changeZoomMenu( int zoom=-1);
+
+ void refreshMenuExpression();
+
+ void updateGridButton();
+
+ void deleteFrame(bool warning=true);
+
+ QPopupMenu * popupMenu( const QString& name );
+
+ QPtrList<KAction> &dataToolActionList() { return m_actionList; }
+ QPtrList<KAction> &variableActionList() { return m_variableActionList; }
+ QPtrList<KAction> &tableActions() { return m_tableActionList; }
+
+ enum { // bitfield
+ ProvidesImage = 1,
+ ProvidesPlainText = 2,
+ ProvidesOasis = 4,
+ ProvidesFormula = 8
+ };
+ static int checkClipboard( QMimeSource *data );
+
+ bool insertInlinePicture();
+
+ void displayFrameInlineInfo();
+
+ void initGUIButton();
+
+ void updateHeaderFooterButton();
+ void updateFooter();
+ void updateHeader();
+ void switchModeView();
+ void changeFootNoteMenuItem( bool b);
+ void insertFile(const KURL& url);
+ void testAndCloseAllFrameSetProtectedContent();
+ void updateBgSpellCheckingState();
+ void updateRulerInProtectContentMode();
+ void deselectAllFrames();
+ void autoSpellCheck(bool b);
+ void insertDirectCursor(bool b);
+ void updateDirectCursorButton();
+
+ void deleteFrameSet( KWFrameSet *);
+
+ QPtrList<KAction> listOfResultOfCheckWord( const QString &word );
+
+ int tableSelectCell(const QString &tableName, uint row, uint col);
+ void tableInsertRow(uint row, KWTableFrameSet *table = 0);
+ void tableInsertCol(uint col, KWTableFrameSet *table = 0);
+ int tableDeleteRow(const QValueList<uint>& rows, KWTableFrameSet *table = 0);
+ int tableDeleteCol(const QValueList<uint>& cols, KWTableFrameSet *table = 0);
+
+ void pasteData( QMimeSource* data, bool drop );
+
+ KWFrameViewManager* frameViewManager() const;
+
+public slots:
+ void fileStatistics();
+ void editCut();
+ void editCopy();
+ void editPaste();
+ void editSelectAll();
+ void editSelectAllFrames();
+ void editSelectCurrentFrame();
+ void editFind();
+ void editFindNext();
+ void editFindPrevious();
+ void editReplace();
+ void editDeleteFrame();
+ void editCustomVariable();
+ void editCustomVars();
+ void editMailMergeDataBase();
+ void createLinkedFrame();
+
+ void viewTextMode();
+ void viewPageMode();
+ void viewPreviewMode();
+ void slotViewFormattingChars();
+ void slotViewFrameBorders();
+ void viewHeader();
+ void viewFooter();
+ void viewZoom( const QString &s );
+ void updateZoom();
+
+ void insertTable();
+ void insertPicture();
+ void insertSpecialChar();
+ void insertFrameBreak();
+ void insertVariable();
+ void insertFootNote();
+ void insertContents();
+ void insertLink();
+ void insertComment();
+ void removeComment();
+ void copyTextOfComment();
+
+ void insertPage();
+ void deletePage();
+
+ void formatFont();
+ void formatParagraph();
+ void formatPage();
+ void formatFrameSet();
+
+ void slotSpellCheck();
+ void extraAutoFormat();
+ void extraFrameStylist();
+ void extraStylist();
+ void extraCreateTemplate();
+
+ void toolsCreateText();
+ void insertFormula( QMimeSource* source=0 );
+ void toolsPart();
+
+ void tableProperties();
+ void tableInsertRow();
+ void tableInsertCol();
+ void tableResizeCol();
+ void tableDeleteRow();
+ void tableDeleteCol();
+ void tableJoinCells();
+ void tableSplitCells();
+ void tableSplitCells(int col, int row);
+ void tableProtectCells(bool);
+ void tableUngroupTable();
+ void tableDelete();
+ void tableStylist();
+ void convertTableToText();
+ void sortText();
+ void addPersonalExpression();
+
+ void slotStyleSelected();
+ void slotFrameStyleSelected();
+ void slotTableStyleSelected();
+ void textStyleSelected( int );
+ void frameStyleSelected( int );
+ void tableStyleSelected( int );
+ void textSizeSelected( int );
+ void increaseFontSize();
+ void decreaseFontSize();
+ void textFontSelected( const QString & );
+ void textBold();
+ void textItalic();
+ void textUnderline();
+ void textStrikeOut();
+ void textColor();
+ void textAlignLeft();
+ void textAlignCenter();
+ void textAlignRight();
+ void textAlignBlock();
+ void textSpacingSingle();
+ void textSpacingOneAndHalf();
+ void textSpacingDouble();
+ void textSuperScript();
+ void textSubScript();
+ void textIncreaseIndent();
+ void textDecreaseIndent();
+ void textDefaultFormat();
+ void slotCounterStyleSelected();
+
+ // Text and Frame borders.
+ void borderOutline();
+ void borderLeft();
+ void borderRight();
+ void borderTop();
+ void borderBottom();
+ void backgroundColor();
+
+ void showFormulaToolbar( bool show );
+
+ void configure();
+ void configureCompletion();
+
+ void newPageLayout( const KoPageLayout &layout );
+ void newLeftIndent( double leftIndent);
+ void newFirstIndent( double firstIndent);
+ void newRightIndent( double rightIndent);
+
+ void clipboardDataChanged();
+ void tabListChanged( const KoTabulatorList & tabList );
+
+ void updatePageInfo();
+ void updateFrameStatusBarItem();
+ void setTemporaryStatusBarText(const QString &text);
+
+ void slotSpecialChar(QChar , const QString &);
+ void slotFrameSetEditChanged();
+ void showMouseMode( int /*KWCanvas::MouseMode*/ mouseMode );
+ void frameSelectedChanged();
+ void docStructChanged(int type);
+ void documentModified( bool );
+ void changeOverwriteMode( bool );
+ void slotHRulerDoubleClicked();
+ void slotHRulerDoubleClicked( double );
+ void slotUnitChanged(KoUnit::Unit);
+
+ void numPagesChanged();
+
+ void insertExpression();
+
+ void updateTocActionText(bool hasToc);
+
+ void changeCaseOfText();
+
+ void editPersonalExpr();
+
+ void slotUpdateRuler();
+ void slotEmbedImage( const QString &filename );
+
+ void insertCustomVariable();
+ void insertNewCustomVariable();
+ void slotSpecialCharDlgClosed();
+
+ void refreshCustomMenu();
+
+ void changePicture();
+
+ void configureHeaderFooter();
+
+ void inlineFrame();
+
+ /** Move the selected frame above maximum 1 frame that is in front of it. */
+ void raiseFrame() { adjustZOrderOfSelectedFrames(RaiseFrame); };
+ /** Move the selected frame behind maximum 1 frame that is behind it */
+ void lowerFrame() { adjustZOrderOfSelectedFrames(LowerFrame); };
+ /** Move the selected frame(s) to be in the front most position. */
+ void bringToFront() { adjustZOrderOfSelectedFrames(BringToFront); };
+ /** Move the selected frame(s) to be behind all other frames */
+ void sendToBack() { adjustZOrderOfSelectedFrames(SendToBack); };
+
+ void openLink();
+ void changeLink();
+ void copyLink();
+ void removeLink();
+ void addToBookmark();
+ void editComment();
+ void showDocStructure();
+ void showRuler();
+ void viewGrid();
+ void viewSnapToGrid();
+
+ void slotSoftHyphen();
+ void slotLineBreak();
+ void slotNonbreakingSpace();
+ void slotNonbreakingHyphen();
+
+ void slotIncreaseNumberingLevel();
+ void slotDecreaseNumberingLevel();
+
+ void refreshAllVariable();
+
+ void slotAllowAutoFormat();
+
+ void slotCompletion();
+
+ void applyAutoFormat();
+ void createStyleFromSelection();
+
+ void configureFootEndNote();
+ void editFootEndNote();
+ void changeFootNoteType();
+ void savePicture();
+
+ void autoSpellCheck();
+ void goToFootEndNote();
+
+ // Document Structure Area popup menu.
+ void docStructEdit();
+ void docStructSpeak();
+ void docStructSelect();
+ void docStructDelete();
+ void docStructProperties();
+ void openDocStructurePopupMenu( const QPoint &p, KWFrameSet *frameset, KWTextParag *parag);
+
+ void insertFile();
+
+ void addBookmark();
+ void selectBookmark();
+ void importStyle();
+
+ void createFrameStyle();
+
+ void insertDirectCursor();
+
+ void convertToTextBox();
+
+ void slotAddIgnoreAllWord();
+
+ void embeddedStoreInternal();
+
+ void goToDocumentStructure();
+ void goToDocument();
+
+ void addWordToDictionary();
+
+ void insertPicture( const KoPicture& picture, const bool makeInline, const bool keepRatio, int suggestedWidth, int suggestedHeight );
+
+ // end of public methods
+protected slots:
+ virtual void slotChildActivated( bool a ); ///< from KoView
+ void slotSetInitialPosition();
+
+ void spellCheckerMisspelling( const QString &, int );
+ void spellCheckerCorrected( const QString &, int, const QString & );
+ void spellCheckerDone( const QString & );
+ void spellCheckerCancel();
+
+ void spellAddAutoCorrect (const QString & originalword, const QString & newword);
+ void slotApplyFont();
+ void slotApplyParag();
+ void slotPageLayoutChanged( const KoPageLayout& layout );
+ void slotChangeCaseState(bool b);
+ void slotChangeCutState(bool b);
+ void slotCorrectWord();
+
+ /// This slot is called when the document has finished loading.
+ void slotDocumentLoadingCompleted();
+
+protected:
+ void addVariableActions( int type, const QStringList & texts,
+ KActionMenu * parentMenu, const QString & menuText );
+
+ void loadexpressionActions( KActionMenu * parentMenu);
+
+ void createExpressionActions( KActionMenu * parentMenu,const QString& filename,int &i , bool insertSepar, const QMap<QString, KShortcut>& personalShortCut );
+
+ void showParagraphDialog( int initialPage = -1, double initialTabPos = 0.0 );
+
+ KWTextFrameSetEdit *currentTextEdit() const;
+ /** The current text-edit if there is one, otherwise the selected text objects
+ * This is what the "bold", "italic" etc. buttons apply to. */
+ QPtrList<KoTextFormatInterface> applicableTextInterfaces() const;
+
+ void setupActions();
+
+ virtual void resizeEvent( QResizeEvent *e );
+ virtual void guiActivateEvent( KParts::GUIActivateEvent *ev );
+
+ virtual void updateReadWrite( bool readwrite );
+ /**
+ * Make sure the actions related to tables have the right texts and enabled options.
+ * @param selectFrames a list of selected frames
+ * @see KWFrameViewManager::selectedFrames()
+ */
+ void updateTableActions( QValueList<KWFrameView*> selectFrames);
+
+
+ void startKSpell();
+ void clearSpellChecker(bool cancelSpellCheck = false );
+
+ QValueList<QString> getInlineFramesets( const QDomNode &framesetElem );
+
+ // Helper stuff for the frame adjustment;
+ enum MoveFrameType { RaiseFrame, LowerFrame, BringToFront, SendToBack };
+ void adjustZOrderOfSelectedFrames(MoveFrameType moveType);
+ void increaseAllZOrdersAbove(int refZOrder, int pageNum, const QPtrList<KWFrame>& frameSelection);
+ void decreaseAllZOrdersUnder(int refZOrder, int pageNum, const QPtrList<KWFrame>& frameSelection);
+ int raiseFrame(const QPtrList<KWFrame>& frameSelection, const KWFrame *frame);
+ int lowerFrame(const QPtrList<KWFrame>& frameSelection, const KWFrame *frame);
+ int bringToFront(const QPtrList<KWFrame>& frameSelection, const KWFrame *frame);
+ int sendToBack(const QPtrList<KWFrame>& frameSelection, const KWFrame *frame);
+ void textStyleSelected( KoParagStyle *sty );
+ void frameStyleSelected( KWFrameStyle *sty );
+ void tableStyleSelected( KWTableStyle *sty );
+ void changeFootEndNoteState();
+ void refreshDeletePageAction();
+
+ void spellCheckerRemoveHighlight();
+
+ void setSpacing( KoParagLayout::SpacingType spacing, const QString &commandName );
+
+private: // methods
+ void deleteSelectedFrames();
+ void borderChanged(KoBorder::BorderType type);
+ void updateZoomControls();
+
+private: // variables
+ KWDocument *m_doc;
+
+ KAction *m_actionFileStatistics;
+ KAction *m_actionEditCut;
+ KAction *m_actionEditCopy;
+ KAction *m_actionEditPaste;
+ KAction *m_actionEditSelectAll;
+ KAction *m_actionEditSelectCurrentFrame;
+ KAction *m_actionEditDelFrame;
+ KAction *m_actionCreateLinkedFrame;
+ KAction *m_actionRaiseFrame;
+ KAction *m_actionLowerFrame;
+ KAction *m_actionSendBackward;
+ KAction *m_actionBringToFront;
+
+ KAction *m_actionEditCustomVars;
+ KAction *m_actionEditCustomVarsEdit;
+ KAction *m_actionEditFind;
+ KAction *m_actionEditFindNext;
+ KAction *m_actionEditFindPrevious;
+ KAction *m_actionEditReplace;
+ KAction *m_actionApplyAutoFormat;
+
+ KToggleAction *m_actionViewTextMode;
+ KToggleAction *m_actionViewPageMode;
+ KToggleAction *m_actionViewPreviewMode;
+
+ KToggleAction *m_actionViewFormattingChars;
+ KToggleAction *m_actionViewFrameBorders;
+ KToggleAction *m_actionViewHeader;
+ KToggleAction *m_actionViewFooter;
+ KToggleAction *m_actionViewFootNotes;
+ KToggleAction *m_actionViewEndNotes;
+ KToggleAction *m_actionShowDocStruct;
+ KToggleAction *m_actionShowRuler;
+ KToggleAction *m_actionViewShowGrid;
+ KToggleAction *m_actionViewSnapToGrid;
+ KToggleAction *m_actionAllowAutoFormat;
+
+ KToggleAction *m_actionAllowBgSpellCheck;
+
+ KSelectAction *m_actionViewZoom;
+
+ KAction *m_actionInsertFrameBreak;
+ KAction *m_actionInsertFootEndNote;
+ KAction *m_actionInsertContents;
+ KAction *m_actionInsertLink;
+ KAction *m_actionInsertComment;
+ KAction *m_actionEditComment;
+ KAction *m_actionRemoveComment;
+ KAction *m_actionCopyTextOfComment;
+ //KAction *actionInsertPage;
+ KAction *m_actionDeletePage;
+
+ KActionMenu *actionInsertVariable;
+ struct VariableDef {
+ int type;
+ int subtype;
+ };
+ typedef QMap<KAction *, VariableDef> VariableDefMap;
+ KActionMenu *m_actionInsertExpression;
+
+ KActionMenu *m_actionInsertCustom;
+
+ VariableDefMap m_variableDefMap;
+ KAction *m_actionInsertFormula;
+ KAction *m_actionInsertTable;
+ KAction *m_actionAutoFormat;
+
+ KToggleAction *m_actionToolsCreateText;
+ KToggleAction *m_actionToolsCreatePix;
+ KoPartSelectAction *m_actionToolsCreatePart;
+
+ KAction *m_actionFormatFont;
+ KAction *m_actionFormatDefault;
+ KAction *m_actionFormatFrameStylist;
+ KAction *m_actionFormatStylist;
+ KAction *m_actionFormatPage;
+
+ KAction *m_actionFontSizeIncrease;
+ KAction *m_actionFontSizeDecrease;
+
+ KFontSizeAction *m_actionFormatFontSize;
+ KFontAction *m_actionFormatFontFamily;
+ KSelectAction *m_actionFormatStyle;
+ KActionMenu *m_actionFormatStyleMenu;
+ KToggleAction *m_actionFormatBold;
+ KToggleAction *m_actionFormatItalic;
+ KToggleAction *m_actionFormatUnderline;
+ KToggleAction *m_actionFormatStrikeOut;
+ TKSelectColorAction *m_actionFormatColor;
+ KToggleAction *m_actionFormatAlignLeft;
+ KToggleAction *m_actionFormatAlignCenter;
+ KToggleAction *m_actionFormatAlignRight;
+ KToggleAction *m_actionFormatAlignBlock;
+ KToggleAction *m_actionFormatSpacingSingle;
+ KToggleAction *m_actionFormatSpacingOneAndHalf;
+ KToggleAction *m_actionFormatSpacingDouble;
+ KAction *m_actionFormatParag;
+ KAction *m_actionFormatFrameSet;
+ KAction *m_actionFormatIncreaseIndent;
+ KAction *m_actionFormatDecreaseIndent;
+ KActionMenu *m_actionFormatBullet;
+ KActionMenu *m_actionFormatNumber;
+ KToggleAction *m_actionFormatSuper;
+ KToggleAction *m_actionFormatSub;
+ KAction* m_actionInsertSpecialChar;
+
+ // Text and Frame borders.
+ KSelectAction *m_actionFrameStyle;
+ KActionMenu *m_actionFrameStyleMenu;
+ KSelectAction *m_actionTableStyle;
+ KActionMenu *m_actionTableStyleMenu;
+ KToggleAction *m_actionBorderLeft;
+ KToggleAction *m_actionBorderRight;
+ KToggleAction *m_actionBorderTop;
+ KToggleAction *m_actionBorderBottom;
+ KToggleAction *m_actionBorderOutline;
+ TKSelectColorAction *m_actionBorderColor;
+ KSelectAction *m_actionBorderWidth;
+ KSelectAction *m_actionBorderStyle;
+ TKSelectColorAction *m_actionBackgroundColor;
+
+ KAction *m_actionTableDelRow;
+ KAction *m_actionTableDelCol;
+ KAction *m_actionTableInsertRow;
+ KAction *m_actionTableInsertCol;
+ KAction *m_actionTableResizeCol;
+ KAction *m_actionTableJoinCells;
+ KAction *m_actionTableSplitCells;
+ KAction *m_actionConvertTableToText;
+ KAction *m_actionSortText;
+ KAction *m_actionAddPersonalExpression;
+ KToggleAction *m_actionTableProtectCells;
+
+ KAction *m_actionTableUngroup;
+ KAction *m_actionTableDelete;
+
+ KAction *m_actionTableStylist;
+ KAction *m_actionTablePropertiesMenu;
+ KAction *m_actionTableProperties;
+
+ KAction *m_actionExtraCreateTemplate;
+
+ KAction *m_actionChangeCase;
+
+ KAction *m_actionEditPersonnalExpr;
+
+ KAction *m_actionConfigure;
+
+ KAction *m_actionConfigureCompletion;
+
+ KAction *m_actionSavePicture;
+
+ KAction *m_actionConfigureHeaderFooter;
+ KToggleAction *m_actionInlineFrame;
+
+ KAction *m_actionOpenLink;
+ KAction *m_actionChangeLink;
+ KAction *m_actionCopyLink;
+ KAction *m_actionAddLinkToBookmak;
+ KAction *m_actionRemoveLink;
+
+ KAction *m_actionRefreshAllVariable;
+ KAction *m_actionCreateStyleFromSelection;
+
+ KAction *m_actionConfigureFootEndNote;
+
+ KAction *m_actionEditFootEndNote;
+
+ KAction *m_actionChangeFootNoteType;
+
+ KAction *m_actionGoToFootEndNote;
+
+ // Document Structure Area popup menu.
+ KAction *m_actionDocStructEdit;
+ KAction *m_actionDocStructSpeak;
+ KAction *m_actionDocStructSelect;
+ KAction *m_actionDocStructDelete;
+ KAction *m_actionDocStructProperties;
+
+ KAction *m_actionInsertFile;
+
+ KAction *m_actionAddBookmark;
+ KAction *m_actionSelectBookmark;
+
+ KAction *m_actionImportStyle;
+
+ KAction *m_actionCreateFrameStyle;
+
+ KAction *m_actionConvertToTextBox;
+
+ KAction *m_actionSpellIgnoreAll;
+ KAction *m_actionSpellCheck;
+
+ KToggleAction *m_actionEmbeddedStoreInternal;
+
+ KAction *m_actionAddWordToPersonalDictionary;
+
+ KToggleAction *m_actionInsertDirectCursor;
+
+ KAction *m_actionGoToDocumentStructure;
+ KAction *m_actionGoToDocument;
+
+
+ KoCharSelectDia *m_specialCharDlg;
+ KoFontDia *m_fontDlg;
+ KoParagDia *m_paragDlg;
+
+ KWGUI *m_gui;
+
+ DCOPObject *m_dcop;
+
+ KoSearchContext *m_searchEntry, *m_replaceEntry;
+ KWFindReplace *m_findReplace;
+
+ QPtrList<KAction> m_actionList; // for the kodatatools
+ QPtrList<KAction> m_variableActionList;
+ QPtrList<KAction> m_tableActionList;
+
+ KWPage *m_currentPage; ///< current page number
+
+ // Statusbar items
+ KStatusBarLabel* m_sbPageLabel; ///< 'Current page number and page count' label
+ KStatusBarLabel* m_sbModifiedLabel;
+ KStatusBarLabel* m_sbFramesLabel; ///< Info about selected frames
+ KStatusBarLabel* m_sbOverwriteLabel;
+ KStatusBarLabel* m_sbUnitLabel;
+ KStatusBarLabel* m_sbZoomLabel;
+
+ // Zoom values for each viewmode ( todo a viewmode enum and a qmap or so )
+ struct KWZoomValueStore {
+ int m_zoom;
+ KoZoomMode::Mode m_zoomMode;
+ };
+ KWZoomValueStore m_zoomViewModeNormal;
+ KWZoomValueStore m_zoomViewModePreview;
+
+ bool m_viewFrameBorders /*, m_viewTableGrid*/;
+
+ /// Spell-checking
+ struct {
+ KoSpell *kospell;
+ KMacroCommand * macroCmdSpellCheck;
+ QStringList replaceAll;
+ KoTextIterator * textIterator;
+ KSpell2::Dialog *dlg;
+ } m_spell;
+ KSpell2::Broker::Ptr m_broker;
+
+
+ KWFrameSet *m_fsInline;
+
+ // Split cell in table
+ struct {
+ unsigned int columns, rows;
+ } m_tableSplit;
+};
+
+/******************************************************************/
+/* Class: KWViewWidget */
+/******************************************************************/
+class KWViewWidget : public QWidget
+{
+ Q_OBJECT
+
+public:
+ KWViewWidget( QWidget *parent, KWView *view );
+
+protected:
+ void resizeEvent( QResizeEvent *e );
+
+ // A pointer to the view.
+ KWView *m_view;
+};
+
+/******************************************************************/
+/* Class: KWGUI */
+/******************************************************************/
+
+class KWGUI : public QHBox
+{
+ Q_OBJECT
+
+public:
+ KWGUI( const QString& viewMode, QWidget *parent, KWView *view );
+
+ void showGUI();
+
+ KWView *getView()const { return m_view; }
+ KWCanvas *canvasWidget()const { return m_canvas; }
+ KoRuler *getVertRuler()const { return m_vertRuler; }
+ KoRuler *getHorzRuler()const { return m_horRuler; }
+ KoTabChooser *getTabChooser()const { return m_tabChooser; }
+ KWDocStruct *getDocStruct()const { return m_docStruct; }
+
+public slots:
+ void reorganize();
+
+protected slots:
+ void unitChanged( KoUnit::Unit );
+
+protected:
+ void resizeEvent( QResizeEvent *e );
+
+ // A pointer to the view.
+ KWView *m_view;
+
+ // The left side
+ KWDocStruct *m_docStruct;
+
+ // The right side
+ QWidget *m_right; // The layout widget.
+
+ KoTabChooser *m_tabChooser;
+ KoRuler *m_vertRuler;
+ KoRuler *m_horRuler;
+ KWCanvas *m_canvas;
+
+ QSplitter *m_panner;
+
+};
+
+#endif
diff --git a/kword/KWViewMode.cpp b/kword/KWViewMode.cpp
new file mode 100644
index 00000000..df6c8ed1
--- /dev/null
+++ b/kword/KWViewMode.cpp
@@ -0,0 +1,603 @@
+/* This file is part of the KDE project
+ Copyright (C) 2001-2005 David Faure <faure@kde.org>
+ Copyright (C) 2005 Thomas Zander <zander@kde.org>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+*/
+
+#include "KWViewMode.h"
+#include "KWCanvas.h"
+#include "KWView.h"
+#include "KWDocument.h"
+#include "KWTextFrameSet.h"
+#include "KWFrameSet.h"
+#include "KWTableFrameSet.h"
+#include "KWPageManager.h"
+#include "KWPage.h"
+#include "KWFrameViewManager.h"
+#include "KWFrameView.h"
+#include <qapplication.h>
+#include <kdebug.h>
+
+const unsigned short KWViewMode::s_shadowOffset = 3;
+
+QSize KWViewMode::availableSizeForText( KWTextFrameSet* textfs )
+{
+ KWFrame* frame = textfs->frameIterator().getLast();
+ return m_doc->zoomSize( KoSize( frame->innerWidth(), frame->internalY() + frame->innerHeight() ) );
+
+}
+
+void KWViewMode::drawOnePageBorder( QPainter * painter, const QRect & crect, const QRect & _pageRect,
+ const QRegion & emptySpaceRegion )
+{
+ if ( !crect.intersects( _pageRect ) )
+ return;
+
+ QRect pageRect( _pageRect );
+ //kdDebug() << "KWViewMode::drawOnePageBorder drawing page rect " << pageRect << endl;
+ painter->drawRect( pageRect );
+ // Exclude page border line, to get the page contents rect (avoids flicker)
+ pageRect.rLeft() += 1;
+ pageRect.rTop() += 1;
+ pageRect.rRight() -= 1;
+ pageRect.rBottom() -= 1;
+ // The empty space to clear up inside this page
+ QRect pagecrect = pageRect.intersect( crect );
+ if ( !pagecrect.isEmpty() )
+ {
+ //kdDebug() << "KWViewMode::drawOnePageBorder : pagecrect=" << pagecrect << " emptySpaceRegion: " << emptySpaceRegion << endl;
+ QRegion pageEmptyRegion = emptySpaceRegion.intersect( pagecrect );
+ //kdDebug() << "RESULT: pageEmptyRegion: " << pageEmptyRegion << endl;
+ if ( !pageEmptyRegion.isEmpty() )
+ m_doc->eraseEmptySpace( painter, pageEmptyRegion, QApplication::palette().active().brush( QColorGroup::Base ) );
+ }
+}
+
+QRect KWViewMode::drawRightShadow( QPainter * painter, const QRect & crect, const QRect & pageRect, int topOffset )
+{
+ QRect shadowRect( pageRect.right() + 1, pageRect.top() + topOffset, s_shadowOffset, pageRect.height() - topOffset );
+ shadowRect &= crect; // intersect
+ if ( !shadowRect.isEmpty() )
+ {
+ painter->fillRect( shadowRect,
+ QApplication::palette().active().brush( QColorGroup::Shadow ) );
+ }
+ return shadowRect;
+}
+
+QRect KWViewMode::drawBottomShadow( QPainter * painter, const QRect & crect, const QRect & pageRect, int leftOffset )
+{
+ QRect shadowRect( pageRect.left() + leftOffset, pageRect.bottom() + 1, pageRect.width(), s_shadowOffset );
+ shadowRect &= crect; // intersect
+ if ( !shadowRect.isEmpty() )
+ painter->fillRect( shadowRect,
+ QApplication::palette().active().brush( QColorGroup::Shadow ) );
+ return shadowRect;
+}
+
+QPoint KWViewMode::pageCorner()
+{
+ // Same code as KWView::slotUpdateRuler
+ KWFrame * frame = 0L;
+ // Use the currently edited (fallback: the first selected) frame
+ if( m_canvas->currentFrameSetEdit() && m_canvas->currentFrameSetEdit()->currentFrame() )
+ frame = m_canvas->currentFrameSetEdit()->currentFrame();
+ else {
+ KWFrameView *view = m_canvas->frameViewManager()->selectedFrame();
+ frame = view == 0 ? 0 : view->frame();
+ }
+
+ int pageNum = 0;
+ if ( frame )
+ pageNum = frame->pageNumber();
+ QPoint nPoint( 0, m_doc->pageTop(pageNum) + 1 );
+ QPoint cPoint( normalToView( nPoint ) );
+ /*kdDebug() << "KWViewMode::pageCorner frame=" << frame << " pagenum=" << pageNum
+ << " nPoint=" << nPoint.x() << "," << nPoint.y()
+ << " cPoint=" << cPoint.x() << "," << cPoint.y() << endl;*/
+ return cPoint;
+}
+
+QRect KWViewMode::rulerFrameRect()
+{
+ // Set the "frame start" in the ruler (tabs are relative to that position)
+ KWFrameSetEdit * edit = m_canvas->currentFrameSetEdit();
+ KWFrame * frame = 0L;
+ // Use the currently edited (fallback: the first selected) frame
+ if ( edit && edit->currentFrame() )
+ frame = edit->currentFrame();
+ else {
+ KWFrameView *view = m_canvas->frameViewManager()->selectedFrame();
+ frame = view == 0 ? 0 : view->frame();
+ }
+ if( !frame) {
+ KWFrameSet *fs= m_doc->frameSet(0);
+ if(fs) frame=fs->frame(0);
+ }
+ if ( frame )
+ {
+ QRect r = normalToView( m_doc->zoomRect( frame->innerRect() ) );
+
+ // Calculate page corner (see pageCorner above)
+ int pageNum = frame->pageNumber();
+ QPoint nPoint( 0, m_doc->pageTop(pageNum) + 1 );
+ QPoint cPoint( normalToView( nPoint ) );
+
+ // Frame start/end is relative to page corner.
+ r.moveBy( -cPoint.x(), -cPoint.y() );
+ return r;
+ }
+ return QRect();
+}
+
+void KWViewMode::setPageLayout( KoRuler* hRuler, KoRuler* vRuler, const KoPageLayout& layout )
+{
+ hRuler->setPageLayout( layout );
+ vRuler->setPageLayout( layout );
+}
+
+// static
+KWViewMode * KWViewMode::create( const QString & viewModeType, KWDocument *doc, KWCanvas* canvas )
+{
+ Q_ASSERT(doc);
+ if(viewModeType=="ModeNormal")
+ {
+ return new KWViewModeNormal( doc, canvas, doc->viewFrameBorders() );
+ }
+ else if(viewModeType=="ModeEmbedded")
+ {
+ return new KWViewModeEmbedded( doc, canvas );
+ }
+ else if(viewModeType=="ModePreview")
+ {
+ return new KWViewModePreview( doc, canvas, doc->viewFrameBorders(), doc->nbPagePerRow() );
+ }
+ else if(viewModeType=="ModeText")
+ {
+ KWTextFrameSet* fs = KWViewModeText::determineTextFrameSet( doc ); // could be 0
+ return new KWViewModeText( doc, canvas, fs );
+ }
+ else
+ {
+ kdDebug() << viewModeType << " mode type is unknown\n";
+ return 0;
+ }
+}
+
+////
+
+QSize KWViewModeNormal::contentsSize()
+{
+ return QSize( m_doc->paperWidth(m_doc->startPage()),
+ m_doc->zoomItY( m_doc->pageManager()->bottomOfPage(m_doc->lastPage()) ) );
+}
+
+QRect KWViewModeNormal::viewPageRect( int pgNum )
+{
+ KWPage* page = m_doc->pageManager()->page( pgNum );
+ QRect r = page->zoomedRect( m_doc );
+ r.moveBy( xOffset( page ), 0 );
+ return r;
+}
+
+QPoint KWViewModeNormal::normalToView( const QPoint & nPoint )
+{
+ double unzoomedY = m_doc->unzoomItY( nPoint.y() );
+ KWPage *page = m_doc->pageManager()->page(unzoomedY); // quotient
+ if( !page) {
+ kdWarning(31001) << "KWViewModeNormal::normalToView request for conversion out of the document! Check your input data.. ("<< nPoint << ")" << endl;
+ return QPoint(0,0);
+ }
+ Q_ASSERT(canvas());
+ return QPoint( xOffset(page) + nPoint.x(), nPoint.y() );
+}
+
+QPoint KWViewModeNormal::viewToNormal( const QPoint & vPoint )
+{
+ // Opposite of the above
+ // The Y is unchanged by the centering so we can use it to get the page.
+ double unzoomedY = m_doc->unzoomItY( vPoint.y() );
+ KWPage *page = m_doc->pageManager()->page(unzoomedY); // quotient
+ if( !page) {
+ kdWarning(31001) << "KWViewModeNormal::normalToView request for conversion out of the document! Check your input data.. ("<< vPoint << ")" << endl;
+ return QPoint(-1,-1); // yes this is an ugly way to mark this as an excetional state...
+ }
+ Q_ASSERT(canvas());
+ return QPoint( vPoint.x() - xOffset(page), vPoint.y() );
+}
+
+int KWViewModeNormal::xOffset(KWPage *page, int canvasWidth /* = -1 */) {
+ // Center horizontally
+ if(canvasWidth < 0)
+ canvasWidth = canvas()->visibleWidth();
+ return kMax( 0, ( canvasWidth - m_doc->zoomItX( page->width() ) ) / 2 );
+}
+
+void KWViewModeNormal::drawPageBorders( QPainter * painter, const QRect & crect, const QRegion & emptySpaceRegion )
+{
+ painter->save();
+ painter->setPen( QApplication::palette().active().color( QColorGroup::Dark ) );
+ painter->setBrush( Qt::NoBrush );
+ QRect pageRect;
+
+ int lastPage = m_doc->lastPage();
+ Q_ASSERT(canvas());
+ const int canvasWidth = canvas()->visibleWidth();
+ double pagePosPt = 0;
+ int topOfPage = 0; // in pixels
+ for ( int pageNr = m_doc->startPage(); pageNr <= lastPage; pageNr++ )
+ {
+ KWPage *page = m_doc->pageManager()->page(pageNr);
+
+ int pageWidth = m_doc->zoomItX( page->width() );
+ int pageHeight = m_doc->zoomItY( pagePosPt + page->height() ) - topOfPage;
+ if ( crect.bottom() < topOfPage )
+ break;
+ // Center horizontally
+ int x = xOffset(page, canvasWidth);
+ // Draw page border (and erase empty area inside page)
+ pageRect = QRect( x, topOfPage, pageWidth, pageHeight );
+ drawOnePageBorder( painter, crect, pageRect, emptySpaceRegion );
+
+ // The area on the left of the page
+ QRect leftArea( 0, topOfPage, x, pageHeight );
+ leftArea &= crect;
+ if ( !leftArea.isEmpty() ) {
+ painter->fillRect( leftArea,
+ QApplication::palette().active().brush( QColorGroup::Mid ) );
+ }
+
+ // The area on the right of the page
+ QRect rightArea( x + pageWidth, topOfPage, crect.right() - pageWidth + 1, pageHeight );
+ rightArea &= crect;
+ if ( !rightArea.isEmpty() )
+ {
+ painter->fillRect( rightArea,
+ QApplication::palette().active().brush( QColorGroup::Mid ) );
+
+ // Draw a shadow
+ int topOffset = ( page==0 ) ? s_shadowOffset : 0; // leave a few pixels on top, only for first page
+ drawRightShadow( painter, crect, pageRect, topOffset );
+ }
+ pagePosPt += page->height(); // for next page already..
+ topOfPage += pageHeight;
+ }
+ // Take care of the area at the bottom of the last page
+ if ( crect.bottom() > topOfPage )
+ {
+ QRect bottomArea( 0, topOfPage, crect.right() + 1, crect.bottom() - topOfPage + 1 );
+ QRect repaintRect = bottomArea.intersect( crect );
+ if ( !repaintRect.isEmpty() )
+ {
+ painter->fillRect( repaintRect,
+ QApplication::palette().active().brush( QColorGroup::Mid ) );
+ // Draw a shadow
+ drawBottomShadow( painter, crect, pageRect, s_shadowOffset );
+ }
+ }
+ painter->restore();
+}
+
+////
+
+QRect KWViewModeEmbedded::viewPageRect( int pgNum )
+{
+ // Only one page makes sense in embedded mode though
+ return m_doc->pageManager()->page( pgNum )->zoomedRect( m_doc );
+}
+
+//////////////////////// Preview mode ////////////////////////////////
+
+KWViewModePreview::KWViewModePreview( KWDocument * doc, KWCanvas* canvas,
+ bool drawFrameBorders, int _nbPagePerRow )
+ : KWViewMode( doc, canvas, drawFrameBorders ),
+ m_pagesPerRow(_nbPagePerRow),
+ m_spacing(10)
+{}
+
+int KWViewModePreview::leftSpacing()
+{
+ if ( canvas() )
+ {
+ int pagesPerRow;
+ if ( m_doc->pageCount() < m_pagesPerRow )
+ pagesPerRow = m_doc->pageCount();
+ else
+ pagesPerRow = m_pagesPerRow;
+
+ int pagesWidth = ( m_spacing + ( m_doc->paperWidth(m_doc->startPage()) + m_spacing ) * pagesPerRow );
+ if ( pagesWidth < canvas()->visibleWidth() )
+ return ( m_spacing + ( canvas()->visibleWidth() / 2 ) - ( pagesWidth / 2 ) );
+ }
+ return m_spacing;
+}
+
+int KWViewModePreview::topSpacing()
+{
+ if ( canvas() )
+ {
+ int pagesHeight = ( m_spacing + ( m_doc->paperHeight(m_doc->startPage()) + m_spacing ) * numRows() );
+ if ( pagesHeight < canvas()->visibleHeight() )
+ return ( m_spacing + ( canvas()->visibleHeight() / 2 ) - ( pagesHeight / 2 ) );
+ }
+ return m_spacing;
+}
+
+int KWViewModePreview::numRows() const
+{
+ return ( m_doc->pageCount() ) / m_pagesPerRow + 1;
+}
+
+QSize KWViewModePreview::contentsSize()
+{
+ int pages = m_doc->pageCount();
+ int rows = (pages-1) / m_pagesPerRow + 1;
+ int hPages = rows > 1 ? m_pagesPerRow : pages;
+ return QSize( m_spacing + hPages * ( m_doc->paperWidth(m_doc->startPage()) + m_spacing ),
+ m_spacing + rows * ( m_doc->paperHeight(m_doc->startPage()) + m_spacing ) /* bottom of last row */ );
+}
+
+QPoint KWViewModePreview::normalToView( const QPoint & nPoint )
+{
+ // Can't use nPoint.y() / m_doc->paperHeight() since this would be a rounding problem
+ double unzoomedY = m_doc->unzoomItY( nPoint.y() );
+ KWPage *page = m_doc->pageManager()->page(unzoomedY); // quotient
+ if( !page) {
+ kdWarning(31001) << "KWViewModePreview::normalToView request for conversion out of the document! Check your input data.. ("<< nPoint << ")" << endl;
+ return QPoint(0,0);
+ }
+
+ double yInPagePt = unzoomedY - page->offsetInDocument();// and rest
+ int row = (page->pageNumber() - m_doc->startPage()) / m_pagesPerRow;
+ int col = (page->pageNumber() - m_doc->startPage()) % m_pagesPerRow;
+ /*kdDebug() << "KWViewModePreview::normalToView nPoint=" << nPoint
+ << " unzoomedY=" << unzoomedY
+ << " page=" << page->pageNumber() << " row=" << row << " col=" << col
+ << " yInPagePt=" << yInPagePt << endl;*/
+ return QPoint( leftSpacing() + col * ( m_doc->paperWidth(page->pageNumber()) +
+ m_spacing ) + nPoint.x(),
+ topSpacing() + row * ( m_doc->paperHeight(page->pageNumber()) +
+ m_spacing ) + m_doc->zoomItY( yInPagePt ) );
+}
+
+QRect KWViewModePreview::viewPageRect( int pgNum )
+{
+ int row = (pgNum - m_doc->startPage()) / m_pagesPerRow;
+ int col = (pgNum - m_doc->startPage()) % m_pagesPerRow;
+ const int paperWidth = m_doc->paperWidth( pgNum );
+ const int paperHeight = m_doc->paperHeight( pgNum );
+ return QRect( leftSpacing() + col * ( paperWidth + m_spacing ),
+ topSpacing() + row * ( paperHeight + m_spacing ),
+ paperWidth,
+ paperHeight );
+}
+
+QPoint KWViewModePreview::viewToNormal( const QPoint & vPoint )
+{
+ // Well, just the opposite of the above.... hmm.... headache....
+ int paperWidth = m_doc->paperWidth(m_doc->startPage());
+ int paperHeight = m_doc->paperHeight(m_doc->startPage());
+ QPoint p( vPoint.x() - leftSpacing(), vPoint.y() - topSpacing() );
+ int col = static_cast<int>( p.x() / ( paperWidth + m_spacing ) );
+ int xInPage = p.x() - col * ( paperWidth + m_spacing );
+ int row = static_cast<int>( p.y() / ( paperHeight + m_spacing ) );
+ int yInPage = p.y() - row * ( paperHeight + m_spacing );
+ int page = row * m_pagesPerRow + col + m_doc->startPage();
+ if ( page > m_doc->lastPage() ) // [this happens when moving frames around and going out of the pages]
+ return QPoint( paperWidth, m_doc->pageTop( m_doc->lastPage() ) );
+ else // normal case
+ return QPoint( xInPage, yInPage + m_doc->pageTop( page ) );
+}
+
+void KWViewModePreview::drawPageBorders( QPainter * painter, const QRect & crect, const QRegion & emptySpaceRegion )
+{
+ painter->save();
+ painter->setPen( QApplication::palette().active().color( QColorGroup::Dark ) );
+ painter->setBrush( Qt::NoBrush );
+ //kdDebug() << "KWViewModePreview::drawPageBorders crect=" << DEBUGRECT( crect ) << endl;
+ QRegion grayRegion( crect );
+ int pageCount = m_doc->pageCount();
+ for ( int counter = 0; counter < pageCount; counter++ )
+ {
+ int row = counter / m_pagesPerRow;
+ int col = counter % m_pagesPerRow;
+ int page = m_doc->startPage() + counter;
+ int paperWidth = m_doc->paperWidth(page);
+ int paperHeight = m_doc->paperHeight(page);
+ QRect pageRect( leftSpacing() + col * ( paperWidth + m_spacing ),
+ topSpacing() + row * ( paperHeight + m_spacing ),
+ paperWidth, paperHeight );
+ drawOnePageBorder( painter, crect, pageRect, emptySpaceRegion );
+ if( pageRect.top() > crect.bottom())
+ break;
+ if ( pageRect.intersects( crect ) )
+ grayRegion -= pageRect;
+ QRect rightShadow = drawRightShadow( painter, crect, pageRect, s_shadowOffset );
+ if ( !rightShadow.isEmpty() )
+ grayRegion -= rightShadow;
+ QRect bottomShadow = drawBottomShadow( painter, crect, pageRect, s_shadowOffset );
+ if ( !bottomShadow.isEmpty() )
+ grayRegion -= bottomShadow;
+
+ //kdDebug() << "KWViewModePreview::drawPageBorders grayRegion is now : " << endl;
+ //DEBUGREGION( grayRegion );
+ }
+ if ( !grayRegion.isEmpty() )
+ {
+ //kdDebug() << "KWViewModePreview::drawPageBorders grayRegion's bounding Rect = " << DEBUGRECT( grayRegion.boundingRect() ) << endl;
+ m_doc->eraseEmptySpace( painter, grayRegion, QApplication::palette().active().brush( QColorGroup::Mid ) );
+ }
+ painter->restore();
+}
+
+//////////////////
+
+KWViewModeText::KWViewModeText( KWDocument * doc, KWCanvas* canvas, KWTextFrameSet* fs )
+ : KWViewMode( doc, canvas, false )
+{
+ m_textFrameSet = fs;
+}
+
+KWTextFrameSet * KWViewModeText::textFrameSet() const
+{
+ if ( !m_textFrameSet ) // e.g. when we set this mode before we had any frames (doc not loaded yet)
+ m_textFrameSet = determineTextFrameSet( m_doc );
+ return m_textFrameSet;
+}
+
+KWTextFrameSet * KWViewModeText::determineTextFrameSet( KWDocument* doc ) // static
+{
+ KWTextFrameSet* fs = 0L;
+
+ if(!doc->getAllViews().empty()) { // try the one that is selected
+ KWView *view = doc->getAllViews()[0];
+ KWFrameView *fv = view->getGUI()->canvasWidget()->frameViewManager()->selectedFrame();
+ KWFrame *f = fv == 0 ? 0 : fv->frame();
+ if(f)
+ fs = dynamic_cast<KWTextFrameSet *>( f->frameSet() );
+
+ if (!fs) { // try the one I am editing
+ KWFrameSetEdit *fse = view->getGUI()->canvasWidget()->currentFrameSetEdit();
+ if(fse)
+ fs = dynamic_cast<KWTextFrameSet *>( fse->frameSet() );
+ }
+ }
+
+ if (!fs || fs->isHeaderOrFooter() || fs->isFootEndNote())
+ // if not a textFS, or header/footer/footnote: fallback to fs 0
+ if ( doc->frameSetCount() > 0 && doc->frameSet( 0 )->isVisible() )
+ fs = dynamic_cast<KWTextFrameSet *>( doc->frameSet( 0 ) );
+
+ return fs;
+}
+
+QPoint KWViewModeText::normalToView( const QPoint & nPoint )
+{
+ QPoint r (nPoint);
+ r.setX(r.x() + OFFSET);
+ return r;
+}
+
+QPoint KWViewModeText::viewToNormal( const QPoint & vPoint )
+{
+ QPoint r (vPoint);
+ r.setX(r.x() - OFFSET);
+ return r;
+}
+
+QSize KWViewModeText::contentsSize()
+{
+ if (!textFrameSet())
+ return QSize();
+
+ // The actual contents only depend on the amount of text.
+ // The width is the one from the text, so that the placement of tabs makes a bit of sense, etc.
+ // The minimum height is the one of a normal page though.
+
+ int width = m_doc->layoutUnitToPixelX( m_textFrameSet->textDocument()->width() );
+
+ int height = QMAX((int)m_doc->paperHeight(m_doc->startPage()),
+ m_doc->layoutUnitToPixelY( m_textFrameSet->textDocument()->height() ) );
+ //kdDebug() << "KWViewModeText::contentsSize " << width << "x" << height << endl;
+ return QSize( width, height );
+}
+
+QSize KWViewModeText::availableSizeForText( KWTextFrameSet* /*textfs*/ )
+{
+ return contentsSize();
+}
+
+bool KWViewModeText::isFrameSetVisible( const KWFrameSet *fs )
+{
+ if(fs==NULL) return false; // assertion
+ if(fs==textFrameSet()) return true;
+
+ const KWFrameSet* parentFrameset = fs->groupmanager() ? fs->groupmanager() : fs;
+ while ( parentFrameset->isFloating() ) {
+ parentFrameset = parentFrameset->anchorFrameset();
+ if ( parentFrameset == m_textFrameSet )
+ return true;
+ }
+ return false;
+}
+
+void KWViewModeText::drawPageBorders( QPainter * painter, const QRect & crect,
+ const QRegion & /*emptySpaceRegion*/ )
+{
+ painter->save();
+ QRegion grayRegion( crect );
+ //kdDebug() << "KWViewModeText::drawPageBorders crect=" << grayRegion << endl;
+ painter->setPen( QApplication::palette().active().color( QColorGroup::Dark ) );
+ QSize cSize = contentsSize();
+ // Draw a line on the right -- ## or a shadow?
+ // +1 to be out of the contents, and +1 for QRect
+ QRect frameRect( OFFSET, 0, cSize.width() + 2, cSize.height() );
+ //kdDebug() << "KWViewModeText::drawPageBorders right line: " << frameRect.topRight() << " " << frameRect.bottomRight()<< endl;
+ painter->drawLine( frameRect.topRight(), frameRect.bottomRight() );
+ if ( frameRect.intersects( crect ) )
+ grayRegion -= frameRect;
+
+ //kdDebug() << "KWViewModeText::drawPageBorders grayRegion is now " << grayRegion << endl;
+ if ( crect.bottom() >= cSize.height() )
+ {
+ // And draw a line at the bottom -- ## or a shadow?
+ painter->drawLine( 0, cSize.height(),
+ cSize.width(), cSize.height() );
+ grayRegion -= QRect( 0, cSize.height(),
+ cSize.width(), cSize.height() );
+ }
+ //kdDebug() << "KWViewModeText::drawPageBorders erasing grayRegion " << grayRegion << endl;
+ if ( !grayRegion.isEmpty() )
+ m_doc->eraseEmptySpace( painter, grayRegion, QApplication::palette().active().brush( QColorGroup::Mid ) );
+ painter->restore();
+}
+
+QRect KWViewModeText::rulerFrameRect()
+{
+ return QRect( QPoint(OFFSET, 0), contentsSize() );
+}
+
+void KWViewModeText::setPageLayout( KoRuler* hRuler, KoRuler* vRuler, const KoPageLayout& /*layout*/ )
+{
+ // Create a dummy page-layout, as if we had a single page englobing the whole text.
+ KoPageLayout layout;
+ layout.format = PG_CUSTOM;
+ layout.orientation = PG_PORTRAIT;
+ QSize cSize = contentsSize();
+ layout.ptWidth = m_doc->unzoomItX( cSize.width() );
+ layout.ptHeight = m_doc->unzoomItY( cSize.height() );
+ //kdDebug() << "KWViewModeText::setPageLayout layout size " << layout.ptWidth << "x" << layout.ptHeight << endl;
+ layout.ptLeft = OFFSET;
+ layout.ptRight = 0;
+ layout.ptTop = 0;
+ layout.ptBottom = 0;
+ layout.ptBindingSide = 0;
+ layout.ptPageEdge = 0;
+ hRuler->setPageLayout( layout );
+ vRuler->setPageLayout( layout );
+}
+
+bool KWViewModeText::isTextModeFrameset(KWFrameSet *fs) const {
+ return fs == textFrameSet();
+}
+
+
+int KWViewModePrint::xOffset(KWPage *page, int canvasWidth) {
+ Q_UNUSED(page);
+ Q_UNUSED(canvasWidth);
+ return 0;
+}
diff --git a/kword/KWViewMode.h b/kword/KWViewMode.h
new file mode 100644
index 00000000..8afde053
--- /dev/null
+++ b/kword/KWViewMode.h
@@ -0,0 +1,297 @@
+/* This file is part of the KDE project
+ Copyright (C) 2001 David Faure <faure@kde.org>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+*/
+
+#ifndef kwviewmode_h
+#define kwviewmode_h
+
+#include <qrect.h>
+class KWDocument;
+class QPainter;
+class QRegion;
+class KWTextFrameSet;
+class KWFrameSet;
+class KWCanvas;
+class KoRuler;
+class KoPageLayout;
+class KWPage;
+
+/**
+ * Abstract base class for KWCanvas's view modes.
+ *
+ * The 'normal' mode is the WYSIWYG mode ("page mode"), in which pages are one
+ * below another. Since frames are in this coordinate system, the view modes
+ * other than the normal mode implement a transformation between the normal mode's
+ * coordinate system and its own.
+ * When drawing, we use normalcoord->viewcoord and when handling mouse clicks
+ * we use viewcoord->normalcoord.
+ * Note that this all in zoomed (pixel) coordinates (see DESIGN file).
+ *
+ * The View Mode is obviously also responsible for drawing pages etc.
+ */
+class KWViewMode
+{
+protected:
+ KWViewMode( KWDocument * doc, KWCanvas* canvas, bool drawFrameBorders )
+ : m_doc( doc ), m_canvas( canvas ), m_drawFrameBorders( drawFrameBorders )
+ {}
+public:
+ virtual ~KWViewMode() {}
+
+ /** Normal coord -> view coord */
+ virtual QPoint normalToView( const QPoint & nPoint ) = 0;
+
+ /** Normal coord -> view coord */
+ QRect normalToView( const QRect & nRect )
+ { return QRect( normalToView( nRect.topLeft() ), nRect.size() ); }
+
+ /** View coord -> normal coord */
+ virtual QPoint viewToNormal( const QPoint & vPoint ) = 0;
+
+ /** View coord -> normal coord */
+ QRect viewToNormal( const QRect & nRect )
+ { return QRect( viewToNormal( nRect.topLeft() ), viewToNormal( nRect.bottomRight() ) ); }
+
+ /** Return view coord for page rect. Avoids rounding problems when doing normalToView(zoomedRect) */
+ virtual QRect viewPageRect( int pgNum ) = 0;
+
+ /** Size of the contents area, in pixels */
+ virtual QSize contentsSize() = 0;
+
+ /** Size (in pixels) of the total area available for text in a given textframeset
+ * This is used by KWTextFrameSet::drawFrame to erase between the bottom of the
+ * last paragraph and the bottom of the available area. */
+ virtual QSize availableSizeForText( KWTextFrameSet* textfs );
+
+ /** "Topleft of current page" - concept used by the rulers.
+ * The default implementation is good enough for any page-based viewmode,
+ * since it calls normalToView. But the textmode has no page concept. */
+ virtual QPoint pageCorner();
+ /** The result of this is passed to setFrameStartEnd for both rulers
+ * (after adjustement with pageCorner()) */
+ virtual QRect rulerFrameRect();
+ /** Called when the page layout is set, or changes.
+ * Usually this is directly passed to KoRuler (for page-based viewmodes) */
+ virtual void setPageLayout( KoRuler* hRuler, KoRuler* vRuler, const KoPageLayout& layout );
+
+ virtual void drawPageBorders( QPainter * painter, const QRect & crect, const QRegion & emptySpaceRegion ) = 0;
+
+ /** Config option for KWViewModePreview (a bit of a hack) */
+ virtual void setPagesPerRow(int) {}
+ virtual int pagesPerRow() { return 0; }
+
+ /** Should selected text be drawn as such? */
+ virtual bool drawSelections() { return true; }
+
+ /** Should frame background be drawn? Usually yes, but not for embedded docs with transparent=true */
+ virtual bool drawFrameBackground() { return true; }
+
+ /** Should we see frame borders? This setting doesn't always come from KWView... */
+ bool drawFrameBorders() const { return m_drawFrameBorders; }
+ void setDrawFrameBorders(bool b) { m_drawFrameBorders = b; }
+
+ /** Should this frameset be visible in this viewmode? True by default, all are shown. */
+ virtual bool isFrameSetVisible( const KWFrameSet* /*frameset*/ ) { return true; }
+
+ /** Should formatVertically() happen (to skip frame bottom, frames on top, etc.) */
+ // TODO: maybe this should be more fine-grained.
+ virtual bool shouldFormatVertically() { return true; }
+
+ /** Should adjust[LR]Margin() happen (to run the text around frames on top etc.) */
+ virtual bool shouldAdjustMargins() { return true; }
+
+ /** Does this viewmode know anything about frames? */
+ virtual bool hasFrames() { return true; }
+
+ /** Does this viewmode know anything about pages? */
+ virtual bool hasPages() { return true; }
+
+ /** Return the name of the viewmode, used for loading/saving. */
+ virtual const QString type() const = 0;
+
+ /** Answers the question if argument frameset has to be drawn as a text-mode
+ * text area if true, or if false as a frame with its own contents. */
+ virtual bool isTextModeFrameset(KWFrameSet *) const { return false; }
+
+ static KWViewMode *create( const QString& viewModeType, KWDocument* doc, KWCanvas* canvas );
+
+ KWCanvas * canvas() const { return m_canvas; }
+
+protected:
+ /**
+ * Draw the border around one page, and clear up the empty space in that page
+ * @param crect the rect we're interested in painting (in view pixels)
+ * @param pageRect the rect for the page, in view pixels
+ * @param emptySpaceRegion the empty space to clear up inside the page (in view pixels)
+ * @param painter the painter to paint the border on.
+ */
+ void drawOnePageBorder( QPainter * painter, const QRect & crect, const QRect & pageRect,
+ const QRegion & emptySpaceRegion );
+ QRect drawRightShadow( QPainter * painter, const QRect & crect, const QRect & pageRect, int topOffset );
+ QRect drawBottomShadow( QPainter * painter, const QRect & crect, const QRect & pageRect, int leftOffset );
+ static const unsigned short s_shadowOffset;
+
+ KWDocument * m_doc;
+ KWCanvas * m_canvas;
+ bool m_drawFrameBorders;
+};
+
+/** The 'normal' view mode (pages below one another) */
+class KWViewModeNormal : public KWViewMode
+{
+public:
+ KWViewModeNormal( KWDocument * doc, KWCanvas* canvas, bool drawFrameBorders )
+ : KWViewMode( doc, canvas, drawFrameBorders ) {}
+ virtual ~KWViewModeNormal() {}
+
+ virtual QPoint normalToView( const QPoint & nPoint );
+ virtual QPoint viewToNormal( const QPoint & vPoint );
+ virtual QRect viewPageRect( int pgNum );
+ virtual QSize contentsSize();
+
+ virtual const QString type() const { return "ModeNormal"; }
+
+ virtual void drawPageBorders( QPainter * painter, const QRect & crect, const QRegion & emptySpaceRegion );
+
+protected:
+ virtual int xOffset(KWPage *page, int canvasWidth = -1);
+};
+
+/** The view mode used when printing (pages under one another, no selections) */
+class KWViewModePrint : public KWViewModeNormal // we inherit the "normal" viewmode
+{
+public:
+ KWViewModePrint( KWDocument * doc, KWCanvas* canvas )
+ : KWViewModeNormal( doc, canvas, false /*drawFrameBorders*/ ) {}
+ virtual ~KWViewModePrint() {}
+ virtual bool drawSelections() { return false; }
+protected:
+ virtual int xOffset(KWPage *page, int canvasWidth = -1);
+};
+
+/** The 'embedded' view mode (usually a single page, no selections) */
+class KWViewModeEmbedded : public KWViewMode
+{
+public:
+ KWViewModeEmbedded ( KWDocument * doc, KWCanvas* canvas )
+ : KWViewMode( doc, canvas, false /*drawFrameBorders*/ ),
+ mDrawFrameBackground( true ),
+ mDrawSelections( true )
+ {}
+ virtual ~ KWViewModeEmbedded() {}
+
+ void setDrawFrameBackground( bool b ) { mDrawFrameBackground = b; }
+ void setDrawSelections( bool b ) { mDrawSelections = b; }
+
+ // This view mode is very easy to implement ;-P
+ virtual QPoint normalToView( const QPoint & nPoint ) { return nPoint; }
+ virtual QPoint viewToNormal( const QPoint & vPoint ) { return vPoint; }
+ virtual QRect viewPageRect( int pgNum );
+ virtual QSize contentsSize() { return QSize(); }
+ virtual bool hasPages() { return false; }
+
+ virtual void drawPageBorders( QPainter *, const QRect &, const QRegion & ){}
+ virtual bool drawSelections() { return mDrawSelections; }
+
+ virtual const QString type() const { return "ModeEmbedded"; }
+ virtual bool drawFrameBackground() { return mDrawFrameBackground; }
+
+private:
+ bool mDrawFrameBackground;
+ bool mDrawSelections;
+};
+
+
+/** A mode for previewing the overall document
+ Pages are organized in a grid (mostly useful when zooming out a lot) */
+class KWViewModePreview : public KWViewMode
+{
+public:
+ KWViewModePreview( KWDocument * doc, KWCanvas* canvas, bool drawFrameBorders, int _nbPagePerRow );
+ virtual ~KWViewModePreview() {}
+
+ virtual QPoint normalToView( const QPoint & nPoint );
+ virtual QPoint viewToNormal( const QPoint & vPoint );
+ virtual QRect viewPageRect( int pgNum );
+ virtual QSize contentsSize();
+ virtual void drawPageBorders( QPainter * painter, const QRect & crect, const QRegion & emptySpaceRegion );
+
+ virtual void setPagesPerRow(int _nb) {m_pagesPerRow=_nb;}
+ virtual int pagesPerRow() {return m_pagesPerRow;}
+ virtual const QString type() const { return "ModePreview"; }
+
+ int numRows() const;
+
+//protected:
+ /** Return the spacing between the left border of the canvas and the page. */
+ int leftSpacing();
+ /** Return the spacing between the top border of the canvas and the page. */
+ int topSpacing();
+
+private:
+ int m_pagesPerRow;
+ int m_spacing;
+};
+
+/** The 'edit only one text frameset' view mode */
+class KWViewModeText : public KWViewMode
+{
+public:
+
+ KWViewModeText( KWDocument * doc, KWCanvas* canvas, KWTextFrameSet* fs );
+ virtual ~KWViewModeText() {}
+
+ KWTextFrameSet *textFrameSet() const;
+ /**
+ * Return a text frameset that the user has either selected or is currently editing,
+ * returning the main text frameset otherwise.
+ * If the selected frame is not a text FS, and the user is not editing one in the
+ * first view plus the document has no main text frameset then this method will return 0
+ */
+ static KWTextFrameSet *determineTextFrameSet( KWDocument* doc );
+
+ virtual QPoint normalToView( const QPoint & nPoint );
+ virtual QPoint viewToNormal( const QPoint & vPoint );
+ virtual QSize contentsSize();
+ virtual QRect viewPageRect( int ) { return QRect(); }
+ virtual QSize availableSizeForText( KWTextFrameSet* textfs );
+ // There is no page concept. Keep everything relative to (0,0)
+ virtual QPoint pageCorner() { return QPoint( 0, 0 ); }
+ virtual QRect rulerFrameRect();
+ virtual void setPageLayout( KoRuler* hRuler, KoRuler* vRuler, const KoPageLayout& layout );
+
+ virtual void drawPageBorders( QPainter * painter, const QRect & crect, const QRegion & emptySpaceRegion );
+ virtual const QString type() const { return "ModeText"; }
+ virtual bool shouldFormatVertically() { return false; }
+ virtual bool shouldAdjustMargins() { return false; }
+ virtual bool hasFrames() { return false; }
+ virtual bool hasPages() { return false; }
+
+ virtual bool isFrameSetVisible( const KWFrameSet* fs );
+
+ virtual bool isTextModeFrameset(KWFrameSet *fs) const;
+
+ /// hardcoded distance from the left side this viewmode starts its rendering
+ static const int OFFSET = 10;
+
+
+private:
+ mutable KWTextFrameSet *m_textFrameSet;
+};
+
+#endif
diff --git a/kword/KWordDocIface.cpp b/kword/KWordDocIface.cpp
new file mode 100644
index 00000000..f2a1e850
--- /dev/null
+++ b/kword/KWordDocIface.cpp
@@ -0,0 +1,639 @@
+/* This file is part of the KDE project
+ Copyright (C) 2001, 2002 Laurent MONTEL <lmontel@mandrakesoft.com>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+*/
+#include "KWordDocIface.h"
+#include "KWTextFrameSet.h"
+#include "KWordFrameSetIface.h"
+#include "KWDocument.h"
+#include "KWVariable.h"
+#include "KWPageManager.h"
+
+#include <kapplication.h>
+#include <dcopclient.h>
+#include <KoVariable.h>
+#include <KoAutoFormat.h>
+
+KWordDocIface::KWordDocIface( KWDocument *doc_ )
+ : KoDocumentIface( doc_ )
+{
+ doc = doc_;
+}
+
+DCOPRef KWordDocIface::textFrameSet( int num )
+{
+ if( num>= (int)doc->frameSetCount())
+ return DCOPRef();
+ return DCOPRef( kapp->dcopClient()->appId(),
+ doc->textFrameSet( num)->dcopObject()->objId() );
+}
+
+DCOPRef KWordDocIface::frameSet( int num )
+{
+ if( num>= (int)doc->frameSetCount())
+ return DCOPRef();
+ return DCOPRef( kapp->dcopClient()->appId(),
+ doc->frameSet( num)->dcopObject()->objId() );
+}
+
+int KWordDocIface::numFrameSets()const
+{
+ return doc->frameSetCount();
+}
+
+int KWordDocIface::frameSetCount()const
+{
+ return doc->frameSetCount();
+}
+
+unsigned int KWordDocIface::nbColumns()const
+{
+ return doc->numColumns();
+}
+
+double KWordDocIface::ptPageTop( int pgNum )const
+{
+ return doc->pageManager()->topOfPage(pgNum);
+}
+
+QString KWordDocIface::unitName()const
+{
+ return doc->unitName();
+}
+
+void KWordDocIface::recalcAllVariables()
+{
+ //recalc all variable
+ doc->recalcVariables(VT_ALL);
+}
+
+void KWordDocIface::recalcVariables(int _var)
+{
+ doc->recalcVariables(_var);
+}
+
+void KWordDocIface::recalcVariables(const QString &varName)
+{
+ if(varName=="VT_DATE")
+ doc->recalcVariables(0);
+ else if(varName=="VT_TIME")
+ doc->recalcVariables(2);
+ else if(varName=="VT_PGNUM")
+ doc->recalcVariables(4);
+ else if(varName=="VT_CUSTOM")
+ doc->recalcVariables(6);
+ else if(varName=="VT_MAILMERGE")
+ doc->recalcVariables(7);
+ else if(varName=="VT_FIELD")
+ doc->recalcVariables(8);
+ else if(varName=="VT_LINK")
+ doc->recalcVariables(9);
+ else if(varName=="VT_NOTE")
+ doc->recalcVariables(10);
+ else if(varName=="VT_FOOTNOTE")
+ doc->recalcVariables(11);
+ else if(varName=="VT_ALL")
+ doc->recalcVariables(256);
+}
+
+
+bool KWordDocIface::showRuler() const
+{
+ return doc->showRuler();
+}
+
+bool KWordDocIface::showdocStruct() const
+{
+ return doc->showdocStruct();
+}
+
+bool KWordDocIface::viewFrameBorders() const
+{
+ return doc->viewFrameBorders();
+}
+
+void KWordDocIface::setHeaderVisible( bool b)
+{
+ doc->setHeaderVisible(b);
+ doc->refreshGUIButton();
+}
+
+void KWordDocIface::setFooterVisible( bool b)
+{
+ doc->setFooterVisible( b);
+ doc->refreshGUIButton();
+}
+
+void KWordDocIface::setViewFrameBorders( bool b )
+{
+ doc->setViewFrameBorders( b );
+ doc->refreshGUIButton();
+}
+
+void KWordDocIface::setShowRuler(bool b)
+{
+ doc->setShowRuler(b);
+ doc->refreshGUIButton();
+ doc->reorganizeGUI();
+}
+
+bool KWordDocIface::viewFormattingChars() const
+{
+ return doc->viewFormattingChars();
+}
+
+void KWordDocIface::setViewFormattingChars(bool b)
+{
+ doc->setViewFormattingChars(b);
+ doc->refreshGUIButton();
+}
+
+void KWordDocIface::setShowDocStruct(bool b)
+{
+ doc->setShowDocStruct(b);
+ doc->refreshGUIButton();
+ doc->reorganizeGUI();
+}
+
+
+bool KWordDocIface::showStatusBar() const
+{
+ return doc->showStatusBar();
+}
+
+void KWordDocIface::setShowStatusBar( bool _status )
+{
+ doc->setShowStatusBar(_status);
+ doc->reorganizeGUI();
+}
+
+int KWordDocIface::startingPage()const
+{
+ return doc->variableCollection()->variableSetting()->startingPageNumber();
+}
+
+void KWordDocIface::setStartingPage(int nb)
+{
+ doc->variableCollection()->variableSetting()->setStartingPageNumber(nb);
+ doc->recalcVariables(VT_PGNUM);
+}
+
+bool KWordDocIface::displayLink()const
+{
+ return doc->variableCollection()->variableSetting()->displayLink();
+}
+
+void KWordDocIface::setDisplayLink(bool b)
+{
+ doc->variableCollection()->variableSetting()->setDisplayLink(b);
+ doc->recalcVariables(VT_LINK);
+}
+
+bool KWordDocIface::setCustomVariableValue(const QString & varname, const QString & value)
+{
+ bool exist=doc->variableCollection()->customVariableExist(varname);
+ if(exist)
+ {
+ doc->variableCollection()->setVariableValue( varname, value );
+ doc->recalcVariables(VT_CUSTOM);
+ }
+ else
+ return false;
+ return true;
+}
+
+
+QString KWordDocIface::customVariableValue(const QString & varname)const
+{
+ if(doc->variableCollection()->customVariableExist(varname))
+ return doc->variableCollection()->getVariableValue( varname );
+ return QString::null;
+}
+
+void KWordDocIface::initConfig()
+{
+ doc->initConfig();
+}
+
+void KWordDocIface::saveConfig()
+{
+ doc->saveConfig();
+}
+
+bool KWordDocIface::isHeaderVisible() const
+{
+ return doc->isHeaderVisible();
+}
+
+bool KWordDocIface::isFooterVisible() const
+{
+ return doc->isFooterVisible();
+}
+
+bool KWordDocIface::backgroundSpellCheckEnabled() const
+{
+ return doc->backgroundSpellCheckEnabled();
+}
+
+void KWordDocIface::enableBackgroundSpellCheck( bool b )
+{
+ doc->enableBackgroundSpellCheck(b);
+}
+
+void KWordDocIface::startBackgroundSpellCheck()
+{
+ doc->startBackgroundSpellCheck();
+}
+
+void KWordDocIface::reactivateBgSpellChecking()
+{
+ doc->reactivateBgSpellChecking();
+}
+
+void KWordDocIface::setConfigUpperCase( bool _uc )
+{
+ doc->autoFormat()->configUpperCase(_uc);
+}
+
+void KWordDocIface::setConfigUpperUpper( bool _uu )
+{
+ doc->autoFormat()->configUpperUpper(_uu);
+}
+
+void KWordDocIface::setConfigAdvancedAutocorrect( bool _aa )
+{
+ doc->autoFormat()->configAdvancedAutocorrect( _aa );
+
+}
+
+void KWordDocIface::setConfigAutoDetectUrl(bool _au)
+{
+ doc->autoFormat()->configAutoDetectUrl(_au);
+}
+
+void KWordDocIface::setConfigIgnoreDoubleSpace( bool _ids)
+{
+ doc->autoFormat()->configIgnoreDoubleSpace(_ids);
+}
+
+bool KWordDocIface::configUpperCase() const
+{
+ return doc->autoFormat()->getConfigUpperCase();
+}
+
+bool KWordDocIface::configUpperUpper() const
+{
+ return doc->autoFormat()->getConfigUpperUpper();
+}
+
+bool KWordDocIface::configAdvancedAutoCorrect() const
+{
+ return doc->autoFormat()->getConfigAdvancedAutoCorrect();
+
+}
+bool KWordDocIface::configAutoDetectUrl() const
+{
+ return doc->autoFormat()->getConfigAutoDetectUrl();
+
+}
+
+bool KWordDocIface::configIgnoreDoubleSpace() const
+{
+ return doc->autoFormat()->getConfigIgnoreDoubleSpace();
+}
+
+bool KWordDocIface::configRemoveSpaceBeginEndLine() const
+{
+ return doc->autoFormat()->getConfigIgnoreDoubleSpace();
+}
+
+bool KWordDocIface::configUseBulletSyle() const
+{
+ return doc->autoFormat()->getConfigUseBulletSyle();
+}
+
+void KWordDocIface::setConfigRemoveSpaceBeginEndLine( bool _space)
+{
+ doc->autoFormat()->configRemoveSpaceBeginEndLine(_space);
+}
+
+void KWordDocIface::setConfigUseBulletStyle( bool _ubs)
+{
+ doc->autoFormat()->configUseBulletStyle(_ubs);
+}
+
+bool KWordDocIface::configAutoChangeFormat() const
+{
+ return doc->autoFormat()->getConfigAutoChangeFormat();
+}
+
+void KWordDocIface::setConfigAutoChangeFormat( bool _auto)
+{
+ doc->autoFormat()->configAutoChangeFormat(_auto);
+}
+
+bool KWordDocIface::configAutoReplaceNumber() const
+{
+ return doc->autoFormat()->getConfigAutoReplaceNumber();
+}
+
+void KWordDocIface::setConfigAutoReplaceNumber( bool b )
+{
+ doc->autoFormat()->configAutoReplaceNumber(b);
+}
+
+void KWordDocIface::setConfigAutoNumberStyle( bool b )
+{
+ doc->autoFormat()->configAutoNumberStyle(b);
+}
+
+bool KWordDocIface::configAutoNumberStyle() const
+{
+ return doc->autoFormat()->getConfigAutoNumberStyle();
+}
+
+void KWordDocIface::setConfigCompletion( bool b )
+{
+ doc->autoFormat()->configCompletion( b );
+}
+
+bool KWordDocIface::configCompletion() const
+{
+ return doc->autoFormat()->getConfigCompletion();
+}
+
+void KWordDocIface::setConfigToolTipCompletion( bool b )
+{
+ doc->autoFormat()->configToolTipCompletion( b );
+}
+
+bool KWordDocIface::configToolTipCompletion() const
+{
+ return doc->autoFormat()->getConfigToolTipCompletion();
+}
+
+void KWordDocIface::setConfigAppendSpace( bool b)
+{
+ doc->autoFormat()->configAppendSpace( b );
+}
+
+bool KWordDocIface::configAppendSpace() const
+{
+ return doc->autoFormat()->getConfigAppendSpace();
+}
+
+void KWordDocIface::setConfigMinWordLength( uint val )
+{
+ doc->autoFormat()->configMinWordLength( val );
+}
+
+uint KWordDocIface::configMinWordLength() const
+{
+ return doc->autoFormat()->getConfigMinWordLength();
+}
+
+void KWordDocIface::setConfigNbMaxCompletionWord( uint val )
+{
+ doc->autoFormat()->configNbMaxCompletionWord( val );
+}
+
+uint KWordDocIface::configNbMaxCompletionWord() const
+{
+ return doc->autoFormat()->getConfigNbMaxCompletionWord();
+}
+
+void KWordDocIface::setConfigAddCompletionWord( bool b )
+{
+ doc->autoFormat()->configAddCompletionWord( b );
+}
+
+bool KWordDocIface::configAddCompletionWord() const
+{
+ return doc->autoFormat()->getConfigAddCompletionWord();
+}
+
+bool KWordDocIface::configIncludeTwoUpperUpperLetterException() const
+{
+ return doc->autoFormat()->getConfigIncludeTwoUpperUpperLetterException();
+}
+
+void KWordDocIface::setConfigIncludeTwoUpperUpperLetterException( bool b)
+{
+ doc->autoFormat()->configIncludeTwoUpperUpperLetterException( b );
+}
+
+bool KWordDocIface::configIncludeAbbreviation() const
+{
+ return doc->autoFormat()->getConfigIncludeAbbreviation();
+}
+
+void KWordDocIface::setConfigIncludeAbbreviation( bool b)
+{
+ doc->autoFormat()->configIncludeAbbreviation( b );
+}
+
+bool KWordDocIface::displayComment() const
+{
+ return doc->variableCollection()->variableSetting()->displayComment();
+}
+
+void KWordDocIface::setDisplayComment( bool b)
+{
+ doc->variableCollection()->variableSetting()->setDisplayComment( b );
+ doc->recalcVariables(VT_NOTE);
+}
+
+
+bool KWordDocIface::displayFieldCode()const
+{
+ return doc->variableCollection()->variableSetting()->displayFieldCode();
+}
+
+void KWordDocIface::setDisplayFieldCode( bool b)
+{
+ doc->variableCollection()->variableSetting()->setDisplayFieldCode( b );
+ doc->recalcVariables(VT_ALL);
+}
+
+bool KWordDocIface::configAutoSuperScript() const
+{
+ return doc->autoFormat()->getConfigAutoSuperScript();
+}
+
+void KWordDocIface::setConfigAutoSuperScript( bool b)
+{
+ doc->autoFormat()->configAutoSuperScript( b );
+}
+
+void KWordDocIface::addIgnoreWordAll( const QString &word )
+{
+ doc->addSpellCheckIgnoreWord( word );
+}
+
+void KWordDocIface::clearIgnoreWordAll( )
+{
+ doc->setSpellCheckIgnoreList( QStringList() );
+}
+
+QStringList KWordDocIface::spellListIgnoreAll() const
+{
+ return doc->spellCheckIgnoreList();
+}
+
+
+bool KWordDocIface::showScrollBar()const
+{
+ return doc->showScrollBar();
+}
+
+void KWordDocIface::setShowScrollBar( bool _status )
+{
+ doc->setShowScrollBar(_status );
+ doc->reorganizeGUI();
+}
+
+double KWordDocIface::ptTabStopValue() const
+{
+ return doc->tabStopValue();
+}
+
+void KWordDocIface::setPtTabStopValue ( double _tabStop )
+{
+ doc->setTabStopValue (_tabStop );
+}
+
+int KWordDocIface::footNoteSeparatorLineLength() const
+{
+ return doc->footNoteSeparatorLineLength();
+}
+
+void KWordDocIface::setFootNoteSeparatorLineLength( int _length)
+{
+ doc->setFootNoteSeparatorLineLength( _length );
+ doc->repaintAllViews();
+}
+
+void KWordDocIface::setFootNoteSeparatorLinePosition( const QString &pos)
+{
+ SeparatorLinePos tmp=SLP_LEFT;
+ if ( pos.lower()=="left")
+ tmp=SLP_LEFT;
+ else if ( pos.lower()=="centered")
+ tmp=SLP_CENTERED;
+ else if ( pos.lower()=="right")
+ tmp=SLP_RIGHT;
+ doc->setFootNoteSeparatorLinePosition( tmp);
+ doc->repaintAllViews();
+}
+
+QString KWordDocIface::footNoteSeparatorLinePosition()const
+{
+ QString tmp=QString::null;
+ switch( doc->footNoteSeparatorLinePosition() )
+ {
+ case SLP_LEFT:
+ return QString("left");
+ case SLP_RIGHT:
+ return QString("right");
+ case SLP_CENTERED:
+ return QString("centered");
+ }
+ return tmp;
+}
+
+double KWordDocIface::footNoteSeparatorLineWidth() const
+{
+ return doc->footNoteSeparatorLineWidth();
+}
+
+void KWordDocIface::setFootNoteSeparatorLineWidth( double _width)
+{
+ doc->setFootNoteSeparatorLineWidth( _width );
+ doc->repaintAllViews();
+}
+
+void KWordDocIface::deleteBookMark(const QString &_name)
+{
+ doc->deleteBookmark( _name );
+}
+
+void KWordDocIface::renameBookMark(const QString &_oldname, const QString &_newName)
+{
+ doc->renameBookmark( _oldname, _newName);
+}
+
+QStringList KWordDocIface::listOfBookmarkName()const
+{
+ //return all list
+ return doc->listOfBookmarkName(0L);
+}
+
+QString KWordDocIface::configAutoFormatLanguage( )const
+{
+ return doc->autoFormat()->getConfigAutoFormatLanguage( );
+}
+
+bool KWordDocIface::configCapitalizeNameOfDays() const
+{
+ return doc->autoFormat()->getConfigCapitalizeNameOfDays();
+}
+
+void KWordDocIface::setConfigCapitalizeNameOfDays( bool b)
+{
+ doc->autoFormat()->configCapitalizeNameOfDays( b );
+}
+
+bool KWordDocIface::showGrid() const
+{
+ return doc->showGrid();
+}
+
+bool KWordDocIface::snapToGrid() const
+{
+ return doc->snapToGrid();
+}
+
+double KWordDocIface::gridX() const
+{
+ return doc->gridX();
+}
+
+double KWordDocIface::gridY() const
+{
+ return doc->gridY();
+}
+
+void KWordDocIface::setGridX( double _gridX )
+{
+
+ doc->setGridX( QMAX( 0.1, _gridX ) );
+}
+
+void KWordDocIface::setGridY( double _gridY )
+{
+ doc->setGridY( QMAX( 0.1, _gridY ) );
+}
+
+void KWordDocIface::setShowGrid( bool _b )
+{
+ doc->setShowGrid( _b );
+}
+
+void KWordDocIface::setSnapToGrid( bool _b )
+{
+ doc->setSnapToGrid( _b );
+}
diff --git a/kword/KWordDocIface.h b/kword/KWordDocIface.h
new file mode 100644
index 00000000..40dd6e50
--- /dev/null
+++ b/kword/KWordDocIface.h
@@ -0,0 +1,195 @@
+/* This file is part of the KDE project
+ Copyright (C) 1998, 1999 Reginald Stadlbauer <reggie@kde.org>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+*/
+
+#ifndef KWORD_DOC_IFACE_H
+#define KWORD_DOC_IFACE_H
+
+#include <KoDocumentIface.h>
+#include <dcopref.h>
+
+#include <qstring.h>
+#include <qstringlist.h>
+class KWDocument;
+
+class KWordDocIface : public KoDocumentIface
+{
+ K_DCOP
+public:
+ KWordDocIface( KWDocument *doc_ );
+
+k_dcop:
+ virtual DCOPRef textFrameSet( int num );
+ virtual DCOPRef frameSet( int num );
+
+ /// deprecated method, use frameSetCount instead.
+ virtual int numFrameSets()const;
+ virtual int frameSetCount()const;
+ virtual unsigned int nbColumns()const;
+
+ //paper
+ virtual double ptPageTop( int pgNum )const;
+
+ //configure
+ virtual QString unitName()const;
+
+ virtual bool showRuler() const;
+ virtual bool showdocStruct() const;
+ virtual bool viewFrameBorders() const;
+
+ virtual bool showGrid() const;
+ virtual bool snapToGrid() const;
+
+ virtual void setGridX( double _gridX );
+ virtual void setGridY( double _gridY );
+ virtual void setShowGrid( bool _b );
+ virtual void setSnapToGrid( bool _b );
+ virtual double gridY() const;
+ virtual double gridX() const;
+
+ virtual bool viewFormattingChars() const;
+ virtual void setViewFormattingChars(bool _b);
+
+ virtual void setHeaderVisible( bool );
+ virtual void setFooterVisible( bool );
+
+ virtual bool isHeaderVisible() const;
+ virtual bool isFooterVisible() const;
+
+ virtual void setViewFrameBorders( bool b );
+ virtual void setShowRuler(bool b);
+ virtual void setShowDocStruct(bool _b);
+
+ virtual void recalcAllVariables();
+ virtual void recalcVariables(int _var);
+ virtual void recalcVariables(const QString &varName);
+ bool setCustomVariableValue(const QString & varname, const QString & value);
+ virtual QString customVariableValue(const QString & varname)const;
+
+ virtual void setStartingPage(int nb);
+ virtual int startingPage()const;
+
+ virtual void setDisplayLink(bool b);
+ virtual bool displayLink()const;
+
+ virtual bool backgroundSpellCheckEnabled() const;
+ virtual void enableBackgroundSpellCheck( bool b );
+
+ virtual void startBackgroundSpellCheck();
+ virtual void reactivateBgSpellChecking();
+
+ virtual void setConfigUpperCase( bool _uc );
+ virtual void setConfigUpperUpper( bool _uu );
+ virtual void setConfigAdvancedAutocorrect( bool _aa );
+ virtual void setConfigAutoDetectUrl(bool _au);
+ virtual void setConfigIgnoreDoubleSpace( bool _ids);
+
+ virtual bool configUpperCase() const;
+ virtual bool configUpperUpper() const;
+ virtual bool configAdvancedAutoCorrect() const;
+ virtual bool configAutoDetectUrl() const;
+ virtual bool configIgnoreDoubleSpace() const;
+
+ virtual void setConfigRemoveSpaceBeginEndLine( bool _space);
+ virtual void setConfigUseBulletStyle( bool _ubs);
+
+ virtual bool configRemoveSpaceBeginEndLine() const;
+ virtual bool configUseBulletSyle() const;
+
+ virtual bool configAutoChangeFormat() const;
+ virtual void setConfigAutoChangeFormat( bool _auto);
+
+ virtual bool configAutoReplaceNumber() const;
+ virtual void setConfigAutoReplaceNumber( bool b );
+
+ virtual bool showStatusBar() const;
+ virtual void setShowStatusBar( bool _status );
+
+ void setConfigAutoNumberStyle( bool b );
+ bool configAutoNumberStyle() const;
+
+ void setConfigToolTipCompletion( bool b );
+ bool configToolTipCompletion() const;
+
+ void setConfigCompletion( bool b );
+ bool configCompletion() const;
+
+
+ void setConfigAppendSpace( bool b);
+ bool configAppendSpace() const;
+
+ void setConfigMinWordLength( uint val );
+ uint configMinWordLength() const;
+
+ void setConfigNbMaxCompletionWord( uint val );
+ uint configNbMaxCompletionWord() const;
+
+ void setConfigAddCompletionWord( bool b );
+ bool configAddCompletionWord() const;
+
+ bool configIncludeTwoUpperUpperLetterException() const;
+ void setConfigIncludeTwoUpperUpperLetterException( bool b);
+
+ bool configIncludeAbbreviation() const;
+ void setConfigIncludeAbbreviation( bool b);
+
+ bool displayComment()const;
+ void setDisplayComment( bool b);
+
+ bool configAutoSuperScript() const;
+ void setConfigAutoSuperScript( bool b);
+
+ void addIgnoreWordAll( const QString &);
+ void clearIgnoreWordAll( );
+ QStringList spellListIgnoreAll() const;
+
+ //init/save config
+ virtual void initConfig();
+ virtual void saveConfig();
+
+ bool showScrollBar()const;
+ void setShowScrollBar( bool _status );
+
+ double ptTabStopValue() const;
+ void setPtTabStopValue ( double _tabStop );
+
+ int footNoteSeparatorLineLength() const;
+ void setFootNoteSeparatorLineLength( int _length);
+ void setFootNoteSeparatorLinePosition( const QString &pos);
+ QString footNoteSeparatorLinePosition()const;
+
+ double footNoteSeparatorLineWidth() const;
+ void setFootNoteSeparatorLineWidth( double _width);
+
+ void deleteBookMark(const QString &_name);
+ void renameBookMark(const QString &_oldname, const QString &_newName);
+ QStringList listOfBookmarkName()const;
+
+ bool displayFieldCode()const;
+ void setDisplayFieldCode( bool b);
+ QString configAutoFormatLanguage( )const;
+
+ bool configCapitalizeNameOfDays() const;
+ void setConfigCapitalizeNameOfDays( bool b);
+
+private:
+ KWDocument *doc;
+
+};
+
+#endif
diff --git a/kword/KWordFootNoteFrameSetIface.cpp b/kword/KWordFootNoteFrameSetIface.cpp
new file mode 100644
index 00000000..d5e2d352
--- /dev/null
+++ b/kword/KWordFootNoteFrameSetIface.cpp
@@ -0,0 +1,54 @@
+/* This file is part of the KDE project
+ Copyright (C) 2002 Laurent MONTEL <lmontel@mandrakesoft.com>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+*/
+
+#include "KWordFootNoteFrameSetIface.h"
+#include "KWTextFrameSet.h"
+#include <kdebug.h>
+
+KWFootNoteFrameSetIface::KWFootNoteFrameSetIface( KWFootNoteFrameSet *_note )
+ : KWordTextFrameSetIface( _note )
+{
+ m_footNote = _note;
+}
+
+
+QString KWFootNoteFrameSetIface::footEndNoteText() const
+{
+ KWFootNoteVariable* var = m_footNote->footNoteVariable();
+ if ( var )
+ return var->text();
+ else
+ return QString::null;
+}
+
+bool KWFootNoteFrameSetIface::isFootNote() const
+{
+ return m_footNote->isFootNote();
+}
+
+bool KWFootNoteFrameSetIface::isEndNote() const
+{
+ return m_footNote->isEndNote();
+}
+
+void KWFootNoteFrameSetIface::setCounterText( const QString& text )
+{
+ m_footNote->setCounterText( text );
+}
+
diff --git a/kword/KWordFootNoteFrameSetIface.h b/kword/KWordFootNoteFrameSetIface.h
new file mode 100644
index 00000000..0d2a409f
--- /dev/null
+++ b/kword/KWordFootNoteFrameSetIface.h
@@ -0,0 +1,48 @@
+/* This file is part of the KDE project
+ Copyright (C) 2002, Laurent MONTEL <lmontel@mandrakesoft.com>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+*/
+
+#ifndef KWORD_FOOTNOTEFRAMESET_IFACE_H
+#define KWORD_FOOTNOTEFRAMESET_IFACE_H
+
+#include <KoDocumentIface.h>
+#include <dcopref.h>
+
+#include <qstring.h>
+#include <qcolor.h>
+#include <qfont.h>
+#include "KWordTextFrameSetIface.h"
+class KWFootNoteFrameSet;
+
+class KWFootNoteFrameSetIface : public KWordTextFrameSetIface
+{
+ K_DCOP
+public:
+ KWFootNoteFrameSetIface( KWFootNoteFrameSet *_note );
+
+k_dcop:
+ QString footEndNoteText() const;
+ bool isFootNote() const;
+ bool isEndNote() const;
+ void setCounterText( const QString& text );
+private:
+ KWFootNoteFrameSet *m_footNote;
+
+};
+
+#endif
diff --git a/kword/KWordFormulaFrameSetEditIface.cpp b/kword/KWordFormulaFrameSetEditIface.cpp
new file mode 100644
index 00000000..ebe4cc31
--- /dev/null
+++ b/kword/KWordFormulaFrameSetEditIface.cpp
@@ -0,0 +1,276 @@
+/* This file is part of the KDE project
+ Copyright (C) 2002 Laurent MONTEL <lmontel@mandrakesoft.com>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+*/
+
+#include "KWordFormulaFrameSetEditIface.h"
+
+#include "KWFrame.h"
+#include "KWFormulaFrameSet.h"
+#include "KWDocument.h"
+#include <dcopclient.h>
+#include <kformulacontainer.h>
+#include <kformuladocument.h>
+#include <kformulaview.h>
+
+KWordFormulaFrameSetEditIface::KWordFormulaFrameSetEditIface( KWFormulaFrameSetEdit *_framesetedit )
+ :DCOPObject()
+{
+ m_framesetedit = _framesetedit;
+}
+
+void KWordFormulaFrameSetEditIface::copy()
+{
+ m_framesetedit->copy();
+}
+
+void KWordFormulaFrameSetEditIface::cut()
+{
+ m_framesetedit->cut();
+}
+
+void KWordFormulaFrameSetEditIface::paste()
+{
+ m_framesetedit->paste();
+}
+
+void KWordFormulaFrameSetEditIface::selectAll()
+{
+ m_framesetedit->selectAll();
+}
+
+void KWordFormulaFrameSetEditIface::addThinSpace()
+{
+ m_framesetedit->formulaFrameSet()->kWordDocument()->formulaDocument()->wrapper()->addThinSpace();
+}
+
+void KWordFormulaFrameSetEditIface::addMediumSpace()
+{
+ m_framesetedit->formulaFrameSet()->kWordDocument()->formulaDocument()->wrapper()->addMediumSpace();
+}
+
+void KWordFormulaFrameSetEditIface::addThickSpace()
+{
+ m_framesetedit->formulaFrameSet()->kWordDocument()->formulaDocument()->wrapper()->addThickSpace();
+}
+
+void KWordFormulaFrameSetEditIface::addQuadSpace()
+{
+ m_framesetedit->formulaFrameSet()->kWordDocument()->formulaDocument()->wrapper()->addQuadSpace();
+}
+
+void KWordFormulaFrameSetEditIface::addBracket( int left, int right )
+{
+ m_framesetedit->formulaFrameSet()->kWordDocument()->formulaDocument()
+ ->wrapper()->addBracket( static_cast<KFormula::SymbolType>( left ),
+ static_cast<KFormula::SymbolType>( right ) );
+}
+
+void KWordFormulaFrameSetEditIface::addParenthesis()
+{
+ m_framesetedit->formulaFrameSet()->kWordDocument()->formulaDocument()->wrapper()->addParenthesis();
+}
+
+void KWordFormulaFrameSetEditIface::addSquareBracket()
+{
+ m_framesetedit->formulaFrameSet()->kWordDocument()->formulaDocument()->wrapper()->addSquareBracket();
+}
+
+void KWordFormulaFrameSetEditIface::addCurlyBracket()
+{
+ m_framesetedit->formulaFrameSet()->kWordDocument()->formulaDocument()->wrapper()->addCurlyBracket();
+}
+
+void KWordFormulaFrameSetEditIface::addLineBracket()
+{
+ m_framesetedit->formulaFrameSet()->kWordDocument()->formulaDocument()->wrapper()->addLineBracket();
+}
+
+void KWordFormulaFrameSetEditIface::addFraction()
+{
+ m_framesetedit->formulaFrameSet()->kWordDocument()->formulaDocument()->wrapper()->addFraction();
+}
+
+void KWordFormulaFrameSetEditIface::addRoot()
+{
+ m_framesetedit->formulaFrameSet()->kWordDocument()->formulaDocument()->wrapper()->addRoot();
+}
+
+void KWordFormulaFrameSetEditIface::addIntegral()
+{
+ m_framesetedit->formulaFrameSet()->kWordDocument()->formulaDocument()->wrapper()->addIntegral();
+}
+
+void KWordFormulaFrameSetEditIface::addProduct()
+{
+ m_framesetedit->formulaFrameSet()->kWordDocument()->formulaDocument()->wrapper()->addProduct();
+}
+
+void KWordFormulaFrameSetEditIface::addSum()
+{
+ m_framesetedit->formulaFrameSet()->kWordDocument()->formulaDocument()->wrapper()->addSum();
+}
+
+void KWordFormulaFrameSetEditIface::addMatrix()
+{
+ m_framesetedit->formulaFrameSet()->kWordDocument()->formulaDocument()->wrapper()->addMatrix();
+}
+
+void KWordFormulaFrameSetEditIface::addMatrix( uint rows, uint columns )
+{
+ m_framesetedit->formulaFrameSet()->kWordDocument()->formulaDocument()->wrapper()->addMatrix( rows, columns );
+}
+
+void KWordFormulaFrameSetEditIface::addOneByTwoMatrix()
+{
+ m_framesetedit->formulaFrameSet()->kWordDocument()->formulaDocument()->wrapper()->addOneByTwoMatrix();
+}
+
+void KWordFormulaFrameSetEditIface::addNameSequence()
+{
+ m_framesetedit->formulaFrameSet()->kWordDocument()->formulaDocument()->wrapper()->addNameSequence();
+}
+
+void KWordFormulaFrameSetEditIface::addLowerLeftIndex()
+{
+ m_framesetedit->formulaFrameSet()->kWordDocument()->formulaDocument()->wrapper()->addLowerLeftIndex();
+}
+
+void KWordFormulaFrameSetEditIface::addUpperLeftIndex()
+{
+ m_framesetedit->formulaFrameSet()->kWordDocument()->formulaDocument()->wrapper()->addUpperLeftIndex();
+}
+
+void KWordFormulaFrameSetEditIface::addLowerRightIndex()
+{
+ m_framesetedit->formulaFrameSet()->kWordDocument()->formulaDocument()->wrapper()->addLowerRightIndex();
+}
+
+void KWordFormulaFrameSetEditIface::addUpperRightIndex()
+{
+ m_framesetedit->formulaFrameSet()->kWordDocument()->formulaDocument()->wrapper()->addUpperRightIndex();
+}
+
+void KWordFormulaFrameSetEditIface::addGenericLowerIndex()
+{
+ m_framesetedit->formulaFrameSet()->kWordDocument()->formulaDocument()->wrapper()->addGenericLowerIndex();
+}
+
+void KWordFormulaFrameSetEditIface::addGenericUpperIndex()
+{
+ m_framesetedit->formulaFrameSet()->kWordDocument()->formulaDocument()->wrapper()->addGenericUpperIndex();
+}
+
+void KWordFormulaFrameSetEditIface::removeEnclosing()
+{
+ m_framesetedit->formulaFrameSet()->kWordDocument()->formulaDocument()->wrapper()->removeEnclosing();
+}
+
+void KWordFormulaFrameSetEditIface::makeGreek()
+{
+ m_framesetedit->formulaFrameSet()->kWordDocument()->formulaDocument()->wrapper()->makeGreek();
+}
+
+void KWordFormulaFrameSetEditIface::insertSymbol( const QString &name )
+{
+ m_framesetedit->formulaFrameSet()->kWordDocument()->formulaDocument()->wrapper()->insertSymbol( name );
+}
+
+void KWordFormulaFrameSetEditIface::appendColumn()
+{
+ m_framesetedit->formulaFrameSet()->kWordDocument()->formulaDocument()->wrapper()->appendColumn();
+}
+
+void KWordFormulaFrameSetEditIface::insertColumn()
+{
+ m_framesetedit->formulaFrameSet()->kWordDocument()->formulaDocument()->wrapper()->insertColumn();
+}
+
+void KWordFormulaFrameSetEditIface::removeColumn()
+{
+ m_framesetedit->formulaFrameSet()->kWordDocument()->formulaDocument()->wrapper()->removeColumn();
+}
+
+void KWordFormulaFrameSetEditIface::appendRow()
+{
+ m_framesetedit->formulaFrameSet()->kWordDocument()->formulaDocument()->wrapper()->appendRow();
+}
+
+void KWordFormulaFrameSetEditIface::insertRow()
+{
+ m_framesetedit->formulaFrameSet()->kWordDocument()->formulaDocument()->wrapper()->insertRow();
+}
+
+void KWordFormulaFrameSetEditIface::removeRow()
+{
+ m_framesetedit->formulaFrameSet()->kWordDocument()->formulaDocument()->wrapper()->removeRow();
+}
+
+void KWordFormulaFrameSetEditIface::moveLeft( int flag )
+{
+ m_framesetedit->getFormulaView()->moveLeft( flag );
+}
+
+void KWordFormulaFrameSetEditIface::moveRight( int flag )
+{
+ m_framesetedit->getFormulaView()->moveRight( flag );
+}
+
+void KWordFormulaFrameSetEditIface::moveUp( int flag )
+{
+ m_framesetedit->getFormulaView()->moveUp( flag );
+}
+
+void KWordFormulaFrameSetEditIface::moveDown( int flag )
+{
+ m_framesetedit->getFormulaView()->moveDown( flag );
+}
+
+void KWordFormulaFrameSetEditIface::moveHome( int flag )
+{
+ m_framesetedit->getFormulaView()->moveHome( flag );
+}
+
+void KWordFormulaFrameSetEditIface::moveEnd( int flag )
+{
+ m_framesetedit->getFormulaView()->moveEnd( flag );
+}
+
+bool KWordFormulaFrameSetEditIface::isHome() const
+{
+ return m_framesetedit->getFormulaView()->isHome();
+}
+
+bool KWordFormulaFrameSetEditIface::isEnd() const
+{
+ return m_framesetedit->getFormulaView()->isEnd();
+}
+
+void KWordFormulaFrameSetEditIface::eraseSelection( int direction )
+{
+ m_framesetedit->getFormulaView()->eraseSelection( static_cast<KFormula::Direction>( direction ) );
+}
+
+void KWordFormulaFrameSetEditIface::addText( const QString &str )
+{
+ m_framesetedit->getFormulaView()->addText( str );
+}
+
+void KWordFormulaFrameSetEditIface::addNegThinSpace()
+{
+ m_framesetedit->formulaFrameSet()->kWordDocument()->formulaDocument()->wrapper()->addNegThinSpace();
+}
diff --git a/kword/KWordFormulaFrameSetEditIface.h b/kword/KWordFormulaFrameSetEditIface.h
new file mode 100644
index 00000000..aecaedf3
--- /dev/null
+++ b/kword/KWordFormulaFrameSetEditIface.h
@@ -0,0 +1,101 @@
+/* This file is part of the KDE project
+ Copyright (C) 2002, Laurent MONTEL <lmontel@mandrakesoft.com>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+*/
+
+#ifndef KWORD_FORMULAFRAMESETEDIT_IFACE_H
+#define KWORD_FORMULAFRAMESETEDIT_IFACE_H
+
+#include <KoDocumentIface.h>
+#include <dcopref.h>
+
+#include <qstring.h>
+#include <qcolor.h>
+class KWFormulaFrameSetEdit;
+
+class KWordFormulaFrameSetEditIface : public DCOPObject
+{
+ K_DCOP
+public:
+ KWordFormulaFrameSetEditIface( KWFormulaFrameSetEdit *_frame );
+
+k_dcop:
+ virtual void copy();
+ virtual void cut();
+ virtual void paste();
+ virtual void selectAll();
+
+ void addThinSpace();
+ void addMediumSpace();
+ void addThickSpace();
+ void addQuadSpace();
+ void addBracket( int left, int right );
+ void addParenthesis();
+ void addSquareBracket();
+ void addCurlyBracket();
+ void addLineBracket();
+ void addFraction();
+ void addRoot();
+ void addIntegral();
+ void addProduct();
+ void addSum();
+ void addMatrix();
+ void addMatrix( uint rows, uint columns );
+ void addOneByTwoMatrix();
+ void addNameSequence();
+ void addNegThinSpace();
+
+ void addLowerLeftIndex();
+ void addUpperLeftIndex();
+ void addLowerRightIndex();
+ void addUpperRightIndex();
+ void addGenericLowerIndex();
+ void addGenericUpperIndex();
+ void removeEnclosing();
+ void makeGreek();
+ void insertSymbol( const QString &name );
+
+ void appendColumn();
+ void insertColumn();
+ void removeColumn();
+ void appendRow();
+ void insertRow();
+ void removeRow();
+
+ void moveLeft( int flag );
+ void moveRight( int flag );
+ void moveUp( int flag );
+ void moveDown( int flag );
+
+ void moveHome( int flag );
+ void moveEnd( int flag );
+
+ /** @returns whether the cursor is at the first position. */
+ bool isHome() const;
+
+ /** @returns whether the cursor is at the last position. */
+ bool isEnd() const;
+
+ void eraseSelection( int direction );
+ void addText( const QString &str );
+
+private:
+ KWFormulaFrameSetEdit *m_framesetedit;
+
+};
+
+#endif // KWORD_FORMULAFRAMESETEDIT_IFACE_H
diff --git a/kword/KWordFormulaFrameSetIface.cpp b/kword/KWordFormulaFrameSetIface.cpp
new file mode 100644
index 00000000..fde7ef87
--- /dev/null
+++ b/kword/KWordFormulaFrameSetIface.cpp
@@ -0,0 +1,48 @@
+/* This file is part of the KDE project
+ Copyright (C) 2002 Laurent MONTEL <lmontel@mandrakesoft.com>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+*/
+
+#include "KWordFormulaFrameSetIface.h"
+#include "KWordViewIface.h"
+#include "KWFrame.h"
+#include "KWFormulaFrameSet.h"
+#include "KWView.h"
+#include "KWCanvas.h"
+#include "KWDocument.h"
+#include <kapplication.h>
+#include <dcopclient.h>
+#include "KWordFrameSetIface.h"
+
+KWordFormulaFrameSetIface::KWordFormulaFrameSetIface( KWFormulaFrameSet *_frame )
+ : KWordFrameSetIface( _frame)
+{
+ m_formulaFrame = _frame;
+}
+
+DCOPRef KWordFormulaFrameSetIface::startEditing()
+{
+ if ( m_formulaFrame->isDeleted() )
+ return DCOPRef();
+ KWDocument *doc = m_formulaFrame->kWordDocument();
+ QValueList<KWView *> views = doc->getAllViews();
+ KWCanvas* canvas = views.first()->getGUI()->canvasWidget();
+ canvas->editFrameSet( m_formulaFrame );
+ return DCOPRef( kapp->dcopClient()->appId(),
+ ( static_cast<KWFormulaFrameSetEdit *>( canvas->currentFrameSetEdit() ) )
+ ->dcopObject()->objId() );
+}
diff --git a/kword/KWordFormulaFrameSetIface.h b/kword/KWordFormulaFrameSetIface.h
new file mode 100644
index 00000000..36324a0a
--- /dev/null
+++ b/kword/KWordFormulaFrameSetIface.h
@@ -0,0 +1,45 @@
+/* This file is part of the KDE project
+ Copyright (C) 2002, Laurent MONTEL <lmontel@mandrakesoft.com>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+*/
+
+#ifndef KWORD_FORMULAFRAMESET_IFACE_H
+#define KWORD_FORMULAFRAMESET_IFACE_H
+
+#include <KoDocumentIface.h>
+#include <dcopref.h>
+
+#include <qstring.h>
+#include <qcolor.h>
+#include "KWordFrameSetIface.h"
+class KWFormulaFrameSet;
+class KWordViewIface;
+
+class KWordFormulaFrameSetIface : public KWordFrameSetIface
+{
+ K_DCOP
+public:
+ KWordFormulaFrameSetIface( KWFormulaFrameSet *_frametext );
+
+k_dcop:
+ virtual DCOPRef startEditing();
+private:
+ KWFormulaFrameSet *m_formulaFrame;
+
+};
+
+#endif
diff --git a/kword/KWordFrameSetIface.cpp b/kword/KWordFrameSetIface.cpp
new file mode 100644
index 00000000..cee12dfc
--- /dev/null
+++ b/kword/KWordFrameSetIface.cpp
@@ -0,0 +1,520 @@
+/* This file is part of the KDE project
+ Copyright (C) 2002 Laurent MONTEL <lmontel@mandrakesoft.com>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+*/
+
+#include "KWordFrameSetIface.h"
+#include "KWFrameSet.h"
+#include "KWView.h"
+#include "KWDocument.h"
+#include <dcopclient.h>
+
+
+KWordFrameSetIface::KWordFrameSetIface( KWFrameSet *_frame )
+ : DCOPObject( _frame->name().utf8() )
+{
+ m_frame = _frame;
+}
+
+bool KWordFrameSetIface::isAHeader() const
+{
+ return m_frame->isAHeader();
+}
+
+bool KWordFrameSetIface::isAFooter() const
+{
+ return m_frame->isAFooter();
+}
+
+bool KWordFrameSetIface::isHeaderOrFooter() const
+{
+ return m_frame->isHeaderOrFooter();
+}
+
+bool KWordFrameSetIface::isMainFrameset() const
+{
+ return m_frame->isMainFrameset();
+}
+
+bool KWordFrameSetIface::isMoveable() const
+{
+ return m_frame->isMoveable();
+}
+
+bool KWordFrameSetIface::isVisible() const
+{
+ return m_frame->isVisible();
+}
+
+bool KWordFrameSetIface::isFloating() const
+{
+ return m_frame->isFloating();
+}
+
+double KWordFrameSetIface::ptWidth() const
+{
+ return m_frame->frame(0)->normalize().width();
+}
+
+double KWordFrameSetIface::ptHeight() const
+{
+ return m_frame->frame(0)->normalize().height();
+}
+
+double KWordFrameSetIface::ptPosX() const
+{
+ return m_frame->frame(0)->normalize().x();
+}
+
+double KWordFrameSetIface::ptPosY() const
+{
+ return m_frame->frame(0)->normalize().y();
+}
+
+int KWordFrameSetIface::zOrder() const
+{
+ return m_frame->frame(0)->zOrder();
+}
+
+int KWordFrameSetIface::pageNumber() const
+{
+ return m_frame->frame(0)->pageNumber();
+}
+
+QBrush KWordFrameSetIface::backgroundColor() const
+{
+ return m_frame->frame(0)->backgroundColor();
+}
+
+void KWordFrameSetIface::setBackgroundColor( const QString &_color )
+{
+ QBrush brush= m_frame->frame(0)->backgroundColor();
+ brush.setColor( QColor( _color ));
+ m_frame->frame(0)->setBackgroundColor( brush );
+}
+
+double KWordFrameSetIface::ptMarginLeft()const
+{
+ return m_frame->frame(0)->paddingLeft();
+}
+
+double KWordFrameSetIface::ptMarginRight()const
+{
+ return m_frame->frame(0)->paddingRight();
+}
+
+double KWordFrameSetIface::ptMarginTop()const
+{
+ return m_frame->frame(0)->paddingTop();
+}
+
+double KWordFrameSetIface::ptMarginBottom()const
+{
+ return m_frame->frame(0)->paddingBottom();
+}
+
+bool KWordFrameSetIface::isCopy()const
+{
+ return m_frame->frame(0)->isCopy();
+}
+
+void KWordFrameSetIface::setPtMarginLeft(double val)
+{
+ m_frame->frame( 0 )->setPaddingLeft(val);
+ m_frame->kWordDocument()->layout();
+}
+
+void KWordFrameSetIface::setPtMarginRight(double val)
+{
+ m_frame->frame( 0 )->setPaddingRight(val);
+ m_frame->kWordDocument()->layout();
+
+}
+void KWordFrameSetIface::setPtMarginTop(double val)
+{
+ m_frame->frame( 0 )->setPaddingTop(val);
+ m_frame->kWordDocument()->layout();
+}
+
+void KWordFrameSetIface::setPtMarginBottom(double val)
+{
+ m_frame->frame( 0 )->setPaddingBottom(val);
+ m_frame->kWordDocument()->layout();
+}
+
+QColor KWordFrameSetIface::leftBorderColor() const
+{
+ return m_frame->frame( 0 )->leftBorder().color;
+}
+
+QColor KWordFrameSetIface::rightBorderColor() const
+{
+ return m_frame->frame( 0 )->rightBorder().color;
+}
+
+QColor KWordFrameSetIface::topBorderColor() const
+{
+ return m_frame->frame( 0 )->topBorder().color;
+}
+
+QColor KWordFrameSetIface::bottomBorderColor() const
+{
+ return m_frame->frame( 0 )->bottomBorder().color;
+}
+
+bool KWordFrameSetIface::isProtectSize()const
+{
+ return m_frame->isProtectSize();
+}
+
+void KWordFrameSetIface::setProtectSize( bool _b )
+{
+ m_frame->setProtectSize( _b );
+}
+
+QString KWordFrameSetIface::bottomBorderStyle() const
+{
+ switch( m_frame->frame( 0 )->bottomBorder().getStyle())
+ {
+ case KoBorder::SOLID:
+ return QString("SOLID");
+ break;
+ case KoBorder::DASH:
+ return QString("DASH");
+ break;
+ case KoBorder::DOT:
+ return QString("DOT");
+ break;
+ case KoBorder::DASH_DOT:
+ return QString("DASH DOT");
+ break;
+ case KoBorder::DASH_DOT_DOT:
+ return QString("DASH DOT DOT");
+
+ break;
+ case KoBorder::DOUBLE_LINE:
+ return QString("DOUBLE LINE");
+ break;
+ }
+ return QString::null;
+}
+
+QString KWordFrameSetIface::topBorderStyle() const
+{
+ switch( m_frame->frame( 0 )->topBorder().getStyle())
+ {
+ case KoBorder::SOLID:
+ return QString("SOLID");
+ break;
+ case KoBorder::DASH:
+ return QString("DASH");
+ break;
+ case KoBorder::DOT:
+ return QString("DOT");
+ break;
+ case KoBorder::DASH_DOT:
+ return QString("DASH DOT");
+ break;
+ case KoBorder::DASH_DOT_DOT:
+ return QString("DASH DOT DOT");
+
+ break;
+ case KoBorder::DOUBLE_LINE:
+ return QString("DOUBLE LINE");
+ break;
+ }
+ return QString::null;
+}
+
+QString KWordFrameSetIface::leftBorderStyle() const
+{
+ switch( m_frame->frame( 0 )->leftBorder().getStyle())
+ {
+ case KoBorder::SOLID:
+ return QString("SOLID");
+ break;
+ case KoBorder::DASH:
+ return QString("DASH");
+ break;
+ case KoBorder::DOT:
+ return QString("DOT");
+ break;
+ case KoBorder::DASH_DOT:
+ return QString("DASH DOT");
+ break;
+ case KoBorder::DASH_DOT_DOT:
+ return QString("DASH DOT DOT");
+
+ break;
+ case KoBorder::DOUBLE_LINE:
+ return QString("DOUBLE LINE");
+ break;
+ }
+ return QString::null;
+}
+
+QString KWordFrameSetIface::rightBorderStyle() const
+{
+ switch( m_frame->frame( 0 )->rightBorder().getStyle())
+ {
+ case KoBorder::SOLID:
+ return QString("SOLID");
+ break;
+ case KoBorder::DASH:
+ return QString("DASH");
+ break;
+ case KoBorder::DOT:
+ return QString("DOT");
+ break;
+ case KoBorder::DASH_DOT:
+ return QString("DASH DOT");
+ break;
+ case KoBorder::DASH_DOT_DOT:
+ return QString("DASH DOT DOT");
+
+ break;
+ case KoBorder::DOUBLE_LINE:
+ return QString("DOUBLE LINE");
+ break;
+ }
+ return QString::null;
+}
+
+double KWordFrameSetIface::rightBorderWidth() const
+{
+ return m_frame->frame( 0 )->rightBorder().penWidth();
+}
+
+double KWordFrameSetIface::topBorderWidth() const
+{
+ return m_frame->frame( 0 )->topBorder().penWidth();
+}
+
+double KWordFrameSetIface::bottomBorderWidth() const
+{
+ return m_frame->frame( 0 )->bottomBorder().penWidth();
+}
+double KWordFrameSetIface::leftBorderWidth() const
+{
+ return m_frame->frame( 0 )->leftBorder().penWidth();
+}
+
+void KWordFrameSetIface::setRightBorderWitdh( double _width )
+{
+ KoBorder tmp = m_frame->frame( 0 )->rightBorder();
+ tmp.setPenWidth(_width);
+ m_frame->frame( 0 )->setRightBorder(tmp);
+}
+
+void KWordFrameSetIface::setLeftBorderWitdh( double _width )
+{
+ KoBorder tmp = m_frame->frame( 0 )->leftBorder();
+ tmp.setPenWidth(_width);
+ m_frame->frame( 0 )->setLeftBorder(tmp);
+}
+
+void KWordFrameSetIface::setTopBorderWitdh( double _width )
+{
+ KoBorder tmp = m_frame->frame( 0 )->topBorder();
+ tmp.setPenWidth(_width);
+ m_frame->frame( 0 )->setTopBorder(tmp);
+}
+
+void KWordFrameSetIface::setBottomBorderWitdh( double _width )
+{
+ KoBorder tmp = m_frame->frame( 0 )->bottomBorder();
+ tmp.setPenWidth(_width);
+ m_frame->frame( 0 )->setBottomBorder(tmp);
+}
+
+void KWordFrameSetIface::setRightBorderStyle(const QString & _style)
+{
+ KoBorder tmp = m_frame->frame( 0 )->rightBorder();
+ if ( _style.lower()=="solid")
+ tmp.setStyle(KoBorder::SOLID);
+ else if ( _style.lower()=="dash")
+ tmp.setStyle(KoBorder::DASH);
+ else if ( _style.lower()=="dot")
+ tmp.setStyle(KoBorder::DOT);
+ else if ( _style.lower()=="dash dot")
+ tmp.setStyle(KoBorder::DASH_DOT);
+ else if ( _style.lower()=="dash dot dot")
+ tmp.setStyle(KoBorder::DASH_DOT_DOT);
+ else if ( _style.lower()=="double line")
+ tmp.setStyle(KoBorder::DOUBLE_LINE);
+ else
+ {
+ kdDebug()<<" style :"<<_style<<" do not exist!\n";
+ return;
+ }
+ m_frame->frame( 0 )->setRightBorder(tmp);
+}
+
+void KWordFrameSetIface::setLeftBorderStyle(const QString & _style)
+{
+ KoBorder tmp = m_frame->frame( 0 )->leftBorder();
+ if ( _style.lower()=="solid")
+ tmp.setStyle(KoBorder::SOLID);
+ else if ( _style.lower()=="dash")
+ tmp.setStyle(KoBorder::DASH);
+ else if ( _style.lower()=="dot")
+ tmp.setStyle(KoBorder::DOT);
+ else if ( _style.lower()=="dash dot")
+ tmp.setStyle(KoBorder::DASH_DOT);
+ else if ( _style.lower()=="dash dot dot")
+ tmp.setStyle(KoBorder::DASH_DOT_DOT);
+ else if ( _style.lower()=="double line")
+ tmp.setStyle(KoBorder::DOUBLE_LINE);
+ else
+ {
+ kdDebug()<<" style :"<<_style<<" do not exist!\n";
+ return;
+ }
+ m_frame->frame( 0 )->setLeftBorder(tmp);
+
+}
+
+void KWordFrameSetIface::setTopBorderStyle(const QString & _style)
+{
+ KoBorder tmp = m_frame->frame( 0 )->topBorder();
+
+ if ( _style.lower()=="solid")
+ tmp.setStyle(KoBorder::SOLID);
+ else if ( _style.lower()=="dash")
+ tmp.setStyle(KoBorder::DASH);
+ else if ( _style.lower()=="dot")
+ tmp.setStyle(KoBorder::DOT);
+ else if ( _style.lower()=="dash dot")
+ tmp.setStyle(KoBorder::DASH_DOT);
+ else if ( _style.lower()=="dash dot dot")
+ tmp.setStyle(KoBorder::DASH_DOT_DOT);
+ else if ( _style.lower()=="double line")
+ tmp.setStyle(KoBorder::DOUBLE_LINE);
+ else
+ {
+ kdDebug()<<" style :"<<_style<<" do not exist!\n";
+ return;
+ }
+ m_frame->frame( 0 )->setTopBorder(tmp);
+}
+
+void KWordFrameSetIface::setBottomBorderStyle(const QString & _style)
+{
+ KoBorder tmp = m_frame->frame( 0 )->bottomBorder();
+ if ( _style.lower()=="solid")
+ tmp.setStyle(KoBorder::SOLID);
+ else if ( _style.lower()=="dash")
+ tmp.setStyle(KoBorder::DASH);
+ else if ( _style.lower()=="dot")
+ tmp.setStyle(KoBorder::DOT);
+ else if ( _style.lower()=="dash dot")
+ tmp.setStyle(KoBorder::DASH_DOT);
+ else if ( _style.lower()=="dash dot dot")
+ tmp.setStyle(KoBorder::DASH_DOT_DOT);
+ else if ( _style.lower()=="double line")
+ tmp.setStyle(KoBorder::DOUBLE_LINE);
+ else
+ {
+ kdDebug()<<" style :"<<_style<<" do not exist!\n";
+ return;
+ }
+ m_frame->frame( 0 )->setBottomBorder(tmp);
+}
+
+bool KWordFrameSetIface::isFootEndNote() const
+{
+ return m_frame->isFootEndNote();
+}
+
+QString KWordFrameSetIface::frameSetInfo() const
+{
+ switch( m_frame->frameSetInfo() )
+ {
+ case KWFrameSet::FI_BODY:
+ return QString("body");
+ break;
+ case KWFrameSet::FI_FIRST_HEADER:
+ return QString("First header");
+ break;
+ case KWFrameSet::FI_ODD_HEADER:
+ return QString("First even header");
+ break;
+ case KWFrameSet::FI_EVEN_HEADER:
+ return QString("First odd header");
+ break;
+ case KWFrameSet::FI_FIRST_FOOTER:
+ return QString("First footer");
+ break;
+ case KWFrameSet::FI_EVEN_FOOTER:
+ return QString("Odd footer");
+ break;
+ case KWFrameSet::FI_ODD_FOOTER:
+ return QString("Even footer");
+ break;
+ case KWFrameSet::FI_FOOTNOTE:
+ return QString("FootNote");
+ break;
+ default:
+ return QString::null;
+ break;
+ }
+}
+
+void KWordFrameSetIface::setFrameSetInfo( const QString & _type)
+{
+ if ( _type.lower() =="body")
+ {
+ m_frame->setFrameSetInfo( KWFrameSet::FI_BODY );
+ }
+ else if ( _type.lower() =="first header")
+ {
+ m_frame->setFrameSetInfo( KWFrameSet::FI_FIRST_HEADER );
+ }
+ else if ( _type.lower() =="first even header")
+ {
+ m_frame->setFrameSetInfo( KWFrameSet::FI_ODD_HEADER );
+ }
+ else if ( _type.lower() =="first odd header")
+ {
+ m_frame->setFrameSetInfo( KWFrameSet::FI_EVEN_HEADER );
+ }
+ else if ( _type.lower() =="first footer")
+ {
+ m_frame->setFrameSetInfo( KWFrameSet::FI_FIRST_FOOTER );
+ }
+ else if ( _type.lower() =="odd footer")
+ {
+ m_frame->setFrameSetInfo( KWFrameSet::FI_EVEN_FOOTER );
+ }
+ else if ( _type.lower() =="even footer")
+ {
+ m_frame->setFrameSetInfo( KWFrameSet::FI_ODD_FOOTER );
+ }
+ else if ( _type.lower() =="even footer")
+ {
+ m_frame->setFrameSetInfo( KWFrameSet::FI_ODD_FOOTER );
+ }
+ else if ( _type.lower() =="footnote")
+ {
+ m_frame->setFrameSetInfo( KWFrameSet::FI_FOOTNOTE );
+ }
+ else
+ {
+ kdDebug()<<" Error in setFrameSetInfo() :"<<_type<<endl;
+ }
+}
+
diff --git a/kword/KWordFrameSetIface.h b/kword/KWordFrameSetIface.h
new file mode 100644
index 00000000..b9dbc8e4
--- /dev/null
+++ b/kword/KWordFrameSetIface.h
@@ -0,0 +1,104 @@
+/* This file is part of the KDE project
+ Copyright (C) 2002, Laurent MONTEL <lmontel@mandrakesoft.com>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+*/
+
+#ifndef KWORD_FRAMESET_IFACE_H
+#define KWORD_FRAMESET_IFACE_H
+
+#include <KoDocumentIface.h>
+#include <dcopref.h>
+
+#include <qstring.h>
+#include <qcolor.h>
+#include <qbrush.h>
+class KWFrameSet;
+
+class KWordFrameSetIface : public DCOPObject
+{
+ K_DCOP
+public:
+ KWordFrameSetIface( KWFrameSet *_frame );
+
+k_dcop:
+ virtual bool isAHeader() const;
+ virtual bool isAFooter() const;
+ virtual bool isHeaderOrFooter() const;
+ virtual bool isFootEndNote() const;
+
+ virtual bool isMainFrameset() const;
+ virtual bool isMoveable() const;
+ virtual bool isVisible() const;
+ virtual bool isFloating() const;
+ //use frame(0)
+ virtual double ptWidth() const;
+ virtual double ptHeight() const;
+ virtual double ptPosX() const;
+ virtual double ptPosY() const;
+ virtual int zOrder() const;
+ virtual int pageNumber() const;
+ virtual QBrush backgroundColor() const;
+ virtual void setBackgroundColor( const QString &_color );
+
+ virtual double ptMarginLeft()const;
+ virtual double ptMarginRight()const;
+ virtual double ptMarginTop()const;
+ virtual double ptMarginBottom()const;
+
+ virtual void setPtMarginLeft(double val);
+ virtual void setPtMarginRight(double val);
+ virtual void setPtMarginTop(double val);
+ virtual void setPtMarginBottom(double val);
+
+ virtual QColor leftBorderColor() const;
+ virtual QColor rightBorderColor() const;
+ virtual QColor topBorderColor() const;
+ virtual QColor bottomBorderColor() const;
+
+ virtual bool isCopy()const;
+ virtual bool isProtectSize()const;
+ virtual void setProtectSize( bool _b );
+ //it's for frame 0
+ QString bottomBorderStyle()const;
+ QString topBorderStyle()const;
+ QString leftBorderStyle()const;
+ QString rightBorderStyle()const;
+
+ double rightBorderWidth() const;
+ double topBorderWidth() const;
+ double bottomBorderWidth() const;
+ double leftBorderWidth() const;
+
+ void setBottomBorderWitdh( double _width );
+ void setTopBorderWitdh( double _width );
+ void setLeftBorderWitdh( double _width );
+ void setRightBorderWitdh( double _width );
+
+ void setBottomBorderStyle(const QString & _style);
+ void setTopBorderStyle(const QString & _style);
+ void setLeftBorderStyle(const QString & _style);
+ void setRightBorderStyle(const QString & _style);
+
+ QString frameSetInfo() const;
+ void setFrameSetInfo( const QString & _type);
+
+
+private:
+ KWFrameSet *m_frame;
+};
+
+#endif
diff --git a/kword/KWordMailMergeDatabaseIface.h b/kword/KWordMailMergeDatabaseIface.h
new file mode 100644
index 00000000..fdf18293
--- /dev/null
+++ b/kword/KWordMailMergeDatabaseIface.h
@@ -0,0 +1,52 @@
+/* This file is part of the KDE project
+ Copyright (C) 2001 Joseph Wenninger <jowenn@kde.org>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+*/
+
+#ifndef __KWordMailMergeDatabaseIface_h__
+#define __KWordMailMergeDatabaseIface_h__
+
+#include <dcopobject.h>
+#include <qstringlist.h>
+/**
+ * DCOP interface for the MailMergeDataBase class
+ */
+class KWordMailMergeDatabaseIface : public DCOPObject
+{
+ K_DCOP
+public:
+ KWordMailMergeDatabaseIface(const QCString &name);
+ ~KWordMailMergeDatabaseIface();
+k_dcop:
+ virtual void refresh(bool)=0; //will not be blocked when the configuration dialog is open
+
+ virtual QStringList availablePlugins()=0; //will not be blocked when configuration dialog is open
+ virtual bool isConfigDialogShown()=0; // will not be blocked when the configuration dialog is open
+
+ /* first parameter plugin name
+ second parameter:
+ open :shows the open dialog if possible
+ create :shows the create dialog if possible
+ silent :doesn't do any further actions than loading
+ This call will return false, when the plugin couldn't be loaded,
+ the user rejected to change the datasource or the configuration dialog is open
+ */
+ virtual bool loadPlugin(const QString &name,const QString &command)=0;
+};
+
+#endif
+
diff --git a/kword/KWordPartFrameSetIface.cpp b/kword/KWordPartFrameSetIface.cpp
new file mode 100644
index 00000000..fa2acefe
--- /dev/null
+++ b/kword/KWordPartFrameSetIface.cpp
@@ -0,0 +1,49 @@
+/* This file is part of the KDE project
+ Copyright (C) 2002 Laurent MONTEL <lmontel@mandrakesoft.com>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+*/
+
+#include "KWordPartFrameSetIface.h"
+#include "KWDocument.h"
+#include "KWPartFrameSet.h"
+#include "KWView.h"
+#include "KWCanvas.h"
+
+#include <kapplication.h>
+#include <kparts/partmanager.h>
+#include <dcopclient.h>
+
+KWordPartFrameSetIface::KWordPartFrameSetIface( KWPartFrameSet *fs )
+ : KWordFrameSetIface( fs )
+{
+ m_partFrameSet = fs;
+}
+
+void KWordPartFrameSetIface::startEditing()
+{
+ if ( m_partFrameSet->isDeleted() )
+ return; // DCOPRef();
+ KWDocument *doc = m_partFrameSet->kWordDocument();
+ KWView* view = doc->getAllViews().first();
+ KoDocument* part = m_partFrameSet->getChild()->document();
+ if ( !part || !view )
+ return;
+ view->partManager()->addPart( part, false );
+ view->partManager()->setActivePart( part, view );
+ /* return DCOPRef( kapp->dcopClient()->appId(),
+ (static_cast<KWPartFrameSetEdit *>( canvas->currentFrameSetEdit()))->dcopObject()->objId() ); */
+}
diff --git a/kword/KWordPartFrameSetIface.h b/kword/KWordPartFrameSetIface.h
new file mode 100644
index 00000000..b22c0fbf
--- /dev/null
+++ b/kword/KWordPartFrameSetIface.h
@@ -0,0 +1,43 @@
+/* This file is part of the KDE project
+ Copyright (C) 2002, Laurent MONTEL <lmontel@mandrakesoft.com>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+*/
+
+#ifndef KWORD_PARTFRAMESET_IFACE_H
+#define KWORD_PARTFRAMESET_IFACE_H
+
+#include <KoDocumentIface.h>
+#include "KWordFrameSetIface.h"
+#include <dcopref.h>
+
+#include <qstring.h>
+#include <qcolor.h>
+class KWPartFrameSet;
+class KWordViewIface;
+
+class KWordPartFrameSetIface : public KWordFrameSetIface
+{
+ K_DCOP
+public:
+ KWordPartFrameSetIface( KWPartFrameSet *fs );
+k_dcop:
+ void startEditing();
+private:
+ KWPartFrameSet *m_partFrameSet;
+};
+
+#endif
diff --git a/kword/KWordPictureFrameSetIface.cpp b/kword/KWordPictureFrameSetIface.cpp
new file mode 100644
index 00000000..57ee2857
--- /dev/null
+++ b/kword/KWordPictureFrameSetIface.cpp
@@ -0,0 +1,47 @@
+/* This file is part of the KDE project
+ Copyright (C) 2002 Laurent MONTEL <lmontel@mandrakesoft.com>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+*/
+
+#include "KWordPictureFrameSetIface.h"
+#include "KWPictureFrameSet.h"
+#include "KWFrame.h"
+#include "KWDocument.h"
+#include <dcopclient.h>
+
+
+KWordPictureFrameSetIface::KWordPictureFrameSetIface( KWPictureFrameSet *_frame )
+ : KWordFrameSetIface( _frame )
+{
+ m_frame = _frame;
+}
+
+bool KWordPictureFrameSetIface::keepAspectRatio() const
+{
+ return m_frame->keepAspectRatio();
+}
+
+void KWordPictureFrameSetIface::setKeepAspectRatio( bool b )
+{
+ m_frame->setKeepAspectRatio(b);
+}
+
+void KWordPictureFrameSetIface::loadImage( const QString &image )
+{
+ m_frame->loadPicture( image );
+ m_frame->kWordDocument()->slotRepaintChanged( m_frame );
+}
diff --git a/kword/KWordPictureFrameSetIface.h b/kword/KWordPictureFrameSetIface.h
new file mode 100644
index 00000000..aa855e7c
--- /dev/null
+++ b/kword/KWordPictureFrameSetIface.h
@@ -0,0 +1,47 @@
+/* This file is part of the KDE project
+ Copyright (C) 2002, Laurent MONTEL <lmontel@mandrakesoft.com>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+*/
+
+#ifndef KWORD_PICTUREFRAMESET_IFACE_H
+#define KWORD_PICTUREFRAMESET_IFACE_H
+
+#include <KoDocumentIface.h>
+#include "KWordFrameSetIface.h"
+#include <dcopref.h>
+
+#include <qstring.h>
+#include <qcolor.h>
+class KWPictureFrameSet;
+class KWordViewIface;
+
+class KWordPictureFrameSetIface : public KWordFrameSetIface
+{
+ K_DCOP
+public:
+ KWordPictureFrameSetIface( KWPictureFrameSet *_frame );
+
+k_dcop:
+ bool keepAspectRatio() const;
+ void setKeepAspectRatio( bool b );
+ void loadImage( const QString &image );
+
+private:
+ KWPictureFrameSet *m_frame;
+};
+
+#endif
diff --git a/kword/KWordTableFrameSetIface.cpp b/kword/KWordTableFrameSetIface.cpp
new file mode 100644
index 00000000..5f117c89
--- /dev/null
+++ b/kword/KWordTableFrameSetIface.cpp
@@ -0,0 +1,87 @@
+/* This file is part of the KDE project
+ Copyright (C) 2002 Laurent MONTEL <lmontel@mandrakesoft.com>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+*/
+
+#include "KWordTableFrameSetIface.h"
+#include "KWordTextFrameSetIface.h"
+#include "KWordTextFrameSetEditIface.h"
+
+#include "KWFrame.h"
+#include "KWTableFrameSet.h"
+#include <kapplication.h>
+#include <dcopclient.h>
+#include "KWView.h"
+#include "KWDocument.h"
+#include "KWCanvas.h"
+
+KWordTableFrameSetIface::KWordTableFrameSetIface( KWTableFrameSet *_frame )
+ : KWordFrameSetIface( _frame)
+{
+ m_table = _frame;
+}
+
+uint KWordTableFrameSetIface::nbRows()
+{
+ return m_table->getRows();
+}
+
+uint KWordTableFrameSetIface::numCols()
+{
+ return m_table->getColumns();
+}
+uint KWordTableFrameSetIface::numCells()
+{
+ return m_table->getNumCells();
+}
+
+DCOPRef KWordTableFrameSetIface::cell( int pos )
+{
+ // This method now sucks
+ KWTableFrameSet::TableIter i(m_table);
+ int p = 0;
+ for(; i && p <= pos; ++i,++p)
+ if( ! i.current() )
+ return DCOPRef();
+
+ return DCOPRef( kapp->dcopClient()->appId(),
+ i->dcopObject()->objId() );
+}
+
+DCOPRef KWordTableFrameSetIface::cell( uint row, uint col )
+{
+ if( row>=m_table->getRows() || col>= m_table->getColumns())
+ return DCOPRef();
+ return DCOPRef( kapp->dcopClient()->appId(),
+ m_table->cell(row,col)->dcopObject()->objId() );
+}
+
+DCOPRef KWordTableFrameSetIface::startEditingCell(uint row, uint col )
+{
+ if( row>=m_table->getRows() || col>= m_table->getColumns())
+ return DCOPRef();
+
+ KWDocument *doc=m_table->kWordDocument();
+ KWView* view = doc->getAllViews().first();
+ KWCanvas* canvas = view->getGUI()->canvasWidget();
+ KWTextFrameSet *m_frametext=m_table->cell(row,col);
+ if( !m_frametext || m_frametext->isDeleted())
+ return DCOPRef();
+ canvas->checkCurrentEdit(m_frametext, true);
+ return DCOPRef( kapp->dcopClient()->appId(),
+ (static_cast<KWTextFrameSetEdit *>( canvas->currentFrameSetEdit()))->dcopObject()->objId() );
+}
diff --git a/kword/KWordTableFrameSetIface.h b/kword/KWordTableFrameSetIface.h
new file mode 100644
index 00000000..d85db10e
--- /dev/null
+++ b/kword/KWordTableFrameSetIface.h
@@ -0,0 +1,51 @@
+/* This file is part of the KDE project
+ Copyright (C) 2002, Laurent MONTEL <lmontel@mandrakesoft.com>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+*/
+
+#ifndef KWORD_TABLEFRAMESET_IFACE_H
+#define KWORD_TABLEFRAMESET_IFACE_H
+
+#include <KoDocumentIface.h>
+#include "KWordFrameSetIface.h"
+#include <dcopref.h>
+
+#include <qstring.h>
+#include <qcolor.h>
+class KWTableFrameSet;
+class KWordViewIface;
+
+class KWordTableFrameSetIface : public KWordFrameSetIface
+{
+ K_DCOP
+public:
+ KWordTableFrameSetIface( KWTableFrameSet *_frame );
+
+k_dcop:
+ uint nbRows();
+ uint numCols();
+ uint numCells() ;
+ //return reference to a cell
+ DCOPRef cell( int pos );
+ DCOPRef cell( uint row, uint col );
+ DCOPRef startEditingCell(uint row, uint col );
+
+private:
+ KWTableFrameSet *m_table;
+};
+
+#endif
diff --git a/kword/KWordTextFrameSetEditIface.cpp b/kword/KWordTextFrameSetEditIface.cpp
new file mode 100644
index 00000000..ff567513
--- /dev/null
+++ b/kword/KWordTextFrameSetEditIface.cpp
@@ -0,0 +1,161 @@
+/* This file is part of the KDE project
+ Copyright (C) 2002 Laurent MONTEL <lmontel@mandrakesoft.com>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+*/
+
+#include "KWordTextFrameSetEditIface.h"
+
+#include "KWTextFrameSet.h"
+#include <dcopclient.h>
+#include "defs.h"
+
+KWordTextFrameSetEditIface::KWordTextFrameSetEditIface( KWTextFrameSetEdit *_framesetedit )
+ :KoTextViewIface(_framesetedit)
+{
+ m_framesetedit = _framesetedit;
+}
+
+void KWordTextFrameSetEditIface::insertExpression(const QString &_c)
+{
+ m_framesetedit->insertExpression(_c);
+}
+
+void KWordTextFrameSetEditIface::insertFrameBreak()
+{
+ m_framesetedit->insertFrameBreak();
+}
+
+void KWordTextFrameSetEditIface::insertVariable( int type, int subtype )
+{
+ m_framesetedit->insertVariable(type,subtype);
+}
+
+void KWordTextFrameSetEditIface::insertCustomVariable( const QString &name)
+{
+ m_framesetedit->insertCustomVariable(name);
+}
+
+void KWordTextFrameSetEditIface::insertLink(const QString &_linkName, const QString & hrefName)
+{
+ m_framesetedit->insertLink(_linkName,hrefName);
+}
+
+void KWordTextFrameSetEditIface::insertTOC()
+{
+ m_framesetedit->insertTOC();
+}
+
+void KWordTextFrameSetEditIface::cut()
+{
+ m_framesetedit->cut();
+}
+
+void KWordTextFrameSetEditIface::copy()
+{
+ m_framesetedit->copy();
+}
+
+void KWordTextFrameSetEditIface::paste()
+{
+ m_framesetedit->paste();
+}
+
+void KWordTextFrameSetEditIface::insertNonbreakingSpace()
+{
+ m_framesetedit->insertNonbreakingSpace();
+}
+
+void KWordTextFrameSetEditIface::insertVariable( const QString & var)
+{
+ if( var=="DATE")
+ m_framesetedit->insertVariable(0,1);
+ else if (var=="FIXED-DATE")
+ m_framesetedit->insertVariable(0,0);
+ else if (var=="TIME")
+ m_framesetedit->insertVariable(2,1);
+ else if (var=="FIXED-TIME")
+ m_framesetedit->insertVariable(2,0);
+ else if (var=="FILENAME")
+ m_framesetedit->insertVariable(8,0);
+ else if (var=="AUTHORNAME")
+ m_framesetedit->insertVariable(8,2);
+ else if (var=="EMAIL")
+ m_framesetedit->insertVariable(8,3);
+ else if (var=="TITLE")
+ m_framesetedit->insertVariable(8,10);
+ else if (var=="ABSTRACT")
+ m_framesetedit->insertVariable(8,11);
+ else if (var=="DIRECTORYNAME")
+ m_framesetedit->insertVariable(8,1);
+ else if (var=="COMPANYNAME")
+ m_framesetedit->insertVariable(8,4);
+ else if (var=="PATHFILENAME")
+ m_framesetedit->insertVariable(8,5);
+ else if (var=="FILENAMEWITHOUTEXTENSION")
+ m_framesetedit->insertVariable(8,6);
+ else if (var=="CURRENTPAGE")
+ m_framesetedit->insertVariable(4,0);
+ else if (var=="TOTALPAGE")
+ m_framesetedit->insertVariable(8,1);
+ else if (var=="TELEPHONE")
+ m_framesetedit->insertVariable(8,7);
+ else if (var=="FAX")
+ m_framesetedit->insertVariable(8,8);
+ else if (var=="COUNTRY")
+ m_framesetedit->insertVariable(8,9);
+ else if (var=="POSTAL_CODE")
+ m_framesetedit->insertVariable(8,12);
+ else if (var=="CITY")
+ m_framesetedit->insertVariable(8,13);
+ else if (var=="STREET")
+ m_framesetedit->insertVariable(8,14);
+}
+
+void KWordTextFrameSetEditIface::insertComment(const QString &_comment)
+{
+ m_framesetedit->insertComment(_comment);
+}
+
+
+void KWordTextFrameSetEditIface::insertAutoFootNote( const QString & type )
+{
+ if ( type.lower() =="footnote")
+ {
+ m_framesetedit->insertFootNote( FootNote, KWFootNoteVariable::Auto, QString::null);
+ }
+ else if ( type.lower()=="endnote")
+ {
+ m_framesetedit->insertFootNote( EndNote, KWFootNoteVariable::Auto, QString::null);
+ }
+}
+
+void KWordTextFrameSetEditIface::insertManualFootNote( const QString & type, const QString & noteText )
+{
+ if ( type.lower() =="footnote")
+ {
+ m_framesetedit->insertFootNote( FootNote, KWFootNoteVariable::Manual, noteText);
+ }
+ else if ( type.lower()=="endnote")
+ {
+ m_framesetedit->insertFootNote( EndNote, KWFootNoteVariable::Manual, noteText);
+ }
+}
+
+void KWordTextFrameSetEditIface::selectAll()
+{
+ m_framesetedit->selectAll();
+}
diff --git a/kword/KWordTextFrameSetEditIface.h b/kword/KWordTextFrameSetEditIface.h
new file mode 100644
index 00000000..0ded9ccf
--- /dev/null
+++ b/kword/KWordTextFrameSetEditIface.h
@@ -0,0 +1,58 @@
+/* This file is part of the KDE project
+ Copyright (C) 2002, Laurent MONTEL <lmontel@mandrakesoft.com>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+*/
+
+#ifndef KWORD_TEXTFRAMESETEDIT_IFACE_H
+#define KWORD_TEXTFRAMESETEDIT_IFACE_H
+
+#include <KoDocumentIface.h>
+#include <dcopref.h>
+
+#include <qstring.h>
+#include <qcolor.h>
+#include <KoTextViewIface.h>
+class KWTextFrameSetEdit;
+
+class KWordTextFrameSetEditIface : public KoTextViewIface
+{
+ K_DCOP
+public:
+ KWordTextFrameSetEditIface( KWTextFrameSetEdit *_frametext );
+
+k_dcop:
+ void insertExpression(const QString &_c);
+ void insertFrameBreak();
+ void insertVariable( int type, int subtype = 0 );
+ void insertVariable( const QString & var);
+ void insertCustomVariable( const QString &name);
+ void insertLink(const QString &_linkName, const QString & hrefName);
+ void insertTOC();
+ void cut();
+ void copy();
+ void paste();
+ void insertNonbreakingSpace();
+ void insertComment(const QString &_comment);
+ void insertAutoFootNote( const QString & type );
+ void insertManualFootNote( const QString & type, const QString & noteText );
+ void selectAll();
+private:
+ KWTextFrameSetEdit *m_framesetedit;
+
+};
+
+#endif
diff --git a/kword/KWordTextFrameSetIface.cpp b/kword/KWordTextFrameSetIface.cpp
new file mode 100644
index 00000000..bec7832b
--- /dev/null
+++ b/kword/KWordTextFrameSetIface.cpp
@@ -0,0 +1,310 @@
+/* This file is part of the KDE project
+ Copyright (C) 2002 Laurent MONTEL <lmontel@mandrakesoft.com>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+*/
+
+#include "KWordTextFrameSetIface.h"
+#include "KWordViewIface.h"
+#include "KWTextFrameSet.h"
+#include <KoTextViewIface.h>
+#include "KWView.h"
+#include <KoTextObject.h>
+#include "KWCanvas.h"
+#include "KWDocument.h"
+#include <kapplication.h>
+#include <dcopclient.h>
+#include "KWordFrameSetIface.h"
+#include <kdebug.h>
+#include <kcommand.h>
+
+KWordTextFrameSetIface::KWordTextFrameSetIface( KWTextFrameSet *_frame )
+ : KWordFrameSetIface( _frame)
+{
+ m_frametext = _frame;
+}
+
+DCOPRef KWordTextFrameSetIface::startEditing()
+{
+ if ( m_frametext->isDeleted() )
+ return DCOPRef();
+ KWDocument *doc=m_frametext->kWordDocument();
+ QValueList<KWView *> views = doc->getAllViews();
+ KWCanvas* canvas = views.first()->getGUI()->canvasWidget();
+ canvas->editFrameSet(m_frametext, true);
+ return DCOPRef( kapp->dcopClient()->appId(),
+ (static_cast<KWTextFrameSetEdit *>( canvas->currentFrameSetEdit()))->dcopObject()->objId() );
+}
+
+bool KWordTextFrameSetIface::hasSelection() const
+{
+ return m_frametext->hasSelection();
+}
+
+int KWordTextFrameSetIface::numberOfParagraphs()
+{
+ return m_frametext->paragraphs();
+}
+
+QString KWordTextFrameSetIface::name() const
+{
+ return m_frametext->name();
+}
+
+QString KWordTextFrameSetIface::selectedText() const
+{
+ return m_frametext->selectedText();
+}
+
+void KWordTextFrameSetIface::selectAll( bool select )
+{
+ m_frametext->textObject()->selectAll(select);
+}
+
+int KWordTextFrameSetIface::paragraphsSelected()
+{
+ return m_frametext->paragraphsSelected();
+}
+
+void KWordTextFrameSetIface::setBoldText( bool b )
+{
+ KCommand *cmd=m_frametext->textObject()->setBoldCommand( b );
+ delete cmd;
+}
+
+void KWordTextFrameSetIface::setItalicText( bool b )
+{
+ KCommand *cmd=m_frametext->textObject()->setItalicCommand(b);
+ delete cmd;
+}
+
+void KWordTextFrameSetIface::setUnderlineText( bool b )
+{
+ KCommand *cmd=m_frametext->textObject()->setUnderlineCommand(b);
+ delete cmd;
+}
+
+void KWordTextFrameSetIface::setDoubleUnderlineText(bool b)
+{
+ KCommand *cmd=m_frametext->textObject()->setDoubleUnderlineCommand(b);
+ delete cmd;
+}
+
+void KWordTextFrameSetIface::setStrikeOutText( bool b )
+{
+ KCommand *cmd=m_frametext->textObject()->setStrikeOutCommand(b);
+ delete cmd;
+}
+
+void KWordTextFrameSetIface::setTextColor( const QColor &col )
+{
+ KCommand *cmd=m_frametext->textObject()->setTextColorCommand(col);
+ delete cmd;
+}
+
+void KWordTextFrameSetIface::setTextPointSize( int s )
+{
+ KCommand *cmd=m_frametext->textObject()->setPointSizeCommand( s );
+ delete cmd;
+}
+
+void KWordTextFrameSetIface::setTextSubScript( bool b )
+{
+ KCommand *cmd=m_frametext->textObject()->setTextSubScriptCommand( b );
+ delete cmd;
+}
+
+void KWordTextFrameSetIface::setTextSuperScript( bool b )
+{
+ KCommand *cmd=m_frametext->textObject()->setTextSuperScriptCommand( b );
+ delete cmd;
+}
+
+void KWordTextFrameSetIface::setTextDefaultFormat()
+{
+ KCommand *cmd=m_frametext->textObject()->setDefaultFormatCommand();
+ delete cmd;
+}
+
+void KWordTextFrameSetIface::setTextBackgroundColor(const QColor & col)
+{
+ KCommand *cmd=m_frametext->textObject()->setTextBackgroundColorCommand(col);
+ delete cmd;
+}
+
+void KWordTextFrameSetIface::setUnderlineColor( const QColor & color )
+{
+
+ KCommand *cmd=m_frametext->textObject()->setUnderlineColorCommand( color );
+ delete cmd;
+}
+
+
+QColor KWordTextFrameSetIface::textColor() const
+{
+ return m_frametext->textObject()->textColor();
+}
+
+QFont KWordTextFrameSetIface::textFont() const
+{
+ return m_frametext->textObject()->textFont();
+}
+
+QString KWordTextFrameSetIface::textFontFamily()const
+{
+ return m_frametext->textObject()->textFontFamily();
+}
+
+QColor KWordTextFrameSetIface::textBackgroundColor() const
+{
+ return m_frametext->textObject()->textBackgroundColor();
+}
+
+bool KWordTextFrameSetIface::textItalic() const
+{
+ return m_frametext->textObject()->textItalic();
+}
+
+bool KWordTextFrameSetIface::textBold() const
+{
+ return m_frametext->textObject()->textBold();
+}
+
+bool KWordTextFrameSetIface::textUnderline()const
+{
+ return m_frametext->textObject()->textUnderline();
+}
+
+bool KWordTextFrameSetIface::textDoubleUnderline()const
+{
+ return m_frametext->textObject()->textDoubleUnderline();
+}
+
+QColor KWordTextFrameSetIface::textUnderlineColor() const
+{
+ return m_frametext->textObject()->textUnderlineColor();
+}
+
+bool KWordTextFrameSetIface::textStrikeOut()const
+{
+ return m_frametext->textObject()->textStrikeOut();
+}
+
+bool KWordTextFrameSetIface::textSubScript() const
+{
+ return m_frametext->textObject()->textSubScript();
+}
+
+bool KWordTextFrameSetIface::textSuperScript() const
+{
+ return m_frametext->textObject()->textSuperScript();
+}
+
+void KWordTextFrameSetIface::setTextFamilyFont(const QString &font)
+{
+ KCommand *cmd=m_frametext->textObject()->setFamilyCommand(font);
+ delete cmd;
+}
+
+void KWordTextFrameSetIface::changeCaseOfText( const QString & caseType)
+{
+ KCommand *cmd=0L;
+ if( caseType.lower() == "uppercase" )
+ {
+ cmd = m_frametext->textObject()->setChangeCaseOfTextCommand( KoChangeCaseDia::UpperCase );
+ }
+ else if( caseType.lower() =="lowercase" )
+ {
+ cmd = m_frametext->textObject()->setChangeCaseOfTextCommand( KoChangeCaseDia::LowerCase );
+ }
+ else if( caseType.lower() =="titlecase" )
+ {
+ cmd = m_frametext->textObject()->setChangeCaseOfTextCommand( KoChangeCaseDia::TitleCase );
+ }
+ else if( caseType.lower() =="togglecase" )
+ {
+ cmd = m_frametext->textObject()->setChangeCaseOfTextCommand( KoChangeCaseDia::ToggleCase );
+ }
+ else if( caseType.lower() =="sentencecase" )
+ {
+ cmd = m_frametext->textObject()->setChangeCaseOfTextCommand( KoChangeCaseDia::SentenceCase );
+ }
+
+ else
+ kdDebug()<<"Error in void KWordTextFrameSetIface::changeCaseOfText( const QString & caseType) parameter\n";
+ delete cmd;
+}
+
+// ## move to KWordFrameSetIface
+void KWordTextFrameSetIface::setProtectContent ( bool _protect )
+{
+ m_frametext->setProtectContent( _protect );
+}
+
+bool KWordTextFrameSetIface::isProtectContent() const
+{
+ return m_frametext->protectContent();
+}
+
+/*
+bool KWordTextFrameSetIface::textShadow() const
+{
+ return m_frametext->textObject()->textShadow();
+}
+
+void KWordTextFrameSetIface::setTextShadow( bool b )
+{
+ KCommand *cmd=m_frametext->textObject()->setShadowTextCommand( b );
+ delete cmd;
+}
+*/
+
+double KWordTextFrameSetIface::relativeTextSize() const
+{
+ return m_frametext->textObject()->relativeTextSize();
+}
+
+void KWordTextFrameSetIface::setRelativeTextSize( double _size )
+{
+ KCommand *cmd=m_frametext->textObject()->setRelativeTextSizeCommand(_size );
+ delete cmd;
+}
+
+bool KWordTextFrameSetIface::wordByWord() const
+{
+ return m_frametext->textObject()->wordByWord();
+}
+
+void KWordTextFrameSetIface::setWordByWord( bool _b )
+{
+ KCommand *cmd=m_frametext->textObject()->setWordByWordCommand(_b );
+ delete cmd;
+}
+
+QString KWordTextFrameSetIface::fontAttibute()const
+{
+ return KoTextFormat::attributeFontToString( m_frametext->textObject()->fontAttribute() );
+}
+
+QString KWordTextFrameSetIface::underlineLineStyle() const
+{
+ return KoTextFormat::underlineStyleToString( m_frametext->textObject()->underlineStyle() );
+}
+
+QString KWordTextFrameSetIface::strikeOutLineStyle()const
+{
+ return KoTextFormat::strikeOutStyleToString( m_frametext->textObject()->strikeOutStyle() );
+}
diff --git a/kword/KWordTextFrameSetIface.h b/kword/KWordTextFrameSetIface.h
new file mode 100644
index 00000000..9411679d
--- /dev/null
+++ b/kword/KWordTextFrameSetIface.h
@@ -0,0 +1,102 @@
+/* This file is part of the KDE project
+ Copyright (C) 2002, Laurent MONTEL <lmontel@mandrakesoft.com>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+*/
+
+#ifndef KWORD_TEXTFRAMESET_IFACE_H
+#define KWORD_TEXTFRAMESET_IFACE_H
+
+#include <KoDocumentIface.h>
+#include <dcopref.h>
+
+#include <qstring.h>
+#include <qcolor.h>
+#include <qfont.h>
+#include "KWordFrameSetIface.h"
+class KWTextFrameSet;
+class KWordViewIface;
+
+class KWordTextFrameSetIface : public KWordFrameSetIface
+{
+ K_DCOP
+public:
+ KWordTextFrameSetIface( KWTextFrameSet *_frametext );
+
+k_dcop:
+ virtual DCOPRef startEditing();
+ bool hasSelection() const;
+ int numberOfParagraphs();
+ int paragraphsSelected();
+ QString name() const;
+ QString selectedText() const;
+ void selectAll( bool select );
+ void setBoldText( bool b );
+ void setItalicText( bool b );
+ void setUnderlineText( bool b );
+ void setDoubleUnderlineText(bool on);
+ void setStrikeOutText( bool b );
+ void setTextColor( const QColor &col );
+ void setTextPointSize( int s );
+ void setTextSubScript( bool b );
+ void setTextSuperScript( bool b );
+ void setTextDefaultFormat();
+ void setTextBackgroundColor(const QColor & col);
+ void setTextFamilyFont(const QString &font);
+ void setUnderlineColor( const QColor & color );
+
+ void changeCaseOfText( const QString & caseType);
+
+ QColor textColor() const;
+ QFont textFont() const;
+ QString textFontFamily()const;
+ QColor textBackgroundColor()const;
+ QColor textUnderlineColor() const;
+
+
+ bool textItalic() const;
+ bool textBold() const;
+ bool textUnderline()const;
+ bool textDoubleUnderline()const;
+
+ bool textStrikeOut()const;
+ bool textSubScript() const;
+ bool textSuperScript() const;
+ void setProtectContent ( bool _protect );
+ bool isProtectContent() const;
+
+
+ //bool textShadow() const;
+ //void setTextShadow( bool b );
+
+ double relativeTextSize() const;
+ void setRelativeTextSize( double _size );
+
+ bool wordByWord() const;
+ void setWordByWord( bool _b );
+
+ QString fontAttibute()const;
+
+ QString underlineLineStyle() const;
+ QString strikeOutLineStyle()const;
+
+
+private:
+ KWTextFrameSet *m_frametext;
+
+};
+
+#endif
diff --git a/kword/KWordViewIface.cpp b/kword/KWordViewIface.cpp
new file mode 100644
index 00000000..9c4f1b80
--- /dev/null
+++ b/kword/KWordViewIface.cpp
@@ -0,0 +1,466 @@
+/* This file is part of the KDE project
+ Copyright (C) 2001 Laurent Montel <lmontel@mandrakesoft.com>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+*/
+
+#include "KWordViewIface.h"
+
+#include <kurl.h>
+
+#include "KWView.h"
+#include "KWCanvas.h"
+#include "KWDocument.h"
+#include "KWFrameSet.h"
+
+#include <dcopclient.h>
+
+KWordViewIface::KWordViewIface( KWView *view_ )
+ : KoViewIface( view_ )
+{
+ view = view_;
+}
+
+void KWordViewIface::fileStatistics()
+{
+ view->fileStatistics();
+}
+
+void KWordViewIface::editFind()
+{
+ view->editFind();
+}
+
+void KWordViewIface::editReplace()
+{
+ view->editReplace();
+}
+
+void KWordViewIface::editCustomVars()
+{
+ view->editCustomVars();
+}
+
+void KWordViewIface::editMailMergeDataBase()
+{
+ view->editMailMergeDataBase();
+}
+
+void KWordViewIface::viewPageMode()
+{
+ view->viewPageMode();
+}
+
+void KWordViewIface::viewPreviewMode()
+{
+ view->viewPreviewMode();
+}
+
+void KWordViewIface::configure()
+{
+ view->configure();
+}
+
+void KWordViewIface::spelling()
+{
+ view->slotSpellCheck();
+}
+
+void KWordViewIface::autoFormat()
+{
+ view->extraAutoFormat();
+}
+
+void KWordViewIface::stylist()
+{
+ view->extraStylist();
+}
+
+void KWordViewIface::createTemplate()
+{
+ view->extraCreateTemplate();
+}
+
+void KWordViewIface::insertTable()
+{
+ view->insertTable();
+}
+
+void KWordViewIface::insertPicture()
+{
+ view->insertPicture();
+}
+
+static KoPicture picture( const QString& fileName )
+{
+ KoPicture picture;
+ KoPictureKey key;
+ key.setKeyFromFile( fileName );
+ picture.setKey( key );
+ picture.loadFromFile( fileName );
+ return picture;
+}
+
+void KWordViewIface::insertPictureFromFile( QString fileName, double x, double y, int w, int h )
+{
+ view->getGUI()->canvasWidget()->insertPictureDirect( picture( fileName ), KoPoint( x, y ), QSize(w, h) );
+}
+
+void KWordViewIface::insertInlinePicture( QString fileName, int w, int h )
+{
+ view->insertPicture( picture( fileName ), true /*makeInline*/, true /*keepRatio*/, w, h );
+ view->getGUI()->canvasWidget()->insertInlinePicture();
+}
+
+void KWordViewIface::formatPage()
+{
+ view->formatPage();
+}
+
+void KWordViewIface::toolsPart()
+{
+ view->toolsPart();
+}
+
+double KWordViewIface::zoom()
+{
+ return view->kWordDocument()->zoom();
+}
+
+
+void KWordViewIface::setZoom( int zoom)
+{
+ view->showZoom( zoom ); // share the same zoom
+ view->setZoom( zoom,true);
+ view->kWordDocument()->updateZoomRuler();
+}
+
+void KWordViewIface::editPersonalExpression()
+{
+ view->editPersonalExpr();
+}
+
+void KWordViewIface::insertLink()
+{
+ view->insertLink();
+}
+
+void KWordViewIface::insertFormula()
+{
+ view->insertFormula();
+}
+
+void KWordViewIface::formatFont()
+{
+ view->formatFont();
+}
+
+void KWordViewIface::formatParagraph()
+{
+ view->formatParagraph();
+}
+
+void KWordViewIface::raiseFrame()
+{
+ view->raiseFrame();
+}
+
+void KWordViewIface::lowerFrame()
+{
+ view->lowerFrame();
+}
+
+void KWordViewIface::bringToFront()
+{
+ view->bringToFront();
+}
+
+void KWordViewIface::sendToBack()
+{
+ view->sendToBack();
+}
+
+
+void KWordViewIface::applyAutoFormat()
+{
+ view->applyAutoFormat();
+}
+
+
+void KWordViewIface::createStyleFromSelection()
+{
+ view->createStyleFromSelection();
+}
+
+int KWordViewIface::tableSelectCell(const QString &name, uint row, uint col)
+{
+ return view->tableSelectCell(name, row, col);
+}
+
+void KWordViewIface::tableInsertRow()
+{
+ view->tableInsertRow();
+}
+
+void KWordViewIface::tableInsertRow(uint row)
+{
+ view->tableInsertRow(row);
+}
+
+void KWordViewIface::tableInsertCol()
+{
+ view->tableInsertCol();
+}
+
+void KWordViewIface::tableInsertCol(uint col)
+{
+ view->tableInsertCol(col);
+}
+
+void KWordViewIface::tableResizeCol()
+{
+ view->tableResizeCol();
+}
+
+void KWordViewIface::tableDeleteRow()
+{
+ view->tableDeleteRow();
+}
+
+int KWordViewIface::tableDeleteRow(uint row)
+{
+ QValueList<uint> list;
+ list.append(row);
+ return view->tableDeleteRow(list);
+}
+
+void KWordViewIface::tableDeleteCol()
+{
+ view->tableDeleteCol();
+}
+
+int KWordViewIface::tableDeleteCol(uint col)
+{
+ QValueList<uint> list;
+ list.append(col);
+ return view->tableDeleteCol(list);
+}
+
+void KWordViewIface::tableJoinCells()
+{
+ view->tableJoinCells();
+}
+
+void KWordViewIface::tableSplitCells()
+{
+ view->tableSplitCells();
+}
+
+void KWordViewIface::tableSplitCells(uint rows, uint cols)
+{
+ view->tableSplitCells(cols, rows);
+}
+
+void KWordViewIface::tableUngroupTable()
+{
+ view->tableUngroupTable();
+}
+
+void KWordViewIface::insertFootNote()
+{
+ view->insertFootNote();
+}
+
+int KWordViewIface::configTableRows() const
+{
+ return (int)view->getGUI()->canvasWidget()->tableRows();
+}
+
+int KWordViewIface::configTableCols() const
+{
+ return (int)view->getGUI()->canvasWidget()->tableCols();
+}
+
+bool KWordViewIface::configTableIsFloating() const
+{
+ return view->getGUI()->canvasWidget()->tableIsFloating();
+}
+
+QString KWordViewIface::configTableTemplateName() const
+{
+ return view->getGUI()->canvasWidget()->tableTemplateName();
+}
+
+void KWordViewIface::setConfigTableTemplateName(const QString &_name)
+{
+ view->getGUI()->canvasWidget()->setTableTemplateName( _name );
+}
+
+void KWordViewIface::selectAllFrames()
+{
+ view->getGUI()->canvasWidget()->selectAllFrames(true);
+}
+
+void KWordViewIface::unSelectAllFrames()
+{
+ view->getGUI()->canvasWidget()->selectAllFrames(false);
+}
+
+
+void KWordViewIface::editFootEndNote()
+{
+ view->editFootEndNote();
+}
+
+void KWordViewIface::savePicture()
+{
+ view->savePicture();
+}
+
+void KWordViewIface::insertFile()
+{
+ view->insertFile();
+}
+
+void KWordViewIface::tableStylist()
+{
+ view->tableStylist();
+}
+
+void KWordViewIface::addBookmark()
+{
+ view->addBookmark();
+}
+
+void KWordViewIface::selectBookmark()
+{
+ view->selectBookmark();
+}
+
+void KWordViewIface::tableProperties()
+{
+ view->tableProperties();
+}
+
+void KWordViewIface::importStyle()
+{
+ view->importStyle();
+}
+
+// ### TODO: network transparency
+void KWordViewIface::insertFile(const QString & path)
+{
+
+ KURL url;
+ url.setPath( path );
+ view->insertFile( url );
+}
+
+void KWordViewIface::createFrameStyle()
+{
+ view->createFrameStyle();
+}
+
+void KWordViewIface::setPictureInline( bool _inline)
+{
+ view->getGUI()->canvasWidget()->setPictureInline( _inline);
+}
+
+bool KWordViewIface::pictureInline() const
+{
+ return view->getGUI()->canvasWidget()->pictureInline();
+}
+
+void KWordViewIface::setPictureKeepRatio( bool _keep)
+{
+ view->getGUI()->canvasWidget()->setPictureKeepRatio( _keep);
+}
+
+bool KWordViewIface::pictureKeepRatio() const
+{
+ return view->getGUI()->canvasWidget()->pictureKeepRatio();
+}
+
+void KWordViewIface::changeAutoSpellCheckStatus(bool b)
+{
+ view->autoSpellCheck(b);
+}
+
+void KWordViewIface::deselectAllFrames()
+{
+ view->deselectAllFrames();
+}
+
+int KWordViewIface::currentPage()
+{
+ return view->currentPage();
+}
+
+void KWordViewIface::convertTableToText()
+{
+ view->convertTableToText();
+}
+
+void KWordViewIface::convertToTextBox()
+{
+ view->convertToTextBox();
+}
+
+void KWordViewIface::addIgnoreAllWord()
+{
+ view->slotAddIgnoreAllWord();
+}
+
+void KWordViewIface::addPersonalExpression()
+{
+ view->addPersonalExpression();
+}
+
+void KWordViewIface::addWordToDictionary()
+{
+ view->addWordToDictionary();
+}
+
+void KWordViewIface::sortText()
+{
+ view->sortText();
+}
+
+void KWordViewIface::insertPage()
+{
+ view->insertPage();
+}
+
+void KWordViewIface::createLinkedFrame()
+{
+ view->createLinkedFrame();
+}
+
+
+void KWordViewIface::lineBreak()
+{
+ view->slotLineBreak();
+}
+
+void KWordViewIface::increaseNumberingLevel()
+{
+ view->slotIncreaseNumberingLevel();
+}
+
+void KWordViewIface::decreaseNumberingLevel()
+{
+ view->slotDecreaseNumberingLevel();
+}
diff --git a/kword/KWordViewIface.h b/kword/KWordViewIface.h
new file mode 100644
index 00000000..1404a4b4
--- /dev/null
+++ b/kword/KWordViewIface.h
@@ -0,0 +1,151 @@
+/* This file is part of the KDE project
+ Copyright (C) 2001 Laurent Montel <lmontel@mandrakesoft.com>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+*/
+
+#ifndef KWORD_VIEW_IFACE_H
+#define KWORD_VIEW_IFACE_H
+
+#include <KoViewIface.h>
+
+#include <qstring.h>
+
+class KWView;
+
+class KWordViewIface : public KoViewIface
+{
+ K_DCOP
+public:
+ KWordViewIface( KWView *view_ );
+ KWView * getView()const{return view;}
+k_dcop:
+ void fileStatistics();
+ void editFind();
+ void editReplace();
+ void editCustomVars();
+ void editMailMergeDataBase();
+ void viewPageMode();
+ void viewPreviewMode();
+ void configure();
+ void spelling();
+ void autoFormat();
+ void stylist();
+ void createTemplate();
+
+ int tableSelectCell(const QString &name, uint row, uint col);
+ void insertTable();
+ void tableInsertRow();
+ void tableInsertRow(uint row);
+ void tableInsertCol();
+ void tableInsertCol(uint col);
+ void tableResizeCol();
+ void tableDeleteRow();
+ int tableDeleteRow(uint row);
+ void tableDeleteCol();
+ int tableDeleteCol(uint col);
+ void tableJoinCells();
+ void tableSplitCells();
+ void tableSplitCells(uint rows, uint cols);
+ void tableUngroupTable();
+
+ void insertPicture(); // not good, triggers the dialog
+
+ /**
+ * Insert an inline picture at the current character position
+ * TODO
+ */
+ void insertInlinePicture( QString fileName, int w = 0, int h = 0 );
+ /**
+ * Insert a (non-inline) picture at the given position
+ * If w and h are 0, the default size from the image is used
+ */
+ void insertPictureFromFile( QString fileName, double x, double y, int w = 0, int h = 0 );
+
+
+ void toolsPart();
+
+ double zoom();
+ void setZoom( int zoom);
+ void editPersonalExpression();
+ void insertLink();
+ void insertFormula();
+
+ void formatFont();
+ void formatParagraph();
+ void formatPage();
+ void raiseFrame();
+ void lowerFrame();
+ void bringToFront();
+ void sendToBack();
+ void applyAutoFormat();
+ void createStyleFromSelection();
+
+ void insertFootNote();
+
+ int configTableRows() const;
+ int configTableCols() const;
+ bool configTableIsFloating() const;
+
+ //it can return QString::null if there is any template selected
+ QString configTableTemplateName() const;
+ void setConfigTableTemplateName(const QString &_name);
+
+ void selectAllFrames();
+ void unSelectAllFrames();
+
+ void editFootEndNote();
+ void savePicture();
+
+ void insertFile();
+ void tableStylist();
+
+ void addBookmark();
+ void selectBookmark();
+ void tableProperties();
+ void importStyle();
+
+ void insertFile(const QString & path);
+ void createFrameStyle();
+
+ void setPictureInline( bool _inline);
+ bool pictureInline() const;
+
+ void setPictureKeepRatio( bool _keep);
+ bool pictureKeepRatio() const;
+ void changeAutoSpellCheckStatus(bool b);
+ void deselectAllFrames();
+ int currentPage();
+ void convertTableToText();
+ void convertToTextBox();
+ void addIgnoreAllWord();
+ void addPersonalExpression();
+ void addWordToDictionary();
+ void sortText();
+ void insertPage();
+ void createLinkedFrame();
+
+ void lineBreak();
+
+ void increaseNumberingLevel();
+ void decreaseNumberingLevel();
+
+private:
+ KWView *view;
+
+};
+
+#endif
diff --git a/kword/Makefile.am b/kword/Makefile.am
new file mode 100644
index 00000000..2fd145f6
--- /dev/null
+++ b/kword/Makefile.am
@@ -0,0 +1,94 @@
+# We use STL sorting so we need some typedefs
+KDE_CXXFLAGS = -UQT_NO_STL
+
+INCLUDES = $(KOFFICE_INCLUDES) -I$(top_srcdir)/lib/kformula \
+ $(KOTEXT_INCLUDES) $(all_includes)
+
+kde_module_LTLIBRARIES = libkwordpart.la
+lib_LTLIBRARIES = libkwmailmerge_interface.la libkwordprivate.la
+
+## The part
+libkwordpart_la_SOURCES = KWFactoryInit.cpp
+libkwordpart_la_LDFLAGS = $(all_libraries) -module $(KDE_PLUGIN)
+libkwordpart_la_LIBADD = libkwordprivate.la
+
+## A lib with all the code
+libkwordprivate_la_SOURCES = KWTableFrameSet.cpp KWCanvas.cpp KWFrame.cpp KWFormulaFrameSet.cpp \
+ KWFactory.cpp KWDocument.cpp \
+ KWView.cpp \
+ KWViewMode.cpp \
+ KWTextParag.cpp KWTextDocument.cpp \
+ KWTextFrameSet.cpp KWPartFrameSet.cpp \
+ KWTextImage.cpp KWAnchor.cpp \
+ KWConfig.cpp \
+ KWVariable.cpp \
+ KWFrameDia.cpp KWFootNoteDia.cpp \
+ KWFrameStyle.cpp KWFrameStyleManager.cpp \
+ KWTableStyle.cpp KWTableStyleManager.cpp \
+ KWTableTemplate.cpp KWTableTemplateSelector.cpp KWTableDia.cpp \
+ KWInsertDia.cpp KWDeleteDia.cpp KWDocStruct.cpp \
+ KWInsertTOCCommand.cpp KWStyleManager.cpp KWFindReplace.cpp \
+ KWCommand.cpp KWStatisticsDialog.cpp \
+ KWordMailMergeDatabaseIface.skel kwordmailmergedatabaseiface.cpp KWMailMergeDataBase.cpp \
+ KWMailMergeLabelAction.cpp \
+ KWEditPersonnalExpression.cpp \
+ KWSplitCellDia.cpp KWInsertPicDia.cpp \
+ KWordDocIface.skel KWordDocIface.cpp \
+ KWordViewIface.skel KWordViewIface.cpp \
+ KWordTextFrameSetIface.skel KWordTextFrameSetIface.cpp \
+ KWordTextFrameSetEditIface.skel KWordTextFrameSetEditIface.cpp \
+ KWordFrameSetIface.skel KWordFrameSetIface.cpp \
+ KWordFormulaFrameSetIface.skel KWordFormulaFrameSetIface.cpp \
+ KWordFormulaFrameSetEditIface.skel KWordFormulaFrameSetEditIface.cpp \
+ KWordPictureFrameSetIface.skel KWordPictureFrameSetIface.cpp \
+ KWordTableFrameSetIface.skel KWordTableFrameSetIface.cpp \
+ KWordPartFrameSetIface.skel KWordPartFrameSetIface.cpp \
+ KWBgSpellCheck.cpp KWResizeTableDia.cpp KWFrameLayout.cpp \
+ KWConfigFootNoteDia.cpp KWCreateBookmarkDia.cpp KWImportStyleDia.cpp \
+ KWordFootNoteFrameSetIface.skel KWordFootNoteFrameSetIface.cpp \
+ KWCreateBookmarkDiaBase.ui KWSelectBookmarkDiaBase.ui \
+ KWSortDia.cpp KWInsertPageDia.cpp KWCollectFramesetsVisitor.cpp \
+ KWOasisLoader.cpp KWOasisSaver.cpp KWFrameList.cpp KWPage.cpp \
+ KWPageManager.cpp KWFrameSet.cpp KWFrameSetEdit.cpp KWPictureFrameSet.cpp \
+ KWFrameViewManager.cpp KWFrameView.cpp KWStartupWidgetBase.ui KWStartupWidget.cpp \
+ KWLoadingInfo.cpp
+
+
+libkwordprivate_la_LDFLAGS = $(all_libraries) -version-info 4:0 -no-undefined
+libkwordprivate_la_LIBADD = $(LIB_KOFFICEUI) $(LIB_KOTEXT) ../lib/kformula/libkformulalib.la ./libkwmailmerge_interface.la
+
+METASOURCES = AUTO
+
+## The mailmerge interface library
+libkwmailmerge_interface_la_SOURCES = KWMailMergeDataSource.cpp KWMailMergeDataSource.skel
+libkwmailmerge_interface_la_LDFLAGS = $(all_libraries) -version-info 4:0 -no-undefined
+libkwmailmerge_interface_la_LIBADD = $(LIB_QT) -lDCOP
+kwincludedir = $(includedir)/kword
+kwinclude_HEADERS = KWMailMergeDataSource.h
+
+kwmailmerge_servicetype_DATA=kwmailmerge.desktop
+kwmailmerge_servicetypedir=$(kde_servicetypesdir)
+
+## The kdeinit loadable module and the kword binary
+kdeinit_LTLIBRARIES = kword.la
+bin_PROGRAMS =
+kword_la_SOURCES = main.cpp
+kword_la_LDFLAGS = $(all_libraries) -module $(KDE_PLUGIN)
+kword_la_LIBADD = $(LIB_KOFFICECORE)
+
+xdg_apps_DATA = kword.desktop
+
+kde_services_DATA = kwordpart.desktop
+
+rcdir = $(kde_datadir)/kword
+rc_DATA = kword.rc kword_readonly.rc
+
+SUBDIRS = . mailmerge templates dtd pics toolbar expression data tests
+
+messages: rc.cpp
+ $(EXTRACTRC) --tag-group=koffice expression/*.xml > xml_doc.cpp
+ $(EXTRACTRC) `find mailmerge -name \*.ui` >> rc.cpp
+ $(XGETTEXT) rc.cpp *.cpp `find mailmerge -name \*.cpp -o -name \*.cpp` KWAboutData.h -o $(podir)/kword.pot
+ -rm xml_doc.cpp
+
+include $(top_srcdir)/admin/Doxyfile.am
diff --git a/kword/OASIS b/kword/OASIS
new file mode 100644
index 00000000..b840b92d
--- /dev/null
+++ b/kword/OASIS
@@ -0,0 +1,72 @@
+Notes about the use of the OpenDocument format in kword:
+-------------------------------------------------
+
+* Tables
+In OpenDocument, tables are treated like paragraphs.
+In KWord, tables are either "inline as character" or "at a fixed position".
+This gives three cases:
+ + inline table, alone in its paragraph -> can be saved the OpenDocument way.
+ + inline table with other things in the paragraph -> wrapper frame+textbox needed
+ The wrapper frame is marked with a koffice-specific attribute, koffice:is-wrapper-frame="true".
+ Upon loading, the wrapper textbox is removed if it doesn't contain anything else.
+ + fixed-position table -> wrapper frame+textbox would be needed here too.
+ But anyway those tables are very difficult to handle, and offer nothing
+ compared to "putting an inline table in a non-inline textbox", so I have disabled them.
+
+* Frame behavior on new pages
+KWord supports "What happens on new page: create a new frame and reconnect, no followup, make copy."
+OpenDocument doesn't, but this doesn't matter, it doesn't affect rendering of existing documents, only editing.
+So we save this with a koffice:frame-behavior-on-new-page attribute, possible values:
+followup, copy or none. Default value: copy for header/footers, none otherwise.
+
+* DTP
+KWord supports both the normal word processing (paragraphs directly inside the body)
+and the page-based DTP mode (page-sequence element).
+
+* Headers and footers
+OpenDocument supports odd/even headers and footers using "header" and "header-left".
+But for first page header/footer KWord should create a separate page layout,
+this is not done yet (it uses its own tag instead, as a temporary hack).
+Also OpenDocument doesn't allow a different style for header and header-left,
+so they must have the same min-size, border, margins...
+
+* Columns
+OpenDocument has "number of columns" and "space between columns", so it's OK for kword.
+OOo however also supports columns of different sizes and with different spaces, we can't load that.
+
+Notes about interoperability with OpenOffice.org-2.0:
+-----------------------------------------------------
+
+List of bugs in OOo-1.9.113 affecting interoperability:
+ - <text:notes-configuration text:note-class="footnote"...> uses 0-based values for text:start-value instead of 1-based (private mail sent)
+ - DTP mode not really supported; but even with single page, frames are misplaced (private mail sent)
+ - <text:numbered-paragraph> isn't loaded!!! http://www.openoffice.org/issues/show_bug.cgi?id=52127
+
+List of bugs in OOo-1.9.113 not affecting interoperability:
+ - style:text-underline-type="single" is missing for underlined text, only style is specified (code has workaround)
+ - display-levels not respected in chapters.odt
+
+List of features that KWord has, but OOo doesn't have, and which are in the OpenDocument standard:
+ - OOo doesn't load nor save the cursor-position processing instruction
+ - DTP mode (page-sequence)
+ - frame break (we model it with fo:break-after="column" in the paragraph style)
+ - copy-frames (probably)
+ - hyphenation bool as character property, for more control (probably)
+ - diagonal lines in table cells (probably)
+ - line style for footnote separator (probably)
+ - table templates (probably)
+ - DTP mode using the draw:page element (probably)
+ - (after 1.0) border around a word or any run of text (probably)
+
+List of features that KWord doesn't have, and which OpenDocument has:
+ (that list would be quite long, but let's list the real-life interoperability problems)
+ - lack of section support (changes of page layout, but also changes of column settings
+ in the middle of a page)
+ We could at least keep section styles and section markers (begin/end),
+ so that load+save preserves it.
+ - some anchoring options are not supported, e.g. paragraph-anchored frames. We load
+ them as page-anchored frames, but this means the placement is wrong, obviously.
+
+Differences in rendering:
+ - In KWord endnotes are right under the end of the text; in OOo they are on a separate page.
+
diff --git a/kword/TODO b/kword/TODO
new file mode 100644
index 00000000..680b5429
--- /dev/null
+++ b/kword/TODO
@@ -0,0 +1,60 @@
+TODO-List
+=========
+
+Bugs:
+-----
+- textformatter: need to check for line-level breaking during the formatting of each line
+Currently we do it afterwards, so if the margins differ, where the line ends up, we can't notice.
+- solve problem with a change in the available width right in the middle of the
+character we're trying to place (e.g. and it needs to move down to where the width is bigger)
+Possible solution: let getMargins return a "valid for a height of ... only",
+and then kotextformatter needs to move down by that height if .... hmm done.
+- footnotes: check move to next page, endnotes
+- anything else that http://bugs.kde.org mentions ;)
+
+Differences with OO that ought to be fixed:
+-------------------------------------------
+- space above and below paragraphs is QMAX()ed indeed, like QRichText originally did.
+- offsetFromBaseline should be a % (of the font size) instead of an absolute pt value,
+ even in the GUI (which currently limits to +/- 9pt).
+
+Missing or incomplete stuff:
+----------------------------
+- Even/odd pages
+ - Add SheetSide config in framedia
+- Tables should get a title (with positioning posibility)
+ This will basicly be a new frame placed on top or at bottom of table.
+ And it shouldn't be limited to tables - any frame could get that.
+
+Other missing features:
+
+Sideheads (for text)
+Split frames needs to be implemented.
+Styles have to be saved external (and/or an import/export facility).
+Books (collection of documents) should be implemented
+Implement complete DCOP interface
+Make everything scriptable
+Add "TopOfFrame"-TopOfPage" etc to styles.
+add "Keep this parag with the next/prev" options to styles.
+
+
+External files:
+--------------
+Included files (pictures/parts/formula's)
+- It should be possible to keep files external. Kword should also notice a changed file
+ (preferably at runtime) and reload it.
+
+OK-ing the stylist seems to apply style change to all styles, not just the changed ones...
+
+Add a RMB option on a copy-frame to update position of all copies in that FS.
+Add RMB option on text to copy current format to a (new) style. Including tab positions..
+
+- picture insertion point when pasting should be as an inline frame. Using default placing methods.
+- cut/paste of images do not work across documents (also in bugs.kde.org)
+- auto-update TOC before printing, so no doc is printed with an out-of-date TOC. It might alter the layout, ok, but an out-of-date TOC is just a waste of paper (besides being misleading...)
+- interaction with frame breaks are a bit strange. How do you remove it? You cannot select it, nor can you use backspace or del..
+- one should be able to introduce dependencies between styles, so if I want to change the general font of the text, I do not have to modify all the styles.
+- when writing bulks of text, when the cursor gets to the border of the window, it should not only scroll 1 line (to make sure the cursor stays in the visible portion of the document) but should be moved to the center of the window (like in emacs:-). So the average position of the cursor is the center of the window, rather than the bollom line.
+
+- interaction with KoParts is somehow strange. Especially positioning them in the document, as the size when using the handles is not the same as the end product. But I am not used to it in the Windows world either...
+ This is due to the problemsn that we don't zoom and dont allow easy moving in the parts. A square which representst the whole placed document when moving just the little screen would be nice.
diff --git a/kword/data/Makefile.am b/kword/data/Makefile.am
new file mode 100644
index 00000000..ef0cfd82
--- /dev/null
+++ b/kword/data/Makefile.am
@@ -0,0 +1,2 @@
+kworddir = $(kde_datadir)/kword
+kword_DATA = framestyles.xml tablestyles.xml tabletemplates.xml
diff --git a/kword/data/framestyles.xml b/kword/data/framestyles.xml
new file mode 100644
index 00000000..f194b21c
--- /dev/null
+++ b/kword/data/framestyles.xml
@@ -0,0 +1,108 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<FRAMESTYLES>
+ <FRAMESTYLE red="255" green="255" blue="255">
+ <NAME value="Plain"/>
+ <TOPBORDER red="0" green="0" blue="0" style="0" width="0"/>
+ <BOTTOMBORDER red="0" green="0" blue="0" style="0" width="0"/>
+ <RIGHTBORDER red="0" green="0" blue="0" style="0" width="0"/>
+ <LEFTBORDER red="0" green="0" blue="0" style="0" width="0"/>
+ </FRAMESTYLE>
+ <FRAMESTYLE red="255" green="255" blue="255">
+ <NAME value="Borders 1"/>
+ <TOPBORDER red="0" green="0" blue="0" style="0" width="1"/>
+ <BOTTOMBORDER red="0" green="0" blue="0" style="0" width="1"/>
+ <RIGHTBORDER red="0" green="0" blue="0" style="0" width="1"/>
+ <LEFTBORDER red="0" green="0" blue="0" style="0" width="1"/>
+ </FRAMESTYLE>
+ <FRAMESTYLE red="255" green="255" blue="255">
+ <NAME value="Borders 2"/>
+ <TOPBORDER red="0" green="0" blue="0" style="0" width="2"/>
+ <BOTTOMBORDER red="0" green="0" blue="0" style="0" width="2"/>
+ <RIGHTBORDER red="0" green="0" blue="0" style="0" width="2"/>
+ <LEFTBORDER red="0" green="0" blue="0" style="0" width="2"/>
+ </FRAMESTYLE>
+ <FRAMESTYLE red="255" green="255" blue="255">
+ <NAME value="Borders 3"/>
+ <TOPBORDER red="0" green="0" blue="0" style="0" width="3"/>
+ <BOTTOMBORDER red="0" green="0" blue="0" style="0" width="3"/>
+ <RIGHTBORDER red="0" green="0" blue="0" style="0" width="3"/>
+ <LEFTBORDER red="0" green="0" blue="0" style="0" width="3"/>
+ </FRAMESTYLE>
+ <FRAMESTYLE red="255" green="255" blue="255">
+ <NAME value="Row"/>
+ <TOPBORDER red="0" green="0" blue="0" style="0" width="1"/>
+ <BOTTOMBORDER red="0" green="0" blue="0" style="0" width="1"/>
+ <RIGHTBORDER red="0" green="0" blue="0" style="0" width="0"/>
+ <LEFTBORDER red="0" green="0" blue="0" style="0" width="0"/>
+ </FRAMESTYLE>
+ <FRAMESTYLE red="255" green="255" blue="255">
+ <NAME value="Column"/>
+ <TOPBORDER red="0" green="0" blue="0" style="0" width="0"/>
+ <BOTTOMBORDER red="0" green="0" blue="0" style="0" width="0"/>
+ <RIGHTBORDER red="0" green="0" blue="0" style="0" width="1"/>
+ <LEFTBORDER red="0" green="0" blue="0" style="0" width="1"/>
+ </FRAMESTYLE>
+ <FRAMESTYLE red="211" green="211" blue="211">
+ <NAME value="Light Gray"/>
+ <TOPBORDER red="0" green="0" blue="0" style="0" width="1"/>
+ <BOTTOMBORDER red="0" green="0" blue="0" style="0" width="1"/>
+ <RIGHTBORDER red="0" green="0" blue="0" style="0" width="1"/>
+ <LEFTBORDER red="0" green="0" blue="0" style="0" width="1"/>
+ </FRAMESTYLE>
+ <FRAMESTYLE red="169" green="169" blue="169">
+ <NAME value="Dark Gray"/>
+ <TOPBORDER red="0" green="0" blue="0" style="0" width="1"/>
+ <BOTTOMBORDER red="0" green="0" blue="0" style="0" width="1"/>
+ <RIGHTBORDER red="0" green="0" blue="0" style="0" width="1"/>
+ <LEFTBORDER red="0" green="0" blue="0" style="0" width="1"/>
+ </FRAMESTYLE>
+ <FRAMESTYLE red="0" green="0" blue="0">
+ <NAME value="Black"/>
+ <TOPBORDER red="0" green="0" blue="0" style="0" width="1"/>
+ <BOTTOMBORDER red="0" green="0" blue="0" style="0" width="1"/>
+ <RIGHTBORDER red="0" green="0" blue="0" style="0" width="1"/>
+ <LEFTBORDER red="0" green="0" blue="0" style="0" width="1"/>
+ </FRAMESTYLE>
+ <FRAMESTYLE red="173" green="216" blue="230">
+ <NAME value="Light Blue"/>
+ <TOPBORDER red="0" green="0" blue="0" style="0" width="1"/>
+ <BOTTOMBORDER red="0" green="0" blue="0" style="0" width="1"/>
+ <RIGHTBORDER red="0" green="0" blue="0" style="0" width="1"/>
+ <LEFTBORDER red="0" green="0" blue="0" style="0" width="1"/>
+ </FRAMESTYLE>
+ <FRAMESTYLE red="0" green="0" blue="139">
+ <NAME value="Dark Blue"/>
+ <TOPBORDER red="0" green="0" blue="0" style="0" width="1"/>
+ <BOTTOMBORDER red="0" green="0" blue="0" style="0" width="1"/>
+ <RIGHTBORDER red="0" green="0" blue="0" style="0" width="1"/>
+ <LEFTBORDER red="0" green="0" blue="0" style="0" width="1"/>
+ </FRAMESTYLE>
+ <FRAMESTYLE red="255" green="0" blue="0">
+ <NAME value="Red"/>
+ <TOPBORDER red="0" green="0" blue="0" style="0" width="1"/>
+ <BOTTOMBORDER red="0" green="0" blue="0" style="0" width="1"/>
+ <RIGHTBORDER red="0" green="0" blue="0" style="0" width="1"/>
+ <LEFTBORDER red="0" green="0" blue="0" style="0" width="1"/>
+ </FRAMESTYLE>
+ <FRAMESTYLE red="255" green="255" blue="0">
+ <NAME value="Yellow"/>
+ <TOPBORDER red="0" green="0" blue="0" style="0" width="1"/>
+ <BOTTOMBORDER red="0" green="0" blue="0" style="0" width="1"/>
+ <RIGHTBORDER red="0" green="0" blue="0" style="0" width="1"/>
+ <LEFTBORDER red="0" green="0" blue="0" style="0" width="1"/>
+ </FRAMESTYLE>
+ <FRAMESTYLE red="255" green="255" blue="0">
+ <NAME value="Colorful"/>
+ <TOPBORDER red="255" green="0" blue="0" style="0" width="1"/>
+ <BOTTOMBORDER red="255" green="0" blue="0" style="0" width="1"/>
+ <RIGHTBORDER red="255" green="0" blue="0" style="0" width="1"/>
+ <LEFTBORDER red="255" green="0" blue="0" style="0" width="1"/>
+ </FRAMESTYLE>
+ <FRAMESTYLE red="173" green="216" blue="230">
+ <NAME value="Bluish"/>
+ <TOPBORDER red="0" green="0" blue="139" style="0" width="1"/>
+ <BOTTOMBORDER red="0" green="0" blue="139" style="0" width="1"/>
+ <RIGHTBORDER red="0" green="0" blue="139" style="0" width="1"/>
+ <LEFTBORDER red="0" green="0" blue="139" style="0" width="1"/>
+ </FRAMESTYLE>
+</FRAMESTYLES>
diff --git a/kword/data/tablestyles.xml b/kword/data/tablestyles.xml
new file mode 100644
index 00000000..84d2258b
--- /dev/null
+++ b/kword/data/tablestyles.xml
@@ -0,0 +1,53 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<TABLESTYLES>
+ <TABLESTYLE>
+ <NAME value="Plain"/>
+ <PFRAMESTYLE name="Plain"/>
+ <PSTYLE name="Standard"/>
+ </TABLESTYLE>
+ <TABLESTYLE>
+ <NAME value="Simple 1"/>
+ <PFRAMESTYLE name="Borders 1"/>
+ <PSTYLE name="Standard"/>
+ </TABLESTYLE>
+ <TABLESTYLE>
+ <NAME value="Simple 2"/>
+ <PFRAMESTYLE name="Borders 2"/>
+ <PSTYLE name="Standard"/>
+ </TABLESTYLE>
+ <TABLESTYLE>
+ <NAME value="Simple 3"/>
+ <PFRAMESTYLE name="Borders 3"/>
+ <PSTYLE name="Standard"/>
+ </TABLESTYLE>
+ <TABLESTYLE>
+ <NAME value="Row"/>
+ <PFRAMESTYLE name="Row"/>
+ <PSTYLE name="Standard"/>
+ </TABLESTYLE>
+ <TABLESTYLE>
+ <NAME value="Column"/>
+ <PFRAMESTYLE name="Column"/>
+ <PSTYLE name="Standard"/>
+ </TABLESTYLE>
+ <TABLESTYLE>
+ <NAME value="Header 1"/>
+ <PFRAMESTYLE name="Light Gray"/>
+ <PSTYLE name="Standard"/>
+ </TABLESTYLE>
+ <TABLESTYLE>
+ <NAME value="Header 2"/>
+ <PFRAMESTYLE name="Light Blue"/>
+ <PSTYLE name="Standard"/>
+ </TABLESTYLE>
+ <TABLESTYLE>
+ <NAME value="Header 3"/>
+ <PFRAMESTYLE name="Dark Gray"/>
+ <PSTYLE name="Standard"/>
+ </TABLESTYLE>
+ <TABLESTYLE>
+ <NAME value="Header 4"/>
+ <PFRAMESTYLE name="Dark Blue"/>
+ <PSTYLE name="Standard"/>
+ </TABLESTYLE>
+</TABLESTYLES>
diff --git a/kword/data/tabletemplates.xml b/kword/data/tabletemplates.xml
new file mode 100644
index 00000000..e90666ee
--- /dev/null
+++ b/kword/data/tabletemplates.xml
@@ -0,0 +1,62 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<TABLETEMPLATES>
+ <TABLETEMPLATE>
+ <NAME value="Plain"/>
+ <BODYCELL name="Plain"/>
+ </TABLETEMPLATE>
+ <TABLETEMPLATE>
+ <NAME value="Grid 1"/>
+ <BODYCELL name="Simple 1"/>
+ </TABLETEMPLATE>
+ <TABLETEMPLATE>
+ <NAME value="Grid 2"/>
+ <BODYCELL name="Simple 2"/>
+ </TABLETEMPLATE>
+ <TABLETEMPLATE>
+ <NAME value="Grid 3"/>
+ <BODYCELL name="Simple 3"/>
+ </TABLETEMPLATE>
+ <TABLETEMPLATE>
+ <NAME value="Blue Heading"/>
+ <FIRSTROW name="Header 2" topleftcorner="1" toprightcorner="1"/>
+ <BODYCELL name="Simple 1"/>
+ </TABLETEMPLATE>
+ <TABLETEMPLATE>
+ <NAME value="Gray Heading"/>
+ <FIRSTROW name="Header 1" topleftcorner="1" toprightcorner="1"/>
+ <BODYCELL name="Simple 1"/>
+ </TABLETEMPLATE>
+ <TABLETEMPLATE>
+ <NAME value="Blue Traditional"/>
+ <FIRSTROW name="Header 4" topleftcorner="1" toprightcorner="1"/>
+ <FIRSTCOL name="Header 2" bottomleftcorner="1"/>
+ <BODYCELL name="Simple 1"/>
+ </TABLETEMPLATE>
+ <TABLETEMPLATE>
+ <NAME value="Gray Traditional"/>
+ <FIRSTROW name="Header 3" topleftcorner="1" toprightcorner="1"/>
+ <FIRSTCOL name="Header 1" bottomleftcorner="1"/>
+ <BODYCELL name="Simple 1"/>
+ </TABLETEMPLATE>
+ <TABLETEMPLATE>
+ <NAME value="Blue Top and Bottom"/>
+ <FIRSTROW name="Header 4" topleftcorner="1" toprightcorner="1"/>
+ <LASTROW name="Header 2" bottomleftcorner="1" bottomrightcorner="1"/>
+ <BODYCELL name="Simple 1"/>
+ </TABLETEMPLATE>
+ <TABLETEMPLATE>
+ <NAME value="Gray Top and Bottom"/>
+ <FIRSTROW name="Header 3" topleftcorner="1" toprightcorner="1"/>
+ <LASTROW name="Header 1" bottomleftcorner="1" bottomrightcorner="1"/>
+ <BODYCELL name="Simple 1"/>
+ </TABLETEMPLATE>
+ <TABLETEMPLATE>
+ <NAME value="Columns 1"/>
+ <BODYCELL name="Column"/>
+ </TABLETEMPLATE>
+ <TABLETEMPLATE>
+ <NAME value="Columns 2"/>
+ <FIRSTROW name="Header 1" topleftcorner="1" toprightcorner="1"/>
+ <BODYCELL name="Column"/>
+ </TABLETEMPLATE>
+</TABLETEMPLATES>
diff --git a/kword/defs.h b/kword/defs.h
new file mode 100644
index 00000000..ea9d1489
--- /dev/null
+++ b/kword/defs.h
@@ -0,0 +1,84 @@
+/* This file is part of the KDE project
+ Copyright (C) 1998, 1999 Reginald Stadlbauer <reggie@kde.org>, Torben Weis <weis@kde.org>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+*/
+
+#ifndef defs_h
+#define defs_h
+
+#include <qtextstream.h>
+#include <qstring.h>
+#include <KoGlobal.h>
+#include "KWFactory.h"
+
+// Try to add new defines and enums in the most appropriate class
+// instead of in this file. Only very global things should be here.
+
+#define KWBarIcon( x ) BarIcon( x, KWFactory::instance() )
+
+#define DEBUGRECT(rc) (rc).x() << "," << (rc).y() << " " << (rc).width() << "x" << (rc).height()
+#define DEBUGREGION(reg) { QMemArray<QRect>rs=reg.rects(); for (int i=0;i<rs.size();++i) \
+ kdDebug()<<" "<<DEBUGRECT(rs[i] )<<endl; }
+
+const unsigned int s_minFrameWidth=4;
+const unsigned int s_minFrameHeight=11;
+
+/** The different types of framesets
+ * FT_BASE = unused <br>
+ * FT_TEXT = text only, this is the only frameset that can have multiple frames. <br>
+ * FT_PICTURE = One frame with an picture (only image, if for KWord 1.1.x compactibility)<br>
+ * FT_PART = one frame with an embedded part, can be a spreadsheet to a kword doc.<br>
+ * FT_FORMULA = one frame with an embedded formula frame. This is semi-native
+ * FT_CLIPART = One frame with a clipart (deprecated, only for KWord 1.1.x compactibility)<br>
+ * FT_HORZLINE = reserved
+ * FT_TABLE = Frameset which contains table cells.
+ * Table is 10 so that in the XML file we can use 7, 8, 9 in the future.
+ */
+enum FrameSetType { FT_BASE = 0, FT_TEXT = 1, FT_PICTURE = 2, FT_PART = 3,
+ FT_FORMULA = 4, FT_CLIPART = 5,
+ FT_TABLE = 10 };
+// This has to remain here because of KWDocument::refreshDocStructure()
+
+// This one has better remain here, otherwise kwdoc.cc needs docstruct.h
+enum TypeStructDocItem {Arrangement=1, Tables=2, Pictures=4, TextFrames=16, Embedded=32, FormulaFrames=64};
+
+// This one has better remain here, otherwise kwtexframeset.h needs footnote.h
+// Yes, if gcc was faster we would choose more modular code over compilation speed...
+enum NoteType { FootNote, EndNote };
+
+enum SeparatorLinePos { SLP_LEFT = 0, SLP_CENTERED = 1, SLP_RIGHT = 2};
+enum SeparatorLineLineType { SLT_SOLID = 0, SLT_DASH = 1, SLT_DOT = 2, SLT_DASH_DOT = 3, SLT_DASH_DOT_DOT = 4};
+
+// Shared between sortdia.h and kwtextframeset.h
+enum SortType { KW_SORTINCREASE, KW_SORTDECREASE };
+
+/**
+ Relative position of the mouse compared to a frame, or "meaning of a click right there".
+ Can be: nothing ; inside a frame ; or on a border.
+ When clicking on a frame's border, this can be for moving it, resizing it, or simply select it. */
+enum MouseMeaning { MEANING_NONE = 0, MEANING_MOUSE_INSIDE, MEANING_MOUSE_INSIDE_TEXT,
+ MEANING_MOUSE_OVER_LINK, MEANING_MOUSE_OVER_FOOTNOTE,
+ MEANING_MOUSE_MOVE, MEANING_MOUSE_SELECT, MEANING_ACTIVATE_PART,
+ MEANING_TOPLEFT, MEANING_TOP, MEANING_TOPRIGHT, MEANING_RIGHT,
+ MEANING_BOTTOMRIGHT, MEANING_BOTTOM, MEANING_BOTTOMLEFT, MEANING_LEFT,
+ MEANING_RESIZE_COLUMN, MEANING_RESIZE_ROW, MEANING_SELECT_RANGE,
+ MEANING_SELECT_COLUMN, MEANING_SELECT_ROW, MEANING_FORBIDDEN };
+
+enum InsertPagePos { KW_INSERTPAGEAFTER=0 , KW_INSERTPAGEBEFORE=1 };
+
+
+#endif
diff --git a/kword/demos/DTPTest.kwt b/kword/demos/DTPTest.kwt
new file mode 100644
index 00000000..6601be85
--- /dev/null
+++ b/kword/demos/DTPTest.kwt
@@ -0,0 +1,380 @@
+<?xml version="1.0" encoding="UTF-8"?><!DOCTYPE DOC ><DOC mime="application/x-kword" syntaxVersion="1" editor="KWord" >
+ <PAPER width="595" zoom="100" spHeadBody="9" format="1" height="841" fType="0" orientation="0" hType="0" columnspacing="3" spFootBody="9" columns="1" >
+ <PAPERBORDERS right="0" left="0" bottom="0" top="0" />
+ </PAPER>
+ <ATTRIBUTES standardpage="1" hasFooter="0" unit="mm" hasHeader="0" processing="1" />
+ <FRAMESETS>
+ <FRAMESET removable="0" frameType="1" frameInfo="0" name="Frameset 1" visible="1" >
+ <FRAME runaround="1" right="300" left="28" bottom="600" runaroundGap="14" top="42" />
+ <FRAME runaround="1" right="500" left="310" bottom="600" runaroundGap="14" top="42" />
+ <PARAGRAPH>
+ <TEXT></TEXT>
+ <LAYOUT>
+ <NAME value="Standard" />
+ <FLOW align="left" />
+ <COUNTER bullet="176" numberingtype="0" bulletfont="times" type="0" start="0" depth="0" />
+ <FORMAT id="1" >
+ <WEIGHT value="50" />
+ <COLOR blue="0" red="0" green="0" />
+ <FONT name="times" />
+ <SIZE value="12" />
+ <ITALIC value="0" />
+ <UNDERLINE value="0" />
+ <STRIKEOUT value="0" />
+ <VERTALIGN value="0" />
+ </FORMAT>
+ </LAYOUT>
+ </PARAGRAPH>
+ </FRAMESET>
+ <FRAMESET removable="0" frameType="1" frameInfo="0" name="Frameset 2" visible="1" >
+ <FRAME right="200" left="28" bottom="300" runaroundGap="2" top="100" autoCreateNewFrame="0" />
+ <FRAME right="300" left="200" bottom="510" runaroundGap="2" top="400" autoCreateNewFrame="0" />
+ <PARAGRAPH>
+ <TEXT></TEXT>
+ <LAYOUT>
+ <NAME value="Standard" />
+ <FLOW align="left" />
+ <COUNTER bullet="45" numberingtype="0" bulletfont="times" type="0" start="0" depth="0" />
+ <FORMAT id="1" >
+ <WEIGHT value="50" />
+ <COLOR blue="0" red="0" green="0" />
+ <FONT name="times" />
+ <SIZE value="12" />
+ <ITALIC value="0" />
+ <UNDERLINE value="0" />
+ <STRIKEOUT value="0" />
+ <VERTALIGN value="0" />
+ </FORMAT>
+ </LAYOUT>
+ </PARAGRAPH>
+ </FRAMESET>
+ <FRAMESET removable="0" frameType="1" frameInfo="1" name="TextFrameset 3" visible="1" >
+ <FRAME right="594" left="0" bottom="19" runaroundGap="2" top="0" autoCreateNewFrame="0" />
+ <PARAGRAPH>
+ <TEXT></TEXT>
+ <LAYOUT>
+ <NAME value="Standard" />
+ <FLOW align="left" />
+ <COUNTER bullet="176" numberingtype="0" bulletfont="times" type="0" start="0" depth="0" />
+ <FORMAT id="1" >
+ <WEIGHT value="50" />
+ <COLOR blue="0" red="0" green="0" />
+ <FONT name="times" />
+ <SIZE value="12" />
+ <ITALIC value="0" />
+ <UNDERLINE value="0" />
+ <STRIKEOUT value="0" />
+ <VERTALIGN value="0" />
+ </FORMAT>
+ </LAYOUT>
+ </PARAGRAPH>
+ </FRAMESET>
+ <FRAMESET removable="0" frameType="1" frameInfo="3" name="TextFrameset 4" visible="1" >
+ <FRAME right="594" left="0" bottom="19" runaroundGap="2" top="0" autoCreateNewFrame="0" />
+ <PARAGRAPH>
+ <TEXT></TEXT>
+ <LAYOUT>
+ <NAME value="Standard" />
+ <FLOW align="left" />
+ <COUNTER bullet="176" numberingtype="0" bulletfont="times" type="0" start="0" depth="0" />
+ <FORMAT id="1" >
+ <WEIGHT value="50" />
+ <COLOR blue="0" red="0" green="0" />
+ <FONT name="times" />
+ <SIZE value="12" />
+ <ITALIC value="0" />
+ <UNDERLINE value="0" />
+ <STRIKEOUT value="0" />
+ <VERTALIGN value="0" />
+ </FORMAT>
+ </LAYOUT>
+ </PARAGRAPH>
+ </FRAMESET>
+ <FRAMESET removable="0" frameType="1" frameInfo="2" name="TextFrameset 5" visible="1" >
+ <FRAME right="594" left="0" bottom="19" runaroundGap="2" top="0" autoCreateNewFrame="0" />
+ <PARAGRAPH>
+ <TEXT></TEXT>
+ <LAYOUT>
+ <NAME value="Standard" />
+ <FLOW align="left" />
+ <COUNTER bullet="176" numberingtype="0" bulletfont="times" type="0" start="0" depth="0" />
+ <FORMAT id="1" >
+ <WEIGHT value="50" />
+ <COLOR blue="0" red="0" green="0" />
+ <FONT name="times" />
+ <SIZE value="12" />
+ <ITALIC value="0" />
+ <UNDERLINE value="0" />
+ <STRIKEOUT value="0" />
+ <VERTALIGN value="0" />
+ </FORMAT>
+ </LAYOUT>
+ </PARAGRAPH>
+ </FRAMESET>
+ <FRAMESET removable="0" frameType="1" frameInfo="4" name="TextFrameset 6" visible="1" >
+ <FRAME right="594" left="0" bottom="840" runaroundGap="2" top="821" autoCreateNewFrame="0" />
+ <PARAGRAPH>
+ <TEXT></TEXT>
+ <LAYOUT>
+ <NAME value="Standard" />
+ <FLOW align="left" />
+ <COUNTER bullet="176" numberingtype="0" bulletfont="times" type="0" start="0" depth="0" />
+ <FORMAT id="1" >
+ <WEIGHT value="50" />
+ <COLOR blue="0" red="0" green="0" />
+ <FONT name="times" />
+ <SIZE value="12" />
+ <ITALIC value="0" />
+ <UNDERLINE value="0" />
+ <STRIKEOUT value="0" />
+ <VERTALIGN value="0" />
+ </FORMAT>
+ </LAYOUT>
+ </PARAGRAPH>
+ </FRAMESET>
+ <FRAMESET removable="0" frameType="1" frameInfo="6" name="TextFrameset 7" visible="1" >
+ <FRAME right="594" left="0" bottom="840" runaroundGap="2" top="821" autoCreateNewFrame="0" />
+ <PARAGRAPH>
+ <TEXT></TEXT>
+ <LAYOUT>
+ <NAME value="Standard" />
+ <FLOW align="left" />
+ <COUNTER bullet="176" numberingtype="0" bulletfont="times" type="0" start="0" depth="0" />
+ <FORMAT id="1" >
+ <WEIGHT value="50" />
+ <COLOR blue="0" red="0" green="0" />
+ <FONT name="times" />
+ <SIZE value="12" />
+ <ITALIC value="0" />
+ <UNDERLINE value="0" />
+ <STRIKEOUT value="0" />
+ <VERTALIGN value="0" />
+ </FORMAT>
+ </LAYOUT>
+ </PARAGRAPH>
+ </FRAMESET>
+ <FRAMESET removable="0" frameType="1" frameInfo="5" name="TextFrameset 8" visible="1" >
+ <FRAME right="594" left="0" bottom="840" runaroundGap="2" top="821" autoCreateNewFrame="0" />
+ <PARAGRAPH>
+ <TEXT></TEXT>
+ <LAYOUT>
+ <NAME value="Standard" />
+ <FLOW align="left" />
+ <COUNTER bullet="176" numberingtype="0" bulletfont="times" type="0" start="0" depth="0" />
+ <FORMAT id="1" >
+ <WEIGHT value="50" />
+ <COLOR blue="0" red="0" green="0" />
+ <FONT name="times" />
+ <SIZE value="12" />
+ <ITALIC value="0" />
+ <UNDERLINE value="0" />
+ <STRIKEOUT value="0" />
+ <VERTALIGN value="0" />
+ </FORMAT>
+ </LAYOUT>
+ </PARAGRAPH>
+ </FRAMESET>
+ <FRAMESET removable="0" frameType="1" frameInfo="7" name="Footnotes" visible="0" >
+ <FRAME runaround="1" right="594" left="0" bottom="840" top="821" autoCreateNewFrame="0" />
+ <PARAGRAPH>
+ <TEXT></TEXT>
+ <LAYOUT>
+ <NAME value="Standard" />
+ <FLOW align="left" />
+ <COUNTER bullet="176" numberingtype="0" bulletfont="times" type="0" start="0" depth="0" />
+ <FORMAT id="1" >
+ <WEIGHT value="50" />
+ <COLOR blue="0" red="0" green="0" />
+ <FONT name="Arial" />
+ <SIZE value="11" />
+ <ITALIC value="0" />
+ <UNDERLINE value="0" />
+ <STRIKEOUT value="0" />
+ <VERTALIGN value="0" />
+ </FORMAT>
+ </LAYOUT>
+ </PARAGRAPH>
+ </FRAMESET>
+ </FRAMESETS>
+ <STYLES>
+ <STYLE>
+ <NAME value="Standard" />
+ <FLOW align="left" />
+ <COUNTER bullet="176" numberingtype="0" bulletfont="times" type="0" start="0" depth="0" />
+ <FOLLOWING name="Standard" />
+ <FORMAT id="1" >
+ <WEIGHT value="50" />
+ <COLOR blue="0" red="0" green="0" />
+ <FONT name="times" />
+ <SIZE value="12" />
+ <ITALIC value="0" />
+ <UNDERLINE value="0" />
+ <STRIKEOUT value="0" />
+ <VERTALIGN value="0" />
+ </FORMAT>
+ </STYLE>
+ <STYLE>
+ <NAME value="Head 1" />
+ <FLOW align="left" />
+ <COUNTER bullet="176" numberingtype="1" bulletfont="times" righttext="." type="1" start="1" depth="0" />
+ <FOLLOWING name="Standard" />
+ <FORMAT id="1" >
+ <WEIGHT value="75" />
+ <COLOR blue="0" red="0" green="0" />
+ <FONT name="helvetica" />
+ <SIZE value="24" />
+ <ITALIC value="0" />
+ <UNDERLINE value="0" />
+ <STRIKEOUT value="0" />
+ <VERTALIGN value="0" />
+ </FORMAT>
+ </STYLE>
+ <STYLE>
+ <NAME value="Head 2" />
+ <FLOW align="left" />
+ <COUNTER bullet="176" numberingtype="1" bulletfont="times" righttext="." type="1" start="1" depth="1" />
+ <FOLLOWING name="Standard" />
+ <FORMAT id="1" >
+ <WEIGHT value="75" />
+ <COLOR blue="0" red="0" green="0" />
+ <FONT name="helvetica" />
+ <SIZE value="16" />
+ <ITALIC value="0" />
+ <UNDERLINE value="0" />
+ <STRIKEOUT value="0" />
+ <VERTALIGN value="0" />
+ </FORMAT>
+ </STYLE>
+ <STYLE>
+ <NAME value="Head 3" />
+ <FLOW align="left" />
+ <COUNTER bullet="176" numberingtype="1" bulletfont="times" righttext="." type="1" start="1" depth="2" />
+ <FOLLOWING name="Standard" />
+ <FORMAT id="1" >
+ <WEIGHT value="75" />
+ <COLOR blue="0" red="0" green="0" />
+ <FONT name="helvetica" />
+ <SIZE value="12" />
+ <ITALIC value="0" />
+ <UNDERLINE value="0" />
+ <STRIKEOUT value="0" />
+ <VERTALIGN value="0" />
+ </FORMAT>
+ </STYLE>
+ <STYLE>
+ <NAME value="Enumerated List" />
+ <FLOW align="left" />
+ <COUNTER bullet="176" numberingtype="0" bulletfont="times" righttext="." type="1" start="1" depth="0" />
+ <FOLLOWING name="Enumerated List" />
+ <FORMAT id="1" >
+ <WEIGHT value="50" />
+ <COLOR blue="0" red="0" green="0" />
+ <FONT name="times" />
+ <SIZE value="12" />
+ <ITALIC value="0" />
+ <UNDERLINE value="0" />
+ <STRIKEOUT value="0" />
+ <VERTALIGN value="0" />
+ </FORMAT>
+ </STYLE>
+ <STYLE>
+ <NAME value="Alphabetical List" />
+ <FLOW align="left" />
+ <COUNTER bullet="176" numberingtype="0" bulletfont="times" righttext=")" type="2" start="1" depth="0" />
+ <FOLLOWING name="Alphabetical List" />
+ <FORMAT id="1" >
+ <WEIGHT value="50" />
+ <COLOR blue="0" red="0" green="0" />
+ <FONT name="times" />
+ <SIZE value="12" />
+ <ITALIC value="0" />
+ <UNDERLINE value="0" />
+ <STRIKEOUT value="0" />
+ <VERTALIGN value="0" />
+ </FORMAT>
+ </STYLE>
+ <STYLE>
+ <NAME value="Bullet List" />
+ <FLOW align="left" />
+ <COUNTER bullet="0" numberingtype="0" type="10" start="1" depth="0" />
+ <FOLLOWING name="Bullet List" />
+ <FORMAT id="1" >
+ <WEIGHT value="50" />
+ <COLOR blue="0" red="0" green="0" />
+ <FONT name="times" />
+ <SIZE value="12" />
+ <ITALIC value="0" />
+ <UNDERLINE value="0" />
+ <STRIKEOUT value="0" />
+ <VERTALIGN value="0" />
+ </FORMAT>
+ </STYLE>
+ <STYLE>
+ <NAME value="Contents Title" />
+ <FLOW align="center" />
+ <TOPBORDER width="1" style="0" blue="0" red="0" green="0" />
+ <BOTTOMBORDER width="1" style="0" blue="0" red="0" green="0" />
+ <COUNTER bullet="183" numberingtype="0" bulletfont="symbol" type="0" start="0" depth="0" />
+ <FOLLOWING name="Standard" />
+ <FORMAT id="1" >
+ <WEIGHT value="75" />
+ <COLOR blue="0" red="0" green="0" />
+ <FONT name="helvetica" />
+ <SIZE value="20" />
+ <ITALIC value="0" />
+ <UNDERLINE value="0" />
+ <STRIKEOUT value="0" />
+ <VERTALIGN value="0" />
+ </FORMAT>
+ </STYLE>
+ <STYLE>
+ <NAME value="Contents Head 1" />
+ <FLOW align="left" />
+ <COUNTER bullet="183" numberingtype="0" bulletfont="symbol" type="0" start="0" depth="0" />
+ <FOLLOWING name="Standard" />
+ <FORMAT id="1" >
+ <WEIGHT value="75" />
+ <COLOR blue="0" red="0" green="0" />
+ <FONT name="helvetica" />
+ <SIZE value="16" />
+ <ITALIC value="0" />
+ <UNDERLINE value="0" />
+ <STRIKEOUT value="0" />
+ <VERTALIGN value="0" />
+ </FORMAT>
+ </STYLE>
+ <STYLE>
+ <NAME value="Contents Head 2" />
+ <FLOW align="left" />
+ <COUNTER bullet="183" numberingtype="0" bulletfont="symbol" type="0" start="0" depth="0" />
+ <FOLLOWING name="Standard" />
+ <FORMAT id="1" >
+ <WEIGHT value="75" />
+ <COLOR blue="0" red="0" green="0" />
+ <FONT name="helvetica" />
+ <SIZE value="12" />
+ <ITALIC value="0" />
+ <UNDERLINE value="0" />
+ <STRIKEOUT value="0" />
+ <VERTALIGN value="0" />
+ </FORMAT>
+ </STYLE>
+ <STYLE>
+ <NAME value="Contents Head 3" />
+ <FLOW align="left" />
+ <COUNTER bullet="183" numberingtype="0" bulletfont="symbol" type="0" start="0" depth="0" />
+ <FOLLOWING name="Standard" />
+ <FORMAT id="1" >
+ <WEIGHT value="50" />
+ <COLOR blue="0" red="0" green="0" />
+ <FONT name="helvetica" />
+ <SIZE value="12" />
+ <ITALIC value="1" />
+ <UNDERLINE value="0" />
+ <STRIKEOUT value="0" />
+ <VERTALIGN value="0" />
+ </FORMAT>
+ </STYLE>
+ </STYLES>
+ <PIXMAPS/>
+</DOC>
diff --git a/kword/demos/bidi.kwd b/kword/demos/bidi.kwd
new file mode 100644
index 00000000..5792017f
--- /dev/null
+++ b/kword/demos/bidi.kwd
Binary files differ
diff --git a/kword/demos/chapters.kwd b/kword/demos/chapters.kwd
new file mode 100644
index 00000000..76c94cc7
--- /dev/null
+++ b/kword/demos/chapters.kwd
@@ -0,0 +1,1541 @@
+<?xml version="1.0"?>
+<DOC author="Reginald Stadlbauer and Torben Weis" email="reggie@kde.org and weis@kde.org" editor="KWord" mime="application/x-kword">
+ <PAPER format="1" ptWidth="595" ptHeight="841" mmWidth ="210" mmHeight="297" inchWidth ="8.26772" inchHeight="11.6929" orientation="0" columns="1" ptColumnspc="2" mmColumnspc="1" inchColumnspc="0.0393701" hType="0" fType="0" ptHeadBody="9" ptFootBody="9" mmHeadBody="3.5" mmFootBody="3.5" inchHeadBody="0.137795" inchFootBody="0.137795">
+ <PAPERBORDERS mmLeft="10" mmTop="15" mmRight="10" mmBottom="15" ptLeft="28" ptTop="42" ptRight="28" ptBottom="42" inchLeft="0.393701" inchTop="0.590551" inchRight="0.393701" inchBottom="0.590551"/>
+ </PAPER>
+ <ATTRIBUTES processing="0" standardpage="1" hasHeader="0" hasFooter="0" unit="mm"/>
+ <FRAMESETS>
+ <FRAMESET frameType="1" autoCreateNewFrame="1" frameInfo="0">
+ <FRAME left="28" top="42" right="566" bottom="798" runaround="1" runaGapPT="2" runaGapMM="1" runaGapINCH="0.0393701" lWidth="1" lRed="255" lGreen="255" lBlue="255" lStyle="0" rWidth="1" rRed="255" rGreen="255" rBlue="255" rStyle="0" tWidth="1" tRed="255" tGreen="255" tBlue="255" tStyle="0" bWidth="1" bRed="255" bGreen="255" bBlue="255" bStyle="0" bkRed="255" bkGreen="255" bkBlue="255" bleftpt="0" bleftmm="0" bleftinch="0" brightpt="0" brightmm="0" brightinch="0" btoppt="0" btopmm="0" btopinch="0" bbottompt="0" bbottommm="0" bbottominch="0"/>
+ <PARAGRAPH>
+ <TEXT>First header</TEXT>
+ <HARDBRK frame="0"/>
+ <FORMATS>
+ <FORMAT id="1" pos="0" len="12">
+ <COLOR red="0" green="0" blue="0"/>
+ <FONT name="helvetica"/>
+ <SIZE value="24"/>
+ <WEIGHT value="75"/>
+ <ITALIC value="0"/>
+ <UNDERLINE value="0"/>
+ <VERTALIGN value="0"/>
+ </FORMAT>
+ </FORMATS>
+ <LAYOUT>
+ <NAME value="Head 1"/>
+ <FOLLOWING name="Standard"/>
+ <FLOW value="0"/>
+ <OHEAD pt="0" mm="0" inch="0"/>
+ <OFOOT pt="0" mm="0" inch="0"/>
+ <IFIRST pt="0" mm="0" inch="0"/>
+ <ILEFT pt="0" mm="0" inch="0"/>
+ <LINESPACE pt="0" mm="0" inch="0"/>
+ <COUNTER type="1" depth="0" bullet="-73" start="1" numberingtype="1" lefttext="" righttext="." bulletfont="symbol"/>
+ <LEFTBORDER red="255" green="255" blue="255" style="0" width="0"/>
+ <RIGHTBORDER red="255" green="255" blue="255" style="0" width="0"/>
+ <TOPBORDER red="255" green="255" blue="255" style="0" width="0"/>
+ <BOTTOMBORDER red="255" green="255" blue="255" style="0" width="0"/>
+ <FORMAT>
+ <COLOR red="0" green="0" blue="0"/>
+ <FONT name="helvetica"/>
+ <SIZE value="24"/>
+ <WEIGHT value="75"/>
+ <ITALIC value="0"/>
+ <UNDERLINE value="0"/>
+ <VERTALIGN value="0"/>
+ </FORMAT>
+ </LAYOUT>
+ </PARAGRAPH>
+ <PARAGRAPH>
+ <TEXT>blablaba</TEXT>
+ <HARDBRK frame="0"/>
+ <FORMATS>
+ <FORMAT id="1" pos="0" len="8">
+ <COLOR red="0" green="0" blue="0"/>
+ <FONT name="times"/>
+ <SIZE value="12"/>
+ <WEIGHT value="50"/>
+ <ITALIC value="0"/>
+ <UNDERLINE value="0"/>
+ <VERTALIGN value="0"/>
+ </FORMAT>
+ </FORMATS>
+ <LAYOUT>
+ <NAME value="Standard"/>
+ <FOLLOWING name="Standard"/>
+ <FLOW value="0"/>
+ <OHEAD pt="0" mm="0" inch="0"/>
+ <OFOOT pt="0" mm="0" inch="0"/>
+ <IFIRST pt="0" mm="0" inch="0"/>
+ <ILEFT pt="0" mm="0" inch="0"/>
+ <LINESPACE pt="0" mm="0" inch="0"/>
+ <COUNTER type="0" depth="0" bullet="-73" start="0" numberingtype="0" lefttext="" righttext="" bulletfont="symbol"/>
+ <LEFTBORDER red="255" green="255" blue="255" style="0" width="0"/>
+ <RIGHTBORDER red="255" green="255" blue="255" style="0" width="0"/>
+ <TOPBORDER red="255" green="255" blue="255" style="0" width="0"/>
+ <BOTTOMBORDER red="255" green="255" blue="255" style="0" width="0"/>
+ <FORMAT>
+ <COLOR red="0" green="0" blue="0"/>
+ <FONT name="times"/>
+ <SIZE value="12"/>
+ <WEIGHT value="50"/>
+ <ITALIC value="0"/>
+ <UNDERLINE value="0"/>
+ <VERTALIGN value="0"/>
+ </FORMAT>
+ <TABULATOR mmpos="63" ptpos="179" inchpos="1.6061e-19" type="0"/>
+ <TABULATOR mmpos="128" ptpos="363" inchpos="1.1009e+15" type="0"/>
+ </LAYOUT>
+ </PARAGRAPH>
+ <PARAGRAPH>
+ <TEXT>First header in the first header</TEXT>
+ <HARDBRK frame="0"/>
+ <FORMATS>
+ <FORMAT id="1" pos="0" len="32">
+ <COLOR red="0" green="0" blue="0"/>
+ <FONT name="helvetica"/>
+ <SIZE value="16"/>
+ <WEIGHT value="75"/>
+ <ITALIC value="0"/>
+ <UNDERLINE value="0"/>
+ <VERTALIGN value="0"/>
+ </FORMAT>
+ </FORMATS>
+ <LAYOUT>
+ <NAME value="Head 2"/>
+ <FOLLOWING name="Standard"/>
+ <FLOW value="0"/>
+ <OHEAD pt="0" mm="0" inch="0"/>
+ <OFOOT pt="0" mm="0" inch="0"/>
+ <IFIRST pt="0" mm="0" inch="0"/>
+ <ILEFT pt="0" mm="0" inch="0"/>
+ <LINESPACE pt="0" mm="0" inch="0"/>
+ <COUNTER type="1" depth="1" bullet="-73" start="1" numberingtype="1" lefttext="" righttext="." bulletfont="symbol"/>
+ <LEFTBORDER red="255" green="255" blue="255" style="0" width="0"/>
+ <RIGHTBORDER red="255" green="255" blue="255" style="0" width="0"/>
+ <TOPBORDER red="255" green="255" blue="255" style="0" width="0"/>
+ <BOTTOMBORDER red="255" green="255" blue="255" style="0" width="0"/>
+ <FORMAT>
+ <COLOR red="0" green="0" blue="0"/>
+ <FONT name="helvetica"/>
+ <SIZE value="16"/>
+ <WEIGHT value="75"/>
+ <ITALIC value="0"/>
+ <UNDERLINE value="0"/>
+ <VERTALIGN value="0"/>
+ </FORMAT>
+ </LAYOUT>
+ </PARAGRAPH>
+ <PARAGRAPH>
+ <TEXT>blablabka</TEXT>
+ <HARDBRK frame="0"/>
+ <FORMATS>
+ <FORMAT id="1" pos="0" len="9">
+ <COLOR red="0" green="0" blue="0"/>
+ <FONT name="times"/>
+ <SIZE value="12"/>
+ <WEIGHT value="50"/>
+ <ITALIC value="0"/>
+ <UNDERLINE value="0"/>
+ <VERTALIGN value="0"/>
+ </FORMAT>
+ </FORMATS>
+ <LAYOUT>
+ <NAME value="Standard"/>
+ <FOLLOWING name="Standard"/>
+ <FLOW value="0"/>
+ <OHEAD pt="0" mm="0" inch="0"/>
+ <OFOOT pt="0" mm="0" inch="0"/>
+ <IFIRST pt="0" mm="0" inch="0"/>
+ <ILEFT pt="0" mm="0" inch="0"/>
+ <LINESPACE pt="0" mm="0" inch="0"/>
+ <COUNTER type="0" depth="0" bullet="-73" start="0" numberingtype="0" lefttext="" righttext="" bulletfont="symbol"/>
+ <LEFTBORDER red="255" green="255" blue="255" style="0" width="0"/>
+ <RIGHTBORDER red="255" green="255" blue="255" style="0" width="0"/>
+ <TOPBORDER red="255" green="255" blue="255" style="0" width="0"/>
+ <BOTTOMBORDER red="255" green="255" blue="255" style="0" width="0"/>
+ <FORMAT>
+ <COLOR red="0" green="0" blue="0"/>
+ <FONT name="times"/>
+ <SIZE value="12"/>
+ <WEIGHT value="50"/>
+ <ITALIC value="0"/>
+ <UNDERLINE value="0"/>
+ <VERTALIGN value="0"/>
+ </FORMAT>
+ <TABULATOR mmpos="63" ptpos="179" inchpos="1.6061e-19" type="0"/>
+ <TABULATOR mmpos="128" ptpos="363" inchpos="1.1009e+15" type="0"/>
+ </LAYOUT>
+ </PARAGRAPH>
+ <PARAGRAPH>
+ <TEXT>And more blabla</TEXT>
+ <HARDBRK frame="0"/>
+ <FORMATS>
+ <FORMAT id="1" pos="0" len="15">
+ <COLOR red="0" green="0" blue="0"/>
+ <FONT name="times"/>
+ <SIZE value="12"/>
+ <WEIGHT value="50"/>
+ <ITALIC value="0"/>
+ <UNDERLINE value="0"/>
+ <VERTALIGN value="0"/>
+ </FORMAT>
+ </FORMATS>
+ <LAYOUT>
+ <NAME value="Standard"/>
+ <FOLLOWING name="Standard"/>
+ <FLOW value="0"/>
+ <OHEAD pt="0" mm="0" inch="0"/>
+ <OFOOT pt="0" mm="0" inch="0"/>
+ <IFIRST pt="0" mm="0" inch="0"/>
+ <ILEFT pt="0" mm="0" inch="0"/>
+ <LINESPACE pt="0" mm="0" inch="0"/>
+ <COUNTER type="0" depth="0" bullet="-73" start="0" numberingtype="0" lefttext="" righttext="" bulletfont="symbol"/>
+ <LEFTBORDER red="255" green="255" blue="255" style="0" width="0"/>
+ <RIGHTBORDER red="255" green="255" blue="255" style="0" width="0"/>
+ <TOPBORDER red="255" green="255" blue="255" style="0" width="0"/>
+ <BOTTOMBORDER red="255" green="255" blue="255" style="0" width="0"/>
+ <FORMAT>
+ <COLOR red="0" green="0" blue="0"/>
+ <FONT name="times"/>
+ <SIZE value="12"/>
+ <WEIGHT value="50"/>
+ <ITALIC value="0"/>
+ <UNDERLINE value="0"/>
+ <VERTALIGN value="0"/>
+ </FORMAT>
+ <TABULATOR mmpos="63" ptpos="179" inchpos="1.6061e-19" type="0"/>
+ <TABULATOR mmpos="128" ptpos="363" inchpos="1.1009e+15" type="0"/>
+ </LAYOUT>
+ </PARAGRAPH>
+ <PARAGRAPH>
+ <TEXT>Second header in the first header</TEXT>
+ <HARDBRK frame="0"/>
+ <FORMATS>
+ <FORMAT id="1" pos="0" len="33">
+ <COLOR red="0" green="0" blue="0"/>
+ <FONT name="helvetica"/>
+ <SIZE value="16"/>
+ <WEIGHT value="75"/>
+ <ITALIC value="0"/>
+ <UNDERLINE value="0"/>
+ <VERTALIGN value="0"/>
+ </FORMAT>
+ </FORMATS>
+ <LAYOUT>
+ <NAME value="Head 2"/>
+ <FOLLOWING name="Standard"/>
+ <FLOW value="0"/>
+ <OHEAD pt="0" mm="0" inch="0"/>
+ <OFOOT pt="0" mm="0" inch="0"/>
+ <IFIRST pt="0" mm="0" inch="0"/>
+ <ILEFT pt="0" mm="0" inch="0"/>
+ <LINESPACE pt="0" mm="0" inch="0"/>
+ <COUNTER type="1" depth="1" bullet="-73" start="1" numberingtype="1" lefttext="" righttext="." bulletfont="symbol"/>
+ <LEFTBORDER red="255" green="255" blue="255" style="0" width="0"/>
+ <RIGHTBORDER red="255" green="255" blue="255" style="0" width="0"/>
+ <TOPBORDER red="255" green="255" blue="255" style="0" width="0"/>
+ <BOTTOMBORDER red="255" green="255" blue="255" style="0" width="0"/>
+ <FORMAT>
+ <COLOR red="0" green="0" blue="0"/>
+ <FONT name="helvetica"/>
+ <SIZE value="16"/>
+ <WEIGHT value="75"/>
+ <ITALIC value="0"/>
+ <UNDERLINE value="0"/>
+ <VERTALIGN value="0"/>
+ </FORMAT>
+ </LAYOUT>
+ </PARAGRAPH>
+ <PARAGRAPH>
+ <TEXT>Again some blabla to use some space...</TEXT>
+ <HARDBRK frame="0"/>
+ <FORMATS>
+ <FORMAT id="1" pos="0" len="38">
+ <COLOR red="0" green="0" blue="0"/>
+ <FONT name="times"/>
+ <SIZE value="12"/>
+ <WEIGHT value="50"/>
+ <ITALIC value="0"/>
+ <UNDERLINE value="0"/>
+ <VERTALIGN value="0"/>
+ </FORMAT>
+ </FORMATS>
+ <LAYOUT>
+ <NAME value="Standard"/>
+ <FOLLOWING name="Standard"/>
+ <FLOW value="0"/>
+ <OHEAD pt="0" mm="0" inch="0"/>
+ <OFOOT pt="0" mm="0" inch="0"/>
+ <IFIRST pt="0" mm="0" inch="0"/>
+ <ILEFT pt="0" mm="0" inch="0"/>
+ <LINESPACE pt="0" mm="0" inch="0"/>
+ <COUNTER type="0" depth="0" bullet="-73" start="0" numberingtype="0" lefttext="" righttext="" bulletfont="symbol"/>
+ <LEFTBORDER red="255" green="255" blue="255" style="0" width="0"/>
+ <RIGHTBORDER red="255" green="255" blue="255" style="0" width="0"/>
+ <TOPBORDER red="255" green="255" blue="255" style="0" width="0"/>
+ <BOTTOMBORDER red="255" green="255" blue="255" style="0" width="0"/>
+ <FORMAT>
+ <COLOR red="0" green="0" blue="0"/>
+ <FONT name="times"/>
+ <SIZE value="12"/>
+ <WEIGHT value="50"/>
+ <ITALIC value="0"/>
+ <UNDERLINE value="0"/>
+ <VERTALIGN value="0"/>
+ </FORMAT>
+ <TABULATOR mmpos="63" ptpos="179" inchpos="1.6061e-19" type="0"/>
+ <TABULATOR mmpos="128" ptpos="363" inchpos="1.1009e+15" type="0"/>
+ </LAYOUT>
+ </PARAGRAPH>
+ <PARAGRAPH>
+ <TEXT>First header in the scond header of the first header</TEXT>
+ <HARDBRK frame="0"/>
+ <FORMATS>
+ <FORMAT id="1" pos="0" len="52">
+ <COLOR red="0" green="0" blue="0"/>
+ <FONT name="helvetica"/>
+ <SIZE value="12"/>
+ <WEIGHT value="75"/>
+ <ITALIC value="0"/>
+ <UNDERLINE value="0"/>
+ <VERTALIGN value="0"/>
+ </FORMAT>
+ </FORMATS>
+ <LAYOUT>
+ <NAME value="Head 3"/>
+ <FOLLOWING name="Standard"/>
+ <FLOW value="0"/>
+ <OHEAD pt="0" mm="0" inch="0"/>
+ <OFOOT pt="0" mm="0" inch="0"/>
+ <IFIRST pt="0" mm="0" inch="0"/>
+ <ILEFT pt="0" mm="0" inch="0"/>
+ <LINESPACE pt="0" mm="0" inch="0"/>
+ <COUNTER type="1" depth="2" bullet="-73" start="1" numberingtype="1" lefttext="" righttext="." bulletfont="symbol"/>
+ <LEFTBORDER red="255" green="255" blue="255" style="0" width="0"/>
+ <RIGHTBORDER red="255" green="255" blue="255" style="0" width="0"/>
+ <TOPBORDER red="255" green="255" blue="255" style="0" width="0"/>
+ <BOTTOMBORDER red="255" green="255" blue="255" style="0" width="0"/>
+ <FORMAT>
+ <COLOR red="0" green="0" blue="0"/>
+ <FONT name="helvetica"/>
+ <SIZE value="12"/>
+ <WEIGHT value="75"/>
+ <ITALIC value="0"/>
+ <UNDERLINE value="0"/>
+ <VERTALIGN value="0"/>
+ </FORMAT>
+ </LAYOUT>
+ </PARAGRAPH>
+ <PARAGRAPH>
+ <TEXT>Second header in the second header of the first header</TEXT>
+ <HARDBRK frame="0"/>
+ <FORMATS>
+ <FORMAT id="1" pos="0" len="54">
+ <COLOR red="0" green="0" blue="0"/>
+ <FONT name="helvetica"/>
+ <SIZE value="12"/>
+ <WEIGHT value="75"/>
+ <ITALIC value="0"/>
+ <UNDERLINE value="0"/>
+ <VERTALIGN value="0"/>
+ </FORMAT>
+ </FORMATS>
+ <LAYOUT>
+ <NAME value="Head 3"/>
+ <FOLLOWING name="Standard"/>
+ <FLOW value="0"/>
+ <OHEAD pt="0" mm="0" inch="0"/>
+ <OFOOT pt="0" mm="0" inch="0"/>
+ <IFIRST pt="0" mm="0" inch="0"/>
+ <ILEFT pt="0" mm="0" inch="0"/>
+ <LINESPACE pt="0" mm="0" inch="0"/>
+ <COUNTER type="1" depth="2" bullet="-73" start="1" numberingtype="1" lefttext="" righttext="." bulletfont="symbol"/>
+ <LEFTBORDER red="255" green="255" blue="255" style="0" width="0"/>
+ <RIGHTBORDER red="255" green="255" blue="255" style="0" width="0"/>
+ <TOPBORDER red="255" green="255" blue="255" style="0" width="0"/>
+ <BOTTOMBORDER red="255" green="255" blue="255" style="0" width="0"/>
+ <FORMAT>
+ <COLOR red="0" green="0" blue="0"/>
+ <FONT name="helvetica"/>
+ <SIZE value="12"/>
+ <WEIGHT value="75"/>
+ <ITALIC value="0"/>
+ <UNDERLINE value="0"/>
+ <VERTALIGN value="0"/>
+ </FORMAT>
+ </LAYOUT>
+ </PARAGRAPH>
+ <PARAGRAPH>
+ <TEXT>Let's write some words here</TEXT>
+ <HARDBRK frame="0"/>
+ <FORMATS>
+ <FORMAT id="1" pos="0" len="27">
+ <COLOR red="0" green="0" blue="0"/>
+ <FONT name="times"/>
+ <SIZE value="12"/>
+ <WEIGHT value="50"/>
+ <ITALIC value="0"/>
+ <UNDERLINE value="0"/>
+ <VERTALIGN value="0"/>
+ </FORMAT>
+ </FORMATS>
+ <LAYOUT>
+ <NAME value="Standard"/>
+ <FOLLOWING name="Standard"/>
+ <FLOW value="0"/>
+ <OHEAD pt="0" mm="0" inch="0"/>
+ <OFOOT pt="0" mm="0" inch="0"/>
+ <IFIRST pt="0" mm="0" inch="0"/>
+ <ILEFT pt="0" mm="0" inch="0"/>
+ <LINESPACE pt="0" mm="0" inch="0"/>
+ <COUNTER type="0" depth="0" bullet="-73" start="0" numberingtype="0" lefttext="" righttext="" bulletfont="symbol"/>
+ <LEFTBORDER red="255" green="255" blue="255" style="0" width="0"/>
+ <RIGHTBORDER red="255" green="255" blue="255" style="0" width="0"/>
+ <TOPBORDER red="255" green="255" blue="255" style="0" width="0"/>
+ <BOTTOMBORDER red="255" green="255" blue="255" style="0" width="0"/>
+ <FORMAT>
+ <COLOR red="0" green="0" blue="0"/>
+ <FONT name="times"/>
+ <SIZE value="12"/>
+ <WEIGHT value="50"/>
+ <ITALIC value="0"/>
+ <UNDERLINE value="0"/>
+ <VERTALIGN value="0"/>
+ </FORMAT>
+ <TABULATOR mmpos="63" ptpos="179" inchpos="1.6061e-19" type="0"/>
+ <TABULATOR mmpos="128" ptpos="363" inchpos="1.1009e+15" type="0"/>
+ </LAYOUT>
+ </PARAGRAPH>
+ <PARAGRAPH>
+ <TEXT>Third header in the first header</TEXT>
+ <HARDBRK frame="0"/>
+ <FORMATS>
+ <FORMAT id="1" pos="0" len="32">
+ <COLOR red="0" green="0" blue="0"/>
+ <FONT name="helvetica"/>
+ <SIZE value="16"/>
+ <WEIGHT value="75"/>
+ <ITALIC value="0"/>
+ <UNDERLINE value="0"/>
+ <VERTALIGN value="0"/>
+ </FORMAT>
+ </FORMATS>
+ <LAYOUT>
+ <NAME value="Head 2"/>
+ <FOLLOWING name="Standard"/>
+ <FLOW value="0"/>
+ <OHEAD pt="0" mm="0" inch="0"/>
+ <OFOOT pt="0" mm="0" inch="0"/>
+ <IFIRST pt="0" mm="0" inch="0"/>
+ <ILEFT pt="0" mm="0" inch="0"/>
+ <LINESPACE pt="0" mm="0" inch="0"/>
+ <COUNTER type="1" depth="1" bullet="-73" start="1" numberingtype="1" lefttext="" righttext="." bulletfont="symbol"/>
+ <LEFTBORDER red="255" green="255" blue="255" style="0" width="0"/>
+ <RIGHTBORDER red="255" green="255" blue="255" style="0" width="0"/>
+ <TOPBORDER red="255" green="255" blue="255" style="0" width="0"/>
+ <BOTTOMBORDER red="255" green="255" blue="255" style="0" width="0"/>
+ <FORMAT>
+ <COLOR red="0" green="0" blue="0"/>
+ <FONT name="helvetica"/>
+ <SIZE value="16"/>
+ <WEIGHT value="75"/>
+ <ITALIC value="0"/>
+ <UNDERLINE value="0"/>
+ <VERTALIGN value="0"/>
+ </FORMAT>
+ </LAYOUT>
+ </PARAGRAPH>
+ <PARAGRAPH>
+ <TEXT>And here some plain text once again....</TEXT>
+ <HARDBRK frame="0"/>
+ <FORMATS>
+ <FORMAT id="1" pos="0" len="39">
+ <COLOR red="0" green="0" blue="0"/>
+ <FONT name="times"/>
+ <SIZE value="12"/>
+ <WEIGHT value="50"/>
+ <ITALIC value="0"/>
+ <UNDERLINE value="0"/>
+ <VERTALIGN value="0"/>
+ </FORMAT>
+ </FORMATS>
+ <LAYOUT>
+ <NAME value="Standard"/>
+ <FOLLOWING name="Standard"/>
+ <FLOW value="0"/>
+ <OHEAD pt="0" mm="0" inch="0"/>
+ <OFOOT pt="0" mm="0" inch="0"/>
+ <IFIRST pt="0" mm="0" inch="0"/>
+ <ILEFT pt="0" mm="0" inch="0"/>
+ <LINESPACE pt="0" mm="0" inch="0"/>
+ <COUNTER type="0" depth="0" bullet="-73" start="0" numberingtype="0" lefttext="" righttext="" bulletfont="symbol"/>
+ <LEFTBORDER red="255" green="255" blue="255" style="0" width="0"/>
+ <RIGHTBORDER red="255" green="255" blue="255" style="0" width="0"/>
+ <TOPBORDER red="255" green="255" blue="255" style="0" width="0"/>
+ <BOTTOMBORDER red="255" green="255" blue="255" style="0" width="0"/>
+ <FORMAT>
+ <COLOR red="0" green="0" blue="0"/>
+ <FONT name="times"/>
+ <SIZE value="12"/>
+ <WEIGHT value="50"/>
+ <ITALIC value="0"/>
+ <UNDERLINE value="0"/>
+ <VERTALIGN value="0"/>
+ </FORMAT>
+ <TABULATOR mmpos="63" ptpos="179" inchpos="1.6061e-19" type="0"/>
+ <TABULATOR mmpos="128" ptpos="363" inchpos="1.1009e+15" type="0"/>
+ </LAYOUT>
+ </PARAGRAPH>
+ <PARAGRAPH>
+ <TEXT>The fourth header in the first header</TEXT>
+ <HARDBRK frame="0"/>
+ <FORMATS>
+ <FORMAT id="1" pos="0" len="37">
+ <COLOR red="0" green="0" blue="0"/>
+ <FONT name="helvetica"/>
+ <SIZE value="16"/>
+ <WEIGHT value="75"/>
+ <ITALIC value="0"/>
+ <UNDERLINE value="0"/>
+ <VERTALIGN value="0"/>
+ </FORMAT>
+ </FORMATS>
+ <LAYOUT>
+ <NAME value="Head 2"/>
+ <FOLLOWING name="Standard"/>
+ <FLOW value="0"/>
+ <OHEAD pt="0" mm="0" inch="0"/>
+ <OFOOT pt="0" mm="0" inch="0"/>
+ <IFIRST pt="0" mm="0" inch="0"/>
+ <ILEFT pt="0" mm="0" inch="0"/>
+ <LINESPACE pt="0" mm="0" inch="0"/>
+ <COUNTER type="1" depth="1" bullet="-73" start="1" numberingtype="1" lefttext="" righttext="." bulletfont="symbol"/>
+ <LEFTBORDER red="255" green="255" blue="255" style="0" width="0"/>
+ <RIGHTBORDER red="255" green="255" blue="255" style="0" width="0"/>
+ <TOPBORDER red="255" green="255" blue="255" style="0" width="0"/>
+ <BOTTOMBORDER red="255" green="255" blue="255" style="0" width="0"/>
+ <FORMAT>
+ <COLOR red="0" green="0" blue="0"/>
+ <FONT name="helvetica"/>
+ <SIZE value="16"/>
+ <WEIGHT value="75"/>
+ <ITALIC value="0"/>
+ <UNDERLINE value="0"/>
+ <VERTALIGN value="0"/>
+ </FORMAT>
+ </LAYOUT>
+ </PARAGRAPH>
+ <PARAGRAPH>
+ <TEXT>Second header</TEXT>
+ <HARDBRK frame="0"/>
+ <FORMATS>
+ <FORMAT id="1" pos="0" len="13">
+ <COLOR red="0" green="0" blue="0"/>
+ <FONT name="helvetica"/>
+ <SIZE value="24"/>
+ <WEIGHT value="75"/>
+ <ITALIC value="0"/>
+ <UNDERLINE value="0"/>
+ <VERTALIGN value="0"/>
+ </FORMAT>
+ </FORMATS>
+ <LAYOUT>
+ <NAME value="Head 1"/>
+ <FOLLOWING name="Standard"/>
+ <FLOW value="0"/>
+ <OHEAD pt="0" mm="0" inch="0"/>
+ <OFOOT pt="0" mm="0" inch="0"/>
+ <IFIRST pt="0" mm="0" inch="0"/>
+ <ILEFT pt="0" mm="0" inch="0"/>
+ <LINESPACE pt="0" mm="0" inch="0"/>
+ <COUNTER type="1" depth="0" bullet="-73" start="1" numberingtype="1" lefttext="" righttext="." bulletfont="symbol"/>
+ <LEFTBORDER red="255" green="255" blue="255" style="0" width="0"/>
+ <RIGHTBORDER red="255" green="255" blue="255" style="0" width="0"/>
+ <TOPBORDER red="255" green="255" blue="255" style="0" width="0"/>
+ <BOTTOMBORDER red="255" green="255" blue="255" style="0" width="0"/>
+ <FORMAT>
+ <COLOR red="0" green="0" blue="0"/>
+ <FONT name="helvetica"/>
+ <SIZE value="24"/>
+ <WEIGHT value="75"/>
+ <ITALIC value="0"/>
+ <UNDERLINE value="0"/>
+ <VERTALIGN value="0"/>
+ </FORMAT>
+ </LAYOUT>
+ </PARAGRAPH>
+ <PARAGRAPH>
+ <TEXT>First header in the second header</TEXT>
+ <HARDBRK frame="0"/>
+ <FORMATS>
+ <FORMAT id="1" pos="0" len="33">
+ <COLOR red="0" green="0" blue="0"/>
+ <FONT name="helvetica"/>
+ <SIZE value="16"/>
+ <WEIGHT value="75"/>
+ <ITALIC value="0"/>
+ <UNDERLINE value="0"/>
+ <VERTALIGN value="0"/>
+ </FORMAT>
+ </FORMATS>
+ <LAYOUT>
+ <NAME value="Head 2"/>
+ <FOLLOWING name="Standard"/>
+ <FLOW value="0"/>
+ <OHEAD pt="0" mm="0" inch="0"/>
+ <OFOOT pt="0" mm="0" inch="0"/>
+ <IFIRST pt="0" mm="0" inch="0"/>
+ <ILEFT pt="0" mm="0" inch="0"/>
+ <LINESPACE pt="0" mm="0" inch="0"/>
+ <COUNTER type="1" depth="1" bullet="-73" start="1" numberingtype="1" lefttext="" righttext="." bulletfont="symbol"/>
+ <LEFTBORDER red="255" green="255" blue="255" style="0" width="0"/>
+ <RIGHTBORDER red="255" green="255" blue="255" style="0" width="0"/>
+ <TOPBORDER red="255" green="255" blue="255" style="0" width="0"/>
+ <BOTTOMBORDER red="255" green="255" blue="255" style="0" width="0"/>
+ <FORMAT>
+ <COLOR red="0" green="0" blue="0"/>
+ <FONT name="helvetica"/>
+ <SIZE value="16"/>
+ <WEIGHT value="75"/>
+ <ITALIC value="0"/>
+ <UNDERLINE value="0"/>
+ <VERTALIGN value="0"/>
+ </FORMAT>
+ </LAYOUT>
+ </PARAGRAPH>
+ <PARAGRAPH>
+ <TEXT>And some text to fill the chapter</TEXT>
+ <HARDBRK frame="0"/>
+ <FORMATS>
+ <FORMAT id="1" pos="0" len="33">
+ <COLOR red="0" green="0" blue="0"/>
+ <FONT name="times"/>
+ <SIZE value="12"/>
+ <WEIGHT value="50"/>
+ <ITALIC value="0"/>
+ <UNDERLINE value="0"/>
+ <VERTALIGN value="0"/>
+ </FORMAT>
+ </FORMATS>
+ <LAYOUT>
+ <NAME value="Standard"/>
+ <FOLLOWING name="Standard"/>
+ <FLOW value="0"/>
+ <OHEAD pt="0" mm="0" inch="0"/>
+ <OFOOT pt="0" mm="0" inch="0"/>
+ <IFIRST pt="0" mm="0" inch="0"/>
+ <ILEFT pt="0" mm="0" inch="0"/>
+ <LINESPACE pt="0" mm="0" inch="0"/>
+ <COUNTER type="0" depth="0" bullet="-73" start="0" numberingtype="0" lefttext="" righttext="" bulletfont="symbol"/>
+ <LEFTBORDER red="255" green="255" blue="255" style="0" width="0"/>
+ <RIGHTBORDER red="255" green="255" blue="255" style="0" width="0"/>
+ <TOPBORDER red="255" green="255" blue="255" style="0" width="0"/>
+ <BOTTOMBORDER red="255" green="255" blue="255" style="0" width="0"/>
+ <FORMAT>
+ <COLOR red="0" green="0" blue="0"/>
+ <FONT name="times"/>
+ <SIZE value="12"/>
+ <WEIGHT value="50"/>
+ <ITALIC value="0"/>
+ <UNDERLINE value="0"/>
+ <VERTALIGN value="0"/>
+ </FORMAT>
+ <TABULATOR mmpos="63" ptpos="179" inchpos="1.6061e-19" type="0"/>
+ <TABULATOR mmpos="128" ptpos="363" inchpos="1.1009e+15" type="0"/>
+ </LAYOUT>
+ </PARAGRAPH>
+ <PARAGRAPH>
+ <TEXT>First header in the scond header of the second header</TEXT>
+ <HARDBRK frame="0"/>
+ <FORMATS>
+ <FORMAT id="1" pos="0" len="53">
+ <COLOR red="0" green="0" blue="0"/>
+ <FONT name="helvetica"/>
+ <SIZE value="12"/>
+ <WEIGHT value="75"/>
+ <ITALIC value="0"/>
+ <UNDERLINE value="0"/>
+ <VERTALIGN value="0"/>
+ </FORMAT>
+ </FORMATS>
+ <LAYOUT>
+ <NAME value="Head 3"/>
+ <FOLLOWING name="Standard"/>
+ <FLOW value="0"/>
+ <OHEAD pt="0" mm="0" inch="0"/>
+ <OFOOT pt="0" mm="0" inch="0"/>
+ <IFIRST pt="0" mm="0" inch="0"/>
+ <ILEFT pt="0" mm="0" inch="0"/>
+ <LINESPACE pt="0" mm="0" inch="0"/>
+ <COUNTER type="1" depth="2" bullet="-73" start="1" numberingtype="1" lefttext="" righttext="." bulletfont="symbol"/>
+ <LEFTBORDER red="255" green="255" blue="255" style="0" width="0"/>
+ <RIGHTBORDER red="255" green="255" blue="255" style="0" width="0"/>
+ <TOPBORDER red="255" green="255" blue="255" style="0" width="0"/>
+ <BOTTOMBORDER red="255" green="255" blue="255" style="0" width="0"/>
+ <FORMAT>
+ <COLOR red="0" green="0" blue="0"/>
+ <FONT name="helvetica"/>
+ <SIZE value="12"/>
+ <WEIGHT value="75"/>
+ <ITALIC value="0"/>
+ <UNDERLINE value="0"/>
+ <VERTALIGN value="0"/>
+ </FORMAT>
+ </LAYOUT>
+ </PARAGRAPH>
+ <PARAGRAPH>
+ <TEXT>Second header in the second header</TEXT>
+ <HARDBRK frame="0"/>
+ <FORMATS>
+ <FORMAT id="1" pos="0" len="34">
+ <COLOR red="0" green="0" blue="0"/>
+ <FONT name="helvetica"/>
+ <SIZE value="16"/>
+ <WEIGHT value="75"/>
+ <ITALIC value="0"/>
+ <UNDERLINE value="0"/>
+ <VERTALIGN value="0"/>
+ </FORMAT>
+ </FORMATS>
+ <LAYOUT>
+ <NAME value="Head 2"/>
+ <FOLLOWING name="Standard"/>
+ <FLOW value="0"/>
+ <OHEAD pt="0" mm="0" inch="0"/>
+ <OFOOT pt="0" mm="0" inch="0"/>
+ <IFIRST pt="0" mm="0" inch="0"/>
+ <ILEFT pt="0" mm="0" inch="0"/>
+ <LINESPACE pt="0" mm="0" inch="0"/>
+ <COUNTER type="1" depth="1" bullet="-73" start="1" numberingtype="1" lefttext="" righttext="." bulletfont="symbol"/>
+ <LEFTBORDER red="255" green="255" blue="255" style="0" width="0"/>
+ <RIGHTBORDER red="255" green="255" blue="255" style="0" width="0"/>
+ <TOPBORDER red="255" green="255" blue="255" style="0" width="0"/>
+ <BOTTOMBORDER red="255" green="255" blue="255" style="0" width="0"/>
+ <FORMAT>
+ <COLOR red="0" green="0" blue="0"/>
+ <FONT name="helvetica"/>
+ <SIZE value="16"/>
+ <WEIGHT value="75"/>
+ <ITALIC value="0"/>
+ <UNDERLINE value="0"/>
+ <VERTALIGN value="0"/>
+ </FORMAT>
+ </LAYOUT>
+ </PARAGRAPH>
+ <PARAGRAPH>
+ <TEXT>Third header in the second header</TEXT>
+ <HARDBRK frame="0"/>
+ <FORMATS>
+ <FORMAT id="1" pos="0" len="33">
+ <COLOR red="0" green="0" blue="0"/>
+ <FONT name="helvetica"/>
+ <SIZE value="16"/>
+ <WEIGHT value="75"/>
+ <ITALIC value="0"/>
+ <UNDERLINE value="0"/>
+ <VERTALIGN value="0"/>
+ </FORMAT>
+ </FORMATS>
+ <LAYOUT>
+ <NAME value="Head 2"/>
+ <FOLLOWING name="Standard"/>
+ <FLOW value="0"/>
+ <OHEAD pt="0" mm="0" inch="0"/>
+ <OFOOT pt="0" mm="0" inch="0"/>
+ <IFIRST pt="0" mm="0" inch="0"/>
+ <ILEFT pt="0" mm="0" inch="0"/>
+ <LINESPACE pt="0" mm="0" inch="0"/>
+ <COUNTER type="1" depth="1" bullet="-73" start="1" numberingtype="1" lefttext="" righttext="." bulletfont="symbol"/>
+ <LEFTBORDER red="255" green="255" blue="255" style="0" width="0"/>
+ <RIGHTBORDER red="255" green="255" blue="255" style="0" width="0"/>
+ <TOPBORDER red="255" green="255" blue="255" style="0" width="0"/>
+ <BOTTOMBORDER red="255" green="255" blue="255" style="0" width="0"/>
+ <FORMAT>
+ <COLOR red="0" green="0" blue="0"/>
+ <FONT name="helvetica"/>
+ <SIZE value="16"/>
+ <WEIGHT value="75"/>
+ <ITALIC value="0"/>
+ <UNDERLINE value="0"/>
+ <VERTALIGN value="0"/>
+ </FORMAT>
+ </LAYOUT>
+ </PARAGRAPH>
+ <PARAGRAPH>
+ <TEXT>First header in the third header of the second header</TEXT>
+ <HARDBRK frame="0"/>
+ <FORMATS>
+ <FORMAT id="1" pos="0" len="53">
+ <COLOR red="0" green="0" blue="0"/>
+ <FONT name="helvetica"/>
+ <SIZE value="12"/>
+ <WEIGHT value="75"/>
+ <ITALIC value="0"/>
+ <UNDERLINE value="0"/>
+ <VERTALIGN value="0"/>
+ </FORMAT>
+ </FORMATS>
+ <LAYOUT>
+ <NAME value="Head 3"/>
+ <FOLLOWING name="Standard"/>
+ <FLOW value="0"/>
+ <OHEAD pt="0" mm="0" inch="0"/>
+ <OFOOT pt="0" mm="0" inch="0"/>
+ <IFIRST pt="0" mm="0" inch="0"/>
+ <ILEFT pt="0" mm="0" inch="0"/>
+ <LINESPACE pt="0" mm="0" inch="0"/>
+ <COUNTER type="1" depth="2" bullet="-73" start="1" numberingtype="1" lefttext="" righttext="." bulletfont="symbol"/>
+ <LEFTBORDER red="255" green="255" blue="255" style="0" width="0"/>
+ <RIGHTBORDER red="255" green="255" blue="255" style="0" width="0"/>
+ <TOPBORDER red="255" green="255" blue="255" style="0" width="0"/>
+ <BOTTOMBORDER red="255" green="255" blue="255" style="0" width="0"/>
+ <FORMAT>
+ <COLOR red="0" green="0" blue="0"/>
+ <FONT name="helvetica"/>
+ <SIZE value="12"/>
+ <WEIGHT value="75"/>
+ <ITALIC value="0"/>
+ <UNDERLINE value="0"/>
+ <VERTALIGN value="0"/>
+ </FORMAT>
+ </LAYOUT>
+ </PARAGRAPH>
+ <PARAGRAPH>
+ <TEXT>And let's write some words in this paragraph</TEXT>
+ <HARDBRK frame="0"/>
+ <FORMATS>
+ <FORMAT id="1" pos="0" len="44">
+ <COLOR red="0" green="0" blue="0"/>
+ <FONT name="times"/>
+ <SIZE value="12"/>
+ <WEIGHT value="50"/>
+ <ITALIC value="0"/>
+ <UNDERLINE value="0"/>
+ <VERTALIGN value="0"/>
+ </FORMAT>
+ </FORMATS>
+ <LAYOUT>
+ <NAME value="Standard"/>
+ <FOLLOWING name="Standard"/>
+ <FLOW value="0"/>
+ <OHEAD pt="0" mm="0" inch="0"/>
+ <OFOOT pt="0" mm="0" inch="0"/>
+ <IFIRST pt="0" mm="0" inch="0"/>
+ <ILEFT pt="0" mm="0" inch="0"/>
+ <LINESPACE pt="0" mm="0" inch="0"/>
+ <COUNTER type="0" depth="0" bullet="-73" start="0" numberingtype="0" lefttext="" righttext="" bulletfont="symbol"/>
+ <LEFTBORDER red="255" green="255" blue="255" style="0" width="0"/>
+ <RIGHTBORDER red="255" green="255" blue="255" style="0" width="0"/>
+ <TOPBORDER red="255" green="255" blue="255" style="0" width="0"/>
+ <BOTTOMBORDER red="255" green="255" blue="255" style="0" width="0"/>
+ <FORMAT>
+ <COLOR red="0" green="0" blue="0"/>
+ <FONT name="times"/>
+ <SIZE value="12"/>
+ <WEIGHT value="50"/>
+ <ITALIC value="0"/>
+ <UNDERLINE value="0"/>
+ <VERTALIGN value="0"/>
+ </FORMAT>
+ <TABULATOR mmpos="63" ptpos="179" inchpos="1.6061e-19" type="0"/>
+ <TABULATOR mmpos="128" ptpos="363" inchpos="1.1009e+15" type="0"/>
+ </LAYOUT>
+ </PARAGRAPH>
+ <PARAGRAPH>
+ <TEXT>Second header in the third header of the second header</TEXT>
+ <HARDBRK frame="0"/>
+ <FORMATS>
+ <FORMAT id="1" pos="0" len="54">
+ <COLOR red="0" green="0" blue="0"/>
+ <FONT name="helvetica"/>
+ <SIZE value="12"/>
+ <WEIGHT value="75"/>
+ <ITALIC value="0"/>
+ <UNDERLINE value="0"/>
+ <VERTALIGN value="0"/>
+ </FORMAT>
+ </FORMATS>
+ <LAYOUT>
+ <NAME value="Head 3"/>
+ <FOLLOWING name="Standard"/>
+ <FLOW value="0"/>
+ <OHEAD pt="0" mm="0" inch="0"/>
+ <OFOOT pt="0" mm="0" inch="0"/>
+ <IFIRST pt="0" mm="0" inch="0"/>
+ <ILEFT pt="0" mm="0" inch="0"/>
+ <LINESPACE pt="0" mm="0" inch="0"/>
+ <COUNTER type="1" depth="2" bullet="-73" start="1" numberingtype="1" lefttext="" righttext="." bulletfont="symbol"/>
+ <LEFTBORDER red="255" green="255" blue="255" style="0" width="0"/>
+ <RIGHTBORDER red="255" green="255" blue="255" style="0" width="0"/>
+ <TOPBORDER red="255" green="255" blue="255" style="0" width="0"/>
+ <BOTTOMBORDER red="255" green="255" blue="255" style="0" width="0"/>
+ <FORMAT>
+ <COLOR red="0" green="0" blue="0"/>
+ <FONT name="helvetica"/>
+ <SIZE value="12"/>
+ <WEIGHT value="75"/>
+ <ITALIC value="0"/>
+ <UNDERLINE value="0"/>
+ <VERTALIGN value="0"/>
+ </FORMAT>
+ </LAYOUT>
+ </PARAGRAPH>
+ <PARAGRAPH>
+ <TEXT>Third header</TEXT>
+ <HARDBRK frame="0"/>
+ <FORMATS>
+ <FORMAT id="1" pos="0" len="12">
+ <COLOR red="0" green="0" blue="0"/>
+ <FONT name="helvetica"/>
+ <SIZE value="24"/>
+ <WEIGHT value="75"/>
+ <ITALIC value="0"/>
+ <UNDERLINE value="0"/>
+ <VERTALIGN value="0"/>
+ </FORMAT>
+ </FORMATS>
+ <LAYOUT>
+ <NAME value="Head 1"/>
+ <FOLLOWING name="Standard"/>
+ <FLOW value="0"/>
+ <OHEAD pt="0" mm="0" inch="0"/>
+ <OFOOT pt="0" mm="0" inch="0"/>
+ <IFIRST pt="0" mm="0" inch="0"/>
+ <ILEFT pt="0" mm="0" inch="0"/>
+ <LINESPACE pt="0" mm="0" inch="0"/>
+ <COUNTER type="1" depth="0" bullet="-73" start="1" numberingtype="1" lefttext="" righttext="." bulletfont="symbol"/>
+ <LEFTBORDER red="255" green="255" blue="255" style="0" width="0"/>
+ <RIGHTBORDER red="255" green="255" blue="255" style="0" width="0"/>
+ <TOPBORDER red="255" green="255" blue="255" style="0" width="0"/>
+ <BOTTOMBORDER red="255" green="255" blue="255" style="0" width="0"/>
+ <FORMAT>
+ <COLOR red="0" green="0" blue="0"/>
+ <FONT name="helvetica"/>
+ <SIZE value="24"/>
+ <WEIGHT value="75"/>
+ <ITALIC value="0"/>
+ <UNDERLINE value="0"/>
+ <VERTALIGN value="0"/>
+ </FORMAT>
+ </LAYOUT>
+ </PARAGRAPH>
+ <PARAGRAPH>
+ <TEXT>First header in third header</TEXT>
+ <HARDBRK frame="0"/>
+ <FORMATS>
+ <FORMAT id="1" pos="0" len="28">
+ <COLOR red="0" green="0" blue="0"/>
+ <FONT name="helvetica"/>
+ <SIZE value="16"/>
+ <WEIGHT value="75"/>
+ <ITALIC value="0"/>
+ <UNDERLINE value="0"/>
+ <VERTALIGN value="0"/>
+ </FORMAT>
+ </FORMATS>
+ <LAYOUT>
+ <NAME value="Head 2"/>
+ <FOLLOWING name="Standard"/>
+ <FLOW value="0"/>
+ <OHEAD pt="0" mm="0" inch="0"/>
+ <OFOOT pt="0" mm="0" inch="0"/>
+ <IFIRST pt="0" mm="0" inch="0"/>
+ <ILEFT pt="0" mm="0" inch="0"/>
+ <LINESPACE pt="0" mm="0" inch="0"/>
+ <COUNTER type="1" depth="1" bullet="-73" start="1" numberingtype="1" lefttext="" righttext="." bulletfont="symbol"/>
+ <LEFTBORDER red="255" green="255" blue="255" style="0" width="0"/>
+ <RIGHTBORDER red="255" green="255" blue="255" style="0" width="0"/>
+ <TOPBORDER red="255" green="255" blue="255" style="0" width="0"/>
+ <BOTTOMBORDER red="255" green="255" blue="255" style="0" width="0"/>
+ <FORMAT>
+ <COLOR red="0" green="0" blue="0"/>
+ <FONT name="helvetica"/>
+ <SIZE value="16"/>
+ <WEIGHT value="75"/>
+ <ITALIC value="0"/>
+ <UNDERLINE value="0"/>
+ <VERTALIGN value="0"/>
+ </FORMAT>
+ </LAYOUT>
+ </PARAGRAPH>
+ <PARAGRAPH>
+ <TEXT>Second header in third header</TEXT>
+ <HARDBRK frame="0"/>
+ <FORMATS>
+ <FORMAT id="1" pos="0" len="29">
+ <COLOR red="0" green="0" blue="0"/>
+ <FONT name="helvetica"/>
+ <SIZE value="16"/>
+ <WEIGHT value="75"/>
+ <ITALIC value="0"/>
+ <UNDERLINE value="0"/>
+ <VERTALIGN value="0"/>
+ </FORMAT>
+ </FORMATS>
+ <LAYOUT>
+ <NAME value="Head 2"/>
+ <FOLLOWING name="Standard"/>
+ <FLOW value="0"/>
+ <OHEAD pt="0" mm="0" inch="0"/>
+ <OFOOT pt="0" mm="0" inch="0"/>
+ <IFIRST pt="0" mm="0" inch="0"/>
+ <ILEFT pt="0" mm="0" inch="0"/>
+ <LINESPACE pt="0" mm="0" inch="0"/>
+ <COUNTER type="1" depth="1" bullet="-73" start="1" numberingtype="1" lefttext="" righttext="." bulletfont="symbol"/>
+ <LEFTBORDER red="255" green="255" blue="255" style="0" width="0"/>
+ <RIGHTBORDER red="255" green="255" blue="255" style="0" width="0"/>
+ <TOPBORDER red="255" green="255" blue="255" style="0" width="0"/>
+ <BOTTOMBORDER red="255" green="255" blue="255" style="0" width="0"/>
+ <FORMAT>
+ <COLOR red="0" green="0" blue="0"/>
+ <FONT name="helvetica"/>
+ <SIZE value="16"/>
+ <WEIGHT value="75"/>
+ <ITALIC value="0"/>
+ <UNDERLINE value="0"/>
+ <VERTALIGN value="0"/>
+ </FORMAT>
+ </LAYOUT>
+ </PARAGRAPH>
+ <PARAGRAPH>
+ <TEXT>Third header in third header</TEXT>
+ <HARDBRK frame="0"/>
+ <FORMATS>
+ <FORMAT id="1" pos="0" len="28">
+ <COLOR red="0" green="0" blue="0"/>
+ <FONT name="helvetica"/>
+ <SIZE value="16"/>
+ <WEIGHT value="75"/>
+ <ITALIC value="0"/>
+ <UNDERLINE value="0"/>
+ <VERTALIGN value="0"/>
+ </FORMAT>
+ </FORMATS>
+ <LAYOUT>
+ <NAME value="Head 2"/>
+ <FOLLOWING name="Standard"/>
+ <FLOW value="0"/>
+ <OHEAD pt="0" mm="0" inch="0"/>
+ <OFOOT pt="0" mm="0" inch="0"/>
+ <IFIRST pt="0" mm="0" inch="0"/>
+ <ILEFT pt="0" mm="0" inch="0"/>
+ <LINESPACE pt="0" mm="0" inch="0"/>
+ <COUNTER type="1" depth="1" bullet="-73" start="1" numberingtype="1" lefttext="" righttext="." bulletfont="symbol"/>
+ <LEFTBORDER red="255" green="255" blue="255" style="0" width="0"/>
+ <RIGHTBORDER red="255" green="255" blue="255" style="0" width="0"/>
+ <TOPBORDER red="255" green="255" blue="255" style="0" width="0"/>
+ <BOTTOMBORDER red="255" green="255" blue="255" style="0" width="0"/>
+ <FORMAT>
+ <COLOR red="0" green="0" blue="0"/>
+ <FONT name="helvetica"/>
+ <SIZE value="16"/>
+ <WEIGHT value="75"/>
+ <ITALIC value="0"/>
+ <UNDERLINE value="0"/>
+ <VERTALIGN value="0"/>
+ </FORMAT>
+ </LAYOUT>
+ </PARAGRAPH>
+ <PARAGRAPH>
+ <TEXT>Fourth header in third header</TEXT>
+ <HARDBRK frame="0"/>
+ <FORMATS>
+ <FORMAT id="1" pos="0" len="29">
+ <COLOR red="0" green="0" blue="0"/>
+ <FONT name="helvetica"/>
+ <SIZE value="16"/>
+ <WEIGHT value="75"/>
+ <ITALIC value="0"/>
+ <UNDERLINE value="0"/>
+ <VERTALIGN value="0"/>
+ </FORMAT>
+ </FORMATS>
+ <LAYOUT>
+ <NAME value="Head 2"/>
+ <FOLLOWING name="Standard"/>
+ <FLOW value="0"/>
+ <OHEAD pt="0" mm="0" inch="0"/>
+ <OFOOT pt="0" mm="0" inch="0"/>
+ <IFIRST pt="0" mm="0" inch="0"/>
+ <ILEFT pt="0" mm="0" inch="0"/>
+ <LINESPACE pt="0" mm="0" inch="0"/>
+ <COUNTER type="1" depth="1" bullet="-73" start="1" numberingtype="1" lefttext="" righttext="." bulletfont="symbol"/>
+ <LEFTBORDER red="255" green="255" blue="255" style="0" width="0"/>
+ <RIGHTBORDER red="255" green="255" blue="255" style="0" width="0"/>
+ <TOPBORDER red="255" green="255" blue="255" style="0" width="0"/>
+ <BOTTOMBORDER red="255" green="255" blue="255" style="0" width="0"/>
+ <FORMAT>
+ <COLOR red="0" green="0" blue="0"/>
+ <FONT name="helvetica"/>
+ <SIZE value="16"/>
+ <WEIGHT value="75"/>
+ <ITALIC value="0"/>
+ <UNDERLINE value="0"/>
+ <VERTALIGN value="0"/>
+ </FORMAT>
+ </LAYOUT>
+ </PARAGRAPH>
+ <PARAGRAPH>
+ <TEXT>First header in fourth header of third header</TEXT>
+ <HARDBRK frame="0"/>
+ <FORMATS>
+ <FORMAT id="1" pos="0" len="45">
+ <COLOR red="0" green="0" blue="0"/>
+ <FONT name="helvetica"/>
+ <SIZE value="12"/>
+ <WEIGHT value="75"/>
+ <ITALIC value="0"/>
+ <UNDERLINE value="0"/>
+ <VERTALIGN value="0"/>
+ </FORMAT>
+ </FORMATS>
+ <LAYOUT>
+ <NAME value="Head 3"/>
+ <FOLLOWING name="Standard"/>
+ <FLOW value="0"/>
+ <OHEAD pt="0" mm="0" inch="0"/>
+ <OFOOT pt="0" mm="0" inch="0"/>
+ <IFIRST pt="0" mm="0" inch="0"/>
+ <ILEFT pt="0" mm="0" inch="0"/>
+ <LINESPACE pt="0" mm="0" inch="0"/>
+ <COUNTER type="1" depth="2" bullet="-73" start="1" numberingtype="1" lefttext="" righttext="." bulletfont="symbol"/>
+ <LEFTBORDER red="255" green="255" blue="255" style="0" width="0"/>
+ <RIGHTBORDER red="255" green="255" blue="255" style="0" width="0"/>
+ <TOPBORDER red="255" green="255" blue="255" style="0" width="0"/>
+ <BOTTOMBORDER red="255" green="255" blue="255" style="0" width="0"/>
+ <FORMAT>
+ <COLOR red="0" green="0" blue="0"/>
+ <FONT name="helvetica"/>
+ <SIZE value="12"/>
+ <WEIGHT value="75"/>
+ <ITALIC value="0"/>
+ <UNDERLINE value="0"/>
+ <VERTALIGN value="0"/>
+ </FORMAT>
+ </LAYOUT>
+ </PARAGRAPH>
+ <PARAGRAPH>
+ <TEXT>And the last header of this document!</TEXT>
+ <HARDBRK frame="0"/>
+ <FORMATS>
+ <FORMAT id="1" pos="0" len="37">
+ <COLOR red="0" green="0" blue="0"/>
+ <FONT name="helvetica"/>
+ <SIZE value="12"/>
+ <WEIGHT value="75"/>
+ <ITALIC value="0"/>
+ <UNDERLINE value="0"/>
+ <VERTALIGN value="0"/>
+ </FORMAT>
+ </FORMATS>
+ <LAYOUT>
+ <NAME value="Head 3"/>
+ <FOLLOWING name="Standard"/>
+ <FLOW value="0"/>
+ <OHEAD pt="0" mm="0" inch="0"/>
+ <OFOOT pt="0" mm="0" inch="0"/>
+ <IFIRST pt="0" mm="0" inch="0"/>
+ <ILEFT pt="0" mm="0" inch="0"/>
+ <LINESPACE pt="0" mm="0" inch="0"/>
+ <COUNTER type="1" depth="2" bullet="-73" start="1" numberingtype="1" lefttext="" righttext="." bulletfont="symbol"/>
+ <LEFTBORDER red="255" green="255" blue="255" style="0" width="0"/>
+ <RIGHTBORDER red="255" green="255" blue="255" style="0" width="0"/>
+ <TOPBORDER red="255" green="255" blue="255" style="0" width="0"/>
+ <BOTTOMBORDER red="255" green="255" blue="255" style="0" width="0"/>
+ <FORMAT>
+ <COLOR red="0" green="0" blue="0"/>
+ <FONT name="helvetica"/>
+ <SIZE value="12"/>
+ <WEIGHT value="75"/>
+ <ITALIC value="0"/>
+ <UNDERLINE value="0"/>
+ <VERTALIGN value="0"/>
+ </FORMAT>
+ </LAYOUT>
+ </PARAGRAPH>
+ </FRAMESET>
+ <FRAMESET frameType="1" autoCreateNewFrame="0" frameInfo="1">
+ <FRAME left="28" top="42" right="566" bottom="61" runaround="0" runaGapPT="2" runaGapMM="1" runaGapINCH="0.0393701" lWidth="1" lRed="255" lGreen="255" lBlue="255" lStyle="0" rWidth="1" rRed="255" rGreen="255" rBlue="255" rStyle="0" tWidth="1" tRed="255" tGreen="255" tBlue="255" tStyle="0" bWidth="1" bRed="255" bGreen="255" bBlue="255" bStyle="0" bkRed="255" bkGreen="255" bkBlue="255" bleftpt="0" bleftmm="0" bleftinch="0" brightpt="0" brightmm="0" brightinch="0" btoppt="0" btopmm="0" btopinch="0" bbottompt="0" bbottommm="0" bbottominch="0"/>
+ <PARAGRAPH>
+ <TEXT></TEXT>
+ <HARDBRK frame="0"/>
+ <FORMATS>
+ </FORMATS>
+ <LAYOUT>
+ <NAME value="Standard"/>
+ <FOLLOWING name="Standard"/>
+ <FLOW value="0"/>
+ <OHEAD pt="0" mm="0" inch="0"/>
+ <OFOOT pt="0" mm="0" inch="0"/>
+ <IFIRST pt="0" mm="0" inch="0"/>
+ <ILEFT pt="0" mm="0" inch="0"/>
+ <LINESPACE pt="0" mm="0" inch="0"/>
+ <COUNTER type="0" depth="0" bullet="-73" start="0" numberingtype="0" lefttext="" righttext="" bulletfont="symbol"/>
+ <LEFTBORDER red="255" green="255" blue="255" style="0" width="0"/>
+ <RIGHTBORDER red="255" green="255" blue="255" style="0" width="0"/>
+ <TOPBORDER red="255" green="255" blue="255" style="0" width="0"/>
+ <BOTTOMBORDER red="255" green="255" blue="255" style="0" width="0"/>
+ <FORMAT>
+ <COLOR red="0" green="0" blue="0"/>
+ <FONT name="times"/>
+ <SIZE value="12"/>
+ <WEIGHT value="50"/>
+ <ITALIC value="0"/>
+ <UNDERLINE value="0"/>
+ <VERTALIGN value="0"/>
+ </FORMAT>
+ <TABULATOR mmpos="63" ptpos="179" inchpos="1.6061e-19" type="0"/>
+ <TABULATOR mmpos="128" ptpos="363" inchpos="1.1009e+15" type="0"/>
+ </LAYOUT>
+ </PARAGRAPH>
+ </FRAMESET>
+ <FRAMESET frameType="1" autoCreateNewFrame="0" frameInfo="3">
+ <FRAME left="28" top="42" right="566" bottom="61" runaround="0" runaGapPT="2" runaGapMM="1" runaGapINCH="0.0393701" lWidth="1" lRed="255" lGreen="255" lBlue="255" lStyle="0" rWidth="1" rRed="255" rGreen="255" rBlue="255" rStyle="0" tWidth="1" tRed="255" tGreen="255" tBlue="255" tStyle="0" bWidth="1" bRed="255" bGreen="255" bBlue="255" bStyle="0" bkRed="255" bkGreen="255" bkBlue="255" bleftpt="0" bleftmm="0" bleftinch="0" brightpt="0" brightmm="0" brightinch="0" btoppt="0" btopmm="0" btopinch="0" bbottompt="0" bbottommm="0" bbottominch="0"/>
+ <PARAGRAPH>
+ <TEXT></TEXT>
+ <HARDBRK frame="0"/>
+ <FORMATS>
+ </FORMATS>
+ <LAYOUT>
+ <NAME value="Standard"/>
+ <FOLLOWING name="Standard"/>
+ <FLOW value="0"/>
+ <OHEAD pt="0" mm="0" inch="0"/>
+ <OFOOT pt="0" mm="0" inch="0"/>
+ <IFIRST pt="0" mm="0" inch="0"/>
+ <ILEFT pt="0" mm="0" inch="0"/>
+ <LINESPACE pt="0" mm="0" inch="0"/>
+ <COUNTER type="0" depth="0" bullet="-73" start="0" numberingtype="0" lefttext="" righttext="" bulletfont="symbol"/>
+ <LEFTBORDER red="255" green="255" blue="255" style="0" width="0"/>
+ <RIGHTBORDER red="255" green="255" blue="255" style="0" width="0"/>
+ <TOPBORDER red="255" green="255" blue="255" style="0" width="0"/>
+ <BOTTOMBORDER red="255" green="255" blue="255" style="0" width="0"/>
+ <FORMAT>
+ <COLOR red="0" green="0" blue="0"/>
+ <FONT name="times"/>
+ <SIZE value="12"/>
+ <WEIGHT value="50"/>
+ <ITALIC value="0"/>
+ <UNDERLINE value="0"/>
+ <VERTALIGN value="0"/>
+ </FORMAT>
+ <TABULATOR mmpos="63" ptpos="179" inchpos="1.6061e-19" type="0"/>
+ <TABULATOR mmpos="128" ptpos="363" inchpos="1.1009e+15" type="0"/>
+ </LAYOUT>
+ </PARAGRAPH>
+ </FRAMESET>
+ <FRAMESET frameType="1" autoCreateNewFrame="0" frameInfo="2">
+ <FRAME left="28" top="42" right="566" bottom="61" runaround="0" runaGapPT="2" runaGapMM="1" runaGapINCH="0.0393701" lWidth="1" lRed="255" lGreen="255" lBlue="255" lStyle="0" rWidth="1" rRed="255" rGreen="255" rBlue="255" rStyle="0" tWidth="1" tRed="255" tGreen="255" tBlue="255" tStyle="0" bWidth="1" bRed="255" bGreen="255" bBlue="255" bStyle="0" bkRed="255" bkGreen="255" bkBlue="255" bleftpt="0" bleftmm="0" bleftinch="0" brightpt="0" brightmm="0" brightinch="0" btoppt="0" btopmm="0" btopinch="0" bbottompt="0" bbottommm="0" bbottominch="0"/>
+ <PARAGRAPH>
+ <TEXT></TEXT>
+ <HARDBRK frame="0"/>
+ <FORMATS>
+ </FORMATS>
+ <LAYOUT>
+ <NAME value="Standard"/>
+ <FOLLOWING name="Standard"/>
+ <FLOW value="0"/>
+ <OHEAD pt="0" mm="0" inch="0"/>
+ <OFOOT pt="0" mm="0" inch="0"/>
+ <IFIRST pt="0" mm="0" inch="0"/>
+ <ILEFT pt="0" mm="0" inch="0"/>
+ <LINESPACE pt="0" mm="0" inch="0"/>
+ <COUNTER type="0" depth="0" bullet="-73" start="0" numberingtype="0" lefttext="" righttext="" bulletfont="symbol"/>
+ <LEFTBORDER red="255" green="255" blue="255" style="0" width="0"/>
+ <RIGHTBORDER red="255" green="255" blue="255" style="0" width="0"/>
+ <TOPBORDER red="255" green="255" blue="255" style="0" width="0"/>
+ <BOTTOMBORDER red="255" green="255" blue="255" style="0" width="0"/>
+ <FORMAT>
+ <COLOR red="0" green="0" blue="0"/>
+ <FONT name="times"/>
+ <SIZE value="12"/>
+ <WEIGHT value="50"/>
+ <ITALIC value="0"/>
+ <UNDERLINE value="0"/>
+ <VERTALIGN value="0"/>
+ </FORMAT>
+ <TABULATOR mmpos="63" ptpos="179" inchpos="1.6061e-19" type="0"/>
+ <TABULATOR mmpos="128" ptpos="363" inchpos="1.1009e+15" type="0"/>
+ </LAYOUT>
+ </PARAGRAPH>
+ </FRAMESET>
+ <FRAMESET frameType="1" autoCreateNewFrame="0" frameInfo="4">
+ <FRAME left="28" top="779" right="566" bottom="798" runaround="0" runaGapPT="2" runaGapMM="1" runaGapINCH="0.0393701" lWidth="1" lRed="255" lGreen="255" lBlue="255" lStyle="0" rWidth="1" rRed="255" rGreen="255" rBlue="255" rStyle="0" tWidth="1" tRed="255" tGreen="255" tBlue="255" tStyle="0" bWidth="1" bRed="255" bGreen="255" bBlue="255" bStyle="0" bkRed="255" bkGreen="255" bkBlue="255" bleftpt="0" bleftmm="0" bleftinch="0" brightpt="0" brightmm="0" brightinch="0" btoppt="0" btopmm="0" btopinch="0" bbottompt="0" bbottommm="0" bbottominch="0"/>
+ <PARAGRAPH>
+ <TEXT></TEXT>
+ <HARDBRK frame="0"/>
+ <FORMATS>
+ </FORMATS>
+ <LAYOUT>
+ <NAME value="Standard"/>
+ <FOLLOWING name="Standard"/>
+ <FLOW value="0"/>
+ <OHEAD pt="0" mm="0" inch="0"/>
+ <OFOOT pt="0" mm="0" inch="0"/>
+ <IFIRST pt="0" mm="0" inch="0"/>
+ <ILEFT pt="0" mm="0" inch="0"/>
+ <LINESPACE pt="0" mm="0" inch="0"/>
+ <COUNTER type="0" depth="0" bullet="-73" start="0" numberingtype="0" lefttext="" righttext="" bulletfont="symbol"/>
+ <LEFTBORDER red="255" green="255" blue="255" style="0" width="0"/>
+ <RIGHTBORDER red="255" green="255" blue="255" style="0" width="0"/>
+ <TOPBORDER red="255" green="255" blue="255" style="0" width="0"/>
+ <BOTTOMBORDER red="255" green="255" blue="255" style="0" width="0"/>
+ <FORMAT>
+ <COLOR red="0" green="0" blue="0"/>
+ <FONT name="times"/>
+ <SIZE value="12"/>
+ <WEIGHT value="50"/>
+ <ITALIC value="0"/>
+ <UNDERLINE value="0"/>
+ <VERTALIGN value="0"/>
+ </FORMAT>
+ <TABULATOR mmpos="63" ptpos="179" inchpos="1.6061e-19" type="0"/>
+ <TABULATOR mmpos="128" ptpos="363" inchpos="1.1009e+15" type="0"/>
+ </LAYOUT>
+ </PARAGRAPH>
+ </FRAMESET>
+ <FRAMESET frameType="1" autoCreateNewFrame="0" frameInfo="6">
+ <FRAME left="28" top="779" right="566" bottom="798" runaround="0" runaGapPT="2" runaGapMM="1" runaGapINCH="0.0393701" lWidth="1" lRed="255" lGreen="255" lBlue="255" lStyle="0" rWidth="1" rRed="255" rGreen="255" rBlue="255" rStyle="0" tWidth="1" tRed="255" tGreen="255" tBlue="255" tStyle="0" bWidth="1" bRed="255" bGreen="255" bBlue="255" bStyle="0" bkRed="255" bkGreen="255" bkBlue="255" bleftpt="0" bleftmm="0" bleftinch="0" brightpt="0" brightmm="0" brightinch="0" btoppt="0" btopmm="0" btopinch="0" bbottompt="0" bbottommm="0" bbottominch="0"/>
+ <PARAGRAPH>
+ <TEXT></TEXT>
+ <HARDBRK frame="0"/>
+ <FORMATS>
+ </FORMATS>
+ <LAYOUT>
+ <NAME value="Standard"/>
+ <FOLLOWING name="Standard"/>
+ <FLOW value="0"/>
+ <OHEAD pt="0" mm="0" inch="0"/>
+ <OFOOT pt="0" mm="0" inch="0"/>
+ <IFIRST pt="0" mm="0" inch="0"/>
+ <ILEFT pt="0" mm="0" inch="0"/>
+ <LINESPACE pt="0" mm="0" inch="0"/>
+ <COUNTER type="0" depth="0" bullet="-73" start="0" numberingtype="0" lefttext="" righttext="" bulletfont="symbol"/>
+ <LEFTBORDER red="255" green="255" blue="255" style="0" width="0"/>
+ <RIGHTBORDER red="255" green="255" blue="255" style="0" width="0"/>
+ <TOPBORDER red="255" green="255" blue="255" style="0" width="0"/>
+ <BOTTOMBORDER red="255" green="255" blue="255" style="0" width="0"/>
+ <FORMAT>
+ <COLOR red="0" green="0" blue="0"/>
+ <FONT name="times"/>
+ <SIZE value="12"/>
+ <WEIGHT value="50"/>
+ <ITALIC value="0"/>
+ <UNDERLINE value="0"/>
+ <VERTALIGN value="0"/>
+ </FORMAT>
+ <TABULATOR mmpos="63" ptpos="179" inchpos="1.6061e-19" type="0"/>
+ <TABULATOR mmpos="128" ptpos="363" inchpos="1.1009e+15" type="0"/>
+ </LAYOUT>
+ </PARAGRAPH>
+ </FRAMESET>
+ <FRAMESET frameType="1" autoCreateNewFrame="0" frameInfo="5">
+ <FRAME left="28" top="779" right="566" bottom="798" runaround="0" runaGapPT="2" runaGapMM="1" runaGapINCH="0.0393701" lWidth="1" lRed="255" lGreen="255" lBlue="255" lStyle="0" rWidth="1" rRed="255" rGreen="255" rBlue="255" rStyle="0" tWidth="1" tRed="255" tGreen="255" tBlue="255" tStyle="0" bWidth="1" bRed="255" bGreen="255" bBlue="255" bStyle="0" bkRed="255" bkGreen="255" bkBlue="255" bleftpt="0" bleftmm="0" bleftinch="0" brightpt="0" brightmm="0" brightinch="0" btoppt="0" btopmm="0" btopinch="0" bbottompt="0" bbottommm="0" bbottominch="0"/>
+ <PARAGRAPH>
+ <TEXT></TEXT>
+ <HARDBRK frame="0"/>
+ <FORMATS>
+ </FORMATS>
+ <LAYOUT>
+ <NAME value="Standard"/>
+ <FOLLOWING name="Standard"/>
+ <FLOW value="0"/>
+ <OHEAD pt="0" mm="0" inch="0"/>
+ <OFOOT pt="0" mm="0" inch="0"/>
+ <IFIRST pt="0" mm="0" inch="0"/>
+ <ILEFT pt="0" mm="0" inch="0"/>
+ <LINESPACE pt="0" mm="0" inch="0"/>
+ <COUNTER type="0" depth="0" bullet="-73" start="0" numberingtype="0" lefttext="" righttext="" bulletfont="symbol"/>
+ <LEFTBORDER red="255" green="255" blue="255" style="0" width="0"/>
+ <RIGHTBORDER red="255" green="255" blue="255" style="0" width="0"/>
+ <TOPBORDER red="255" green="255" blue="255" style="0" width="0"/>
+ <BOTTOMBORDER red="255" green="255" blue="255" style="0" width="0"/>
+ <FORMAT>
+ <COLOR red="0" green="0" blue="0"/>
+ <FONT name="times"/>
+ <SIZE value="12"/>
+ <WEIGHT value="50"/>
+ <ITALIC value="0"/>
+ <UNDERLINE value="0"/>
+ <VERTALIGN value="0"/>
+ </FORMAT>
+ <TABULATOR mmpos="63" ptpos="179" inchpos="1.6061e-19" type="0"/>
+ <TABULATOR mmpos="128" ptpos="363" inchpos="1.1009e+15" type="0"/>
+ </LAYOUT>
+ </PARAGRAPH>
+ </FRAMESET>
+ </FRAMESETS>
+ <STYLES>
+ <STYLE>
+ <NAME value="Standard"/>
+ <FOLLOWING name="Standard"/>
+ <FLOW value="0"/>
+ <OHEAD pt="0" mm="0" inch="0"/>
+ <OFOOT pt="0" mm="0" inch="0"/>
+ <IFIRST pt="0" mm="0" inch="0"/>
+ <ILEFT pt="0" mm="0" inch="0"/>
+ <LINESPACE pt="0" mm="0" inch="0"/>
+ <COUNTER type="0" depth="0" bullet="-73" start="0" numberingtype="0" lefttext="" righttext="" bulletfont="symbol"/>
+ <LEFTBORDER red="255" green="255" blue="255" style="0" width="0"/>
+ <RIGHTBORDER red="255" green="255" blue="255" style="0" width="0"/>
+ <TOPBORDER red="255" green="255" blue="255" style="0" width="0"/>
+ <BOTTOMBORDER red="255" green="255" blue="255" style="0" width="0"/>
+ <FORMAT>
+ <COLOR red="0" green="0" blue="0"/>
+ <FONT name="times"/>
+ <SIZE value="12"/>
+ <WEIGHT value="50"/>
+ <ITALIC value="0"/>
+ <UNDERLINE value="0"/>
+ <VERTALIGN value="0"/>
+ </FORMAT>
+ <TABULATOR mmpos="63" ptpos="179" inchpos="1.6061e-19" type="0"/>
+ <TABULATOR mmpos="128" ptpos="363" inchpos="1.1009e+15" type="0"/>
+ </STYLE>
+ <STYLE>
+ <NAME value="Head 1"/>
+ <FOLLOWING name="Standard"/>
+ <FLOW value="0"/>
+ <OHEAD pt="0" mm="0" inch="0"/>
+ <OFOOT pt="0" mm="0" inch="0"/>
+ <IFIRST pt="0" mm="0" inch="0"/>
+ <ILEFT pt="0" mm="0" inch="0"/>
+ <LINESPACE pt="0" mm="0" inch="0"/>
+ <COUNTER type="1" depth="0" bullet="-73" start="1" numberingtype="1" lefttext="" righttext="." bulletfont="symbol"/>
+ <LEFTBORDER red="255" green="255" blue="255" style="0" width="0"/>
+ <RIGHTBORDER red="255" green="255" blue="255" style="0" width="0"/>
+ <TOPBORDER red="255" green="255" blue="255" style="0" width="0"/>
+ <BOTTOMBORDER red="255" green="255" blue="255" style="0" width="0"/>
+ <FORMAT>
+ <COLOR red="0" green="0" blue="0"/>
+ <FONT name="helvetica"/>
+ <SIZE value="24"/>
+ <WEIGHT value="75"/>
+ <ITALIC value="0"/>
+ <UNDERLINE value="0"/>
+ <VERTALIGN value="0"/>
+ </FORMAT>
+ </STYLE>
+ <STYLE>
+ <NAME value="Head 2"/>
+ <FOLLOWING name="Standard"/>
+ <FLOW value="0"/>
+ <OHEAD pt="0" mm="0" inch="0"/>
+ <OFOOT pt="0" mm="0" inch="0"/>
+ <IFIRST pt="0" mm="0" inch="0"/>
+ <ILEFT pt="0" mm="0" inch="0"/>
+ <LINESPACE pt="0" mm="0" inch="0"/>
+ <COUNTER type="1" depth="1" bullet="-73" start="1" numberingtype="1" lefttext="" righttext="." bulletfont="symbol"/>
+ <LEFTBORDER red="255" green="255" blue="255" style="0" width="0"/>
+ <RIGHTBORDER red="255" green="255" blue="255" style="0" width="0"/>
+ <TOPBORDER red="255" green="255" blue="255" style="0" width="0"/>
+ <BOTTOMBORDER red="255" green="255" blue="255" style="0" width="0"/>
+ <FORMAT>
+ <COLOR red="0" green="0" blue="0"/>
+ <FONT name="helvetica"/>
+ <SIZE value="16"/>
+ <WEIGHT value="75"/>
+ <ITALIC value="0"/>
+ <UNDERLINE value="0"/>
+ <VERTALIGN value="0"/>
+ </FORMAT>
+ </STYLE>
+ <STYLE>
+ <NAME value="Head 3"/>
+ <FOLLOWING name="Standard"/>
+ <FLOW value="0"/>
+ <OHEAD pt="0" mm="0" inch="0"/>
+ <OFOOT pt="0" mm="0" inch="0"/>
+ <IFIRST pt="0" mm="0" inch="0"/>
+ <ILEFT pt="0" mm="0" inch="0"/>
+ <LINESPACE pt="0" mm="0" inch="0"/>
+ <COUNTER type="1" depth="2" bullet="-73" start="1" numberingtype="1" lefttext="" righttext="." bulletfont="symbol"/>
+ <LEFTBORDER red="255" green="255" blue="255" style="0" width="0"/>
+ <RIGHTBORDER red="255" green="255" blue="255" style="0" width="0"/>
+ <TOPBORDER red="255" green="255" blue="255" style="0" width="0"/>
+ <BOTTOMBORDER red="255" green="255" blue="255" style="0" width="0"/>
+ <FORMAT>
+ <COLOR red="0" green="0" blue="0"/>
+ <FONT name="helvetica"/>
+ <SIZE value="12"/>
+ <WEIGHT value="75"/>
+ <ITALIC value="0"/>
+ <UNDERLINE value="0"/>
+ <VERTALIGN value="0"/>
+ </FORMAT>
+ </STYLE>
+ <STYLE>
+ <NAME value="Enumerated List"/>
+ <FOLLOWING name="Enumerated List"/>
+ <FLOW value="0"/>
+ <OHEAD pt="0" mm="0" inch="0"/>
+ <OFOOT pt="0" mm="0" inch="0"/>
+ <IFIRST pt="0" mm="0" inch="0"/>
+ <ILEFT pt="0" mm="0" inch="0"/>
+ <LINESPACE pt="0" mm="0" inch="0"/>
+ <COUNTER type="1" depth="0" bullet="-73" start="1" numberingtype="0" lefttext="" righttext="." bulletfont="symbol"/>
+ <LEFTBORDER red="255" green="255" blue="255" style="0" width="0"/>
+ <RIGHTBORDER red="255" green="255" blue="255" style="0" width="0"/>
+ <TOPBORDER red="255" green="255" blue="255" style="0" width="0"/>
+ <BOTTOMBORDER red="255" green="255" blue="255" style="0" width="0"/>
+ <FORMAT>
+ <COLOR red="0" green="0" blue="0"/>
+ <FONT name="times"/>
+ <SIZE value="12"/>
+ <WEIGHT value="50"/>
+ <ITALIC value="0"/>
+ <UNDERLINE value="0"/>
+ <VERTALIGN value="0"/>
+ </FORMAT>
+ </STYLE>
+ <STYLE>
+ <NAME value="Alphabetical List"/>
+ <FOLLOWING name="Alphabetical List"/>
+ <FLOW value="0"/>
+ <OHEAD pt="0" mm="0" inch="0"/>
+ <OFOOT pt="0" mm="0" inch="0"/>
+ <IFIRST pt="0" mm="0" inch="0"/>
+ <ILEFT pt="0" mm="0" inch="0"/>
+ <LINESPACE pt="0" mm="0" inch="0"/>
+ <COUNTER type="2" depth="0" bullet="-73" start="a" numberingtype="0" lefttext="" righttext=")" bulletfont="symbol"/>
+ <LEFTBORDER red="255" green="255" blue="255" style="0" width="0"/>
+ <RIGHTBORDER red="255" green="255" blue="255" style="0" width="0"/>
+ <TOPBORDER red="255" green="255" blue="255" style="0" width="0"/>
+ <BOTTOMBORDER red="255" green="255" blue="255" style="0" width="0"/>
+ <FORMAT>
+ <COLOR red="0" green="0" blue="0"/>
+ <FONT name="times"/>
+ <SIZE value="12"/>
+ <WEIGHT value="50"/>
+ <ITALIC value="0"/>
+ <UNDERLINE value="0"/>
+ <VERTALIGN value="0"/>
+ </FORMAT>
+ </STYLE>
+ <STYLE>
+ <NAME value="Bullet List"/>
+ <FOLLOWING name="Bullet List"/>
+ <FLOW value="0"/>
+ <OHEAD pt="0" mm="0" inch="0"/>
+ <OFOOT pt="0" mm="0" inch="0"/>
+ <IFIRST pt="0" mm="0" inch="0"/>
+ <ILEFT pt="0" mm="0" inch="0"/>
+ <LINESPACE pt="0" mm="0" inch="0"/>
+ <COUNTER type="6" depth="0" bullet="-73" start="1" numberingtype="0" lefttext="" righttext="" bulletfont="symbol"/>
+ <LEFTBORDER red="255" green="255" blue="255" style="0" width="0"/>
+ <RIGHTBORDER red="255" green="255" blue="255" style="0" width="0"/>
+ <TOPBORDER red="255" green="255" blue="255" style="0" width="0"/>
+ <BOTTOMBORDER red="255" green="255" blue="255" style="0" width="0"/>
+ <FORMAT>
+ <COLOR red="0" green="0" blue="0"/>
+ <FONT name="times"/>
+ <SIZE value="12"/>
+ <WEIGHT value="50"/>
+ <ITALIC value="0"/>
+ <UNDERLINE value="0"/>
+ <VERTALIGN value="0"/>
+ </FORMAT>
+ </STYLE>
+ </STYLES>
+</DOC>
diff --git a/kword/demos/eurosign.kwd b/kword/demos/eurosign.kwd
new file mode 100644
index 00000000..8c701bd7
--- /dev/null
+++ b/kword/demos/eurosign.kwd
@@ -0,0 +1,260 @@
+<?xml version="1.0" encoding="UTF-8"?><!DOCTYPE DOC ><DOC mime="application/x-kword" syntaxVersion="1" editor="KWord" >
+ <PAPER width="595" zoom="100" spHeadBody="9" format="1" height="841" fType="0" orientation="0" hType="0" columnspacing="2" spFootBody="9" columns="1" >
+ <PAPERBORDERS right="28" left="28" bottom="42" top="42" />
+ </PAPER>
+ <ATTRIBUTES standardpage="1" hasFooter="0" unit="mm" hasHeader="0" processing="0" />
+ <FRAMESETS>
+ <FRAMESET removable="0" frameType="1" frameInfo="0" name="Frameset 1" visible="1" >
+ <FRAME runaround="1" right="567" left="28" bottom="799" top="42" />
+ <PARAGRAPH>
+ <TEXT>Euro symbol in arial (needs AntiAliasing) : €</TEXT>
+ <LAYOUT>
+ <NAME value="Standard" />
+ <FLOW align="left" />
+ <COUNTER bullet="0" numberingtype="0" type="0" start="0" depth="0" />
+ <FORMAT id="1" pos="0" len="45" >
+ <WEIGHT value="50" />
+ <COLOR blue="0" red="0" green="0" />
+ <FONT name="Arial" />
+ <SIZE value="11" />
+ <ITALIC value="0" />
+ <UNDERLINE value="0" />
+ <STRIKEOUT value="0" />
+ <VERTALIGN value="0" />
+ </FORMAT>
+ </LAYOUT>
+ </PARAGRAPH>
+ <PARAGRAPH>
+ <TEXT>Euro symbol in fixed font: €</TEXT>
+ <FORMATS>
+ <FORMAT id="1" pos="0" len="28" >
+ <FONT name="fixed" />
+ </FORMAT>
+ </FORMATS>
+ <LAYOUT>
+ <NAME value="Standard" />
+ <FLOW align="left" />
+ <COUNTER bullet="0" numberingtype="0" type="0" start="0" depth="0" />
+ <FORMAT id="1" pos="0" len="28" >
+ <WEIGHT value="50" />
+ <COLOR blue="0" red="0" green="0" />
+ <FONT name="Arial" />
+ <SIZE value="11" />
+ <ITALIC value="0" />
+ <UNDERLINE value="0" />
+ <STRIKEOUT value="0" />
+ <VERTALIGN value="0" />
+ </FORMAT>
+ </LAYOUT>
+ </PARAGRAPH>
+ <PARAGRAPH>
+ <TEXT>Euro symbol in clearlyu font: €</TEXT>
+ <FORMATS>
+ <FORMAT id="1" pos="0" len="31" >
+ <FONT name="clearlyu" />
+ <SIZE value="14" />
+ </FORMAT>
+ </FORMATS>
+ <LAYOUT>
+ <NAME value="Standard" />
+ <FLOW align="left" />
+ <COUNTER bullet="0" numberingtype="0" type="0" start="0" depth="0" />
+ <FORMAT id="1" pos="0" len="31" >
+ <WEIGHT value="50" />
+ <COLOR blue="0" red="0" green="0" />
+ <FONT name="Arial" />
+ <SIZE value="11" />
+ <ITALIC value="0" />
+ <UNDERLINE value="0" />
+ <STRIKEOUT value="0" />
+ <VERTALIGN value="0" />
+ </FORMAT>
+ </LAYOUT>
+ </PARAGRAPH>
+ <PARAGRAPH>
+ <TEXT></TEXT>
+ <LAYOUT>
+ <NAME value="Standard" />
+ <FLOW align="left" />
+ <COUNTER bullet="0" numberingtype="0" type="0" start="0" depth="0" />
+ <FORMAT id="1" >
+ <WEIGHT value="50" />
+ <COLOR blue="0" red="0" green="0" />
+ <FONT name="Arial" />
+ <SIZE value="11" />
+ <ITALIC value="0" />
+ <UNDERLINE value="0" />
+ <STRIKEOUT value="0" />
+ <VERTALIGN value="0" />
+ </FORMAT>
+ </LAYOUT>
+ </PARAGRAPH>
+ </FRAMESET>
+ <FRAMESET removable="0" frameType="1" frameInfo="1" name="TextFrameset 2" visible="1" >
+ <FRAME runaround="1" right="567" left="28" bottom="62" runaroundGap="2.83465" top="42" autoCreateNewFrame="0" />
+ <PARAGRAPH>
+ <TEXT></TEXT>
+ <LAYOUT>
+ <NAME value="Standard" />
+ <FLOW align="left" />
+ <COUNTER bullet="0" numberingtype="0" type="0" start="0" depth="0" />
+ <FORMAT id="1" >
+ <WEIGHT value="50" />
+ <COLOR blue="0" red="0" green="0" />
+ <FONT name="lucidux mono" />
+ <SIZE value="11" />
+ <ITALIC value="0" />
+ <UNDERLINE value="0" />
+ <STRIKEOUT value="0" />
+ <VERTALIGN value="0" />
+ </FORMAT>
+ </LAYOUT>
+ </PARAGRAPH>
+ </FRAMESET>
+ <FRAMESET removable="0" frameType="1" frameInfo="3" name="TextFrameset 3" visible="1" >
+ <FRAME runaround="1" right="567" left="28" bottom="62" runaroundGap="2.83465" top="42" autoCreateNewFrame="0" />
+ <PARAGRAPH>
+ <TEXT></TEXT>
+ <LAYOUT>
+ <NAME value="Standard" />
+ <FLOW align="left" />
+ <COUNTER bullet="0" numberingtype="0" type="0" start="0" depth="0" />
+ <FORMAT id="1" >
+ <WEIGHT value="50" />
+ <COLOR blue="0" red="0" green="0" />
+ <FONT name="lucidux mono" />
+ <SIZE value="11" />
+ <ITALIC value="0" />
+ <UNDERLINE value="0" />
+ <STRIKEOUT value="0" />
+ <VERTALIGN value="0" />
+ </FORMAT>
+ </LAYOUT>
+ </PARAGRAPH>
+ </FRAMESET>
+ <FRAMESET removable="0" frameType="1" frameInfo="2" name="TextFrameset 4" visible="1" >
+ <FRAME runaround="1" right="567" left="28" bottom="62" runaroundGap="2.83465" top="42" autoCreateNewFrame="0" />
+ <PARAGRAPH>
+ <TEXT></TEXT>
+ <LAYOUT>
+ <NAME value="Standard" />
+ <FLOW align="left" />
+ <COUNTER bullet="0" numberingtype="0" type="0" start="0" depth="0" />
+ <FORMAT id="1" >
+ <WEIGHT value="50" />
+ <COLOR blue="0" red="0" green="0" />
+ <FONT name="lucidux mono" />
+ <SIZE value="11" />
+ <ITALIC value="0" />
+ <UNDERLINE value="0" />
+ <STRIKEOUT value="0" />
+ <VERTALIGN value="0" />
+ </FORMAT>
+ </LAYOUT>
+ </PARAGRAPH>
+ </FRAMESET>
+ <FRAMESET removable="0" frameType="1" frameInfo="4" name="TextFrameset 5" visible="1" >
+ <FRAME runaround="1" right="567" left="28" bottom="799" runaroundGap="2.83465" top="779" autoCreateNewFrame="0" />
+ <PARAGRAPH>
+ <TEXT></TEXT>
+ <LAYOUT>
+ <NAME value="Standard" />
+ <FLOW align="left" />
+ <COUNTER bullet="0" numberingtype="0" type="0" start="0" depth="0" />
+ <FORMAT id="1" >
+ <WEIGHT value="50" />
+ <COLOR blue="0" red="0" green="0" />
+ <FONT name="lucidux mono" />
+ <SIZE value="11" />
+ <ITALIC value="0" />
+ <UNDERLINE value="0" />
+ <STRIKEOUT value="0" />
+ <VERTALIGN value="0" />
+ </FORMAT>
+ </LAYOUT>
+ </PARAGRAPH>
+ </FRAMESET>
+ <FRAMESET removable="0" frameType="1" frameInfo="6" name="TextFrameset 6" visible="1" >
+ <FRAME runaround="1" right="567" left="28" bottom="799" runaroundGap="2.83465" top="779" autoCreateNewFrame="0" />
+ <PARAGRAPH>
+ <TEXT></TEXT>
+ <LAYOUT>
+ <NAME value="Standard" />
+ <FLOW align="left" />
+ <COUNTER bullet="0" numberingtype="0" type="0" start="0" depth="0" />
+ <FORMAT id="1" >
+ <WEIGHT value="50" />
+ <COLOR blue="0" red="0" green="0" />
+ <FONT name="lucidux mono" />
+ <SIZE value="11" />
+ <ITALIC value="0" />
+ <UNDERLINE value="0" />
+ <STRIKEOUT value="0" />
+ <VERTALIGN value="0" />
+ </FORMAT>
+ </LAYOUT>
+ </PARAGRAPH>
+ </FRAMESET>
+ <FRAMESET removable="0" frameType="1" frameInfo="5" name="TextFrameset 7" visible="1" >
+ <FRAME runaround="1" right="567" left="28" bottom="799" runaroundGap="2.83465" top="779" autoCreateNewFrame="0" />
+ <PARAGRAPH>
+ <TEXT></TEXT>
+ <LAYOUT>
+ <NAME value="Standard" />
+ <FLOW align="left" />
+ <COUNTER bullet="0" numberingtype="0" type="0" start="0" depth="0" />
+ <FORMAT id="1" >
+ <WEIGHT value="50" />
+ <COLOR blue="0" red="0" green="0" />
+ <FONT name="lucidux mono" />
+ <SIZE value="11" />
+ <ITALIC value="0" />
+ <UNDERLINE value="0" />
+ <STRIKEOUT value="0" />
+ <VERTALIGN value="0" />
+ </FORMAT>
+ </LAYOUT>
+ </PARAGRAPH>
+ </FRAMESET>
+ <FRAMESET removable="0" frameType="1" frameInfo="7" name="Footnotes" visible="0" >
+ <FRAME runaround="1" right="567" left="28" bottom="799" runaroundGap="2.83465" top="779" autoCreateNewFrame="0" />
+ <PARAGRAPH>
+ <TEXT></TEXT>
+ <LAYOUT>
+ <NAME value="Standard" />
+ <FLOW align="left" />
+ <COUNTER bullet="0" numberingtype="0" type="0" start="0" depth="0" />
+ <FORMAT id="1" >
+ <WEIGHT value="50" />
+ <COLOR blue="0" red="0" green="0" />
+ <FONT name="lucidux mono" />
+ <SIZE value="11" />
+ <ITALIC value="0" />
+ <UNDERLINE value="0" />
+ <STRIKEOUT value="0" />
+ <VERTALIGN value="0" />
+ </FORMAT>
+ </LAYOUT>
+ </PARAGRAPH>
+ </FRAMESET>
+ </FRAMESETS>
+ <STYLES>
+ <STYLE>
+ <NAME value="Standard" />
+ <FLOW align="left" />
+ <COUNTER bullet="0" numberingtype="0" type="0" start="0" depth="0" />
+ <FOLLOWING name="Standard" />
+ <FORMAT id="1" >
+ <WEIGHT value="50" />
+ <COLOR blue="0" red="0" green="0" />
+ <FONT name="Arial" />
+ <SIZE value="11" />
+ <ITALIC value="0" />
+ <UNDERLINE value="0" />
+ <STRIKEOUT value="0" />
+ <VERTALIGN value="0" />
+ </FORMAT>
+ </STYLE>
+ </STYLES>
+ <PIXMAPS/>
+</DOC>
diff --git a/kword/demos/flatland.kwd b/kword/demos/flatland.kwd
new file mode 100644
index 00000000..9bd30f35
--- /dev/null
+++ b/kword/demos/flatland.kwd
Binary files differ
diff --git a/kword/demos/framestest.kwd b/kword/demos/framestest.kwd
new file mode 100644
index 00000000..c9e7fb03
--- /dev/null
+++ b/kword/demos/framestest.kwd
@@ -0,0 +1,710 @@
+<?xml version="1.0" encoding="UTF-8"?><!DOCTYPE DOC ><DOC mime="application/x-kword" syntaxVersion="1" editor="KWord" >
+ <PAPER width="595" zoom="100" spHeadBody="9" format="1" height="841" fType="0" orientation="0" hType="0" columnspacing="2" spFootBody="9" columns="1" >
+ <PAPERBORDERS right="28" left="28" bottom="42" top="42" />
+ </PAPER>
+ <ATTRIBUTES standardpage="1" hasFooter="0" unit="mm" hasHeader="0" processing="0" />
+ <FRAMESETS>
+ <FRAMESET removable="0" frameType="1" frameInfo="0" name="Frameset 1" visible="1" >
+ <FRAME runaround="1" right="566" left="28" bottom="798" runaroundGap="0" top="42" />
+ <PARAGRAPH>
+ <TEXT>Don't be surprised, this test uses debug output to fill in some text :)</TEXT>
+ <LAYOUT>
+ <NAME value="Standard" />
+ <FLOW align="left" />
+ <COUNTER bullet="176" lefttext="" numberingtype="1" bulletfont="times" righttext="" type="0" start="1" depth="0" customdef="" />
+ <FORMAT id="1" pos="0" len="71" >
+ <WEIGHT value="50" />
+ <FONT name="times" />
+ <SIZE value="12" />
+ <ITALIC value="0" />
+ <UNDERLINE value="0" />
+ <STRIKEOUT value="0" />
+ <VERTALIGN value="0" />
+ </FORMAT>
+ </LAYOUT>
+ </PARAGRAPH>
+ <PARAGRAPH>
+ <TEXT>Height=26kwo rd (formatting): KWTextFrameSet::updateFrames 0x8222128 setWidth=539</TEXT>
+ <LAYOUT>
+ <NAME value="Standard" />
+ <FLOW align="left" />
+ <COUNTER bullet="176" lefttext="" numberingtype="1" bulletfont="times" righttext="" type="0" start="1" depth="0" customdef="" />
+ <FORMAT id="1" pos="0" len="81" >
+ <WEIGHT value="50" />
+ <FONT name="times" />
+ <SIZE value="12" />
+ <ITALIC value="0" />
+ <UNDERLINE value="0" />
+ <STRIKEOUT value="0" />
+ <VERTALIGN value="0" />
+ </FORMAT>
+ </LAYOUT>
+ </PARAGRAPH>
+ <PARAGRAPH>
+ <TEXT>kword (formatting): KWTextFrameSet::updateFrames m_availableHeight=26</TEXT>
+ <LAYOUT>
+ <NAME value="Standard" />
+ <FLOW align="left" />
+ <COUNTER bullet="176" lefttext="" numberingtype="1" bulletfont="times" righttext="" type="0" start="1" depth="0" customdef="" />
+ <FORMAT id="1" pos="0" len="69" >
+ <WEIGHT value="50" />
+ <FONT name="times" />
+ <SIZE value="12" />
+ <ITALIC value="0" />
+ <UNDERLINE value="0" />
+ <STRIKEOUT value="0" />
+ <VERTALIGN value="0" />
+ </FORMAT>
+ </LAYOUT>
+ </PARAGRAPH>
+ <PARAGRAPH>
+ <TEXT>kword (formatting): KWTextFrameSet::updateFrames 0x8224710 setWidth=539</TEXT>
+ <LAYOUT>
+ <NAME value="Standard" />
+ <FLOW align="left" />
+ <COUNTER bullet="176" lefttext="" numberingtype="1" bulletfont="times" righttext="" type="0" start="1" depth="0" customdef="" />
+ <FORMAT id="1" pos="0" len="71" >
+ <WEIGHT value="50" />
+ <FONT name="times" />
+ <SIZE value="12" />
+ <ITALIC value="0" />
+ <UNDERLINE value="0" />
+ <STRIKEOUT value="0" />
+ <VERTALIGN value="0" />
+ </FORMAT>
+ </LAYOUT>
+ </PARAGRAPH>
+ <PARAGRAPH>
+ <TEXT>kword (formatting): KWTextFrameSet::updateFrames m_availableHeight=26</TEXT>
+ <LAYOUT>
+ <NAME value="Standard" />
+ <FLOW align="left" />
+ <COUNTER bullet="176" lefttext="" numberingtype="1" bulletfont="times" righttext="" type="0" start="1" depth="0" customdef="" />
+ <FORMAT id="1" pos="0" len="69" >
+ <WEIGHT value="50" />
+ <FONT name="times" />
+ <SIZE value="12" />
+ <ITALIC value="0" />
+ <UNDERLINE value="0" />
+ <STRIKEOUT value="0" />
+ <VERTALIGN value="0" />
+ </FORMAT>
+ </LAYOUT>
+ </PARAGRAPH>
+ <PARAGRAPH>
+ <TEXT>kword (formatting): KWTextFrameSet::updateFrames 0x82179b8 setWidth=539</TEXT>
+ <LAYOUT>
+ <NAME value="Standard" />
+ <FLOW align="left" />
+ <COUNTER bullet="176" lefttext="" numberingtype="1" bulletfont="times" righttext="" type="0" start="1" depth="0" customdef="" />
+ <FORMAT id="1" pos="0" len="71" >
+ <WEIGHT value="50" />
+ <FONT name="times" />
+ <SIZE value="12" />
+ <ITALIC value="0" />
+ <UNDERLINE value="0" />
+ <STRIKEOUT value="0" />
+ <VERTALIGN value="0" />
+ </FORMAT>
+ </LAYOUT>
+ </PARAGRAPH>
+ <PARAGRAPH>
+ <TEXT>kword (formatting): KWTextFrameSet::updateFrames m_availableHeight=26</TEXT>
+ <LAYOUT>
+ <NAME value="Standard" />
+ <FLOW align="left" />
+ <COUNTER bullet="176" lefttext="" numberingtype="1" bulletfont="times" righttext="" type="0" start="1" depth="0" customdef="" />
+ <FORMAT id="1" pos="0" len="69" >
+ <WEIGHT value="50" />
+ <FONT name="times" />
+ <SIZE value="12" />
+ <ITALIC value="0" />
+ <UNDERLINE value="0" />
+ <STRIKEOUT value="0" />
+ <VERTALIGN value="0" />
+ </FORMAT>
+ </LAYOUT>
+ </PARAGRAPH>
+ <PARAGRAPH>
+ <TEXT>This is a line of text.</TEXT>
+ <LAYOUT>
+ <NAME value="Standard" />
+ <FLOW align="left" />
+ <COUNTER bullet="176" lefttext="" numberingtype="1" bulletfont="times" righttext="" type="0" start="1" depth="0" customdef="" />
+ <FORMAT id="1" pos="0" len="23" >
+ <WEIGHT value="50" />
+ <FONT name="times" />
+ <SIZE value="12" />
+ <ITALIC value="0" />
+ <UNDERLINE value="0" />
+ <STRIKEOUT value="0" />
+ <VERTALIGN value="0" />
+ </FORMAT>
+ </LAYOUT>
+ </PARAGRAPH>
+ <PARAGRAPH>
+ <TEXT>And here is another line, which aims to be a little bit longer.</TEXT>
+ <LAYOUT>
+ <NAME value="Standard" />
+ <FLOW align="left" />
+ <COUNTER bullet="176" lefttext="" numberingtype="1" bulletfont="times" righttext="" type="0" start="1" depth="0" customdef="" />
+ <FORMAT id="1" pos="0" len="63" >
+ <WEIGHT value="50" />
+ <FONT name="times" />
+ <SIZE value="12" />
+ <ITALIC value="0" />
+ <UNDERLINE value="0" />
+ <STRIKEOUT value="0" />
+ <VERTALIGN value="0" />
+ </FORMAT>
+ </LAYOUT>
+ </PARAGRAPH>
+ <PARAGRAPH>
+ <TEXT>Short one.</TEXT>
+ <LAYOUT>
+ <NAME value="Standard" />
+ <FLOW align="left" />
+ <COUNTER bullet="176" lefttext="" numberingtype="1" bulletfont="times" righttext="" type="0" start="1" depth="0" customdef="" />
+ <FORMAT id="1" pos="0" len="10" >
+ <WEIGHT value="50" />
+ <FONT name="times" />
+ <SIZE value="12" />
+ <ITALIC value="0" />
+ <UNDERLINE value="0" />
+ <STRIKEOUT value="0" />
+ <VERTALIGN value="0" />
+ </FORMAT>
+ </LAYOUT>
+ </PARAGRAPH>
+ <PARAGRAPH>
+ <TEXT>I am afraid that somehow the lack of inspiration for what to write in this document must surely show :)</TEXT>
+ <LAYOUT>
+ <NAME value="Standard" />
+ <FLOW align="left" />
+ <COUNTER bullet="176" lefttext="" numberingtype="1" bulletfont="times" righttext="" type="0" start="1" depth="0" customdef="" />
+ <FORMAT id="1" pos="0" len="103" >
+ <WEIGHT value="50" />
+ <FONT name="times" />
+ <SIZE value="12" />
+ <ITALIC value="0" />
+ <UNDERLINE value="0" />
+ <STRIKEOUT value="0" />
+ <VERTALIGN value="0" />
+ </FORMAT>
+ </LAYOUT>
+ </PARAGRAPH>
+ <PARAGRAPH>
+ <TEXT>Well, it's quite fun to have all those frames floating around us. Maybe this document will also have a table later... Why not.</TEXT>
+ <LAYOUT>
+ <NAME value="Standard" />
+ <FLOW align="left" />
+ <COUNTER bullet="176" lefttext="" numberingtype="1" bulletfont="times" righttext="" type="0" start="1" depth="0" customdef="" />
+ <FORMAT id="1" pos="0" len="126" >
+ <WEIGHT value="50" />
+ <FONT name="times" />
+ <SIZE value="12" />
+ <ITALIC value="0" />
+ <UNDERLINE value="0" />
+ <STRIKEOUT value="0" />
+ <VERTALIGN value="0" />
+ </FORMAT>
+ </LAYOUT>
+ </PARAGRAPH>
+ <PARAGRAPH>
+ <TEXT>Here is another paragraph, shorter than the previous one.</TEXT>
+ <LAYOUT>
+ <NAME value="Standard" />
+ <FLOW align="left" />
+ <COUNTER bullet="176" lefttext="" numberingtype="1" bulletfont="times" righttext="" type="0" start="1" depth="0" customdef="" />
+ <FORMAT id="1" pos="0" len="57" >
+ <WEIGHT value="50" />
+ <FONT name="times" />
+ <SIZE value="12" />
+ <ITALIC value="0" />
+ <UNDERLINE value="0" />
+ <STRIKEOUT value="0" />
+ <VERTALIGN value="0" />
+ </FORMAT>
+ </LAYOUT>
+ </PARAGRAPH>
+ <PARAGRAPH>
+ <TEXT>Hey this stuff seems to work. Very cool, if you ask me.</TEXT>
+ <LAYOUT>
+ <NAME value="Standard" />
+ <FLOW align="left" />
+ <COUNTER bullet="176" lefttext="" numberingtype="1" bulletfont="times" righttext="" type="0" start="1" depth="0" customdef="" />
+ <FORMAT id="1" pos="0" len="55" >
+ <WEIGHT value="50" />
+ <FONT name="times" />
+ <SIZE value="12" />
+ <ITALIC value="0" />
+ <UNDERLINE value="0" />
+ <STRIKEOUT value="0" />
+ <VERTALIGN value="0" />
+ </FORMAT>
+ </LAYOUT>
+ </PARAGRAPH>
+ <PARAGRAPH>
+ <TEXT></TEXT>
+ <LAYOUT>
+ <NAME value="Standard" />
+ <FLOW align="left" />
+ <COUNTER bullet="176" lefttext="" numberingtype="1" bulletfont="times" righttext="" type="0" start="1" depth="0" customdef="" />
+ <FORMAT id="1" pos="0" len="0" >
+ <WEIGHT value="50" />
+ <FONT name="times" />
+ <SIZE value="12" />
+ <ITALIC value="0" />
+ <UNDERLINE value="0" />
+ <STRIKEOUT value="0" />
+ <VERTALIGN value="0" />
+ </FORMAT>
+ </LAYOUT>
+ </PARAGRAPH>
+ <PARAGRAPH>
+ <TEXT>acbdefghijklmnopqrstuvwxyz. 1234567890. kofficyet sdfgsdfgsdfgsdfg(libty koffitcecore): KoMainWindow::setRootDocument this = [KoMainWindow pointer (0x813ff28) to widget kword-mainwindow#1, geometry=894x723+0+0] doc = 0x8133470</TEXT>
+ <LAYOUT>
+ <NAME value="Standard" />
+ <FLOW align="left" />
+ <COUNTER bullet="176" lefttext="" numberingtype="1" bulletfont="times" righttext="" type="0" start="1" depth="0" customdef="" />
+ <FORMAT id="1" pos="0" len="226" >
+ <WEIGHT value="50" />
+ <FONT name="times" />
+ <SIZE value="12" />
+ <ITALIC value="0" />
+ <UNDERLINE value="0" />
+ <STRIKEOUT value="0" />
+ <VERTALIGN value="0" />
+ </FORMAT>
+ </LAYOUT>
+ </PARAGRAPH>
+ <PARAGRAPH>
+ <TEXT>kparts: found Plugin ::(formatting): KWTextFrameSet::formatMore finished</TEXT>
+ <LAYOUT>
+ <NAME value="Standard" />
+ <FLOW align="left" />
+ <COUNTER bullet="176" lefttext="" numberingtype="1" bulletfont="times" righttext="" type="0" start="1" depth="0" customdef="" />
+ <FORMAT id="1" pos="0" len="72" >
+ <WEIGHT value="50" />
+ <FONT name="times" />
+ <SIZE value="12" />
+ <ITALIC value="0" />
+ <UNDERLINE value="0" />
+ <STRIKEOUT value="0" />
+ <VERTALIGN value="0" />
+ </FORMAT>
+ </LAYOUT>
+ </PARAGRAPH>
+ <PARAGRAPH>
+ <TEXT>This is the last line of the document.</TEXT>
+ <LAYOUT>
+ <NAME value="Standard" />
+ <FLOW align="left" />
+ <COUNTER bullet="176" lefttext="" numberingtype="1" bulletfont="times" righttext="" type="0" start="1" depth="0" customdef="" />
+ <FORMAT id="1" pos="0" len="38" >
+ <WEIGHT value="50" />
+ <FONT name="times" />
+ <SIZE value="12" />
+ <ITALIC value="0" />
+ <UNDERLINE value="0" />
+ <STRIKEOUT value="0" />
+ <VERTALIGN value="0" />
+ </FORMAT>
+ </LAYOUT>
+ </PARAGRAPH>
+ </FRAMESET>
+ <FRAMESET removable="0" frameType="1" frameInfo="1" name="TextFrameset 2" visible="1" >
+ <FRAME right="566" left="28" bottom="61" runaroundGap="0" top="42" autoCreateNewFrame="0" />
+ <PARAGRAPH>
+ <TEXT></TEXT>
+ <LAYOUT>
+ <NAME value="Standard" />
+ <FLOW align="left" />
+ <COUNTER bullet="176" lefttext="" numberingtype="0" bulletfont="times" righttext="" type="0" start="0" depth="0" customdef="" />
+ <FORMAT id="1" pos="0" len="0" >
+ <WEIGHT value="50" />
+ <FONT name="times" />
+ <SIZE value="12" />
+ <ITALIC value="0" />
+ <UNDERLINE value="0" />
+ <STRIKEOUT value="0" />
+ <VERTALIGN value="0" />
+ </FORMAT>
+ </LAYOUT>
+ </PARAGRAPH>
+ </FRAMESET>
+ <FRAMESET removable="0" frameType="1" frameInfo="3" name="TextFrameset 3" visible="1" >
+ <FRAME right="566" left="28" bottom="61" runaroundGap="0" top="42" autoCreateNewFrame="0" />
+ <PARAGRAPH>
+ <TEXT></TEXT>
+ <LAYOUT>
+ <NAME value="Standard" />
+ <FLOW align="left" />
+ <COUNTER bullet="176" lefttext="" numberingtype="0" bulletfont="times" righttext="" type="0" start="0" depth="0" customdef="" />
+ <FORMAT id="1" pos="0" len="0" >
+ <WEIGHT value="50" />
+ <FONT name="times" />
+ <SIZE value="12" />
+ <ITALIC value="0" />
+ <UNDERLINE value="0" />
+ <STRIKEOUT value="0" />
+ <VERTALIGN value="0" />
+ </FORMAT>
+ </LAYOUT>
+ </PARAGRAPH>
+ </FRAMESET>
+ <FRAMESET removable="0" frameType="1" frameInfo="2" name="TextFrameset 4" visible="1" >
+ <FRAME right="566" left="28" bottom="61" runaroundGap="0" top="42" autoCreateNewFrame="0" />
+ <PARAGRAPH>
+ <TEXT></TEXT>
+ <LAYOUT>
+ <NAME value="Standard" />
+ <FLOW align="left" />
+ <COUNTER bullet="176" lefttext="" numberingtype="0" bulletfont="times" righttext="" type="0" start="0" depth="0" customdef="" />
+ <FORMAT id="1" pos="0" len="0" >
+ <WEIGHT value="50" />
+ <FONT name="times" />
+ <SIZE value="12" />
+ <ITALIC value="0" />
+ <UNDERLINE value="0" />
+ <STRIKEOUT value="0" />
+ <VERTALIGN value="0" />
+ </FORMAT>
+ </LAYOUT>
+ </PARAGRAPH>
+ </FRAMESET>
+ <FRAMESET removable="0" frameType="1" frameInfo="4" name="TextFrameset 5" visible="1" >
+ <FRAME right="566" left="28" bottom="798" runaroundGap="0" top="779" autoCreateNewFrame="0" />
+ <PARAGRAPH>
+ <TEXT></TEXT>
+ <LAYOUT>
+ <NAME value="Standard" />
+ <FLOW align="left" />
+ <COUNTER bullet="176" lefttext="" numberingtype="0" bulletfont="times" righttext="" type="0" start="0" depth="0" customdef="" />
+ <FORMAT id="1" pos="0" len="0" >
+ <WEIGHT value="50" />
+ <FONT name="times" />
+ <SIZE value="12" />
+ <ITALIC value="0" />
+ <UNDERLINE value="0" />
+ <STRIKEOUT value="0" />
+ <VERTALIGN value="0" />
+ </FORMAT>
+ </LAYOUT>
+ </PARAGRAPH>
+ </FRAMESET>
+ <FRAMESET removable="0" frameType="1" frameInfo="6" name="TextFrameset 6" visible="1" >
+ <FRAME right="566" left="28" bottom="798" runaroundGap="0" top="779" autoCreateNewFrame="0" />
+ <PARAGRAPH>
+ <TEXT></TEXT>
+ <LAYOUT>
+ <NAME value="Standard" />
+ <FLOW align="left" />
+ <COUNTER bullet="176" lefttext="" numberingtype="0" bulletfont="times" righttext="" type="0" start="0" depth="0" customdef="" />
+ <FORMAT id="1" pos="0" len="0" >
+ <WEIGHT value="50" />
+ <FONT name="times" />
+ <SIZE value="12" />
+ <ITALIC value="0" />
+ <UNDERLINE value="0" />
+ <STRIKEOUT value="0" />
+ <VERTALIGN value="0" />
+ </FORMAT>
+ </LAYOUT>
+ </PARAGRAPH>
+ </FRAMESET>
+ <FRAMESET removable="0" frameType="1" frameInfo="5" name="TextFrameset 7" visible="1" >
+ <FRAME right="566" left="28" bottom="798" runaroundGap="0" top="779" autoCreateNewFrame="0" />
+ <PARAGRAPH>
+ <TEXT></TEXT>
+ <LAYOUT>
+ <NAME value="Standard" />
+ <FLOW align="left" />
+ <COUNTER bullet="176" lefttext="" numberingtype="0" bulletfont="times" righttext="" type="0" start="0" depth="0" customdef="" />
+ <FORMAT id="1" pos="0" len="0" >
+ <WEIGHT value="50" />
+ <FONT name="times" />
+ <SIZE value="12" />
+ <ITALIC value="0" />
+ <UNDERLINE value="0" />
+ <STRIKEOUT value="0" />
+ <VERTALIGN value="0" />
+ </FORMAT>
+ </LAYOUT>
+ </PARAGRAPH>
+ </FRAMESET>
+ <FRAMESET removable="0" frameType="1" frameInfo="7" name="Footnotes" visible="0" >
+ <FRAME right="566" left="28" bottom="798" runaroundGap="0" top="779" autoCreateNewFrame="0" />
+ <PARAGRAPH>
+ <TEXT></TEXT>
+ <LAYOUT>
+ <NAME value="Standard" />
+ <FLOW align="left" />
+ <COUNTER bullet="176" lefttext="" numberingtype="0" bulletfont="times" righttext="" type="0" start="0" depth="0" customdef="" />
+ <FORMAT id="1" pos="0" len="0" >
+ <WEIGHT value="50" />
+ <FONT name="Arial" />
+ <SIZE value="11" />
+ <ITALIC value="0" />
+ <UNDERLINE value="0" />
+ <STRIKEOUT value="0" />
+ <VERTALIGN value="0" />
+ </FORMAT>
+ </LAYOUT>
+ </PARAGRAPH>
+ </FRAMESET>
+ <FRAMESET removable="0" frameType="1" frameInfo="0" name="NORA (through)" visible="1" >
+ <FRAME right="356" left="126" bottom="168" runaroundGap="0" top="91" />
+ <FRAME right="356" left="126" bottom="1009" runaroundGap="0" top="932" />
+ <PARAGRAPH>
+ <TEXT>Run through (RA_NO)</TEXT>
+ <LAYOUT>
+ <NAME value="Standard" />
+ <FLOW align="left" />
+ <COUNTER bullet="176" lefttext="" numberingtype="0" bulletfont="times" righttext="" type="0" start="0" depth="0" customdef="" />
+ <FORMAT id="1" pos="0" len="19" >
+ <WEIGHT value="50" />
+ <FONT name="Arial" />
+ <SIZE value="11" />
+ <ITALIC value="0" />
+ <UNDERLINE value="0" />
+ <STRIKEOUT value="0" />
+ <VERTALIGN value="0" />
+ </FORMAT>
+ </LAYOUT>
+ </PARAGRAPH>
+ </FRAMESET>
+ <FRAMESET removable="0" frameType="1" frameInfo="0" name="RunAround rect" visible="1" >
+ <FRAME runaround="1" right="542" left="412" bottom="391" runaroundGap="0" top="329" />
+ <FRAME runaround="1" right="524" left="394" bottom="1223" runaroundGap="0" top="1161" />
+ <PARAGRAPH>
+ <TEXT>Runaround rect (RA_BOUNDINGRECT)</TEXT>
+ <LAYOUT>
+ <NAME value="Standard" />
+ <FLOW align="left" />
+ <COUNTER bullet="176" lefttext="" numberingtype="0" bulletfont="times" righttext="" type="0" start="0" depth="0" customdef="" />
+ <FORMAT id="1" pos="0" len="32" >
+ <WEIGHT value="50" />
+ <FONT name="Arial" />
+ <SIZE value="11" />
+ <ITALIC value="0" />
+ <UNDERLINE value="0" />
+ <STRIKEOUT value="0" />
+ <VERTALIGN value="0" />
+ </FORMAT>
+ </LAYOUT>
+ </PARAGRAPH>
+ </FRAMESET>
+ <FRAMESET removable="0" frameType="1" frameInfo="0" name="H" visible="1" >
+ <FRAME runaround="2" right="427" left="99" bottom="569" runaroundGap="0" top="443" />
+ <FRAME runaround="2" right="427" left="99" bottom="1410" runaroundGap="0" top="1284" />
+ <PARAGRAPH>
+ <TEXT>No runaround (RA_SKIP)</TEXT>
+ <LAYOUT>
+ <NAME value="Standard" />
+ <FLOW align="left" />
+ <COUNTER bullet="176" lefttext="" numberingtype="0" bulletfont="times" righttext="" type="0" start="0" depth="0" customdef="" />
+ <FORMAT id="1" pos="0" len="22" >
+ <WEIGHT value="50" />
+ <FONT name="Arial" />
+ <SIZE value="11" />
+ <ITALIC value="0" />
+ <UNDERLINE value="0" />
+ <STRIKEOUT value="0" />
+ <VERTALIGN value="0" />
+ </FORMAT>
+ </LAYOUT>
+ </PARAGRAPH>
+ </FRAMESET>
+ <FRAMESET removable="0" frameType="1" frameInfo="0" name="Runaround 2" visible="1" >
+ <FRAME runaround="1" right="172" left="48" bottom="395" top="288" />
+ <FRAME runaround="1" right="217" left="48" bottom="1236" top="1129" />
+ <PARAGRAPH>
+ <TEXT>Runaround rect (RA_BOUNDINGRECT)</TEXT>
+ <LAYOUT>
+ <NAME value="" />
+ <FLOW align="left" />
+ <FORMAT id="1" pos="0" len="32" >
+ <WEIGHT value="50" />
+ <FONT name="Arial" />
+ <SIZE value="11" />
+ <ITALIC value="0" />
+ <UNDERLINE value="0" />
+ <STRIKEOUT value="0" />
+ <VERTALIGN value="0" />
+ </FORMAT>
+ </LAYOUT>
+ </PARAGRAPH>
+ </FRAMESET>
+ </FRAMESETS>
+ <STYLES>
+ <STYLE>
+ <FOLLOWING name="Standard" />
+ <NAME value="Standard" />
+ <FLOW align="left" />
+ <COUNTER bullet="176" lefttext="" numberingtype="0" bulletfont="times" righttext="" type="0" start="0" depth="0" customdef="" />
+ <FORMAT id="1" pos="0" len="0" >
+ <WEIGHT value="50" />
+ <FONT name="times" />
+ <SIZE value="12" />
+ <ITALIC value="0" />
+ <UNDERLINE value="0" />
+ <STRIKEOUT value="0" />
+ <VERTALIGN value="0" />
+ </FORMAT>
+ </STYLE>
+ <STYLE>
+ <FOLLOWING name="Standard" />
+ <NAME value="Head 1" />
+ <FLOW align="left" />
+ <COUNTER bullet="176" lefttext="" numberingtype="1" bulletfont="times" righttext="." type="1" start="1" depth="0" customdef="" />
+ <FORMAT id="1" pos="0" len="0" >
+ <WEIGHT value="75" />
+ <FONT name="helvetica" />
+ <SIZE value="24" />
+ <ITALIC value="0" />
+ <UNDERLINE value="0" />
+ <STRIKEOUT value="0" />
+ <VERTALIGN value="0" />
+ </FORMAT>
+ </STYLE>
+ <STYLE>
+ <FOLLOWING name="Standard" />
+ <NAME value="Head 2" />
+ <FLOW align="left" />
+ <COUNTER bullet="176" lefttext="" numberingtype="1" bulletfont="times" righttext="." type="1" start="1" depth="1" customdef="" />
+ <FORMAT id="1" pos="0" len="0" >
+ <WEIGHT value="75" />
+ <FONT name="helvetica" />
+ <SIZE value="16" />
+ <ITALIC value="0" />
+ <UNDERLINE value="0" />
+ <STRIKEOUT value="0" />
+ <VERTALIGN value="0" />
+ </FORMAT>
+ </STYLE>
+ <STYLE>
+ <FOLLOWING name="Standard" />
+ <NAME value="Head 3" />
+ <FLOW align="left" />
+ <COUNTER bullet="176" lefttext="" numberingtype="1" bulletfont="times" righttext="." type="1" start="1" depth="2" customdef="" />
+ <FORMAT id="1" pos="0" len="0" >
+ <WEIGHT value="75" />
+ <FONT name="helvetica" />
+ <SIZE value="12" />
+ <ITALIC value="0" />
+ <UNDERLINE value="0" />
+ <STRIKEOUT value="0" />
+ <VERTALIGN value="0" />
+ </FORMAT>
+ </STYLE>
+ <STYLE>
+ <FOLLOWING name="Enumerated List" />
+ <NAME value="Enumerated List" />
+ <FLOW align="left" />
+ <COUNTER bullet="176" lefttext="" numberingtype="0" bulletfont="times" righttext="." type="1" start="1" depth="0" customdef="" />
+ <FORMAT id="1" pos="0" len="0" >
+ <WEIGHT value="50" />
+ <FONT name="times" />
+ <SIZE value="12" />
+ <ITALIC value="0" />
+ <UNDERLINE value="0" />
+ <STRIKEOUT value="0" />
+ <VERTALIGN value="0" />
+ </FORMAT>
+ </STYLE>
+ <STYLE>
+ <FOLLOWING name="Alphabetical List" />
+ <NAME value="Alphabetical List" />
+ <FLOW align="left" />
+ <COUNTER bullet="176" lefttext="" numberingtype="0" bulletfont="times" righttext=")" type="2" start="1" depth="0" customdef="" />
+ <FORMAT id="1" pos="0" len="0" >
+ <WEIGHT value="50" />
+ <FONT name="times" />
+ <SIZE value="12" />
+ <ITALIC value="0" />
+ <UNDERLINE value="0" />
+ <STRIKEOUT value="0" />
+ <VERTALIGN value="0" />
+ </FORMAT>
+ </STYLE>
+ <STYLE>
+ <FOLLOWING name="Bullet List" />
+ <NAME value="Bullet List" />
+ <FLOW align="left" />
+ <COUNTER bullet="0" lefttext="" numberingtype="0" bulletfont="" righttext="" type="10" start="1" depth="0" customdef="" />
+ <FORMAT id="1" pos="0" len="0" >
+ <WEIGHT value="50" />
+ <FONT name="times" />
+ <SIZE value="12" />
+ <ITALIC value="0" />
+ <UNDERLINE value="0" />
+ <STRIKEOUT value="0" />
+ <VERTALIGN value="0" />
+ </FORMAT>
+ </STYLE>
+ <STYLE>
+ <FOLLOWING name="Standard" />
+ <NAME value="Contents Title" />
+ <FLOW align="center" />
+ <TOPBORDER width="1" style="0" blue="0" red="0" green="0" />
+ <BOTTOMBORDER width="1" style="0" blue="0" red="0" green="0" />
+ <COUNTER bullet="183" lefttext="" numberingtype="0" bulletfont="symbol" righttext="" type="0" start="0" depth="0" customdef="" />
+ <FORMAT id="1" pos="0" len="0" >
+ <WEIGHT value="75" />
+ <FONT name="helvetica" />
+ <SIZE value="20" />
+ <ITALIC value="0" />
+ <UNDERLINE value="0" />
+ <STRIKEOUT value="0" />
+ <VERTALIGN value="0" />
+ </FORMAT>
+ </STYLE>
+ <STYLE>
+ <FOLLOWING name="Standard" />
+ <NAME value="Contents Head 1" />
+ <FLOW align="left" />
+ <COUNTER bullet="183" lefttext="" numberingtype="0" bulletfont="symbol" righttext="" type="0" start="0" depth="0" customdef="" />
+ <FORMAT id="1" pos="0" len="0" >
+ <WEIGHT value="75" />
+ <FONT name="helvetica" />
+ <SIZE value="16" />
+ <ITALIC value="0" />
+ <UNDERLINE value="0" />
+ <STRIKEOUT value="0" />
+ <VERTALIGN value="0" />
+ </FORMAT>
+ </STYLE>
+ <STYLE>
+ <FOLLOWING name="Standard" />
+ <NAME value="Contents Head 2" />
+ <FLOW align="left" />
+ <COUNTER bullet="183" lefttext="" numberingtype="0" bulletfont="symbol" righttext="" type="0" start="0" depth="0" customdef="" />
+ <FORMAT id="1" pos="0" len="0" >
+ <WEIGHT value="75" />
+ <FONT name="helvetica" />
+ <SIZE value="12" />
+ <ITALIC value="0" />
+ <UNDERLINE value="0" />
+ <STRIKEOUT value="0" />
+ <VERTALIGN value="0" />
+ </FORMAT>
+ </STYLE>
+ <STYLE>
+ <FOLLOWING name="Standard" />
+ <NAME value="Contents Head 3" />
+ <FLOW align="left" />
+ <COUNTER bullet="183" lefttext="" numberingtype="0" bulletfont="symbol" righttext="" type="0" start="0" depth="0" customdef="" />
+ <FORMAT id="1" pos="0" len="0" >
+ <WEIGHT value="50" />
+ <FONT name="helvetica" />
+ <SIZE value="12" />
+ <ITALIC value="1" />
+ <UNDERLINE value="0" />
+ <STRIKEOUT value="0" />
+ <VERTALIGN value="0" />
+ </FORMAT>
+ </STYLE>
+ </STYLES>
+ <PIXMAPS/>
+</DOC>
diff --git a/kword/demos/mars.kwd b/kword/demos/mars.kwd
new file mode 100644
index 00000000..73f345d3
--- /dev/null
+++ b/kword/demos/mars.kwd
Binary files differ
diff --git a/kword/demos/statistics.kwd b/kword/demos/statistics.kwd
new file mode 100644
index 00000000..06dd175e
--- /dev/null
+++ b/kword/demos/statistics.kwd
Binary files differ
diff --git a/kword/dtd/DEBUG b/kword/dtd/DEBUG
new file mode 100644
index 00000000..f7e5b994
--- /dev/null
+++ b/kword/dtd/DEBUG
@@ -0,0 +1,11 @@
+How to debug KWord's DTD?
+
+You can debug this DTD with xmllint (from libxml2)
+
+First you have to unzip the KWord file.
+
+Then you can do:
+ xmllint --noout --dtdvalid kword.dtd maindoc.xml
+
+where kword.dtd is the URL to KWord's DTD.
+ \ No newline at end of file
diff --git a/kword/dtd/Makefile.am b/kword/dtd/Makefile.am
new file mode 100644
index 00000000..35fe9977
--- /dev/null
+++ b/kword/dtd/Makefile.am
@@ -0,0 +1,16 @@
+dtd_DATA = kword.dtd
+
+dtddir = $(kde_datadir)/kword/dtd
+
+fs_DATA = framestyles.dtd
+
+fsdir = $(kde_datadir)/kword/dtd
+
+ts_DATA = tablestyles.dtd
+
+tsdir = $(kde_datadir)/kword/dtd
+
+tt_DATA = tabletemplates.dtd
+
+ttdir = $(kde_datadir)/kword/dtd
+
diff --git a/kword/dtd/framestyles.dtd b/kword/dtd/framestyles.dtd
new file mode 100644
index 00000000..0b8c8733
--- /dev/null
+++ b/kword/dtd/framestyles.dtd
@@ -0,0 +1,52 @@
+<!--
+ A framestyle holds properties for borders, background and can be identified with a name.
+-->
+<!ELEMENT FRAMESTYLES
+ (FRAMESTYLE*)>
+<!ELEMENT FRAMESTYLE
+ (NAME|TOPBORDER|BOTTOMBORDER|RIGHTBORDER|LEFTBORDER)>
+<!ATTLIST FRAMESTYLE
+ red CDATA #REQUIRED
+ green CDATA #REQUIRED
+ blue CDATA #REQUIRED>
+
+<!--
+ Copied from kword.dtd (01-06-2002)
+-->
+
+<!ELEMENT NAME
+ EMPTY>
+<!ATTLIST NAME
+ value CDATA #REQUIRED>
+<!ELEMENT LEFTBORDER
+ EMPTY>
+<!ATTLIST LEFTBORDER
+ red CDATA #REQUIRED
+ green CDATA #REQUIRED
+ blue CDATA #REQUIRED
+ style CDATA #REQUIRED
+ width CDATA #REQUIRED>
+<!ELEMENT RIGHTBORDER
+ EMPTY>
+<!ATTLIST RIGHTBORDER
+ red CDATA #REQUIRED
+ green CDATA #REQUIRED
+ blue CDATA #REQUIRED
+ style CDATA #REQUIRED
+ width CDATA #REQUIRED>
+<!ELEMENT TOPBORDER
+ EMPTY>
+<!ATTLIST TOPBORDER
+ red CDATA #REQUIRED
+ green CDATA #REQUIRED
+ blue CDATA #REQUIRED
+ style CDATA #REQUIRED
+ width CDATA #REQUIRED>
+<!ELEMENT BOTTOMBORDER
+ EMPTY>
+<!ATTLIST BOTTOMBORDER
+ red CDATA #REQUIRED
+ green CDATA #REQUIRED
+ blue CDATA #REQUIRED
+ style CDATA #REQUIRED
+ width CDATA #REQUIRED>
diff --git a/kword/dtd/kword.dtd b/kword/dtd/kword.dtd
new file mode 100644
index 00000000..1011ef63
--- /dev/null
+++ b/kword/dtd/kword.dtd
@@ -0,0 +1,1426 @@
+<!-- $Id: kword.dtd 466158 2005-10-01 19:30:05Z dfaure $
+
+This is an XML document type definition (DTD) for the KWord document format.
+Written by Kalle Dalheimer <kalle at kde dot org> with (obviously) input from KWord's
+author Reginald Stadlbauer <reggie at kde dot org>.
+
+Kword DTD version 2 has been created by Thomas Zander, but only small adjustments from
+the original version were made.
+
+(In case of questions about this file, please ask one of the KOffice mailing lists!)
+
+About the version
+=================
+
+This is the DTD version 3, for KWord 1.3
+
+The DTD version 1 was used by KWord-0.8 (KOffice-1.0, the one included in KDE-2.0)
+The DTD version 2 was used by KWord-1.1 and KWord-1.2
+
+KWord will read the previous versions of its own file format but this is considered
+the most complete format, we highly encourage you to use this format.
+
+Version 3 specifics that have another meaning when read by earlier versions of KWord:
+* counter: depth and display-levels have been separated, older versions assume display-levels=depth+1
+* TOC: outline and numberingtype=1 have been separated, older versions assume outline if nt=1
+
+KWord overview
+==============
+
+The main structure of each KWord document is a header and a body. The header
+contains things like the paper size, the margins and so on.
+
+The body is organised around the concept of frames. You might have noticed
+that you can do nearly everything with the frames in your KWord document (e.g.
+move them around, interlock them, let your text "flow" through them, etc.). To
+achieve this flexibility, the body actually has to store the data in a
+hierarchy including framesets, frames, paragraphs, and so on.
+
+Framesets hold the actual text. Frames represent the rectangles in which this
+text is "flowed".
+
+Encoding (for advanced users)
+=============================
+
+KWord's document are encoded as UTF-8 by definition. Please use this encoding
+whenever possible. (Remember: ASCII is UTF-8 too and you could use numerical
+character references like &#8164; to keep your document ASCII-clean.)
+
+If you find that writing in UTF-8 is too difficult on the system that you plan
+to use, then please use ISO-10646-UCS2 (also known as UTF-16.)
+
+Please write publicly available KWord documents only in one of these two encodings!
+
+Of course, if you do not use UTF-8, replace any occurrence of UTF-8 in the text below by the
+encoding that you have chosen. And please be sure to correctly define the XML declaration <?xml
+
+(Sorry, ISO-10646-UCS4 (also known as UTF-32) is not available, as QT cannot handle it.)
+
+Some basic notes on XML
+=======================
+
+- All kinds of numbers are stored like this: foo="1" (between " and " :)
+
+- A rational number looks like this: width="1.03" (note: the '.' separates
+integer and fractional parts).
+
+- <XYZ foo="100" bar="0"/> equals <XYZ foo="100" bar="0"></XYZ>
+
+- Unicode-letters (UTF-8 coded) are used to store the text
+
+- Some special characters ('<', '>', '&', '"', ''') are or can be "escaped" ('&lt;', '&gt;', '&amp;', '&quot;', '&apos;')
+Only these characters can be "escaped". XML cannot handle other "escapes", for example those of HTML are not valid (e.g. &eacute; .)
+
+- Please launch KWord and save an empty file - it is much easier to follow
+this documentation if you wade through an (almost empty) example document.
+
+- The XML begins with a special tag like this (it is called the XML declaration):
+
+ <?xml version="1.0" encoding="UTF-8"?>
+
+Each file starts with this tag. Note: You must not "close" this tag (i.e.
+don't put a </?xml...> at the end of the file!).
+
+-->
+
+<!-- A KWord document consists of a paper description, a number of
+ attributes and the framesets which contain the actual data. It
+ can also define a number of styles.
+
+ Attributes:
+
+ editor: The program this file was written with.
+
+ mime: The MIME type (must always have the value
+ application/x-kword).
+
+ syntaxVersion: Integer version of the syntax in the remainder of
+ this file:
+
+ 1...as for KWord 0.8 (KOffice-1.0)
+ 2...as for KWord 1.1 or 1.2
+ 3...as for KWord 1.3
+ KWord can read all previous versions, but always saves in the latest.
+-->
+<!ELEMENT DOC
+ (PAPER, ATTRIBUTES, VARIABLESETTINGS, FOOTNOTESETTING, ENDNOTESETTING, FRAMESETS, STYLES, PICTURES, PIXMAPS, CLIPARTS, SERIALL, (EMBEDDED*), SPELLCHECKIGNORELIST, BOOKMARKS)>
+<!ATTLIST DOC
+ editor CDATA #IMPLIED
+ mime CDATA #FIXED "application/x-kword"
+ syntaxVersion CDATA #REQUIRED>
+
+<!-- Describes the page format. Can have no or one PAPERBORDERS child that
+ describes the margins. Normally this is the first tag in the "header".
+
+ Attributes:
+
+ format: integer value for the page format:
+
+ 0...DIN A3
+ 1...DIN A4
+ 2...DIN A5
+ 3...US LETTER
+ 4...US LEGAL
+ 5...SCREEN (screen sized)
+ 6...CUSTOM (just enter your preferred size)
+ 7...DIN B5
+ 8...US EXECUTIVE
+ etc. See the enum in koffice/lib/kofficeui/koGlobal.h
+
+ width: width in pt.
+
+ height: height in pt.
+
+ orientation: page orientation:
+
+ 0...Portrait
+ 1...Landscape
+
+ columns: the number of columns (only in wordprocessing
+ mode).
+
+ pages: the number of pages. This is saved for information purposes,
+ but not required nor used by KWord.
+
+ columnspacing: the gap (in pt) between the columns (only in
+ wordprocessing mode).
+
+ hType: header style:
+
+ 0...same on all pages
+ 1...different on first, even and odd pages (2&3)
+ 2...different on first and other pages
+ 3...different on even and odd pages
+
+ fType: footer style:
+
+ 0...same on all pages
+ 1...different on first, even and odd pages (2&3)
+ 2...different on first and other pages
+ 3...different on even and odd pages
+
+ spHeadBody: distance (in pt) between headers and the text body (only in
+ wordprocessing mode).
+
+ spFootBody: distance (in pt) between footers and the text body (only in
+ wordprocessing mode).
+ spFootNoteBody: distance ( in pt ) betwwen footnote and text body
+
+ slFootNotePosition: position of footnote separator line
+ centered, right, left
+
+ slFootNoteLength: percentage of page width default is 20
+ slFootNoteWidth: width of line seperator default = 2pt
+ slFootNoteType: type of line seperator solid, dot, dash etc...
+-->
+<!ELEMENT PAPER
+ (PAPERBORDERS?)>
+<!ATTLIST PAPER
+ format CDATA #REQUIRED
+ width CDATA #REQUIRED
+ height CDATA #REQUIRED
+ orientation CDATA #REQUIRED
+ columns CDATA #REQUIRED
+ columnspacing CDATA #REQUIRED
+ pages CDATA #IMPLIED
+ hType CDATA #IMPLIED
+ fType CDATA #IMPLIED
+ spHeadBody CDATA #IMPLIED
+ spFootBody CDATA #IMPLIED
+ spFootNoteBody CDATA #IMPLIED
+ slFootNotePosition CDATA #IMPLIED
+ slFootNoteLength CDATA #IMPLIED
+ slFootNoteWidth CDATA #IMPLIED
+ slFootNoteType CDATA #IMPLIED>
+
+
+<!-- Describes the margins of the page.
+
+ Attributes:
+
+ left: left margin in pt.
+
+ right: right margin in pt.
+
+ top: top margin in pt.
+
+ bottom: bottom margin in pt.
+-->
+<!ELEMENT PAPERBORDERS
+ EMPTY>
+<!ATTLIST PAPERBORDERS
+ left CDATA #REQUIRED
+ right CDATA #REQUIRED
+ top CDATA #REQUIRED
+ bottom CDATA #REQUIRED>
+
+
+<!-- Contains general attributes of the document. Has no children.
+
+ Attributes:
+
+ processing: 0..."Normal" document (Wordprocessing)
+ 1...DTP-document (DTPing)
+
+ standardpage: currently ignored.
+
+ hasHeader: 0...the document has no headers
+ 1...the document has headers
+
+ hasFooter: 0...the document has no footers
+ 1...the document has footers
+
+ unit: Basic unit for positioning, ruler,...
+ This has no influence on the units in this document, only on what the user sees.
+ mm...
+ pt...
+ inch...
+
+ hasTOC: 0...the document has no TOC
+ 1...the document has TOC
+
+ tabStopValue: tabstop value in pt
+
+ activeFrameset: the name of the frameset that was edited when saving the document
+ cursorParagraph:if activeFrameset is a text frameset, the paragraph ID of the cursor
+ cursorIndex: if activeFrameset is a text frameset, the character index of the cursor
+-->
+<!ELEMENT ATTRIBUTES
+ EMPTY>
+<!ATTLIST ATTRIBUTES
+ processing CDATA #REQUIRED
+ standardpage CDATA #IMPLIED
+ hasHeader CDATA #IMPLIED
+ hasFooter CDATA #IMPLIED
+ unit CDATA #IMPLIED
+ hasTOC CDATA #IMPLIED
+ tabStopValue CDATA #IMPLIED
+ activeFrameset CDATA #IMPLIED
+ cursorParagraph CDATA #IMPLIED
+ cursorIndex CDATA #IMPLIED>
+
+
+<!-- Contains general attributes variables. Has no children.
+
+ Attributes:
+ startingPageNumber: the starting page number.
+ displaylink ### TODO: document!
+ underlinelink: Underline links by default (true/false)
+ displaycomment: Display comment (true/false)
+ displayfieldcode: Display the name of the variables if true (instead of their value)
+ lastPrintingDate: Last printing date, in ISO-8601 format
+ creationDate: Creation date of the document, in ISO-8601 format
+ modificationDate: Modification date of the document, in ISO-8601 format
+-->
+<!ELEMENT VARIABLESETTINGS
+ EMPTY>
+<!ATTLIST VARIABLESETTINGS
+ startingPageNumber CDATA #IMPLIED
+ displaylink CDATA #IMPLIED
+ underlinelink CDATA #IMPLIED
+ displaycomment CDATA #IMPLIED
+ displayfieldcode CDATA #IMPLIED
+ lastPrintingDate CDATA #IMPLIED
+ creationDate CDATA #IMPLIED
+ modificationDate CDATA #IMPLIED>
+
+
+<!-- Contains general attributes for footnote.
+
+ Attributes: see counter !
+
+ Ignore bullet, restart and depth.
+-->
+<!ELEMENT FOOTNOTESETTING
+ EMPTY>
+<!ATTLIST FOOTNOTESETTING
+ type CDATA #REQUIRED
+ depth CDATA #REQUIRED
+ bullet CDATA #IMPLIED
+ start CDATA #IMPLIED
+ numberingtype CDATA #IMPLIED
+ lefttext CDATA #IMPLIED
+ righttext CDATA #IMPLIED
+ bulletfont CDATA #IMPLIED
+ customdef CDATA #IMPLIED
+ restart CDATA #IMPLIED>
+
+<!-- Contains general attributes for endnote.
+
+ Attributes: see counter !
+
+ Ignore bullet, restart and depth.
+-->
+<!ELEMENT ENDNOTESETTING
+ EMPTY>
+<!ATTLIST ENDNOTESETTING
+ type CDATA #REQUIRED
+ depth CDATA #REQUIRED
+ bullet CDATA #IMPLIED
+ start CDATA #IMPLIED
+ numberingtype CDATA #IMPLIED
+ lefttext CDATA #IMPLIED
+ righttext CDATA #IMPLIED
+ bulletfont CDATA #IMPLIED
+ customdef CDATA #IMPLIED
+ restart CDATA #IMPLIED>
+
+
+<!-- Container that has a number of FRAMESET children.
+-->
+<!ELEMENT FRAMESETS
+ (FRAMESET+)>
+
+
+<!-- A frameset that bundles a number of FRAME elements (at least one).
+ In addition it can have a more specific element, depending on frameType.
+
+ Attributes:
+
+ frameType: 0...Base frame (for internal use only!!!)
+ 1...Text frame (contains PARAGRAPH tags)
+ 2...Picture frame (contains a PICTURE tag, or an IMAGE tag for KWord 1.1)
+ 3...Part frame (defined in EMBEDDED at the doc level) ### FIXME: does not happen in a FRAMESET but only in SETTINGS
+ 4...Formula frame (contains a FORMULA tag)
+ 5...Clipart frame (contains a CLIPART tag, only for KWord 1.1)
+ 6...Horizontal line frame (contains a PICTURE tag)
+ 10..reserved (internally for tables)
+
+ frameInfo: 0...normal text (or non-text frame)
+ 1...header for first page
+ 2...header for even pages (user-wise, i.e. with pages starting at 1)
+ 3...header for odd pages (user-wise, i.e. with pages starting at 1)
+ 4...footer for first page
+ 5...footer for even pages (user-wise, i.e. with pages starting at 1)
+ 6...footer for odd pages (user-wise, i.e. with pages starting at 1)
+ 7...footnote
+ When the document uses the same headers on even and odd pages (hType=0,2),
+ the header being used is the one for odd pages (frameInfo=3).
+
+ removable: Whether the header-frame is removable or not:
+ Used in tables where header cells on new pages are
+ auto created with this set to 1.
+ 0...no (default)
+ 1...yes
+
+ visible: Whether the frame is visible or not:
+
+ 0...no
+ 1...yes (default)
+
+ grpMgr: If present, indicates that this frameset is
+ a cell in a table. The value is the name of the
+ group manager for this table. (i.e. If this
+ frameset "belongs" to a table the position and the
+ size are contolled by a group manager (one for
+ each table)).
+
+ row: Position in the table (only for tables). Index
+ starts at 0. The index for the next row must equal
+ the index for the current row, plus the
+ value of "rows" for the current row.
+
+ col: Ditto for columns.
+
+ rows: Size of this cell in rows (only for tables).
+ can be 1 or greater.
+
+ cols: Ditto for columns.
+
+ protectContent: Protect content of text object
+
+ protectSize: Prevent user from changing size and position
+ of the frames in this frameset.
+
+ 0...no (default)
+ 1...yes
+
+
+-->
+<!ELEMENT FRAMESET
+ (FRAME|PARAGRAPH|PICTURE|IMAGE|CLIPART|FORMULA)*> <!-- ### missing: defining FORMULA -->
+<!ATTLIST FRAMESET
+ name CDATA #REQUIRED
+ frameType CDATA #REQUIRED
+ frameInfo CDATA #REQUIRED
+ removable CDATA #IMPLIED
+ visible CDATA #IMPLIED
+ grpMgr CDATA #IMPLIED
+ row CDATA #IMPLIED
+ col CDATA #IMPLIED
+ rows CDATA #IMPLIED
+ cols CDATA #IMPLIED
+ protectContent CDATA #IMPLIED
+ protectSize CDATA #IMPLIED>
+
+<!ELEMENT FRAME
+ EMPTY>
+
+<!-- Describes a frame of a frameset.
+
+ Attributes:
+
+ right, left, top,
+ bottom: absolute coordinates in pt.
+
+ min-height: If set (and >0), this is the minimum height. Applies to AutoExtendFrame.
+
+ runaround: 0...No run around, the text runs through the frame
+ 1...Frame repels text in overlapping frames
+ 2...Text in overlapping frames will avoid the
+ complete horizontal space of this frame.
+
+ runaroundSide: when runaround is 1 specify here the side of the frame
+ on which the text should flow.
+ Values: "left", "right" or "biggest". Default is biggest.
+
+ runaroundGap: when runaround is 1 specify here the distance (in pt)
+ between overlapping frames and runaround text
+
+ autoCreateNewFrame: What to do if the text is bigger than the frame:
+ 0...AutoExtendFrame (use this for headers/footers)
+ Make frame bigger to fit text.
+ 1...AutoCreateNewFrame (use this for the normal text body)
+ Place a new frame on next page.
+ 2...Ignore extra text
+
+ newFrameBehaviour: DEPRECATED use newFrameBehavior instead.
+ newFrameBehavior: 0...On creating a new page, reconnect frame
+ to current frameset (use this for the normal text body).
+ 1...Don't create a followup frame on the new
+ page.
+ 2...This frame will be shown on the new page
+ as well (with the same content)
+
+ copy: 0...Not a copy
+ 1...This frame is a copy of the previous frame in this frameset
+ (default is 1 for headers and footers and 0 for the others)
+
+ sheetSide: 0...AnySide
+ 1...this frame will only be shown on odd pages
+ 2...this frame will only be shown on even pages
+
+ lWidth, rWidth, tWidth, bWidth: width (in pt) of a frame border (left, right, top, bottom)
+
+ lRed, lGreen, lBlue: color (rgb) of the left frame border
+ rRed, rGreen, rBlue: color (rgb) of the right frame border
+ tRed, tGreen, tBlue: color (rgb) of the top frame border
+ bRed, bGreen, bBlue: color (rgb) of the bottom frame border
+
+ lStyle, rStyle, tStyle, bStyle: style of a frame border (left, right, top, bottom)
+ Solid = 0, Dash = 1, Dot = 2, Dash_dot = 3, Dash_dot_dot = 4
+
+ bkRed, bkGreen, bkBlue: color (rgb) used as the frame's background color
+ bkStyle : style of a frame background color
+ None = 0, SolidPattern = 1, Dense1Pattern = 2, Dense2Pattern = 3, Dense3Pattern = 4, Dense4Pattern = 5 etc... (look at in qbrush documentation)
+
+ bleftpt, brightpt, btoppt, bbottompt: frame margins (internal to the frame)
+
+ z-index: z index (signed int).
+ Relative to the other frame in the same page.
+ The frame with the biggest z index in a given page, is on top.
+-->
+<!ATTLIST FRAME
+ left CDATA #REQUIRED
+ right CDATA #REQUIRED
+ top CDATA #REQUIRED
+ bottom CDATA #REQUIRED
+ min-height CDATA #IMPLIED
+ runaround CDATA #IMPLIED
+ runaroundSide CDATA #IMPLIED
+ runaroundGap CDATA #IMPLIED
+ autoCreateNewFrame CDATA #IMPLIED
+ newFrameBehavior CDATA #REQUIRED
+ copy CDATA #IMPLIED
+ sheetSide CDATA #IMPLIED
+ lWidth CDATA #IMPLIED
+ rWidth CDATA #IMPLIED
+ tWidth CDATA #IMPLIED
+ bWidth CDATA #IMPLIED
+ lRed CDATA #IMPLIED
+ lGreen CDATA #IMPLIED
+ lBlue CDATA #IMPLIED
+ rRed CDATA #IMPLIED
+ rGreen CDATA #IMPLIED
+ rBlue CDATA #IMPLIED
+ tRed CDATA #IMPLIED
+ tGreen CDATA #IMPLIED
+ tBlue CDATA #IMPLIED
+ bRed CDATA #IMPLIED
+ bGreen CDATA #IMPLIED
+ bBlue CDATA #IMPLIED
+ lStyle CDATA #IMPLIED
+ rStyle CDATA #IMPLIED
+ tStyle CDATA #IMPLIED
+ bStyle CDATA #IMPLIED
+ bkRed CDATA #IMPLIED
+ bkGreen CDATA #IMPLIED
+ bkBlue CDATA #IMPLIED
+ bkStyle CDATA #IMPLIED
+ bleftpt CDATA #IMPLIED
+ brightpt CDATA #IMPLIED
+ btoppt CDATA #IMPLIED
+ bbottompt CDATA #IMPLIED
+ z-index CDATA #IMPLIED>
+
+<!ELEMENT PARAGRAPH
+ (TEXT|FORMATS|LAYOUT)*>
+
+<!-- Just guess :) The text is stored as UTF-8 coded Unicode
+ glyphs. Note: the format-tags navigate in the text using an index
+ which starts at 0 and runs up till it reaches length-1.
+
+ Some special character codes map to special features:
+ 0xad is a soft hyphen
+ 0xa0 is a non-breaking space
+ 0x2011 is a non-breaking hyphen
+ \n is a linebreak (within the paragraph)
+ \t is a tabulator
+
+ Attributes:
+
+ xml:space: "preserve" tells parsers to keep white spaces
+-->
+<!ELEMENT TEXT
+ (#PCDATA)>
+<!ATTLIST TEXT
+ xml:space (preserve) #FIXED "preserve">
+
+<!-- List of formats that apply to a given paragraph
+-->
+<!ELEMENT FORMATS
+ (FORMAT*)>
+
+<!-- A format tag describes the format of one or more characters in the
+ text.
+
+ Attributes:
+
+ id: type of format information:
+
+ 0...none (mustn't be in a file)
+ 1..."normal" text
+ 2...a picture - in that case, only IMAGE is specified.
+ This is DEPRECATED, use a floating frame instead.
+ 3...tabulator - Not supported anymore. Use a '\t' in the text instead.
+ 4...a variable - in that case, VARIABLE is also specified
+ 5...a footnote - DEPRECATED (KOffice-1.0)
+ 6...an anchor for a floating frame - in that case, only ANCHOR is specified.
+
+ pos: position where the format starts. This is a
+ zero-based index into the text of the
+ paragraph.
+
+ len: number of characters after pos for which the
+ format is used. 1 for all ids except "normal text".
+
+ When FORMAT is used to specify the format of a style, pos and len are omitted.
+-->
+<!ELEMENT FORMAT
+ (COLOR|FONT|SIZE|WEIGHT|ITALIC|UNDERLINE|STRIKEOUT|VERTALIGN|SHADOW|FONTATTRIBUTE|LANGUAGE|ANCHOR|IMAGE|PICTURE|VARIABLE|TEXTBACKGROUNDCOLOR|OFFSETFROMBASELINE)*>
+
+
+<!ATTLIST FORMAT
+ id CDATA #REQUIRED
+ pos CDATA #IMPLIED
+ len CDATA #IMPLIED>
+
+
+<!-- LAYOUT
+ A layout holds all the attributes related to a paragraph,
+ other than its text and formatting.
+ Each of the child elements can be present only once, except
+ TABULATOR which can be repeated.
+ The FORMAT tag here is the 'default format' for the paragraph.
+-->
+<!ENTITY % layout "NAME|FLOW|INDENTS|OFFSETS|LINESPACING|PAGEBREAKING|
+ LEFTBORDER|RIGHTBORDER|TOPBORDER|BOTTOMBORDER|COUNTER|FORMAT|
+ TABULATOR*">
+<!ELEMENT LAYOUT
+ (%layout;)*>
+
+<!--
+ A style is a global setting that is used for all paragraphs which use that
+ style. As the markup is stored in one place (the style) changing the markup
+ throughout the document is simply a task of changing one or two styles.
+ Highly recommended for structured documents.
+
+ A style element contains the same child elements as the LAYOUT tag:
+ all the paragraph properties, as well as a text format.
+ It also contains the name of the following style, i.e. the one used when
+ the user presses Enter in a paragraph using this style.
+
+ Attributes:
+ outline if "true", this style is part of the Table Of Contents.
+ (by default it is not).
+-->
+<!ELEMENT STYLES
+ (STYLE*)>
+<!ELEMENT STYLE
+ (%layout;|FOLLOWING)*>
+<!ATTLIST STYLE
+ outline CDATA #IMPLIED>
+
+<!--
+ Defines the color of the text, using RGB.
+ (-1,-1,-1) means "default color", i.e. the base color from the color scheme
+ (usually black).
+-->
+<!ELEMENT COLOR
+ EMPTY>
+<!ATTLIST COLOR
+ red CDATA #REQUIRED
+ green CDATA #REQUIRED
+ blue CDATA #REQUIRED>
+
+<!--
+ Defines the background color of the text (aka "highlight"), using RGB.
+ (-1,-1,-1) means "default color", i.e. the base color from the color scheme
+ (usually white).
+-->
+<!ELEMENT TEXTBACKGROUNDCOLOR
+ EMPTY>
+<!ATTLIST TEXTBACKGROUNDCOLOR
+ red CDATA #REQUIRED
+ green CDATA #REQUIRED
+ blue CDATA #REQUIRED>
+
+
+<!--
+ A framestyle holds properties for borders, background and can be identified with a name.
+-->
+<!ELEMENT FRAMESTYLES
+ (FRAMESTYLE*)>
+<!ELEMENT FRAMESTYLE
+ (NAME|LEFTBORDER|RIGHTBORDER|TOPBORDER|BOTTOMBORDER)>
+<!ATTLIST FRAMESTYLE
+ red CDATA #REQUIRED
+ green CDATA #REQUIRED
+ blue CDATA #REQUIRED>
+
+
+<!--
+ A tablestyle holds properties for borders, background and (text)style. A tablestyle is
+ identified via its name. The properties are reach via the names corresponding to the
+ framestyle and style.
+-->
+<!ELEMENT TABLESTYLES
+ (TABLESTYLE*)>
+
+<!ELEMENT TABLESTYLE
+ (NAME|PSTYLE|PFRAMESTYLE)>
+
+<!ELEMENT PFRAMESTYLE
+ EMPTY>
+<!ATTLIST PFRAMESTYLE
+ name CDATA #REQUIRED>
+
+<!ELEMENT PSTYLE
+ EMPTY>
+<!ATTLIST PSTYLE
+ name CDATA #REQUIRED>
+
+
+<!--
+ name is the family name. Don't include fontsizes or bold, that is put in another tag.
+-->
+<!ELEMENT FONT
+ EMPTY>
+<!ATTLIST FONT
+ name CDATA #REQUIRED>
+
+<!-- SIZE
+ When size is used in a format the size is in points.
+-->
+<!ELEMENT SIZE
+ EMPTY>
+<!ATTLIST SIZE
+ value CDATA #REQUIRED>
+
+<!-- WEIGHT
+ Weight of a font is it's Boldness. Look at the QFont weight description for precise
+ numbers. Use normal=50, bold=75.
+-->
+<!ELEMENT WEIGHT
+ EMPTY>
+<!ATTLIST WEIGHT
+ value CDATA #REQUIRED>
+
+<!-- ITALIC
+ Value is either 0 or 1 with 1=true and 0=false
+-->
+<!ELEMENT ITALIC
+ EMPTY>
+<!ATTLIST ITALIC
+ value CDATA #REQUIRED>
+
+<!-- UNDERLINE
+ Value is either 0 or 1 or single or double or single-bold
+ 0 = no underline
+ 1 or single = single underline
+ double = double-underline.
+ single-bold = thick underline
+ wave = wave underline
+ styleline type of underline
+ : solid, dash, dot, dashdot, dashdotdot
+ underlinecolor : color of underline line.
+ wordbyword: 0 or 1. If 1, spaces are not underlined. Opposite of fo:score-spaces.
+
+-->
+<!ELEMENT UNDERLINE
+ EMPTY>
+<!ATTLIST UNDERLINE
+ value CDATA #REQUIRED
+ styleline CDATA #REQUIRED
+ underlinecolor CDATA #REQUIRED
+ wordbyword CDATA #REQUIRED>
+
+<!-- STRIKEOUT
+ value: 0, 1 (or single), double, single-bold (see UNDERLINE)
+ styleline: style of strikeout line solid, dash, dot, dashdot, dashdotdot
+ wordbyword: 0 or 1. If 1, spaces are not striked out. Opposite of fo:score-spaces.
+-->
+<!ELEMENT STRIKEOUT
+ EMPTY>
+<!ATTLIST STRIKEOUT
+ value CDATA #REQUIRED
+ styleline CDATA #REQUIRED
+ wordbyword CDATA #REQUIRED>
+
+<!-- VERTALIGN
+ Super/sub script.
+ value: 0 = Normal
+ 1 = Subscript
+ 2 = Superscript
+ relativetextsize: 0.75 means 3/4 of the normal font size.
+-->
+<!ELEMENT VERTALIGN
+ EMPTY>
+<!ATTLIST VERTALIGN
+ value CDATA #REQUIRED
+ relativetextsize CDATA #REQUIRED>
+
+<!-- SHADOW
+ The value is the CSS specification for text-shadow (also used by XSL-FO).
+ http://www.w3.org/TR/REC-CSS2/text.html#text-shadow-props
+ KWord only supports a single shadow, and no blur radius, so it amounts to
+ either "none" or "color length length".
+-->
+<!ELEMENT SHADOW
+ EMPTY>
+<!ATTLIST SHADOW
+ text-shadow CDATA #REQUIRED>
+
+
+<!-- OFFSETFROMBASELINE
+ Value is define in pt
+-->
+<!ELEMENT OFFSETFROMBASELINE
+ EMPTY>
+<!ATTLIST OFFSETFROMBASELINE
+ value CDATA #REQUIRED>
+
+<!-- FONTATTRIBUTE
+ Value is either "none", "smallcaps", "uppercase", or "lowercase"
+-->
+<!ELEMENT FONTATTRIBUTE
+ EMPTY>
+<!ATTLIST FONTATTRIBUTE
+ value CDATA #REQUIRED>
+
+<!-- LANGUAGE
+ The name of the language used by this text span.
+ This is usually a two letters code, or ll_CC where a country is specified.
+-->
+<!ELEMENT LANGUAGE
+ EMPTY>
+<!ATTLIST LANGUAGE
+ value CDATA #REQUIRED>
+
+
+<!-- NAME
+ The name of a style.
+ If inside a <STYLE> tag, this defines the name of the style.
+ If inside a <LAYOUT> tag, this refers to an existing style,
+ to be used for this paragraph.
+-->
+<!ELEMENT NAME
+ EMPTY>
+<!ATTLIST NAME
+ value CDATA #REQUIRED>
+
+<!-- FOLLOWING
+ The FOLLOWING tag is a styles tag. You can only embed it in a style.
+ With this tag you can tell kword to switch to the style 'name' after
+ enter was pressed and the current style was used.
+ Example: Style H1 has the <following name="body"> tag. When the user is
+ finished typing the header tag and presses enter kword switches to the
+ style 'body'
+ The style-name given should be available.
+-->
+<!ELEMENT FOLLOWING
+ EMPTY>
+<!ATTLIST FOLLOWING
+ name CDATA #REQUIRED>
+
+<!-- FLOW
+ FLOW is a paragraph and style tag, that determines the alignment of the text.
+ align's value is one of: 'left', 'right', 'center', 'justify'
+ It can also be 'auto' for styles, meaning right for RTL text, left otherwise.
+
+ dir: Indicates the direction of the paragraph. 'L' or 'R' for left-to-right and right-to-left.
+ Automatic direction (dependent on first character) is the default.
+-->
+<!ELEMENT FLOW
+ EMPTY>
+<!ATTLIST FLOW
+ align (left|right|center|justify|auto) #REQUIRED
+ dir (L|R) #IMPLIED>
+
+<!-- INDENTS
+ left: indent (pt) that is used for the other lines in a paragraph.
+ right: indent (pt) on the right of all lines in the paragraph
+ first: indent (pt) from the left border (of the frame) of the first line of a paragraph.
+ This indent is added from the left indent (or to the right indent
+ in a right-to-left paragraph).
+ If not specified, the default value is 0.
+-->
+<!ELEMENT INDENTS
+ EMPTY>
+<!ATTLIST INDENTS
+ first CDATA #IMPLIED
+ left CDATA #IMPLIED
+ right CDATA #IMPLIED>
+
+<!-- OFFSETS
+ before: space before the paragraph, or "head offset" (KWord-0.8), aka "top margin" (KWord-1.0) (pt)
+ after: space after the paragraph, or "foot offset" (KWord-0.8), aka "bottom margin" (KWord-1.0) (pt)
+ If not specified, the default value is 0.
+-->
+<!ELEMENT OFFSETS
+ EMPTY>
+<!ATTLIST OFFSETS
+ before CDATA #IMPLIED
+ after CDATA #IMPLIED>
+
+<!--
+ A paragraph and a style can have counter data.
+ The document will do the counting of the paragraphs that use this.
+
+ type: 0 = None
+ 1 = Numeral
+ 2 = Alphabetical
+ 3 = Alphabetical uppercase
+ 4 = Roman numbering
+ 5 = Roman numbering uppercase
+ 6 = Custom bullet (one char, set by the 'bullet' attribute)
+ 7 = Custom (complex string, see kword's dialog)
+ 8 = Circle bullet (empty circle)
+ 9 = Square bullet (full square)
+ 10 = Disc bullet (full circle)
+ 11 = Box bullet (empty square)
+
+ depth The level of the numbering.
+ Depth of 0 means the major numbering. (1, 2, 3...)
+ Depth of 1 is 1.1, 1.2, 1.3 etc.
+
+ start The first used number in the numbering (usually 1).
+ List numbering starts at <start> initially, or when restart is set to true.
+ numberingtype
+ 0 = list numbering, 1 = chapter numbering.
+ Chapter numbering is used throughout the whole document (in future throughout books)
+ lefttext
+ The text that is printed left of the first numeral
+ righttext
+ The text that is printed right of the last numeral
+ A usual value for this one is "." (dot).
+
+ bullet The unicode character code that is the custom bullet (for type=6)
+ bulletfont
+ The font to use for the custom bullet can be found in (use "symbol" if in doubt)
+ customdef
+ Definition of a custom counter - not supported yet
+ restart
+ If "true" or "1", this paragraph is numbered as specified by start.
+ Otherwise (default) it will extend the current list (with equal type and depth).
+
+ text The text shown by the counter in the document when it was saved.
+ This is redundant information, unused by KWord upon loading, but useful
+ for export filters.
+
+ display-levels Number of levels to display (e.g. 3 means "1.2.1")
+
+ align Counter alignment. Possible values include:
+ int(Qt::AlignAuto), //left for LTR text and right for RTL text
+ int(Qt::AlignLeft),
+ int(Qt::AlignRight).
+-->
+<!ELEMENT COUNTER
+ EMPTY>
+<!ATTLIST COUNTER
+ type CDATA #REQUIRED
+ depth CDATA #REQUIRED
+ bullet CDATA #IMPLIED
+ start CDATA #IMPLIED
+ numberingtype CDATA #REQUIRED
+ lefttext CDATA #IMPLIED
+ righttext CDATA #IMPLIED
+ bulletfont CDATA #IMPLIED
+ customdef CDATA #IMPLIED
+ restart CDATA #IMPLIED
+ text CDATA #IMPLIED
+ display-levels CDATA #IMPLIED
+ align CDATA #IMPLIED>
+
+<!--
+ Linespacing defines the height of a line in a paragraph.
+ By default the line height is the height of the biggest character in the line.
+
+ The "type" can be "oneandhalf" for 1.5 * line_height and "double" for 2 * line_height.
+ More generally it can also be "multiple", where spacingvalue=3 means 3 * line_height.
+ Other values for the type are
+ "custom": spacingvalue is the distance between the lines in pt (added to the line height)
+ "atleast": the total line height is at least spacingvalue (in pt)
+ "fixed": spacingvalue is equal to the total line height (in pt).
+
+ See koffice/lib/kotext/koparaglayout.h for more details.
+
+ spacingvalue isn't used if type is "oneandhalf" or "double".
+
+ Compatibility note: KWord-1.1 only had a "value" attribute, which could
+ be set to a pt value (for custom), to "oneandhalf" or to "double".
+-->
+<!ELEMENT LINESPACING
+ EMPTY>
+<!ATTLIST LINESPACING
+ type (oneandhalf|double|custom|atleast|multiple|fixed) #IMPLIED
+ spacingvalue CDATA #IMPLIED>
+
+<!--
+ Attributes relating to the way paragraphs are broken at the end of a frame/page.
+ If this element isn't specified, the default is to break between lines of a parag.
+
+ linesTogether: if "true", all the lines of a given paragraph remain together.
+ hardFrameBreak: if "true", this paragraph is always at the beginning of a frame.
+ hardFrameBreakAfter: if "true", this paragraph is always the last in the frame.
+
+ Future extensions: keepWithPrevious, keepWithNext
+-->
+<!ELEMENT PAGEBREAKING
+ EMPTY>
+<!ATTLIST PAGEBREAKING
+ linesTogether (true|false) #IMPLIED
+ hardFrameBreak (true|false) #IMPLIED
+ hardFrameBreakAfter (true|false) #IMPLIED>
+
+<!--
+ The borders can be used on a frame and on a paragraph.
+ the border has a color, displayed in the RGB value.
+ The width is in points.
+ Style 0 = solid
+ 1 = dashes
+ 2 = dots
+ 3 = dash - dot patterns
+ 4 = dash dot dot patterns
+ 5 = double line
+-->
+<!ELEMENT LEFTBORDER
+ EMPTY>
+<!ATTLIST LEFTBORDER
+ red CDATA #REQUIRED
+ green CDATA #REQUIRED
+ blue CDATA #REQUIRED
+ style CDATA #REQUIRED
+ width CDATA #REQUIRED>
+<!ELEMENT RIGHTBORDER
+ EMPTY>
+<!ATTLIST RIGHTBORDER
+ red CDATA #REQUIRED
+ green CDATA #REQUIRED
+ blue CDATA #REQUIRED
+ style CDATA #REQUIRED
+ width CDATA #REQUIRED>
+<!ELEMENT TOPBORDER
+ EMPTY>
+<!ATTLIST TOPBORDER
+ red CDATA #REQUIRED
+ green CDATA #REQUIRED
+ blue CDATA #REQUIRED
+ style CDATA #REQUIRED
+ width CDATA #REQUIRED>
+<!ELEMENT BOTTOMBORDER
+ EMPTY>
+<!ATTLIST BOTTOMBORDER
+ red CDATA #REQUIRED
+ green CDATA #REQUIRED
+ blue CDATA #REQUIRED
+ style CDATA #REQUIRED
+ width CDATA #REQUIRED>
+
+<!-- Defines the position of a tabulation
+ Attributes:
+
+ type: 0 .. left
+ 1 .. center
+ 2 .. right
+ 3 .. alignment at specified character
+
+ ptpos: Position of the tabulation, in pt
+
+ filling: 0 .. blank
+ 1 .. dots
+ 2 .. line
+ 3 .. dash
+ 4 .. dash-dot
+ 5 .. dash-dot-dot
+
+ width: Width of the filling, in pt
+
+ alignchar: character at which text will be aligned when
+ type==3 (former "decimal point") is set
+-->
+<!ELEMENT TABULATOR
+ EMPTY>
+<!ATTLIST TABULATOR
+ type CDATA #REQUIRED
+ ptpos CDATA #REQUIRED
+ filling CDATA #IMPLIED
+ width CDATA #IMPLIED
+ alignchar CDATA #IMPLIED>
+
+<!-- An anchor describes an object which is anchored.
+
+ Attributes:
+
+ type: What kind of object is being anchored?
+
+ grpMgr: a table [deprecated]
+ frameset: a frameset [default]
+
+ instance: An identifier that uniquely names the
+ particular instance of the type of object
+ being anchored.
+ For framesets, this is the frameset name.
+-->
+
+<!ELEMENT ANCHOR
+ EMPTY>
+<!ATTLIST ANCHOR
+ type CDATA #REQUIRED
+ instance CDATA #REQUIRED>
+
+<!-- Definition of a picture - contains only one element, the key to the picture.
+-->
+<!ELEMENT PICTURE
+ (KEY)>
+<!ATTLIST PICTURE
+ keepAspectRatio CDATA #REQUIRED>
+
+<!-- Definition of an image - contains only one element, the key to the image.
+ Only for KWord 1.1. compatibility
+-->
+<!ELEMENT IMAGE
+ (KEY)>
+<!ATTLIST IMAGE
+ keepAspectRatio CDATA #REQUIRED>
+
+<!-- Definition of a clipart - contains only one element, the key to the clipart.
+ Only for KWord 1.1. compatibility
+-->
+<!ELEMENT CLIPART
+ (KEY)>
+
+<!-- Variable
+ A variable has always two child elements:
+ TYPE, and another one depending on the type.
+-->
+<!ELEMENT VARIABLE
+ (TYPE,(DATE|TIME|PGNUM|CUSTOM|MAILMERGE|FIELD|LINK|NOTE|FOOTNOTE))>
+
+<!-- Variable type
+ Attributes:
+ type
+ 0... Date (uses DATE to save it)
+ 1... [currently unused]
+ 2... Time fixed (uses TIME to save it)
+ 3... [currently unused]
+ 4... Page number / number of pages (uses PGNUM to save it)
+ 5... [currently unused]
+ 6... Custom (uses CUSTOM to save it)
+ 7... Mail Merge variable (uses MAILMERGE to save it)
+ 8... Field (uses FIELD to save it)
+ 9... Link (uses LINK)
+ 10... Note (uses NOTE)
+ 11... Footnote (uses FOOTNOTE)
+ 12... Statictic (uses STATISTIC)
+
+ key the description of the variable format used to display this variable.
+ The first 4 letters identify the class of format:
+ DATE = a date
+ TIME = a time
+ NUMB = a number
+ STRI = a string
+ The rest (after the 4 letters) is quite internal, and depends on the type of variable.
+
+ text the text shown by the variable in the document when it was saved.
+ This is redundant information, unused by KWord upon loading, but useful
+ for export filters.
+-->
+<!ELEMENT TYPE
+ EMPTY>
+<!ATTLIST TYPE
+ type CDATA #REQUIRED
+ key CDATA #IMPLIED
+ text CDATA #IMPLIED>
+
+<!-- Date value contained in a date variable.
+ day... the day number
+ month.. the month number
+ year... the year number
+ fix.... 1 if the time is fixed, 0 if it's variable ("the current time")
+ correct... adjustement
+ subtype...
+ 0 = fixed date, will never update itself automatically
+ 1 = current date, updated as soon as the file is loaded
+ The value in the file is the value that the var had when saving.
+ 2 = date of last printing
+ 3 = date of file creation
+ 4 = date of last modification
+-->
+<!ELEMENT DATE
+ EMPTY>
+<!ATTLIST DATE
+ day CDATA #REQUIRED
+ month CDATA #REQUIRED
+ year CDATA #REQUIRED
+ fix CDATA #REQUIRED
+ correct CDATA #IMPLIED
+ subtype CDATA #REQUIRED
+ hour CDATA #IMPLIED
+ minute CDATA #IMPLIED
+ second CDATA #IMPLIED>
+
+<!-- Time value contained in a time variable.
+ hour... the hour number
+ minute.. the minute number
+ second... the second number
+ fix.... 1 if the time is fixed, 0 if it's variable ("the current time")
+ A time that is not fixed (variable) will be updated as soon as the file is loaded.
+ The value in the file is only the value that the var had when saving.
+ correct... adjustement
+-->
+<!ELEMENT TIME
+ EMPTY>
+<!ATTLIST TIME
+ hour CDATA #REQUIRED
+ minute CDATA #REQUIRED
+ second CDATA #REQUIRED
+ fix CDATA #REQUIRED
+ correct CDATA #IMPLIED>
+
+<!-- Details for a page-related variable.
+ subtype... Variable subtype:
+ 0... number of current page.
+ 1... total number of pages.
+ 2... title of the current section
+ value... The variable value, number for subtype=0/1, string for subtype=2
+-->
+<!ELEMENT PGNUM
+ EMPTY>
+<!ATTLIST PGNUM
+ subtype CDATA #REQUIRED
+ value CDATA #REQUIRED>
+
+<!-- Details for a custom variable.
+ name... The variable name
+ value... The variable value
+ Both name and value are entered by the user, they can be anything.
+-->
+<!ELEMENT CUSTOM
+ EMPTY>
+<!ATTLIST CUSTOM
+ name CDATA #REQUIRED
+ value CDATA #REQUIRED>
+
+<!-- <MAILMERGE> exists as two versions:
+ - a mail-merge variable
+ - the global mail merge settings
+
+ The mail-merge variable has the attribute "name" (#REQUIRED in that case) and no children (EMPTY)
+ The global seetings has no attributes but has children (PLUGIN and DATASOURCE)
+-->
+<!ELEMENT MAILMERGE
+ (PLUGIN, DATASOURCE)?>
+<!ATTLIST MAILMERGE
+ name CDATA #IMPLIED>
+
+<!--
+ The plugin being used. library is the name of the lib, like "kwmailmerge_qtsqldb_power"
+-->
+<!ELEMENT PLUGIN
+ EMPTY>
+<!ATTLIST PLUGIN
+ library CDATA #REQUIRED>
+<!--
+ The children of <DATASOURCE> depends on the plugin
+-->
+<!ELEMENT DATASOURCE
+ ANY>
+<!--
+For the QtSQL-power-plugin, the contents of DATASOURCE is
+ (DEFINITION,SAMPLERECORD)
+ DEFINITION is (DATABASE,QUERY)
+ DATABASE has port, driver, username, databasename, hostname attributes.
+ QUERY has a value attribute (containing the SQL query)
+ SAMPLERECORD is (FIELD*)
+ FIELD has a name attribute.
+-->
+
+<!-- A "field" variable (property of the document)
+ subtype... Field subtype:
+ 0... Filename
+ 1... Directory name
+ 2... Author (as saved in documentinfo.xml)
+ 3... Email (as saved in documentinfo.xml)
+ 4... Company Name (as saved in documentinfo.xml)
+ 5... Path filename
+ 6... Filename without extension
+ 7... Telephone
+ 8... Fax
+ 9... Country
+ 10.. Document Title (as saved in documentinfo.xml)
+ 11.. Document Abstract (as saved in documentinfo.xml)
+ 12.. Postal Code
+ 13.. City
+ 14.. Street
+ 15.. AuthorTitle
+ 16.. Initials
+
+
+ value... the value of the field (text)
+-->
+<!ELEMENT FIELD
+ EMPTY>
+<!ATTLIST FIELD
+ subtype CDATA #REQUIRED
+ value CDATA #REQUIRED>
+
+<!-- A variable containing an hyperlink.
+ linkName... The text that appears in the document.
+ hrefName... The URL that this link points to.
+-->
+<!ELEMENT LINK
+ EMPTY>
+<!ATTLIST LINK
+ linkName CDATA #REQUIRED
+ hrefName CDATA #REQUIRED>
+
+<!-- A comment embedded into the text.
+ note... The text of the comment
+-->
+<!ELEMENT NOTE
+ EMPTY>
+<!ATTLIST NOTE
+ note CDATA #REQUIRED>
+
+<!-- A footnote variable.
+ value... The text of the variable (e.g. "1", "2")
+ notetype... "footnote" or "endnote"
+ numberingtype... "auto" or "manual"
+ frameset... The name of the text frameset that contains the text
+ associated with this footnote. The frameset must be defined,
+ and must have frameInfo = 7.
+-->
+<!ELEMENT FOOTNOTE
+ EMPTY>
+<!ATTLIST FOOTNOTE
+ value CDATA #REQUIRED
+ notetype CDATA #REQUIRED
+ numberingtype CDATA #REQUIRED
+ frameset CDATA #REQUIRED>
+
+
+<!-- A statistic variable.
+ value... A number (e.g. "1", "2")
+ type... A type of statistic variable
+ "0" Number of word
+ "1" Number of sentence
+ "2" Number of lines
+ "3" Number of characters
+ "4" Number of characters without space
+ "5" Number of syllable
+ "6" Number of frame
+ "7" Number of embedded object
+ "8" Number of picture
+ "9" Number of table
+-->
+<!ELEMENT STATISTIC
+ EMPTY>
+<!ATTLIST STATISTIC
+ value CDATA #REQUIRED
+ type CDATA #REQUIRED>
+
+
+<!--
+ Picture collection. This list holds the keys of all the picture
+ used by this document (by picture framesets), in the order in which
+ they are stored in the store (under pictures/).
+-->
+<!ELEMENT PICTURES
+ (KEY)*>
+
+<!--
+ Pixmap collection. This list holds the keys of all the pixmaps
+ used by this document (by picture framesets), in the order in which
+ they are stored in the store (under pictures/).
+ Only for KWord 1.1 compatibility.
+-->
+<!ELEMENT PIXMAPS
+ (KEY)*>
+
+<!--
+ Only for KWord 1.1 compatibility.
+-->
+<!ELEMENT CLIPARTS
+ (KEY)*>
+
+<!-- TODO: document! -->
+<!ELEMENT SERIALL
+ EMPTY>
+
+<!ELEMENT SPELLCHECKIGNORELIST ( SPELLCHECKIGNOREWORD+ )>
+<!ATTLIST SPELLCHECKIGNORELIST >
+<!ELEMENT SPELLCHECKIGNOREWORD EMPTY>
+<!ATTLIST SPELLCHECKIGNOREWORD word NMTOKEN #REQUIRED >
+
+<!ELEMENT BOOKMARKS ( BOOKMARKITEM+ )>
+<!ATTLIST BOOKMARKS >
+<!ELEMENT BOOKMARKITEM EMPTY>
+<!ATTLIST BOOKMARKITEM name NMTOKEN #REQUIRED
+ cursorIndexStart NMTOKEN #REQUIRED
+ cursorIndexEnd NMTOKEN #REQUIRED
+ frameset NMTOKEN #REQUIRED
+ startparag NMTOKEN #REQUIRED
+ endparag NMTOKEN #REQUIRED>
+
+<!--
+ The key mapping to one picture
+
+ name: the relative path to the picture in the store (e.g. picture/picture1.ext)
+ (only if <KEY> is a child of <PICTURES>, otherwise the attribute name does not exist.)
+ filename: the original path of the picture
+ year...: the date/time stamp
+ (suggestions:
+ - use UTC if you have the choice
+ - use the *NIX epoch (1970-01-01 00:00:00.000 UTC) if no date is available otherwise)
+-->
+<!ELEMENT KEY
+ EMPTY>
+<!ATTLIST KEY
+ filename CDATA #REQUIRED
+ year CDATA #REQUIRED
+ month CDATA #REQUIRED
+ day CDATA #REQUIRED
+ hour CDATA #REQUIRED
+ minute CDATA #REQUIRED
+ second CDATA #REQUIRED
+ msec CDATA #REQUIRED
+ name CDATA #IMPLIED>
+
+<!--
+ Embedded object
+-->
+<!ELEMENT EMBEDDED
+ (OBJECT,SETTINGS)>
+
+<!--
+ Standard part of the embedded object (part, url and position)
+ mime the mimetype, e.x. application/x-presenter
+ url the url, either external or internal (tar:/N for partN/maindoc.xml)
+-->
+<!ELEMENT OBJECT
+ (RECT)>
+<!ATTLIST OBJECT
+ mime CDATA #REQUIRED
+ url CDATA #REQUIRED>
+<!--
+ Position of the embedded object
+-->
+<!ELEMENT RECT
+ EMPTY>
+<!ATTLIST RECT
+ x CDATA #REQUIRED
+ y CDATA #REQUIRED
+ w CDATA #REQUIRED
+ h CDATA #REQUIRED>
+
+<!--
+ Additionnal attributes of the embedded object.
+ In KWord's case, it's the definition of the frame around the object,
+ and the name of the part-frameset.
+ ### FIXME: the attribute list is the same as FRAMESET
+-->
+<!ELEMENT SETTINGS
+ (FRAME)>
+<!ATTLIST SETTINGS
+ name CDATA #REQUIRED>
diff --git a/kword/dtd/tablestyles.dtd b/kword/dtd/tablestyles.dtd
new file mode 100644
index 00000000..2480596f
--- /dev/null
+++ b/kword/dtd/tablestyles.dtd
@@ -0,0 +1,29 @@
+<!--
+ A tablestyle holds properties for borders, background and (text)style. A tablestyle is
+ identified via its name. The properties are reach via the names corresponding to the
+ framestyle and style.
+-->
+<!ELEMENT TABLESTYLES
+ (TABLESTYLE*)>
+
+<!ELEMENT TABLESTYLE
+ (NAME|PFRAMESTYLE|PSTYLE)>
+
+<!ELEMENT PFRAMESTYLE
+ EMPTY>
+<!ATTLIST PFRAMESTYLE
+ name CDATA #REQUIRED>
+
+<!ELEMENT PSTYLE
+ EMPTY>
+<!ATTLIST PSTYLE
+ name CDATA #REQUIRED>
+
+<!--
+ Copied from kword.dtd (01-06-2002)
+-->
+
+<!ELEMENT NAME
+ EMPTY>
+<!ATTLIST NAME
+ value CDATA #REQUIRED>
diff --git a/kword/dtd/tabletemplates.dtd b/kword/dtd/tabletemplates.dtd
new file mode 100644
index 00000000..f1b96d6e
--- /dev/null
+++ b/kword/dtd/tabletemplates.dtd
@@ -0,0 +1,57 @@
+<!--
+ A tabletemplate holds pointers to a tablestyle for the first, last row and column and body.
+
+ Name is the name of the tablestyle.
+
+ With topleftcorner, toprightcorner, bottomleftcorner and bottomrightcorner attributes you
+ can tell KWord that particular corner belongs to that tablestyle. If you use them just give
+ a value of 1 to it, otherwise leave it out because KWord checks if the attribute is available.
+-->
+
+<!ELEMENT TABLETEMPLATES
+ (TABLETEMPLATE*)>
+
+<!ELEMENT TABLETEMPLATE
+ (NAME|FIRSTROW|LASTROW|FIRSTCOL|LASTCOL|BODYCELL)>
+
+<!ELEMENT FIRSTROW
+ EMPTY>
+<!ATTLIST FIRSTROW
+ name CDATA #REQUIRED
+ topleftcorner CDATA
+ toprightcorner CDATA>
+
+<!ELEMENT FIRSTCOL
+ EMPTY>
+<!ATTLIST FIRSTCOL
+ name CDATA #REQUIRED
+ topleftcorner CDATA
+ bottomleftcorner CDATA>
+
+<!ELEMENT LASTROW
+ EMPTY>
+<!ATTLIST LASTROW
+ name CDATA #REQUIRED
+ bottomleftcorner CDATA
+ bottomrightcorner CDATA>
+
+<!ELEMENT LASTCOL
+ EMPTY>
+<!ATTLIST LASTCOL
+ name CDATA #REQUIRED
+ toprightcorner CDATA
+ bottomrightcorner CDATA>
+
+<!ELEMENT BODYCELL
+ EMPTY>
+<!ATTLIST BODYCELL
+ name CDATA #REQUIRED>
+
+<!--
+ Copied from kword.dtd (01-06-2002)
+-->
+
+<!ELEMENT NAME
+ EMPTY>
+<!ATTLIST NAME
+ value CDATA #REQUIRED>
diff --git a/kword/expression/Makefile.am b/kword/expression/Makefile.am
new file mode 100644
index 00000000..4481aa5e
--- /dev/null
+++ b/kword/expression/Makefile.am
@@ -0,0 +1,4 @@
+
+scripts_DATA = expression.xml
+scriptsdir = $(kde_datadir)/kword/expression
+
diff --git a/kword/expression/expression.xml b/kword/expression/expression.xml
new file mode 100644
index 00000000..debfa05d
--- /dev/null
+++ b/kword/expression/expression.xml
@@ -0,0 +1,114 @@
+<!DOCTYPE KWordExpression>
+<KWordExpression>
+ <Type>
+ <TypeName>Personal</TypeName>
+ <Expression>
+ <Text>Hi!</Text>
+ </Expression>
+ <Expression>
+ <Text>Hello!</Text>
+ </Expression>
+ <Expression>
+ <Text>Bye!</Text>
+ </Expression>
+ <Expression>
+ <Text>Good bye</Text>
+ </Expression>
+ </Type>
+ <Type>
+ <TypeName>Professional</TypeName>
+ <Expression>
+ <Text>Good Morning</Text>
+ </Expression>
+ <Expression>
+ <Text>Good Afternoon</Text>
+ </Expression>
+ <Expression>
+ <Text>Good Evening</Text>
+ </Expression>
+ </Type>
+ <Type>
+ <TypeName>Email</TypeName>
+ <Expression>
+ <Text>To:</Text>
+ </Expression>
+ <Expression>
+ <Text>From:</Text>
+ </Expression>
+ <Expression>
+ <Text>Subject:</Text>
+ </Expression>
+ <Expression>
+ <Text>CC:</Text>
+ </Expression>
+ <Expression>
+ <Text>BCC:</Text>
+ </Expression>
+ <Expression>
+ <Text>Fwd:</Text>
+ </Expression>
+ </Type>
+ <Type>
+ <TypeName>Closing</TypeName>
+ <Expression>
+ <Text>Best regards,</Text>
+ </Expression>
+ <Expression>
+ <Text>Best wishes</Text>
+ </Expression>
+ <Expression>
+ <Text>Cordially,</Text>
+ </Expression>
+ <Expression>
+ <Text>Love,</Text>
+ </Expression>
+ <Expression>
+ <Text>Regards,</Text>
+ </Expression>
+ <Expression>
+ <Text>Thank you,</Text>
+ </Expression>
+ <Expression>
+ <Text>Thanks,</Text>
+ </Expression>
+ </Type>
+ <Type>
+ <TypeName>Subject</TypeName>
+ <Expression>
+ <Text>Subject</Text>
+ </Expression>
+ </Type>
+ <Type>
+ <TypeName>Salutation</TypeName>
+ <Expression>
+ <Text>Dear Sir or Madam:</Text>
+ </Expression>
+ <Expression>
+ <Text>Ladies and Gentlemen:</Text>
+ </Expression>
+ </Type>
+ <Type>
+ <TypeName>Attention</TypeName>
+ <Expression>
+ <Text>Attention:</Text>
+ </Expression>
+ <Expression>
+ <Text>ATTN:</Text>
+ </Expression>
+ </Type>
+ <Type>
+ <TypeName>Instructions</TypeName>
+ <Expression>
+ <Text>CERTIFIED</Text>
+ </Expression>
+ <Expression>
+ <Text>CONFIDENTIAL</Text>
+ </Expression>
+ <Expression>
+ <Text>PERSONAL</Text>
+ </Expression>
+ <Expression>
+ <Text>FACSIMILE</Text>
+ </Expression>
+ </Type>
+</KWordExpression>
diff --git a/kword/horizontalline/Makefile.am b/kword/horizontalline/Makefile.am
new file mode 100644
index 00000000..3a96bf70
--- /dev/null
+++ b/kword/horizontalline/Makefile.am
@@ -0,0 +1,4 @@
+
+img_DATA = line.png
+imgdir = $(kde_datadir)/kword/horizontalline
+
diff --git a/kword/horizontalline/line.png b/kword/horizontalline/line.png
new file mode 100644
index 00000000..52dcfce2
--- /dev/null
+++ b/kword/horizontalline/line.png
Binary files differ
diff --git a/kword/kwmailmerge.desktop b/kword/kwmailmerge.desktop
new file mode 100644
index 00000000..c44d758f
--- /dev/null
+++ b/kword/kwmailmerge.desktop
@@ -0,0 +1,71 @@
+[Desktop Entry]
+Type=ServiceType
+X-KDE-ServiceType=KWord/MailMergePlugin
+Comment=KWord mailmerge plugin
+Comment[ar]=ملحق دمج البريد لدى KWord
+Comment[bg]=Приставка на KWord за генериране на регулярна е-поща
+Comment[bs]=KWord dodatak za spajanje mailova
+Comment[ca]=Connector de KWord per a la fusió de correus
+Comment[cs]=Modul pro KWord pro sériové dopisy
+Comment[cy]=Ategyn uno post KWord
+Comment[da]=KWord postindfletnings-plugin
+Comment[de]=KWord Serienbrief-Modul
+Comment[el]=Πρόσθετο συγχώνευσης αλληλογραφίας του KWord
+Comment[eo]=Retpoŝtintegrilo
+Comment[es]=Complemento de combinación de correo de KWord
+Comment[et]=KWordi kirjakoosteplugin
+Comment[eu]=KWord-en posta bateratzeko plugina
+Comment[fa]=وصلۀ ادغام پستی KWord
+Comment[fi]=KWord-postituslaajennus
+Comment[fr]=Module fusion de courrier pour KWord
+Comment[fy]=KWord-plugin foar standertbrieven (mailmerge)
+Comment[ga]=Breiseán postchumaisc KWord
+Comment[gl]=Plugin de Circulares de KWord
+Comment[he]=תוסף מיזוג דואר ל־KWord
+Comment[hi]=के-वर्ड मेलमर्ज प्लगइन
+Comment[hr]=KWord dodatak za udruživanje pošte
+Comment[hu]=KWord körlevél-bővítőmodul
+Comment[is]=KWord mailmerge íforrit
+Comment[it]=Stampa unione per KWord
+Comment[ja]=KWord mailmerge プラグイン
+Comment[km]=កម្មវិធី​ជំនួយ​សំបុត្រ​សំណុំ​បែបបទ KWord
+Comment[lo]=ປັກອິນລວນເຂົ້າໄວ້ໃນຈົດຫມາຍຂອງເອກະສານຂໍ້ຄວາມ
+Comment[lt]=KWord laiško prijungimo priedas
+Comment[lv]=KWord pasta apvienošanas spraudnis
+Comment[ms]=Plugin cantum mel KWord
+Comment[mt]=Plagin tal-mailmerge ta' KWord
+Comment[nb]=Postflettingsmodul for KWord
+Comment[nds]=Massendruck-Moduul för KWorld
+Comment[ne]=केडीई शब्द पत्र गाँभ्ने प्लगइन
+Comment[nl]=KWord-plugin voor standaardbrieven (mailmerge)
+Comment[nn]=Postflettingsmodul for KWord
+Comment[pl]=Wtyczka korespondencji seryjnej dla KWord
+Comment[pt]='Plugin' de junção de e-mails do KWord
+Comment[pt_BR]=Plug-in de mala direta do KWord
+Comment[ro]=Modul KWord de scrisori combinate
+Comment[ru]=Модуль почтового слияния KWord
+Comment[se]=KWord:a boastabárgidanmoduvla
+Comment[sk]=Modul pre KWord pre sériové listy
+Comment[sl]=Vstavek za združevanje pošte za KWord
+Comment[sr]=KWord-ов прикључак за стапање поште
+Comment[sr@Latn]=KWord-ov priključak za stapanje pošte
+Comment[sv]=Kword-insticksprogram för brevsammanfogning
+Comment[tg]=Дарҷ кардани KWord Якшавии Почта
+Comment[th]=ปลั๊กอินรวมเข้าไว้ในจดหมายของเอกสารข้อความ K
+Comment[tr]=KWord posta bütünleştirme eklentisi
+Comment[uk]=Втулок об'єднання пошти для KWord
+Comment[xh]=Uxutyo lweposi ye plagi yangaphakathi ye KWord
+Comment[zh_CN]=KWord 邮件合并插件
+Comment[zh_TW]=KWord 郵件合併外掛程式
+
+[PropertyDef::X-KDE-Capabilities]
+Type=QStringList
+
+[PropertyDef::X-KDE-InternalName]
+Type=QString
+
+[PropertyDef::X-KDE-Library]
+Type=QString
+
+[PropertyDef::X-KDE-PluginVersion]
+Type=int
diff --git a/kword/kword.desktop b/kword/kword.desktop
new file mode 100644
index 00000000..65760244
--- /dev/null
+++ b/kword/kword.desktop
@@ -0,0 +1,81 @@
+[Desktop Entry]
+Type=Application
+Name=KWord
+Name[af]=Kword
+Name[fo]=KOrð
+Name[hi]=के-वर्ड
+Name[lo]=ເອກະສານຂໍ້ຄວາມ K
+Name[ne]=केडीई शब्द
+Name[sv]=Kword
+Name[th]=เอกสารข้อความ K
+Exec=kword %u
+GenericName=Word Processing
+GenericName[af]=Woord Verwerking
+GenericName[ar]=مُعالجة الكلمات
+GenericName[az]=Kəlmə İşləmə
+GenericName[bg]=Текстообработка
+GenericName[bs]=Obrada teksta
+GenericName[ca]=Processador de text
+GenericName[cs]=Zpracování textu
+GenericName[cy]=Prosesu Geiriau
+GenericName[da]=Tekstbehandling
+GenericName[de]=Textverarbeitung
+GenericName[el]=Επεξεργασία κειμένου
+GenericName[eo]=Verkado kaj aranĝo de tekstoj
+GenericName[es]=Procesado de textos
+GenericName[et]=Tekstitöötlus
+GenericName[eu]=Testu-prozesadorea
+GenericName[fa]=پردازش واژه
+GenericName[fi]=Tekstinkäsittely
+GenericName[fo]=Tekstviðgerð
+GenericName[fr]=Traitement de texte
+GenericName[fy]=Tekstferwurker
+GenericName[ga]=Próiseáil Focal
+GenericName[gl]=Procesamento de Texto
+GenericName[he]=עיבוד תמלילים
+GenericName[hi]=शब्द संसाधन
+GenericName[hr]=Obrada teksta
+GenericName[hu]=Szövegszerkesztő
+GenericName[is]=Ritvinnsla
+GenericName[it]=Videoscrittura
+GenericName[ja]=ワープロ
+GenericName[km]=កម្មវិធី​វាយ​អត្ថបទ​
+GenericName[lo]=ໂປຣແກມປະມວນຜົນຄໍາ
+GenericName[lt]=Tekstų apdorojimas
+GenericName[lv]=Tekstu Apstrāde
+GenericName[ms]=Pemproses Kata
+GenericName[nb]=Tekstbehandling
+GenericName[nds]=Textverarbeiden
+GenericName[ne]=शब्द प्रोसेसिङ्ग
+GenericName[nl]=Tekstverwerker
+GenericName[nn]=Teksthandsaming
+GenericName[pl]=Przetwarzanie tekstu
+GenericName[pt]=Processamento de Texto
+GenericName[pt_BR]=Processador de Textos
+GenericName[ro]=Procesare text
+GenericName[ru]=Текстовые документы
+GenericName[se]=Teakstagieđahallan
+GenericName[sk]=Textové procesory
+GenericName[sl]=Urejanje besedila
+GenericName[sr]=Обрада текста
+GenericName[sr@Latn]=Obrada teksta
+GenericName[sv]=Ordbehandling
+GenericName[ta]=சொல் தொகுத்தல்
+GenericName[tg]=Равиши Word
+GenericName[th]=โปรแกรมประมวลผลคำ
+GenericName[tr]=Kelime İşleme
+GenericName[uk]=Текстовий процесор
+GenericName[uz]=Matn protsessori
+GenericName[uz@cyrillic]=Матн процессори
+GenericName[wa]=Sicrijhaedje di tecses
+GenericName[zh_CN]=字处理
+GenericName[zh_TW]=文書處理
+MimeType=application/vnd.oasis.opendocument.text;application/x-kword;application/msword;text/rtf;text/plain;application/x-mswrite
+Icon=kword
+X-KDE-NativeMimeType=application/vnd.oasis.opendocument.text
+#X-KDE-NativeMimeType=application/x-kword
+DocPath=kword/index.html
+X-KDE-StartupNotify=true
+X-DCOP-ServiceType=Multi
+Categories=Qt;KDE;Office;
+InitialPreference=3
diff --git a/kword/kword.rc b/kword/kword.rc
new file mode 100644
index 00000000..97c0923a
--- /dev/null
+++ b/kword/kword.rc
@@ -0,0 +1,511 @@
+<!DOCTYPE kpartgui SYSTEM "kpartgui.dtd" ><kpartgui name="KWord" version="103">
+<MenuBar>
+ <Menu name="file"><text>&amp;File</text>
+ <Action name="extra_template"/>
+ <Separator/>
+ <Action name="file_statistics"/>
+ </Menu>
+ <Menu name="edit"><text>&amp;Edit</text>
+ <Action name="koffice_undo"/>
+ <Action name="koffice_redo"/>
+ <Separator/>
+ <Action name="edit_cut"/>
+ <Action name="edit_copy"/>
+ <Action name="edit_paste"/>
+ <Action name="edit_selectall"/>
+ <Action name="edit_selectallframes"/>
+ <Action name="edit_selectcurrentframe"/>
+ <Separator/>
+ <Action name="edit_find"/>
+ <Action name="edit_findnext"/>
+ <Action name="edit_findprevious"/>
+ <Action name="edit_replace"/>
+ <Separator/>
+ <Action name="delete_page"/>
+ </Menu>
+ <Menu name="view"><text>&amp;View</text>
+ <Action name="view_newview"/>
+ <ActionList name="view_closeallviews"/>
+ <Separator/>
+ <ActionList name="view_split" />
+ <Menu name="view_displaymodes"><text>&amp;Display Mode</text>
+ <Action name="view_pagemode"/>
+ <Action name="view_previewmode"/>
+ <Action name="view_textmode"/>
+ </Menu>
+ <Separator/>
+ <Action name="view_formattingchars"/>
+ <Action name="view_frameborders"/>
+ <Separator/>
+ <Action name="show_docstruct"/>
+ <Action name="show_ruler"/>
+ <Action name="view_grid"/>
+ <Action name="view_snaptogrid"/>
+ <Separator/>
+ <Action name="view_zoom"/>
+ </Menu>
+ <Menu name="insert"><text context="Insert menu">&amp;Insert</text>
+ <!-- Inside the text, simple things (e.g. one char) -->
+ <Action name="insert_specialchar"/>
+ <Action name="insert_framebreak"/>
+ <!-- Code for horizontal line is broken
+ <Action name="insert_horizontal_line"/>
+ -->
+ <Action name="insert_page"/>
+ <Separator/>
+ <!-- Inside the text, more -->
+ <Action name="insert_footendnote"/>
+ <Action name="insert_contents"/>
+ <Action name="insert_variable"/> <!-- menu -->
+ <Action name="insert_expression"/> <!-- menu -->
+ <Action name="insert_link"/>
+ <Action name="insert_comment"/>
+ <Action name="insert_file"/>
+ <Action name="add_bookmark"/>
+ <Separator/>
+ <!-- Frames - the order matches the order of the keybindings -->
+ <Action name="insert_table"/>
+ <Action name="insert_picture"/>
+ <Action name="tools_createtext"/>
+ <Action name="tools_formula"/>
+ <Action name="tools_part"/>
+ </Menu>
+ <Menu name="format"><text>F&amp;ormat</text>
+ <Action name="text_default"/>
+ <Action name="format_font"/>
+ <Action name="format_paragraph"/>
+ <Action name="format_footendnote"/>
+ <Menu name="Formula"><text>Formula</text>
+ <Menu name="matrix"><text>Matrix</text>
+ <Action name="formula_insertcolumn"/>
+ <Action name="formula_appendcolumn"/>
+ <Action name="formula_removecolumn"/>
+ <Action name="formula_insertrow"/>
+ <Action name="formula_appendrow"/>
+ <Action name="formula_removerow"/>
+ </Menu>
+ <Action name="formula_addupperindex"/>
+ <Action name="formula_addlowerindex"/>
+ <Action name="formula_addnegthinspace"/>
+ <Action name="formula_addthinspace"/>
+ <Action name="formula_addmediumspace"/>
+ <Action name="formula_addthickspace"/>
+ <Action name="formula_addquadspace"/>
+ <Action name="formula_removeenclosing"/>
+ <Action name="formula_makegreek"/>
+ <Action name="formula_insertsymbol"/>
+ <Separator/>
+ <Action name="formula_syntaxhighlighting"/>
+ </Menu>
+ <Separator/>
+ <Action name="format_stylemenu"/>
+ <Action name="format_stylist"/>
+ <Action name="import_style"/>
+ <Action name="create_style"/>
+ <Separator/>
+ <Action name="format_page"/>
+ <Separator/>
+ <Action name="format_header"/>
+ <Action name="format_footer"/>
+ </Menu>
+ <Menu name="frames"><text>Fra&amp;mes</text>
+ <Action name="format_frameset"/>
+ <Action name="edit_delframe"/>
+ <Separator/>
+ <Action name="raiseframe"/>
+ <Action name="lowerframe"/>
+ <Action name="bring_tofront_frame"/>
+ <Action name="send_toback_frame"/>
+ <Separator/>
+ <Action name="create_linked_frame"/>
+ <Action name="convert_to_text_box"/>
+ <Separator/>
+ <Action name="frame_stylist"/>
+ <Action name="create_framestyle"/>
+ <Action name="frame_stylemenu"/>
+ <!--<Action name="border_color"/> Can't do that while we're sharing the action with paragraphs-->
+ <Action name="border_backgroundcolor"/>
+ <Menu name="FrameBorders"><text>Configure Frame Border</text>
+ <Action name="border_outline"/>
+ <Action name="border_left"/>
+ <Action name="border_right"/>
+ <Action name="border_top"/>
+ <Action name="border_bottom"/>
+ <Action name="border_style"/>
+ <Action name="border_color"/>
+ </Menu>
+ </Menu>
+ <Menu name="table"><text>Ta&amp;ble</text>
+ <Action name="table_propertiesmenu"/>
+ <Separator/>
+ <Menu name="Row"><text>Row</text>
+ <Action name="table_insrow"/>
+ <Action name="table_delrow"/>
+ </Menu>
+ <Menu name="Column"><text>Column</text>
+ <Action name="table_inscol"/>
+ <Action name="table_delcol"/>
+ <Action name="table_resizecol"/>
+ </Menu>
+ <Separator/>
+ <Menu name="Cell"><text>Cell</text>
+ <Action name="table_joincells"/>
+ <Action name="table_splitcells"/>
+ <Action name="table_protectcells"/>
+ </Menu>
+ <Action name="table_ungroup"/>
+ <Separator/>
+ <Action name="table_delete"/>
+ <Separator/>
+ <Action name="table_stylist"/>
+ <Action name="table_stylemenu"/>
+ <Action name="convert_table_to_text"/>
+ </Menu>
+ <Menu name="tools"><text>&amp;Tools</text>
+ <Menu name="SpellCheck"><text>Spellcheck</text>
+ <Action name="tool_auto_spellcheck"/>
+ <Action name="extra_spellcheck"/>
+ </Menu>
+ <Menu name="AutoFormat"><text>Autocorrection</text>
+ <Action name="enable_autocorrection"/>
+ <Action name="apply_autoformat"/>
+ </Menu>
+ <Separator/>
+ <Action name="change_case"/>
+ <Action name="sort_text"/>
+ <Action name="personal_expr"/>
+ <Action name="add_personal_expression"/>
+ <Action name="custom_vars"/>
+ <Action name="select_bookmark"/>
+ <ActionList name="datatools"/>
+ <Separator/>
+ <Action name="edit_sldatabase"/>
+ </Menu>
+ <Menu name="settings"><text>&amp;Settings</text>
+ <Separator group="settings_show"/>
+ <Action name="direct_cursor" group="settings_show"/>
+ <Separator group="settings_show"/>
+ <Action name="configure_autocorrection" group="settings_show"/>
+ <Action name="configure_completion" group="settings_show"/>
+ <Action name="configure_footendnote" group="settings_show"/>
+ <Separator group="settings_show"/>
+ <Action name="configure" group="settings_configure"/>
+ </Menu>
+</MenuBar>
+<ToolBar name="edit_toolbar" position="top"><Text>Edit</Text>
+ <Action name="koffice_undo"/>
+ <Action name="koffice_redo"/>
+ <Separator/>
+ <Action name="edit_cut"/>
+ <Action name="edit_copy"/>
+ <Action name="edit_paste"/>
+ <Separator/>
+ <Action name="extra_spellcheck"/>
+ <Action name="edit_find"/>
+ <Separator/>
+ <Action name="view_zoom"/>
+</ToolBar>
+<ToolBar hidden="true" name="table_toolbar" position="top"><Text>Table</Text>
+ <Action name="table_properties"/>
+ <Separator/>
+ <Action name="table_style"/>
+ <Separator/>
+ <Action name="table_insrow"/>
+ <Action name="table_inscol"/>
+ <Action name="table_delrow"/>
+ <Action name="table_delcol"/>
+</ToolBar>
+<ToolBar name="insert_toolbar" position="left"><Text>Insert</Text>
+ <Action name="insert_table"/>
+ <Action name="insert_picture"/>
+ <Separator/>
+ <Action name="tools_createtext"/>
+ <Action name="tools_formula"/>
+ <Action name="tools_part"/>
+</ToolBar>
+<ToolBar name="paragraph_toolbar" position="top"><Text>Paragraph</Text>
+ <Action name="format_style"/>
+ <Separator/>
+ <Action name="format_alignleft"/>
+ <Action name="format_aligncenter"/>
+ <Action name="format_alignright"/>
+ <Action name="format_alignblock"/>
+ <Separator/>
+ <Action name="format_number"/>
+ <Action name="format_bullet"/>
+ <Separator/>
+ <Action name="format_decreaseindent"/>
+ <Action name="format_increaseindent"/>
+</ToolBar>
+<ToolBar hidden="true" name="format_toolbar" position="top"><Text>Font</Text>
+ <Action name="format_fontfamily"/>
+ <Action name="format_fontsize"/>
+ <Separator/>
+ <Action name="format_color"/>
+</ToolBar>
+<ToolBar name="charformat_toolbar" position="top"><Text>Format</Text>
+ <Action name="format_bold"/>
+ <Action name="format_italic"/>
+ <Action name="format_underline"/>
+ <Action name="format_strike"/>
+ <Separator/>
+ <Action name="format_super"/>
+ <Action name="format_sub"/>
+</ToolBar>
+<ToolBar hidden="true" name="border_toolbar" position="top"><Text>Borders</Text>
+ <Action name="frame_style"/>
+ <Action name="border_outline"/>
+ <Action name="border_left"/>
+ <Action name="border_right"/>
+ <Action name="border_top"/>
+ <Action name="border_bottom"/>
+ <Action name="border_width"/>
+ <Action name="border_style"/>
+ <Action name="border_color"/>
+ <Action name="border_backgroundcolor"/>
+</ToolBar>
+<!--
+<ToolBar hidden="true" name="mailmerge_toolbar" position="top"><Text>MailMerge</Text>
+ <Action name="mailmerge_draglabel"/>
+ <Action name="mailmerge_varchooser"/>
+ <Action name="edit_sldatabase"/>
+</ToolBar>
+-->
+<ToolBar hidden="true" name="formula_toolbar" position="bottom"><Text>Formula</Text>
+ <Action name="formula_addtext"/>
+ <Action name="formula_addroot"/>
+ <Action name="formula_addfrac"/>
+ <Action name="formula_addbra"/>
+ <Action name="formula_addsqrbra"/>
+ <Action name="formula_addcurbra"/>
+ <Action name="formula_addabsbra"/>
+ <Action name="formula_addoverline"/>
+ <Action name="formula_addunderline"/>
+ <Action name="formula_addintegral"/>
+ <Action name="formula_addsum"/>
+ <Action name="formula_addproduct"/>
+ <Action name="formula_addmatrix"/>
+ <Action name="formula_addupperleft"/>
+ <Action name="formula_addlowerleft"/>
+ <Action name="formula_addupperindex"/>
+ <Action name="formula_addlowerindex"/>
+ <Action name="formula_addupperright"/>
+ <Action name="formula_addlowerright"/>
+ <Action name="formula_typeleft"/>
+ <Action name="formula_typeright"/>
+ <Separator/>
+ <Action name="formula_symbolnames"/>
+ <Action name="formula_insertsymbol"/>
+ <Separator/>
+ <Action name="formula_insertcolumn"/>
+ <Action name="formula_appendcolumn"/>
+ <Action name="formula_removecolumn"/>
+ <Action name="formula_insertrow"/>
+ <Action name="formula_appendrow"/>
+ <Action name="formula_removerow"/>
+</ToolBar>
+<StatusBar/>
+<Menu name="text_popup">
+ <Action name="text_default"/>
+ <Action name="format_font"/>
+ <Action name="format_paragraph"/>
+ <Separator/>
+ <Action name="border_backgroundcolor"/>
+ <Separator/>
+ <Action name="edit_cut"/>
+ <Action name="edit_copy"/>
+ <Action name="edit_paste"/>
+ <ActionList name="datatools"/>
+ <ActionList name="tableactions"/>
+</Menu>
+<Menu name="text_popup_spell">
+ <Action name="text_default"/>
+ <Action name="format_font"/>
+ <Action name="format_paragraph"/>
+ <Separator/>
+ <Action name="border_backgroundcolor"/>
+ <Separator/>
+ <Action name="edit_cut"/>
+ <Action name="edit_copy"/>
+ <Action name="edit_paste"/>
+ <ActionList name="datatools"/>
+ <Action name="ignore_all"/>
+ <Action name="add_word_to_dictionary"/>
+ <ActionList name="tableactions"/>
+</Menu>
+<Menu name="text_popup_spell_with_result">
+ <Action name="text_default"/>
+ <Action name="format_font"/>
+ <Action name="format_paragraph"/>
+ <Separator/>
+ <Action name="border_backgroundcolor"/>
+ <Separator/>
+ <Action name="edit_cut"/>
+ <Action name="edit_copy"/>
+ <Action name="edit_paste"/>
+ <ActionList name="datatools"/>
+ <Action name="ignore_all"/>
+ <Action name="add_word_to_dictionary"/>
+ <ActionList name="tableactions"/>
+ <Separator/>
+ <Menu name="check_spell_list"><text>Spell Check Result</text>
+ <ActionList name="spell_result_action"/>
+ </Menu>
+</Menu>
+<Menu name="custom_var_popup">
+ <Action name="text_default"/>
+ <Action name="format_font"/>
+ <Action name="format_paragraph"/>
+ <Separator/>
+ <Action name="border_backgroundcolor"/>
+ <Separator/>
+ <Action name="edit_cut"/>
+ <Action name="edit_copy"/>
+ <Action name="edit_paste"/>
+ <Separator/>
+ <Action name="edit_customvars"/>
+ <!--<ActionList name="datatools"/> Spell check doesn't work for variables (yet?)-->
+</Menu>
+<Menu name="variable_popup">
+ <Action name="text_default"/>
+ <Action name="format_font"/>
+ <Action name="format_paragraph"/>
+ <Separator/>
+ <Action name="border_backgroundcolor"/>
+ <Separator/>
+ <Action name="edit_cut"/>
+ <Action name="edit_copy"/>
+ <Action name="edit_paste"/>
+ <Separator/>
+ <Menu name="variable_list"><text>Change Variable To</text>
+ <ActionList name="variable_action"/>
+ </Menu>
+ <!--<ActionList name="datatools"/> Spell check doesn't work on variables (yet?)-->
+</Menu>
+<Menu name="text_popup_link">
+ <Action name="text_default"/>
+ <Action name="format_font"/>
+ <Action name="format_paragraph"/>
+ <Separator/>
+ <Action name="border_backgroundcolor"/>
+ <Separator/>
+ <Action name="edit_cut"/>
+ <Action name="edit_copy"/>
+ <Action name="edit_paste"/>
+ <Separator/>
+ <Action name="open_link"/>
+ <Action name="change_link"/>
+ <Action name="copy_link"/>
+ <Action name="remove_link"/>
+ <Action name="add_to_bookmark"/>
+ <!--<ActionList name="datatools_link"/> Spell check doesn't work on links (yet?)-->
+</Menu>
+<Menu name="footnote_popup">
+ <Action name="text_default"/>
+ <Action name="format_font"/>
+ <Action name="format_paragraph"/>
+ <Separator/>
+ <Action name="border_backgroundcolor"/>
+ <Separator/>
+ <Action name="edit_cut"/>
+ <Action name="edit_copy"/>
+ <Action name="edit_paste"/>
+ <Separator/>
+ <Action name="edit_footendnote"/>
+ <Action name="change_footendtype"/>
+ <!--<ActionList name="datatools"/> Spell check doesn't work for variables (yet?)-->
+</Menu>
+<Menu name="comment_popup">
+ <Action name="text_default"/>
+ <Action name="format_font"/>
+ <Action name="format_paragraph"/>
+ <Separator/>
+ <Action name="border_backgroundcolor"/>
+ <Separator/>
+ <Action name="edit_cut"/>
+ <Action name="edit_copy"/>
+ <Action name="edit_paste"/>
+ <Separator/>
+ <Action name="edit_comment"/>
+ <Action name="remove_comment"/>
+ <Action name="copy_text_comment"/>
+ <ActionList name="datatools"/>
+ <ActionList name="spell_action"/>
+</Menu>
+<Menu name="action_popup">
+ <Action name="insert_table"/>
+ <Action name="insert_picture"/>
+ <Separator />
+ <Action name="tools_createtext"/>
+ <Action name="tools_formula"/>
+ <Action name="tools_part"/>
+ <Separator />
+ <Action name="delete_page"/>
+</Menu>
+<Menu name="frame_popup">
+ <Action name="edit_delframe"/>
+ <Separator/>
+ <Action name="create_framestyle"/>
+ <Action name="border_backgroundcolor"/>
+ <Menu name="FrameBorders"><text>Configure Frame Borders</text>
+ <Action name="border_outline"/>
+ <Action name="border_left"/>
+ <Action name="border_right"/>
+ <Action name="border_top"/>
+ <Action name="border_bottom"/>
+ <Action name="border_style"/>
+ <Action name="border_color"/>
+ </Menu>
+ <Separator/>
+ <Action name="edit_cut"/>
+ <Action name="edit_copy"/>
+ <Action name="edit_paste"/>
+ <ActionList name="frameset_type_action"/> <!-- Used for frameset type (picture, part...) spesific actions -->
+ <Action name="format_frameset"/>
+</Menu>
+<Menu name="frame_popup_table">
+ <Action name="format_frameset"/>
+ <Action name="edit_delframe"/>
+ <Action name="create_framestyle"/>
+ <Separator/>
+ <Action name="edit_cut"/>
+ <Action name="edit_copy"/>
+ <Action name="edit_paste"/>
+ <Separator/>
+ <Menu name="Cell"><text>Cell</text>
+ <Action name="table_joincells"/>
+ <Action name="table_splitcells"/>
+ <Action name="table_protectcells"/>
+ </Menu>
+ <Separator/>
+ <Menu name="Row"><text>Row</text>
+ <Action name="table_insrow"/>
+ <Action name="table_delrow"/>
+ </Menu>
+ <Menu name="Column"><text>Column</text>
+ <Action name="table_inscol"/>
+ <Action name="table_delcol"/>
+ <Action name="table_resizecol"/>
+ </Menu>
+ <Separator/>
+ <Menu name="TableBorders"><text>Configure Table Borders</text>
+ <Action name="border_outline"/>
+ <Action name="border_left"/>
+ <Action name="border_right"/>
+ <Action name="border_top"/>
+ <Action name="border_bottom"/>
+ <Action name="border_style"/>
+ <Action name="border_color"/>
+ </Menu>
+ <Action name="table_ungroup"/>
+</Menu>
+<Menu name="docstruct_popup">
+ <Action name="docstruct_edit"/>
+ <Action name="docstruct_speak"/>
+ <Separator/>
+ <Action name="docstruct_select"/>
+ <Action name="docstruct_delete"/>
+ <Separator/>
+ <Action name="docstruct_properties"/>
+</Menu>
+</kpartgui>
diff --git a/kword/kword_readonly.rc b/kword/kword_readonly.rc
new file mode 100644
index 00000000..76f4fbc9
--- /dev/null
+++ b/kword/kword_readonly.rc
@@ -0,0 +1,58 @@
+<!DOCTYPE kpartgui SYSTEM "kpartgui.dtd" ><kpartgui name="KWord" version="4">
+<MenuBar>
+ <Menu name="file"><text>&amp;File</text>
+ <Action name="file_statistics"/>
+ </Menu>
+ <Menu name="edit"><text>&amp;Edit</text>
+ <Action name="edit_copy"/>
+ <Action name="edit_selectall"/>
+ <Separator/>
+ <Action name="edit_find"/>
+ </Menu>
+ <Menu name="view"><text>&amp;View</text>
+ <Separator/>
+ <Menu name="view_displaymodes"><text>&amp;Display Mode</text>
+ <Action name="view_pagemode"/>
+ <Action name="view_previewmode"/>
+ <Action name="view_textmode"/>
+ </Menu>
+ <Separator/>
+ <Action name="view_formattingchars"/>
+ <Action name="view_frameborders"/>
+ <Separator/>
+ <Action name="show_docstruct"/>
+ <Action name="show_ruler"/>
+ <Action name="view_grid"/>
+ <Separator/>
+ <Action name="view_zoom"/>
+ </Menu>
+ <Menu name="tools"><text>&amp;Tools</text>
+ <Separator/>
+ <Action name="select_bookmark"/>
+ </Menu>
+</MenuBar>
+<ToolBar name="edit_toolbar" position="top"><Text>Edit</Text>
+ <Action name="view_zoom"/>
+</ToolBar>
+<Menu name="text_popup">
+</Menu>
+<Menu name="custom_var_popup">
+</Menu>
+<Menu name="variable_popup">
+</Menu>
+<Menu name="text_popup_link">
+</Menu>
+<Menu name="footnote_popup">
+</Menu>
+<Menu name="comment_popup">
+</Menu>
+<Menu name="action_popup">
+</Menu>
+<Menu name="frame_popup">
+</Menu>
+<Menu name="frame_popup_table">
+</Menu>
+<Menu name="docstruct_popup">
+</Menu>
+</kpartgui>
+
diff --git a/kword/kwordmailmergedatabaseiface.cpp b/kword/kwordmailmergedatabaseiface.cpp
new file mode 100644
index 00000000..d123f2d6
--- /dev/null
+++ b/kword/kwordmailmergedatabaseiface.cpp
@@ -0,0 +1,31 @@
+/* This file is part of the KDE project
+ Copyright (C) 2001 Joseph Wenninger <jowenn@kde.org>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; using
+ version 2 of the License.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+*/
+
+#include <dcopobject.h>
+#include "KWordMailMergeDatabaseIface.h"
+
+KWordMailMergeDatabaseIface::KWordMailMergeDatabaseIface(const QCString &name)
+ :DCOPObject(name)
+{
+}
+
+KWordMailMergeDatabaseIface::~KWordMailMergeDatabaseIface()
+{
+}
+
diff --git a/kword/kwordpart.desktop b/kword/kwordpart.desktop
new file mode 100644
index 00000000..d759cf93
--- /dev/null
+++ b/kword/kwordpart.desktop
@@ -0,0 +1,102 @@
+[Desktop Entry]
+Type=Service
+Name=KOffice Word Processing Component
+Name[bg]=Компонент за текстообработка в KOffice
+Name[ca]=Component de processament de text de KOffice
+Name[cy]=Cydran Brosesu Geiriau KOffice
+Name[da]=KOffice tekstbehandlingskomponent
+Name[de]=KOffice-Komponente für Textverarbeitung
+Name[el]=Συστατικό επεξεργασίας κειμένου του KOffice
+Name[eo]=KOffice tekstprilabora komponanto
+Name[es]=Componente de procesamiento de textos de KOffice
+Name[et]=KOffice'i tekstitöötluse komponent
+Name[eu]=KOffice-en testu-prozesadore osagaia
+Name[fa]=مؤلفۀ پردازش واژۀ KOffice
+Name[fi]=KOfficen tekstinkäsittelyohjelma
+Name[fr]=Composant traitement de texte de KOffice
+Name[fy]=KOffice Tekstferwurkingskomponint
+Name[gl]=Componente de Procesamento de Texto de KOffice
+Name[he]=רכיב של KOffice לעיבוד תמלילים
+Name[hi]=के-ऑफ़िस शब्द संसाधक अवयव
+Name[hu]=KOffice szövegszerkesztő komponens
+Name[is]=Ritvinnsluhluti KOffice
+Name[it]=Componente per la videoscrittura di KOffice
+Name[ja]=KOffice ワープロコンポーネント
+Name[km]=សមាសភាគ​កម្មវិធី​វាយ​អត្ថបទ សម្រាប់ KOffice
+Name[lv]=KOffice teksta apstrādes komponente
+Name[ms]=Komponen Pemproses Kata KOffice
+Name[nb]=KOffice-komponent for tekstbehandling
+Name[nds]=Textverarbeiden-Komponent för KOffice
+Name[ne]=केडीई कार्यालय शब्द प्रोसेसिङ्ग अवयव
+Name[nl]=KOffice Tekstverwerkingscomponent
+Name[nn]=KOffice-komponent for teksthandsaming
+Name[pl]=Komponent przetwarzania tekstu dla KOffice
+Name[pt]=Componente de Processamento de Texto do KOffice
+Name[pt_BR]=Componente de Processamento de Texto do KOffice
+Name[ru]=Компонент текстового редактора KOffice
+Name[se]=KOffice sátnegieđahallan komponeanta
+Name[sk]=Komponent KOffice textový procesor
+Name[sl]=Komponenta za obdelovanje besedil za KOffice
+Name[sr]=KOffice-ова компонента за обраду текста
+Name[sr@Latn]=KOffice-ova komponenta za obradu teksta
+Name[sv]=Koffice-ordbehandlingskomponent
+Name[tg]=Компоненти муҳаррири матн¯дар KOffice
+Name[tr]=KOffice Kelime İşlem Bileşeni
+Name[uk]=Компонент текстового редактора KOffice
+Name[uz]=KOffice matn tahrirlash komponenti
+Name[uz@cyrillic]=КOffice матн таҳрирлаш компоненти
+Name[zh_CN]=KOffice 字处理组件
+Name[zh_TW]=KOffice 文書處理文件
+X-KDE-Library=libkwordpart
+X-KDE-NativeMimeType=application/vnd.oasis.opendocument.text
+X-KDE-NativeOasisMimeType=application/vnd.oasis.opendocument.text
+X-KDE-ExtraNativeMimeTypes=application/vnd.oasis.opendocument.text-template,application/x-kword
+MimeType=application/vnd.oasis.opendocument.text;application/vnd.oasis.opendocument.text-template;application/x-kword;application/msword;text/rtf;text/plain;application/x-mswrite
+ServiceTypes=KOfficePart,KParts/ReadOnlyPart,KParts/ReadWritePart
+GenericName=Text Documents
+GenericName[ar]=مُستندات نصيّة
+GenericName[bg]=Текстови документи
+GenericName[br]=Teulioù skrid
+GenericName[ca]=Documents de text
+GenericName[cy]=Dogfennau Testun
+GenericName[da]=Tekstdokument
+GenericName[de]=Textdokument
+GenericName[el]=Έγγραφα κειμένου
+GenericName[eo]=Tekstdokumentoj
+GenericName[es]=Documentos de texto
+GenericName[et]=Tekstidokumendid
+GenericName[fa]=اسناد متنی
+GenericName[fi]=Tekstiasiakirjat
+GenericName[fr]=Documents texte
+GenericName[fy]=Tekstdokuminten
+GenericName[ga]=Cáipéisí Téacs
+GenericName[gl]=Documentos de Texto
+GenericName[hr]=Tekstualni dokumenti
+GenericName[hu]=Szöveges fájlok
+GenericName[is]=Textaskjöl
+GenericName[it]=Documenti di testo
+GenericName[ja]=テキスト文書
+GenericName[km]=ឯកសារ​អត្ថបទ​
+GenericName[lt]=Tekstiniai dokumentai
+GenericName[lv]=Teksta dokumenti
+GenericName[nb]=Tekstdokumenter
+GenericName[nds]=Textdokmenten
+GenericName[ne]=पाठ कागजातहरू
+GenericName[nl]=Tekstdocumenten
+GenericName[pl]=Dokumenty tekstowe
+GenericName[pt]=Documentos de Texto
+GenericName[pt_BR]=Documento de Texto
+GenericName[ru]=Текстовые документы
+GenericName[se]=Teakstadokumeanttat
+GenericName[sk]=Textové dokumenty
+GenericName[sl]=Besedilni dokumenti
+GenericName[sr]=Текстуални документи
+GenericName[sr@Latn]=Tekstualni dokumenti
+GenericName[sv]=Textdokument
+GenericName[uk]=Текстові документи
+GenericName[uz]=Matn hujjatlari
+GenericName[uz@cyrillic]=Матн ҳужжатлари
+GenericName[zh_CN]=文本文档
+GenericName[zh_TW]=文字文件
+Icon=kword
+InitialPreference=3
diff --git a/kword/mailmerge/KWClassicSerialDataSource.cpp b/kword/mailmerge/KWClassicSerialDataSource.cpp
new file mode 100644
index 00000000..0b3f446f
--- /dev/null
+++ b/kword/mailmerge/KWClassicSerialDataSource.cpp
@@ -0,0 +1,569 @@
+/* This file is part of the KDE project
+ Original file (mailmerge.cc): Copyright (C) 1998, 1999 Reginald Stadlbauer <reggie@kde.org>
+ Copyright (C) 2001 Joseph Wenninger <jowenn@kde.org>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+*/
+
+#include "KWClassicSerialDataSource.h"
+#include "KWClassicSerialDataSource.moc"
+#include "KWMailMergeDataBase.h"
+#include <kinputdialog.h>
+#include <qlabel.h>
+#include <qhbox.h>
+#include <qlayout.h>
+#include <qvbox.h>
+#include <qpushbutton.h>
+#include <qlineedit.h>
+#include <qvalidator.h>
+#include <klocale.h>
+#include <kdebug.h>
+#include <qtoolbutton.h>
+#include <qtooltip.h>
+#include <kiconloader.h>
+#include <qheader.h>
+#include "KWDocument.h"
+#include "defs.h"
+
+#define KWSLCPBarIcon( x ) BarIcon( x, db->KWInstance() )
+
+/******************************************************************
+ *
+ * Class: KWClassicSerialDataSource
+ *
+ ******************************************************************/
+
+KWClassicSerialDataSource::KWClassicSerialDataSource(KInstance *inst,QObject *parent)
+ : KWMailMergeDataSource(inst,parent)
+// : doc( doc_ )
+{
+}
+
+KWClassicSerialDataSource::~KWClassicSerialDataSource()
+{
+}
+
+QString KWClassicSerialDataSource::getValue( const QString &name, int record ) const
+{
+ int num = record;
+/* if ( num == -1 )
+ num = doc->getMailMergeRecord(); Is this really needed ?*/
+
+ if ( num < 0 || num > (int)db.count() )
+ return name;
+
+ return db[ num ][ name ];
+}
+
+void KWClassicSerialDataSource::setValue( const QString &name, const QString &value, int record )
+{
+ int num = record;
+/* if ( num == -1 )
+ num = doc->getMailMergeRecord(); Is this really needed?*/
+
+ if ( num < 0 || num > (int)db.count() )
+ return;
+
+ db[ num ][ name ] = value;
+}
+
+void KWClassicSerialDataSource::appendRecord()
+{
+ DbRecord record( sampleRecord );
+ db.append( record );
+}
+
+void KWClassicSerialDataSource::addEntry( const QString &name )
+{
+ sampleRecord[ name ] = i18n( "No Value" );
+ Db::Iterator it = db.begin();
+ for ( ; it != db.end(); ++it )
+ ( *it )[ name ] = sampleRecord[ name ];
+}
+
+void KWClassicSerialDataSource::removeEntry( const QString &name )
+{
+ sampleRecord.remove( name );
+ Db::Iterator it = db.begin();
+ for ( ; it != db.end(); ++it )
+ ( *it ).remove( name );
+}
+
+void KWClassicSerialDataSource::removeRecord( int i )
+{
+ if ( (i < 0) || (i > (int)db.count() - 1) )
+ return;
+
+ kdDebug()<<QString("Removing record %1").arg(i)<<endl;
+
+ Db::Iterator it = db.at( i);
+ db.remove( it );
+}
+
+void KWClassicSerialDataSource::save( QDomDocument &doc, QDomElement &parent)
+{
+ QDomElement def=doc.createElement(QString::fromLatin1("DEFINITION"));
+ parent.appendChild(def);
+ for (DbRecord::Iterator it=sampleRecord.begin();it!=sampleRecord.end();++it)
+ {
+ QDomElement defEnt=doc.createElement(QString::fromLatin1("FIELD"));
+ defEnt.setAttribute(QString::fromLatin1("name"),it.key());
+ def.appendChild(defEnt);
+ }
+ QDomElement cont=doc.createElement(QString::fromLatin1("CONTENT"));
+ parent.appendChild(cont);
+ for (Db::Iterator dbI=db.begin();dbI!=db.end();++dbI)
+ {
+ QDomElement rec=doc.createElement(QString::fromLatin1("RECORD"));
+ cont.appendChild(rec);
+ for (DbRecord::Iterator it=sampleRecord.begin();it!=sampleRecord.end();++it)
+ {
+ QDomElement recEnt=doc.createElement(QString::fromLatin1("ITEM"));
+ recEnt.setAttribute(QString::fromLatin1("name"),it.key());
+ recEnt.setAttribute(QString::fromLatin1("data"),(*dbI)[it.key()]);
+ rec.appendChild(recEnt);
+ }
+ }
+}
+
+void KWClassicSerialDataSource::load( QDomElement& parentElem )
+{
+ db.clear();
+ sampleRecord.clear();
+ QDomNode defNd=parentElem.namedItem("DEFINITION");
+ if (defNd.isNull()) return;
+ QDomElement def=defNd.toElement();
+ for (QDomElement defEnt=def.firstChild().toElement();!defEnt.isNull();defEnt=defEnt.nextSibling().toElement())
+ {
+ sampleRecord[defEnt.attribute(QString::fromLatin1("name"))]=i18n( "No Value" );
+ }
+ QDomNode contNd=parentElem.namedItem("CONTENT");
+ if (contNd.isNull()) return;
+ for (QDomNode rec=contNd.firstChild();!rec.isNull();rec=rec.nextSibling())
+ {
+ appendRecord();
+ for (QDomElement recEnt=rec.firstChild().toElement();!recEnt.isNull();recEnt=recEnt.nextSibling().toElement())
+ {
+ setValue(recEnt.attribute(QString::fromLatin1("name")),
+ recEnt.attribute(QString::fromLatin1("data")),db.count()-1);
+ }
+ }
+}
+
+bool KWClassicSerialDataSource::showConfigDialog(QWidget *par,int action)
+{
+ if (action==KWSLCreate)
+ {
+ db.clear();
+ sampleRecord.clear();
+ }
+ KWClassicMailMergeEditor *dia=new KWClassicMailMergeEditor( par, this );
+ bool ret=(dia->exec()==QDialog::Accepted);
+ delete dia;
+ return ret;
+}
+
+
+/******************************************************************
+ *
+ * Class: KWClassicMailMergeEditorListItem
+ *
+ ******************************************************************/
+
+KWClassicMailMergeEditorListItem::KWClassicMailMergeEditorListItem( QListView *parent )
+ : QListViewItem( parent )
+{
+ editWidget = new QLineEdit( listView()->viewport() );
+ listView()->addChild( editWidget );
+}
+
+KWClassicMailMergeEditorListItem::KWClassicMailMergeEditorListItem( QListView *parent, QListViewItem *after )
+ : QListViewItem( parent, after )
+{
+ editWidget = new QLineEdit( listView()->viewport() );
+ listView()->addChild( editWidget );
+}
+
+KWClassicMailMergeEditorListItem::~KWClassicMailMergeEditorListItem()
+{
+ delete editWidget;
+}
+
+void KWClassicMailMergeEditorListItem::setText( int i, const QString &text )
+{
+ QListViewItem::setText( i, text );
+ if ( i == 1 )
+ editWidget->setText( text );
+}
+
+QString KWClassicMailMergeEditorListItem::text( int i ) const
+{
+ if ( i == 1 )
+ return editWidget->text();
+ return QListViewItem::text( i );
+}
+
+void KWClassicMailMergeEditorListItem::setup()
+{
+ setHeight( QMAX( listView()->fontMetrics().height(),
+ editWidget->sizeHint().height() ) );
+ if ( listView()->columnWidth( 1 ) < editWidget->sizeHint().width() )
+ listView()->setColumnWidth( 1, editWidget->sizeHint().width() );
+}
+
+void KWClassicMailMergeEditorListItem::update()
+{
+ editWidget->resize( listView()->header()->cellSize( 1 ), height() );
+ listView()->moveChild( editWidget, listView()->header()->cellPos( 1 ),
+ listView()->itemPos( this ) + listView()->contentsY() );
+ editWidget->show();
+}
+
+/******************************************************************
+ *
+ * Class: KWClassicMailMergeEditorList
+ *
+ ******************************************************************/
+
+KWClassicMailMergeEditorList::KWClassicMailMergeEditorList( QWidget *parent, KWClassicSerialDataSource *db_ )
+ : QListView( parent ), db( db_ )
+{
+ setSorting( -1 );
+ addColumn( i18n( "Name" ) );
+ addColumn( i18n( "Value" ) );
+ header()->setMovingEnabled( FALSE );
+ connect( header(), SIGNAL( sizeChange( int, int, int ) ),
+ this, SLOT( columnSizeChange( int, int, int ) ) );
+// connect( header(), SIGNAL( sectionClicked( int ) ),
+// this, SLOT( sectionClicked( int ) ) );
+ disconnect( header(), SIGNAL( sectionClicked( int ) ),
+ this, SLOT( changeSortColumn( int ) ) );
+
+ currentRecord = -1;
+}
+
+void KWClassicMailMergeEditorList::invalidateCurrentRecord()
+{
+ currentRecord=-1;
+}
+
+KWClassicMailMergeEditorList::~KWClassicMailMergeEditorList()
+{
+ if ( currentRecord == -1 )
+ return;
+
+ QListViewItemIterator lit( this );
+ QMap< QString, QString >::ConstIterator it = db->getRecordEntries().begin();
+ for ( ; it != db->getRecordEntries().end(); ++it ) {
+ QListViewItem *item = 0;
+ item = lit.current();
+ ++lit;
+ if ( currentRecord != -1 && item )
+ db->setValue( it.key(), item->text( 1 ), currentRecord );
+ }
+}
+
+void KWClassicMailMergeEditorList::columnSizeChange( int c, int, int )
+{
+ if ( c == 0 || c == 1 )
+ updateItems();
+}
+
+void KWClassicMailMergeEditorList::sectionClicked( int )
+{
+ updateItems();
+}
+
+void KWClassicMailMergeEditorList::updateItems()
+{
+ QListViewItemIterator it( this );
+ for ( ; it.current(); ++it )
+ ( (KWClassicMailMergeEditorListItem*)it.current() )->update();
+}
+
+void KWClassicMailMergeEditorList::displayRecord( int i )
+{
+ if ( i < 0 || i >= db->getNumRecords() )
+ return;
+
+ bool create = !firstChild();
+ QListViewItemIterator lit( this );
+ QMap< QString, QString >::ConstIterator it = db->getRecordEntries().begin();
+ QListViewItem *after = 0;
+ for ( ; it != db->getRecordEntries().end(); ++it ) {
+ QListViewItem *item = 0;
+ if ( create ) {
+ item = new KWClassicMailMergeEditorListItem( this, after );
+ item->setText( 0, it.key() );
+ after = item;
+ } else {
+ item = lit.current();
+ ++lit;
+ if ( currentRecord != -1 && item )
+ db->setValue( it.key(), item->text( 1 ), currentRecord );
+ }
+
+ if ( item )
+ item->setText( 1, db->getValue( it.key(), i ) );
+ }
+ updateItems();
+ currentRecord = i;
+}
+
+/******************************************************************
+ *
+ * Class: KWClassicMailMergeEditor
+ *
+ ******************************************************************/
+
+KWClassicMailMergeEditor::KWClassicMailMergeEditor( QWidget *parent, KWClassicSerialDataSource *db_ )
+ : KDialogBase( Plain, i18n( "Mail Merge - Editor" ), Ok | Cancel, Ok, parent, "", true ), db( db_ )
+{
+ back = plainPage();
+
+ QVBoxLayout *l = new QVBoxLayout( back );
+ l->setAutoAdd(true);
+ l->setSpacing( KDialog::spacingHint() );
+
+ QHBox *toolbar = new QHBox( back );
+
+ first = new QToolButton( toolbar );
+ first->setIconSet( SmallIconSet( "start" ) );
+ first->setFixedSize( first->sizeHint() );
+ connect(first, SIGNAL(clicked()), this, SLOT(firstRecord()));
+
+ back_ = new QToolButton( toolbar );
+ back_->setIconSet( SmallIconSet( "back" ) );
+ back_->setFixedSize( back_->sizeHint() );
+ connect(back_, SIGNAL(clicked()), this, SLOT(prevRecord()));
+
+ records = new QSpinBox( 1, db->getNumRecords(), 1, toolbar );
+ records->setMaximumHeight( records->sizeHint().height() );
+ connect( records, SIGNAL( valueChanged( int ) ),
+ this, SLOT( changeRecord( int ) ) );
+
+ forward = new QToolButton( toolbar );
+ forward->setIconSet( SmallIconSet( "forward" ) );
+ forward->setFixedSize( forward->sizeHint() );
+ connect(forward, SIGNAL(clicked()), this, SLOT(nextRecord()));
+
+ finish = new QToolButton( toolbar );
+ finish->setIconSet( SmallIconSet( "finish" ) );
+ finish->setFixedSize( finish->sizeHint() );
+ connect(finish, SIGNAL(clicked()), this, SLOT(lastRecord()));
+
+ QWidget *sep = new QWidget( toolbar );
+ sep->setMaximumWidth( 10 );
+
+ newRecord = new QToolButton( toolbar );
+ newRecord->setIconSet( SmallIconSet( "sl_addrecord" ) );
+ newRecord->setFixedSize( newRecord->sizeHint() );
+ connect( newRecord, SIGNAL( clicked() ),
+ this, SLOT( addRecord() ) );
+ QToolTip::add( newRecord, i18n( "Add record" ) );
+
+ newEntry = new QToolButton( toolbar );
+ newEntry->setIconSet( SmallIconSet( "sl_addentry" ) );
+ newEntry->setFixedSize( newEntry->sizeHint() );
+ connect( newEntry, SIGNAL( clicked() ),
+ this, SLOT( addEntry() ) );
+ QToolTip::add( newEntry, i18n( "Add entry" ) );
+
+ deleteRecord = new QToolButton( toolbar );
+ deleteRecord->setIconSet( SmallIconSet( "sl_delrecord" ) );
+ deleteRecord->setFixedSize( deleteRecord->sizeHint() );
+ connect( deleteRecord, SIGNAL( clicked() ),
+ this, SLOT( removeRecord() ) );
+ QToolTip::add( deleteRecord, i18n( "Remove record" ) );
+
+ deleteEntry = new QToolButton( toolbar );
+ deleteEntry->setIconSet( SmallIconSet( "sl_delentry" ) );
+ deleteEntry->setFixedSize( deleteEntry->sizeHint() );
+ connect( deleteEntry, SIGNAL( clicked() ),
+ this, SLOT( removeEntry() ) );
+ QToolTip::add( deleteEntry, i18n( "Remove entry" ) );
+
+ dbList = new KWClassicMailMergeEditorList( back, db );
+
+ if ( db->getNumRecords() > 0 ) {
+ records->setValue( 1 );
+ dbList->displayRecord(0);
+// dbList->updateItems();
+ } else {
+ first->setEnabled(false);
+ back_->setEnabled(false);
+ forward->setEnabled(false);
+ finish->setEnabled(false);
+ newRecord->setEnabled(false);
+ deleteEntry->setEnabled(false);
+ deleteRecord->setEnabled(false);
+ records->setEnabled(true);
+ }
+ setInitialSize( QSize( 600, 400 ) );
+ updateButton();
+}
+
+void KWClassicMailMergeEditor::firstRecord()
+{
+ records->setValue(1);
+ updateButton();
+}
+
+void KWClassicMailMergeEditor::prevRecord()
+{
+ records->setValue(records->value()-1);
+ updateButton();
+}
+
+void KWClassicMailMergeEditor::nextRecord()
+{
+ records->setValue(records->value()+1);
+ updateButton();
+}
+
+void KWClassicMailMergeEditor::lastRecord()
+{
+ records->setValue(records->maxValue());
+ updateButton();
+}
+
+
+void KWClassicMailMergeEditor::updateButton()
+{
+ int val = records->value();
+ first->setEnabled( val > 1);
+ back_->setEnabled( val> 1 );
+ forward->setEnabled( val < records->maxValue() );
+ finish->setEnabled( val < records->maxValue());
+
+}
+
+void KWClassicMailMergeEditor::resizeEvent( QResizeEvent *e )
+{
+ KDialogBase::resizeEvent( e );
+// back->resize( size() );
+}
+
+void KWClassicMailMergeEditor::changeRecord( int i )
+{
+ dbList->displayRecord( i - 1 );
+}
+
+void KWClassicMailMergeEditor::addEntry()
+{
+ bool ok;
+ QString value=KInputDialog::getText( i18n("Add Entry"),
+ i18n("Enter entry name:"),
+ QString::null,
+ &ok,
+ this);
+ if ((ok) && !value.isEmpty())
+ {
+ if ( db->getNumRecords() == 0 )
+ {
+ first->setEnabled(true);
+ back_->setEnabled(true);
+ forward->setEnabled(true);
+ finish->setEnabled(true);
+ newRecord->setEnabled(true);
+ deleteEntry->setEnabled(true);
+ deleteRecord->setEnabled(true);
+ records->setEnabled(true);
+ addRecord();
+ }
+ dbList->clear();
+ db->addEntry( value );
+ changeRecord( records->value() );
+ dbList->updateItems();
+ }
+ updateButton();
+}
+
+void KWClassicMailMergeEditor::addRecord()
+{
+ db->appendRecord();
+ records->setRange( records->minValue(), records->maxValue() + 1 );
+ records->setValue( db->getNumRecords() );
+ updateButton();
+
+}
+
+void KWClassicMailMergeEditor::removeEntry()
+{
+ QListViewItem * item = dbList->selectedItem ();
+ if ( item )
+ {
+ db->removeEntry( item->text(0) );
+ dbList->clear();
+ changeRecord( records->value() );
+ dbList->updateItems();
+ updateButton();
+ }
+#if defined( Q_CC_GNU )
+#warning reimplement
+#endif
+/*
+ if ( db->getNumRecords() == 0 )
+ return;
+
+ KWMailMergeVariableInsertDia
+ *dia = new KWMailMergeVariableInsertDia( this, db );
+ if ( dia->exec() == QDialog::Accepted ) {
+ dbList->clear();
+ db->removeEntry( dia->getName() );
+ changeRecord( records->value() + 1 );
+ dbList->updateItems();
+ }
+ delete dia;
+*/
+}
+
+void KWClassicMailMergeEditor::removeRecord()
+{
+ if ( db->getNumRecords() == 0 )
+ return;
+
+ db->removeRecord( records->value() - 1 );
+ dbList->invalidateCurrentRecord();
+ if ( db->getNumRecords() > 0 ) {
+ records->setRange( records->minValue(), records->maxValue() - 1 );
+ records->setValue( 1 );
+ dbList->clear();
+ dbList->updateItems();
+ } else
+ {
+ dbList->clear();
+ records->setEnabled( FALSE );
+ }
+
+ if ( db->getNumRecords() == 0 )
+ {
+ newRecord->setEnabled(false);
+ deleteEntry->setEnabled(false);
+ deleteRecord->setEnabled(false);
+ records->setEnabled(true);
+ }
+
+ updateButton();
+}
+
+extern "C" {
+ KWORD_MAILMERGE_EXPORT KWMailMergeDataSource *create_kwmailmerge_classic(KInstance *inst,QObject *parent)
+ {
+ return new KWClassicSerialDataSource(inst,parent);
+ }
+
+}
diff --git a/kword/mailmerge/KWClassicSerialDataSource.h b/kword/mailmerge/KWClassicSerialDataSource.h
new file mode 100644
index 00000000..4f348dfe
--- /dev/null
+++ b/kword/mailmerge/KWClassicSerialDataSource.h
@@ -0,0 +1,172 @@
+/* This file is part of the KDE project
+ Original file (KWMailMergeDataBase.h): Copyright (C) 1998, 1999 Reginald Stadlbauer <reggie@kde.org>
+ Copyright (C) 2001 Joseph Wenninger <jowenn@kde.org>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+*/
+
+#ifndef _SERIALLETTER_CLASSIC_PLUGIN_H_
+#define _SERIALLETTER_CLASSIC_PLUGIN_H_
+
+#include <qdom.h>
+#include <qlistview.h>
+#include <kdialogbase.h>
+#include <KoCustomVariablesDia.h>
+#include "KWMailMergeDataSource.h"
+#include <qspinbox.h>
+
+class QHBox;
+class QVBox;
+class QPushButton;
+class QListBox;
+class QLabel;
+class QLineEdit;
+class QToolButton;
+
+/******************************************************************
+ *
+ * Class: KWClassicSerialDataSource
+ *
+ ******************************************************************/
+typedef QValueList< DbRecord > Db;
+
+class KWClassicSerialDataSource: public KWMailMergeDataSource
+{
+ Q_OBJECT
+ public:
+ KWClassicSerialDataSource(KInstance *inst,QObject *parent);
+ ~KWClassicSerialDataSource();
+
+ virtual void save( QDomDocument &doc,QDomElement&);
+ virtual void load( QDomElement& elem );
+ virtual class QString getValue( const class QString &name, int record = -1 ) const;
+ virtual int getNumRecords() const {
+ return (int)db.count();
+ }
+ virtual bool showConfigDialog(QWidget *,int);
+ virtual void refresh(bool){};
+
+ protected:
+ friend class KWClassicMailMergeEditor;
+ friend class KWClassicMailMergeEditorList;
+
+ void setValue( const QString &name, const QString &value, int record = -1 );
+ void appendRecord();
+ void addEntry( const QString &name );
+ void removeEntry( const QString &name );
+ void removeRecord( int i );
+ Db db;
+};
+
+/******************************************************************
+ *
+ * Class: KWClassicMailMergeEditorListItem
+ *
+ ******************************************************************/
+
+class KWClassicMailMergeEditorListItem : public QListViewItem
+{
+public:
+ KWClassicMailMergeEditorListItem( QListView *parent );
+ KWClassicMailMergeEditorListItem( QListView *parent, QListViewItem *after );
+ virtual ~KWClassicMailMergeEditorListItem();
+
+ virtual void setText( int i, const QString &text );
+ virtual QString text( int i ) const;
+ void setup();
+ void update();
+
+protected:
+ QLineEdit *editWidget;
+
+};
+
+/******************************************************************
+ *
+ * Class: KWClassicMailMergeEditorList
+ *
+ ******************************************************************/
+
+class KWClassicMailMergeEditorList : public QListView
+{
+ Q_OBJECT
+
+public:
+ KWClassicMailMergeEditorList( QWidget *parent, KWClassicSerialDataSource *db_ );
+ virtual ~KWClassicMailMergeEditorList();
+
+ void invalidateCurrentRecord();
+ void updateItems();
+ void displayRecord( int i );
+
+ void setSorting( int, bool increasing = TRUE ) {
+ QListView::setSorting( -1, increasing );
+ }
+
+protected slots:
+ void columnSizeChange( int c, int os, int ns );
+ void sectionClicked( int c );
+
+protected:
+ KWClassicSerialDataSource *db;
+ int currentRecord;
+
+};
+
+/******************************************************************
+ *
+ * Class: KWClassicMailMergeEditor
+ *
+ ******************************************************************/
+
+class KWClassicMailMergeEditor : public KDialogBase
+{
+ Q_OBJECT
+
+public:
+ KWClassicMailMergeEditor( QWidget *parent, KWClassicSerialDataSource *db_ );
+
+protected:
+ void resizeEvent( QResizeEvent *e );
+ void updateButton();
+
+ QSpinBox *records;
+ KWClassicMailMergeEditorList *dbList;
+ QWidget *back;
+ KWClassicSerialDataSource *db;
+
+ QToolButton *first;
+ QToolButton *back_;
+ QToolButton *forward;
+ QToolButton *finish;
+ QToolButton *newRecord;
+ QToolButton *newEntry;
+ QToolButton *deleteRecord;
+ QToolButton *deleteEntry;
+
+protected slots:
+ void changeRecord( int i );
+ void addEntry();
+ void addRecord();
+ void removeEntry();
+ void removeRecord();
+ void firstRecord();
+ void prevRecord();
+ void nextRecord();
+ void lastRecord();
+};
+
+#endif
diff --git a/kword/mailmerge/Makefile.am b/kword/mailmerge/Makefile.am
new file mode 100644
index 00000000..8d596413
--- /dev/null
+++ b/kword/mailmerge/Makefile.am
@@ -0,0 +1,22 @@
+
+KDE_CXXFLAGS = $(USE_RTTI)
+INCLUDES = $(KOFFICE_INCLUDES) -I$(top_srcdir)/lib/kformula $(KOTEXT_INCLUDES) -I$(top_srcdir)/kword $(all_includes)
+
+kde_module_LTLIBRARIES = kwmailmerge_classic.la
+
+## Plugin encapsulating the (old) internally stored style
+kwmailmerge_classic_la_SOURCES = KWClassicSerialDataSource.cpp
+kwmailmerge_classic_la_LDFLAGS = $(all_libraries) -module $(KDE_PLUGIN)
+kwmailmerge_classic_la_LIBADD = ../libkwmailmerge_interface.la $(LIB_KDEUI) $(LIB_KOTEXT)
+
+METASOURCES = AUTO
+
+services_DATA=kwserialletter_classic.desktop
+servicesdir=$(kde_servicesdir)
+
+if include_sql
+SQLDIRECTORY=sql
+endif
+
+SUBDIRS = . kabc kspread $(SQLDIRECTORY)
+
diff --git a/kword/mailmerge/configure.in.in b/kword/mailmerge/configure.in.in
new file mode 100644
index 00000000..9353bafd
--- /dev/null
+++ b/kword/mailmerge/configure.in.in
@@ -0,0 +1,41 @@
+dnl only compile the sql plugin if qt was compiled with sql support
+
+
+AC_MSG_CHECKING([for SQL support in QT])
+
+LIBS_SAVE_KWSL="$LIBS"
+CXXFLAGS_SAVE_KWSL="$CXXFLAGS"
+CFLAGS_SAVE_KWSL="$CFLAGS"
+
+AC_LANG_SAVE
+AC_LANG_CPLUSPLUS
+
+LIBS="$all_libraries -lqimgio -lpng -lz $LIBJPEG $LIBQT"
+CXXFLAGS="$CXXFLAGS -I$qt_includes $all_includes"
+
+AC_TRY_COMPILE([
+#include <qglobal.h>
+],
+[
+#ifdef QT_NO_SQL
+#error "No QT-SQL support"
+#endif
+],
+ac_trycompile_kwsl_qtsql=yes,
+ac_trycompile_kwsl_qtsql=no)
+
+CXXFLAGS="$CXXFLAGS_SAVE_KWSL"
+LIBS="$LIBS_SAVE_KWSL"
+AC_LANG_RESTORE
+
+if eval "test \"`echo $ac_trycompile_kwsl_qtsql`\" = yes"; then
+ SQLDIR=sql
+ AC_SUBST(SQLDIR)
+ AC_MSG_RESULT([QT supports SQL - compile qtsqlmailmerge])
+else
+ SQLDIR=
+ AC_SUBST(SQLDIR)
+ AC_MSG_RESULT([QT supports SQL -- qtsqlmailmerge will not be built])
+fi
+
+AM_CONDITIONAL(include_sql, test -n "$SQLDIR")
diff --git a/kword/mailmerge/kabc/KWMailMergeKABC.cpp b/kword/mailmerge/kabc/KWMailMergeKABC.cpp
new file mode 100644
index 00000000..a5df7e73
--- /dev/null
+++ b/kword/mailmerge/kabc/KWMailMergeKABC.cpp
@@ -0,0 +1,551 @@
+/*
+ This file is part of the KDE project
+ Copyright (C) 2003 Tobias Koenig <tokoe@kde.org>
+ Joseph Wenninger <jowenn@kde.org>
+ Ingo Kloecker <kloecker@kde.org>
+ Copyright (C) 2004 Tobias Koenig <tokoe@kde.org>
+ Joseph Wenninger <jowenn@kde.org>
+ Ingo Kloecker <kloecker@kde.org>
+ Dirk Schmidt <fs@dirk-schmidt.net>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+*/
+
+#include <kdebug.h>
+#include <kglobal.h>
+#include <klocale.h>
+#include <kabc/distributionlist.h>
+#include <kabc/stdaddressbook.h>
+
+#include "KWMailMergeKABC.h"
+#include "KWMailMergeKABCConfig.h"
+
+KWMailMergeKABC::KWMailMergeKABC( KInstance *inst, QObject *parent )
+ : KWMailMergeDataSource( inst, parent )
+{
+ _addressBook = KABC::StdAddressBook::self();
+ _iterator = _addressBook->begin();
+
+
+ // init record list
+ // Using names from kaddressbook.
+ sampleRecord[ ("KAddressbook identifier") ] = KABC::Addressee::uidLabel();
+ sampleRecord[ ("Name" ) ] = KABC::Addressee::nameLabel();
+ sampleRecord[ ("Formatted name" ) ] = KABC::Addressee::formattedNameLabel();
+ sampleRecord[ ("Family names" ) ] = KABC::Addressee::familyNameLabel();
+ sampleRecord[ ("Given name" ) ] = KABC::Addressee::givenNameLabel();
+ sampleRecord[ ("Additional names" ) ] = KABC::Addressee::additionalNameLabel();
+ sampleRecord[ ("Honorific prefixes" ) ] = KABC::Addressee::prefixLabel();
+ sampleRecord[ ("Honorific suffixes" ) ] = KABC::Addressee::suffixLabel();
+ sampleRecord[ ("Nick name" ) ] = KABC::Addressee::nickNameLabel();
+ sampleRecord[ ("Birthday" ) ] = KABC::Addressee::birthdayLabel();
+ sampleRecord[ ("Home address: Street" ) ] = KABC::Addressee::homeAddressStreetLabel();
+ sampleRecord[ ("Home address: Locality" ) ] = KABC::Addressee::homeAddressLocalityLabel();
+ sampleRecord[ ("Home address: Region" ) ] = KABC::Addressee::homeAddressRegionLabel();
+ sampleRecord[ ("Home address: Postal code" ) ] = KABC::Addressee::homeAddressPostalCodeLabel();
+ sampleRecord[ ("Home address: Country" ) ] = KABC::Addressee::homeAddressCountryLabel();
+ sampleRecord[ ("Home address: Label" ) ] = KABC::Addressee::homeAddressLabelLabel();
+ sampleRecord[ ("Business address: Street" ) ] = KABC::Addressee::businessAddressStreetLabel();
+ sampleRecord[ ("Business address: Locality" ) ] = KABC::Addressee::businessAddressLocalityLabel();
+ sampleRecord[ ("Business address: Region" ) ] = KABC::Addressee::businessAddressRegionLabel();
+ sampleRecord[ ("Business address: Postal code" ) ] = KABC::Addressee::businessAddressPostalCodeLabel();
+ sampleRecord[ ("Business address: Country" ) ] = KABC::Addressee::businessAddressCountryLabel();
+ sampleRecord[ ("Business address: Label" ) ] = KABC::Addressee::businessAddressLabelLabel();
+ sampleRecord[ ("Home phone" ) ] = KABC::Addressee::homePhoneLabel();
+ sampleRecord[ ("Business phone" ) ] = KABC::Addressee::businessPhoneLabel();
+ sampleRecord[ ("Mobile phone" ) ] = KABC::Addressee::mobilePhoneLabel();
+ sampleRecord[ ("Home fax" ) ] = KABC::Addressee::homeFaxLabel();
+ sampleRecord[ ("Business fax" ) ] = KABC::Addressee::businessFaxLabel();
+ sampleRecord[ ("Car phone" ) ] = KABC::Addressee::carPhoneLabel();
+ sampleRecord[ ("ISDN" ) ] = KABC::Addressee::isdnLabel();
+ sampleRecord[ ("Pager" ) ] = KABC::Addressee::pagerLabel();
+ sampleRecord[ ("Email" ) ] = KABC::Addressee::emailLabel();
+ sampleRecord[ ("Mailer" ) ] = KABC::Addressee::mailerLabel();
+ sampleRecord[ ("Time zone" ) ] = KABC::Addressee::timeZoneLabel();
+ sampleRecord[ ("Geographic position" ) ] = KABC::Addressee::geoLabel();
+ sampleRecord[ ("Title" ) ] = KABC::Addressee::titleLabel();
+ sampleRecord[ ("Role" ) ] = KABC::Addressee::roleLabel();
+ sampleRecord[ ("Organization" ) ] = KABC::Addressee::organizationLabel();
+ sampleRecord[ ("Note" ) ] = KABC::Addressee::noteLabel();
+ sampleRecord[ ("productId" ) ] = KABC::Addressee::productIdLabel();
+ sampleRecord[ ("Revision" ) ] = KABC::Addressee::revisionLabel();
+ sampleRecord[ ("sortString" ) ] = KABC::Addressee::sortStringLabel();
+ sampleRecord[ ("URL" ) ] = KABC::Addressee::urlLabel();
+ sampleRecord[ ("Secrecy" ) ] = KABC::Addressee::secrecyLabel();
+ sampleRecord[ ("Preferred address: Street" ) ] = QString( "preferedAddressStreet" );
+ sampleRecord[ ("Preferred address: Locality" ) ] = QString( "preferedAddressLocality" );
+ sampleRecord[ ("Preferred address: Region" ) ] = QString( "preferedAddressRegion" );
+ sampleRecord[ ("Preferred address: Postal code" ) ] = QString( "preferedAddressPostalCode" );
+ sampleRecord[ ("Preferred address: Country" ) ] = QString( "preferedAddressCountry" );
+ sampleRecord[ ("Preferred address: Label" ) ] = QString( "preferedAddressLabel" );
+}
+
+
+KWMailMergeKABC::~KWMailMergeKABC()
+{
+ ;
+}
+
+
+void KWMailMergeKABC::addEntry( const QString &uid )
+{
+ _individualUIDs.append( uid );
+ makeUIDsExclusive();
+}
+
+
+void KWMailMergeKABC::addList( const QString &id )
+{
+ _lists.append( id );
+ parseList( id );
+ makeUIDsExclusive();
+}
+
+
+void KWMailMergeKABC::clear()
+{
+ _exclusiveUIDs.clear();
+ _individualUIDs.clear();
+ _listUIDs.clear();
+ _lists.clear();
+}
+
+
+int KWMailMergeKABC::getNumRecords() const
+{
+ kdDebug() << "KWMailMergeKABC::getNumRecords(): " << _exclusiveUIDs.count() << endl;
+ return _exclusiveUIDs.count();
+}
+
+
+QString KWMailMergeKABC::getValue( const QString &name, int record ) const
+{
+ kdDebug() << "KWMailMergeKABC::getValue(" << name << ", " << record << ")" << endl;
+ if ( record < 0 )
+ return name;
+
+ // This doesn't ever happen, right? So why is it there? Dirk Schmidt
+ if ( record == -1 && _iterator == _addressBook->end() )
+ return "";
+
+ //
+ // Set the iterator to the asked Addressee.
+ //
+ bool uidAvailable = false;
+ if ( record != -1 )
+ {
+ int counter = 0;
+
+ for ( _UIDIterator = _exclusiveUIDs.begin(); _UIDIterator != _exclusiveUIDs.end()
+ && counter < record; _UIDIterator++ )
+ {
+ counter++;
+ }
+
+ for ( _iterator = _addressBook->begin(); _iterator != _addressBook->end(); ++_iterator )
+ {
+
+ if( _iterator->uid() == *_UIDIterator )
+ {
+ uidAvailable = true;
+ break;
+ }
+ }
+ }
+
+ if( !uidAvailable )
+ {
+ return ( i18n ( "KAddressbook entry '%1' not available." ).arg( *_UIDIterator ) );
+ }
+
+
+ KABC::Addressee addr = *_iterator;
+ _iterator++; // Don't know why. Could be removed? Dirk Schmidt
+
+
+ //
+ // Return the asked variable.
+ //
+ if ( name == "KAddressbook identifier" )
+ return addr.uid();
+ if ( name == "Name" )
+ return addr.name();
+ if ( name == "Formatted name" )
+ return addr.formattedName();
+ if ( name == "Family names" )
+ return addr.familyName();
+ if ( name == "Given name" )
+ return addr.givenName();
+ if ( name == "Additional names" )
+ return addr.additionalName();
+ if ( name == "Honorific prefixes" )
+ return addr.prefix();
+ if ( name == "Honorific suffixes" )
+ return addr.suffix();
+ if ( name == "Nick name" )
+ return addr.nickName();
+ if ( name == "Birthday" )
+ return KGlobal::locale()->formatDate( addr.birthday().date() );
+
+ if ( name == "Home address: Street" )
+ {
+ KABC::Address a = addr.address( KABC::Address::Home );
+ return a.street();
+ }
+ if ( name == "Home address: Locality" )
+ {
+ KABC::Address a = addr.address( KABC::Address::Home );
+ return a.locality();
+ }
+ if ( name == "Home address: Region" )
+ {
+ KABC::Address a = addr.address( KABC::Address::Home );
+ return a.region();
+ }
+ if ( name == "Home address: Postal code" )
+ {
+ KABC::Address a = addr.address( KABC::Address::Home );
+ return a.postalCode();
+ }
+ if ( name == "Home address: Country" )
+ {
+ KABC::Address a = addr.address( KABC::Address::Home );
+ return a.country();
+ }
+ if ( name == "Home address: Label" )
+ {
+ KABC::Address a = addr.address( KABC::Address::Home );
+ return a.label();
+ }
+
+ if ( name == "Business address: Street" )
+ {
+ KABC::Address a = addr.address( KABC::Address::Work );
+ return a.street();
+ }
+ if ( name == "Business address: Locality" )
+ {
+ KABC::Address a = addr.address( KABC::Address::Work );
+ return a.locality();
+ }
+ if ( name == "Business address: Region" )
+ {
+ KABC::Address a = addr.address( KABC::Address::Work );
+ return a.region();
+ }
+ if ( name == "Business address: Postal code" )
+ {
+ KABC::Address a = addr.address( KABC::Address::Work );
+ return a.postalCode();
+ }
+ if ( name == "Business address: Country" )
+ {
+ KABC::Address a = addr.address( KABC::Address::Work );
+ return a.country();
+ }
+ if ( name == "Business address: Label" )
+ {
+ KABC::Address a = addr.address( KABC::Address::Work );
+ return a.label();
+ }
+
+ if ( name == "Prefered address: Street" )
+ {
+ KABC::Address a = addr.address( KABC::Address::Pref );
+ return a.street();
+ }
+
+ if ( name == "Prefered address: Locality" )
+ {
+ KABC::Address a = addr.address( KABC::Address::Pref );
+ return a.locality();
+ }
+ if ( name == "Prefered address: Region" )
+ {
+ KABC::Address a = addr.address( KABC::Address::Pref );
+ return a.region();
+ }
+ if ( name == "Prefered address: Postal code" )
+ {
+ KABC::Address a = addr.address( KABC::Address::Pref );
+ return a.postalCode();
+ }
+ if ( name == "Prefered address: Country" )
+ {
+ KABC::Address a = addr.address( KABC::Address::Pref );
+ return a.country();
+ }
+ if ( name == "Prefered address: Label" )
+ {
+ KABC::Address a = addr.address( KABC::Address::Pref );
+ return a.label();
+ }
+
+ if ( name == "Home phone" )
+ {
+ KABC::PhoneNumber phone = addr.phoneNumber( KABC::PhoneNumber::Home );
+ return phone.number();
+ }
+ if ( name == "Business phone" )
+ {
+ KABC::PhoneNumber phone = addr.phoneNumber( KABC::PhoneNumber::Work );
+ return phone.number();
+ }
+ if ( name == "Mobile phone" )
+ {
+ KABC::PhoneNumber phone = addr.phoneNumber( KABC::PhoneNumber::Cell );
+ return phone.number();
+ }
+ if ( name == "Home fax" )
+ {
+ KABC::PhoneNumber phone = addr.phoneNumber( KABC::PhoneNumber::Home | KABC::PhoneNumber::Fax );
+ return phone.number();
+ }
+ if ( name == "Business fax" )
+ {
+ KABC::PhoneNumber phone = addr.phoneNumber( KABC::PhoneNumber::Work | KABC::PhoneNumber::Fax );
+ return phone.number();
+ }
+ if ( name == "Car phone" )
+ {
+ KABC::PhoneNumber phone = addr.phoneNumber( KABC::PhoneNumber::Car );
+ return phone.number();
+ }
+ if ( name == "ISDN" )
+ {
+ KABC::PhoneNumber phone = addr.phoneNumber( KABC::PhoneNumber::Isdn );
+ return phone.number();
+ }
+ if ( name == "Pager" )
+ {
+ KABC::PhoneNumber phone = addr.phoneNumber( KABC::PhoneNumber::Pager );
+ return phone.number();
+ }
+
+ if ( name == "Email" )
+ return addr.preferredEmail();
+ if ( name == "Mailer" )
+ return addr.mailer();
+ if ( name == "Time zone" )
+ {
+ KABC::TimeZone zone = addr.timeZone();
+ return QString::number( zone.offset() );
+ }
+ if ( name == "Geographic position" )
+ {
+ KABC::Geo geo = addr.geo();
+ QString lat;
+ QString longi;
+ if( geo.latitude()<0 )
+ lat = QString( i18n("%1 South") ).arg( -geo.latitude() );
+ else
+ lat = QString( i18n("%1 North") ).arg( geo.latitude() );
+
+ if( geo.longitude()<0 )
+ // There is something going wrong, because "W" is replaced by "q ".
+ // Needs fix.
+ longi = QString( i18n("%1 West") ).arg( -geo.longitude() );
+ else
+ longi = QString( i18n("%1 East") ).arg( geo.longitude() );
+
+ return i18n( "Geographic coordinates", "%1, %2" ).arg ( lat, longi );
+ }
+
+ if ( name == "Title" )
+ return addr.title();
+ if ( name == "Role" )
+ return addr.role();
+ if ( name == "Organization" )
+ return addr.organization();
+ if ( name == "Note" )
+ return addr.note();
+ if ( name == "productId" )
+ return addr.productId();
+ if ( name == "Revision" )
+ return KGlobal::locale()->formatDate( addr.revision().date() );
+ if ( name == "sortString" )
+ return addr.sortString();
+ if ( name == "URL" )
+ return addr.url().url();
+ if ( name == "Secrecy" )
+ {
+ KABC::Secrecy secrecy = addr.secrecy();
+ return KABC::Secrecy::typeLabel( secrecy.type() );
+ }
+
+ return ( i18n("Unkown mail merge variable: %1").arg ( name ) ) ;
+}
+
+
+QStringList KWMailMergeKABC::lists() const
+{
+ return _lists;
+}
+
+
+void KWMailMergeKABC::load( QDomElement& parentElem )
+{
+ clear();
+ QDomNode contentNode=parentElem.namedItem("CONTENT");
+ if( contentNode.isNull() )
+ return;
+ for( QDomNode rec=contentNode.firstChild(); !rec.isNull(); rec=rec.nextSibling() )
+ {
+ if( rec.nodeName()== "RECORD" )
+ {
+ for( QDomElement recEnt=rec.firstChild().toElement(); !recEnt.isNull();
+ recEnt=recEnt.nextSibling().toElement() )
+ {
+ addEntry( recEnt.attribute( QString::fromLatin1("uid") ) );
+ }
+ }
+ else if( rec.nodeName() == "LIST" )
+ {
+ for( QDomElement recEnt=rec.firstChild().toElement(); !recEnt.isNull();
+ recEnt=recEnt.nextSibling().toElement() )
+ {
+ addList( recEnt.attribute( QString::fromLatin1("listid") ) );
+ }
+ }
+ else
+ kdDebug() << "rec.nodeName(): " << rec.nodeName() << endl;
+ }
+}
+
+
+void KWMailMergeKABC::makeUIDsExclusive()
+{
+ _exclusiveUIDs = _individualUIDs + _listUIDs;
+ _exclusiveUIDs.sort();
+ kdDebug() << "KWMailMergeKABC::makeUIDsExclusive(): before: " << _exclusiveUIDs.join(",")
+ << endl;
+ QString uid;
+ for( QStringList::Iterator it=_exclusiveUIDs.begin();
+ it!=_exclusiveUIDs.end(); ++it )
+ {
+ if( *it == uid )
+ {
+ it = _exclusiveUIDs.remove( it );
+ }
+ uid = *it;
+ }
+ kdDebug() << "KWMailMergeKABC::makeUIDsExclusive(): after: " << _exclusiveUIDs.join(",")
+ << endl;
+}
+
+
+void KWMailMergeKABC::parseList( const QString& listName )
+{
+ if( listName.isEmpty() )
+ return;
+
+ kdDebug() << "KWMailMergeKABC::parseList: " << listName << endl;
+ KABC::DistributionListManager dlm ( _addressBook );
+ dlm.load();
+
+ QStringList::Iterator listIt;
+
+ KABC::DistributionList* list = dlm.list( listName );
+ KABC::DistributionList::Entry::List entries = list->entries();
+
+ KABC::DistributionList::Entry::List::Iterator itemIt;
+ for ( itemIt = entries.begin(); itemIt != entries.end(); ++itemIt )
+ {
+ kdDebug() << "WMailMergeKABC::parseList: Listentry UID: " <<
+ (*itemIt).addressee.uid() << endl;
+ _listUIDs.append( (*itemIt).addressee.uid() );
+ }
+}
+
+
+void KWMailMergeKABC::refresh( bool )
+{
+ kdDebug() << "KWMailMergeKABC::refresh()" << endl;
+ _iterator = _addressBook->begin();
+ _UIDIterator = _individualUIDs.begin();
+
+}
+
+
+void KWMailMergeKABC::save( QDomDocument& doc, QDomElement& parent)
+{
+ QDomElement cont=doc.createElement(QString::fromLatin1("CONTENT"));
+ parent.appendChild(cont);
+
+ QValueList<QString>::ConstIterator it = _individualUIDs.begin();
+ for( ; it != _individualUIDs.end(); ++it )
+ {
+ QDomElement rec=doc.createElement(QString::fromLatin1("RECORD"));
+ cont.appendChild(rec);
+ QDomElement recEnt=doc.createElement(QString::fromLatin1("ITEM"));
+ recEnt.setAttribute(QString::fromLatin1("uid"),*it);
+ rec.appendChild(recEnt);
+ }
+
+ it = _lists.begin();
+ for( ; !(it == _lists.end()); ++it )
+ {
+ QDomElement rec=doc.createElement(QString::fromLatin1("LIST"));
+ cont.appendChild(rec);
+ QDomElement recEnt=doc.createElement(QString::fromLatin1("ITEM"));
+ recEnt.setAttribute(QString::fromLatin1("listid"),*it);
+ rec.appendChild(recEnt);
+ }
+}
+
+bool KWMailMergeKABC::showConfigDialog( QWidget* par, int action )
+{
+ bool ret=false;
+ if (action == KWSLCreate )
+ {
+ clear();
+ }
+
+ //if (action==KWSLOpen)
+ {
+ KWMailMergeKABCConfig *dia=new KWMailMergeKABCConfig( par, this );
+
+ ret=( dia->exec() == QDialog::Accepted );
+ kdDebug() << "KWMailMergeKABCConfig::Accepted " << ret << endl;
+ delete dia;
+ }
+ refresh(false);
+
+ return ret;
+}
+
+
+QStringList KWMailMergeKABC::singleRecords() const
+{
+ return _individualUIDs;
+}
+
+
+
+extern "C"
+{
+ KWORD_MAILMERGE_EXPORT KWMailMergeDataSource *create_kwmailmerge_kabc( KInstance *inst, QObject *parent )
+ {
+ return new KWMailMergeKABC( inst, parent );
+ }
+}
+
+
+
+
+#include "KWMailMergeKABC.moc"
+
+
diff --git a/kword/mailmerge/kabc/KWMailMergeKABC.h b/kword/mailmerge/kabc/KWMailMergeKABC.h
new file mode 100644
index 00000000..2787ac6f
--- /dev/null
+++ b/kword/mailmerge/kabc/KWMailMergeKABC.h
@@ -0,0 +1,185 @@
+/*
+ This file is part of the KDE project
+ Copyright (C) 2003 Tobias Koenig <tokoe@kde.org>
+ Copyright (C) 2004 Tobias Koenig <tokoe@kde.org>
+ Dirk Schmidt <fs@dirk.schmidt.net>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+*/
+
+#ifndef _KWMAILMERGE_KABC_H_
+#define _KWMAILMERGE_KABC_H_
+
+#include <qdom.h>
+#include <qguardedptr.h>
+
+#include <kabc/addressbook.h>
+
+#include "KWMailMergeDataSource.h"
+
+class KWMailMergeKABC: public KWMailMergeDataSource
+{
+ Q_OBJECT
+
+public:
+ KWMailMergeKABC( KInstance *inst, QObject *parent );
+ ~KWMailMergeKABC();
+
+ /**
+ Saves the mail merge list to the kword document.
+ */
+ virtual void save( QDomDocument&, QDomElement& );
+
+ /**
+ Loads the mail merge list stored in the kword document.
+ */
+ virtual void load( QDomElement& );
+
+ /**
+ @param name The name of the value e.g. "Family name".
+ @param record The position of the the entry in mail merge list.
+ @return The value of the mail merge variable.
+
+ If @p record equals -1, @p name is returned.
+ */
+ virtual class QString getValue( const class QString &name, int record = -1 ) const;
+
+ /**
+ @return The number of available contacts in mail merge list.
+ */
+ virtual int getNumRecords() const;
+
+ /**
+ Only for compatability reasons.
+
+ @param force Hasn't any effect.
+ */
+ virtual void refresh( bool force );
+
+ /**
+ Shows a KWMailMergeKABCConfig dialog for selecting entries from KAddressbook.
+ */
+ virtual bool showConfigDialog( QWidget*, int action);
+
+protected:
+ friend class KWMailMergeKABCConfig;
+
+ /**
+ Adds an entry from KABC::StdAddressBook::self()
+ to the mail merge list.
+
+ To be called by KWMailMergeKABC::load() and
+ KWMailMergeKABCConfig::acceptSelection() only.
+
+ @param uid The entry's KABC::Addressee::uid().
+ */
+ void addEntry( const QString &uid );
+
+ /**
+ Adds a distribution list to the mail merge list.
+
+ To be called by KWMailMergeKABC::load() and
+ KWMailMergeKABCConfig::acceptSelection() only.
+
+ @param id The DistributionList::name().
+ */
+ void addList( const QString &id );
+
+ /**
+ Removes all entries and distribution lists from the mail merge list.
+ */
+ void clear();
+
+ /**
+ @return All selected DistributionList::name().
+
+ To be called by KWMailMergeKABCConfig::initSelectedLists()
+ */
+ virtual QStringList lists() const;
+
+ /**
+ @return The KABC::Addressee::uid() of all individually selected
+ entries in mail merge list.
+
+ To be called by KWMailMergeKABCConfig::initSelectedAddressees()
+ */
+ virtual QStringList singleRecords() const;
+
+private:
+ /**
+ The KABC::StdAddressBook::self().
+ */
+ KABC::AddressBook* _addressBook;
+
+ /**
+ Just an Iterator.
+ */
+ mutable KABC::AddressBook::ConstIterator _iterator;
+
+ /**
+ Just an Iterator.
+ */
+ mutable QStringList::ConstIterator _UIDIterator;
+
+ /**
+ The "real" mail merge list. A list of QStrings. Each represents
+ the KABC::Addressee::uid() of a KAdressbook entry.
+ There is no UID twice in this list.
+
+ Needed because selected contacts may appear in a selected
+ distribution list, too. And we don't want to print it multiple.
+ */
+ QStringList _exclusiveUIDs;
+
+ /**
+ This list contains all the KABC::Addressee::uid() selected
+ individually with the KWMailMergeKABCConfig dialog.
+ */
+ QStringList _individualUIDs;
+
+ /**
+ This list contains all the KABC::Addressee::uid() from the distribution
+ lists selected with the KWMailMergeKABCConfig dialog.
+ */
+ QStringList _listUIDs;
+
+ /**
+ This list contains all the DistributionList::name() selected with the
+ KWMailMergeKABCConfig dialog.
+ */
+ QStringList _lists;
+
+
+ /**
+ Appends all KABC::Addressee::uid() of a distribution list to _listUIDs
+ and updates the mail merge list.
+
+ To be used by KWMailMergeKABCConfig::addList( const QString &id )
+ only.
+
+ @param listName The DistributionList::name() of the distribution list.
+ */
+ void parseList( const QString& listName );
+
+ /**
+ Removes duplicate entries in the mail merge list.
+ */
+ void makeUIDsExclusive();
+
+};
+
+#endif
+
diff --git a/kword/mailmerge/kabc/KWMailMergeKABCConfig.cpp b/kword/mailmerge/kabc/KWMailMergeKABCConfig.cpp
new file mode 100644
index 00000000..dee519c3
--- /dev/null
+++ b/kword/mailmerge/kabc/KWMailMergeKABCConfig.cpp
@@ -0,0 +1,546 @@
+/*
+ This file is part of the KDE project
+ Copyright (C) 2004 Dirk Schmidt <fs@dirk-schmidt.net>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+*/
+
+
+#include <qvbox.h>
+#include <qlayout.h>
+#include <qlineedit.h>
+
+#include <kapplication.h>
+#include <kdebug.h>
+#include <kglobal.h>
+#include <kinputdialog.h>
+#include <klocale.h>
+#include <kmessagebox.h>
+#include <kpushbutton.h>
+#include <krun.h>
+#include <kabc/stdaddressbook.h>
+#include <kabc/distributionlist.h>
+
+#include "addresspicker.h"
+#include "KWMailMergeKABC.h"
+#include "KWMailMergeKABCConfig.h"
+
+
+KWMailMergeKABCConfig::KWMailMergeKABCConfig( QWidget *parent, KWMailMergeKABC *db_)
+ :KDialogBase( Plain, i18n( "Mail Merge - Editor" ),
+ Ok | Cancel, Ok, parent, "", true)
+{
+ _db = db_;
+
+ (new QVBoxLayout(plainPage()))->setAutoAdd(true);
+ setMainWidget( _ui=new AddressPickerUI( plainPage() ) );
+
+ updateAvailable();
+ initSelectedAddressees();
+ initSelectedLists();
+ initSlotSignalConnections();
+}
+
+
+KWMailMergeKABCConfig::~KWMailMergeKABCConfig()
+{
+ ;
+}
+
+
+void KWMailMergeKABCConfig::acceptSelection()
+{
+ _db->clear();
+
+ QListViewItem* top = _ui->mSelectedView->firstChild();
+ while(top)
+ {
+ kdDebug() << "acceptSelection(): " << top->text(0) << endl;
+ if( top->text(0) == i18n("Distribution Lists") )
+ {
+ QListViewItem* item = top->firstChild();
+ while(item)
+ {
+ kdDebug() << "acceptSelection(): " << item->text(0) << endl;
+ _db->addList( item->text(0) );
+ item = item->nextSibling();
+ }
+ }
+ else if( top->text(0) == i18n("Single Entries") )
+ {
+ QListViewItem* item = top->firstChild();
+ while(item)
+ {
+ kdDebug() << "acceptSelection(): " << item->text(0) << endl;
+ _db->addEntry( item->text(-1) );
+ item = item->nextSibling();
+ }
+ }
+ top = top->nextSibling();
+ }
+
+}
+
+
+void KWMailMergeKABCConfig::addSelectedContacts()
+{
+ QListViewItemIterator it( _ui->mAvailableView, QListViewItemIterator::Selected );
+ QListViewItem* selected = _ui->mSelectedView->findItem(
+ i18n("Single Entries"), 0, Qt::ExactMatch );
+ QListViewItem* selectedLists = _ui->mSelectedView->findItem(
+ i18n("Distribution Lists"), 0, Qt::ExactMatch );
+ while ( it.current() )
+ {
+ if( it.current()->depth() > 0 )
+ {
+ QString uid = it.current()->text( -1 );
+ kdDebug() << "addSelectedContacts(): uid :" << uid << endl;
+ if( !uid.isEmpty() )
+ {
+ KWMailMergeKABCConfigListItem *item =
+ static_cast<KWMailMergeKABCConfigListItem*> ( it.current() );
+ if( selected )
+ {
+ selected->insertItem( item );
+ selected->setOpen( true );
+ destroyAvailableClones( uid );
+ }
+ }
+ else if( it.current()->parent()->text(0) == i18n("Distribution Lists") )
+ {
+ if( selectedLists )
+ {
+ selectedLists->insertItem( it.current() );
+ selectedLists->setOpen( true );
+ }
+ }
+ }
+ ++it;
+ }
+ _ui->mSelectedView->selectAll( false );
+}
+
+
+void KWMailMergeKABCConfig::destroyAvailableClones( const QString& uid )
+{
+ if( uid.isEmpty() )
+ return;
+
+ QListViewItemIterator it( _ui->mAvailableView );
+
+ while ( it.current() )
+ {
+ if( it.current()->depth() > 0)
+ {
+ if( it.current()->text(-1)== uid )
+ {
+ delete it.current();
+ }
+ }
+ ++it;
+ }
+}
+
+
+void KWMailMergeKABCConfig::filterChanged( const QString& txt )
+{
+ kdDebug() << "KWMailMergeKABCConfig::filterChanged( " << txt << " )" << endl;
+
+ bool showAll = txt.isEmpty();
+
+ QListViewItem* category = _ui->mAvailableView->firstChild();
+ while(category)
+ {
+ if( category->text(0)!=i18n("Distribution Lists") )
+ {
+ QListViewItem* item = category->firstChild();
+ while(item)
+ {
+ if(showAll)
+ {
+ item->setVisible( true );
+ }
+ else
+ {
+ item->setVisible( item->text(0).contains( txt, false ) );
+ }
+ item = item->nextSibling();
+ }
+ category->setOpen( !showAll );
+ }
+ else
+ {
+ category->setVisible( showAll );
+ }
+ category = category->nextSibling();
+ }
+}
+
+
+void KWMailMergeKABCConfig::initSelectedAddressees()
+{
+ QStringList records = _db->singleRecords();
+
+ QListViewItem* category = _ui->mAvailableView->firstChild();
+ QListViewItem* selected = _ui->mSelectedView->findItem(
+ i18n("Single Entries"), 0, Qt::ExactMatch );
+ while ( category && (records.count()>0) )
+ {
+ if( category->text(0) != i18n("Distribution Lists") )
+ {
+ KWMailMergeKABCConfigListItem* item =
+ static_cast<KWMailMergeKABCConfigListItem*> ( category->firstChild() );
+ while( item && (records.count()>0) )
+ {
+ // Need some temporary item, because after selected->insertItem( item )
+ // the item->nextSibling() is not the one we want.
+ KWMailMergeKABCConfigListItem* nextItem =
+ static_cast<KWMailMergeKABCConfigListItem*> ( item->nextSibling() );
+
+ for( QStringList::Iterator itRecords = records.begin();
+ itRecords != records.end(); ++itRecords )
+ {
+ QString uid = *itRecords;
+ if( item->text(-1) == uid )
+ {
+ selected->insertItem( item );
+
+ // downsize records to speed up iterations
+ itRecords = records.remove( itRecords );
+ --itRecords;
+
+ destroyAvailableClones( uid );
+ }
+ }
+ item = nextItem;
+ }
+ }
+ category = category->nextSibling();
+ }
+}
+
+
+void KWMailMergeKABCConfig::initSelectedLists()
+{
+ QStringList lists = _db->lists();
+
+ kdDebug() << "::initSelectedLists()" << lists.join(",") << endl;
+
+ QListViewItem* l = _ui->mAvailableView->findItem(
+ i18n("Distribution Lists"), 0, Qt::ExactMatch );
+ QListViewItem* selected = _ui->mSelectedView->findItem(
+ i18n("Distribution Lists"), 0, Qt::ExactMatch );
+
+ QListViewItem* item = ( l->firstChild() );
+ while( item && (lists.count()>0) )
+ {
+ QListViewItem* nextItem = item->nextSibling();
+
+ for( QStringList::Iterator itLists = lists.begin();
+ itLists != lists.end(); ++itLists )
+ {
+ QString id = *itLists;
+ if( item->text(0) == id )
+ {
+ selected->insertItem( item );
+ itLists = lists.remove( itLists );
+ --itLists;
+ }
+ }
+ item = nextItem;
+ }
+}
+
+
+void KWMailMergeKABCConfig::initSlotSignalConnections()
+{
+ connect( this, SIGNAL( okClicked() ), SLOT( acceptSelection() ) );
+ connect( _ui->mAddButton, SIGNAL( clicked() ), SLOT( addSelectedContacts() ) );
+ connect( _ui->mAddressBook, SIGNAL( clicked() ), SLOT( launchAddressbook() ) );
+
+ connect( _ui->mAvailableView, SIGNAL( doubleClicked( QListViewItem *, const QPoint &, int ) ),
+ SLOT( addSelectedContacts() ) );
+
+ connect( _ui->mFilterEdit, SIGNAL( textChanged(const QString &) ),
+ SLOT( filterChanged(const QString &) ) );
+ connect( _ui->mRemoveButton, SIGNAL( clicked() ), SLOT( removeSelectedContacts() ) );
+ connect( _ui->mSaveList, SIGNAL( clicked() ), SLOT( saveDistributionList() ) );
+ connect( _ui->mSelectedView, SIGNAL( doubleClicked( QListViewItem *, const QPoint &, int ) ),
+ SLOT( removeSelectedContacts() ) );
+}
+
+
+void KWMailMergeKABCConfig::launchAddressbook() const
+{
+ kapp->startServiceByDesktopName( "kaddressbook", QString() );
+}
+
+
+
+void KWMailMergeKABCConfig::removeContact( QListViewItem* item )
+{
+ QStringList& categories = _usedCategories;
+ QListViewItem* availableLists = _ui->mAvailableView->findItem(
+ i18n("Distribution Lists"), 0, Qt::ExactMatch );
+ if( item->depth() > 0 )
+ {
+ if( !item->text( -1 ).isEmpty() ) // remove selected single entry here
+ {
+ KWMailMergeKABCConfigListItem* rightItem =
+ static_cast<KWMailMergeKABCConfigListItem*> ( item );
+
+ QStringList entryCategories = rightItem->addressee().categories();
+ for ( QStringList::Iterator itEntryCat = entryCategories.begin();
+ itEntryCat != entryCategories.end(); ++itEntryCat )
+ {
+ int i = categories.findIndex(*itEntryCat);
+ if( i == -1 )
+ {
+ QListViewItem* category = new QListViewItem( _ui->mAvailableView,
+ *itEntryCat );
+ categories.append( *itEntryCat );
+
+ KWMailMergeKABCConfigListItem* leftItem = new KWMailMergeKABCConfigListItem(
+ category, rightItem->addressee() );
+ }
+ else
+ {
+ KWMailMergeKABCConfigListItem* leftItem = new
+ KWMailMergeKABCConfigListItem(
+ _ui->mAvailableView->findItem(
+ *itEntryCat, 0,
+ Qt::ExactMatch),
+ rightItem->addressee() );
+ }
+ }
+ if( entryCategories.isEmpty() )
+ {
+ QString noCat = i18n("no category");
+ KWMailMergeKABCConfigListItem* leftItem = new KWMailMergeKABCConfigListItem(
+ _ui->mAvailableView->findItem(
+ noCat, 0, Qt::ExactMatch),
+ rightItem->addressee() );
+ }
+ delete item;
+ }
+ else if( item->parent()->text(0) == i18n("Distribution Lists") ) // remove a list
+ {
+ if( availableLists )
+ availableLists->insertItem( item );
+ }
+ }
+}
+
+void KWMailMergeKABCConfig::removeSelectedContacts()
+{
+ QListViewItemIterator it( _ui->mSelectedView, QListViewItemIterator::Selected );
+
+ while( it.current() )
+ {
+ kdDebug() << "removeSelectedContacts(): text: " << it.current()->text(-1) << endl;
+ removeContact( it.current() );
+ ++it;
+ }
+ _ui->mAvailableView->selectAll( false );
+}
+
+
+void KWMailMergeKABCConfig::saveDistributionList()
+{
+ KABC::DistributionListManager dlm( KABC::StdAddressBook::self() );
+ dlm.load();
+
+ bool ok = false;
+ QString listName = KInputDialog::getText( i18n("New Distribution List"),
+ i18n("Please enter name:"),
+ QString::null, &ok,
+ this );
+ if ( !ok || listName.isEmpty() )
+ return;
+
+ if ( dlm.list( listName ) )
+ {
+ KMessageBox::information( 0,
+ i18n( "<qt>Distribution list with the given name <b>%1</b> "
+ "already exists. Please select a different name.</qt>" )
+ .arg( listName ) );
+ return;
+ }
+ KABC::DistributionList *distList = new KABC::DistributionList( &dlm, listName );
+
+ QListViewItem* newListItem = new QListViewItem( _ui->mSelectedView->findItem(
+ i18n("Distribution Lists"),0 , Qt::ExactMatch), listName );
+
+ QListViewItem* category = _ui->mSelectedView->firstChild();
+ while(category)
+ {
+ if( category->text(0)==i18n("Single Entries") )
+ {
+ KWMailMergeKABCConfigListItem* item =
+ static_cast<KWMailMergeKABCConfigListItem*> ( category->firstChild() );
+
+ while(item)
+ {
+ distList->insertEntry( item->addressee() );
+
+ KABC::Addressee addr = item->addressee();
+ QString formattedName = addr.formattedName();
+ QListViewItem* newItem = new QListViewItem(
+ newListItem, item->addressee().formattedName() );
+ newItem->setEnabled( false );
+
+ item = static_cast<KWMailMergeKABCConfigListItem*>( item->nextSibling() );
+ }
+
+ QListViewItemIterator it ( category->firstChild() );
+ while( it.current() )
+ {
+ removeContact( it.current() );
+ ++it;
+ }
+ }
+ category = category->nextSibling();
+ }
+
+ dlm.save();
+ newListItem->setOpen( true );
+}
+
+
+void KWMailMergeKABCConfig::updateAvailable()
+{
+ _ui->mAvailableView->clear();
+ _ui->mAvailableView->setRootIsDecorated( true );
+
+ //
+ // First append the addressees.
+ //
+ QListViewItem* noCategory = new QListViewItem( _ui->mAvailableView,
+ i18n("no category") );
+
+ QStringList& categories = _usedCategories ;
+ categories.clear();
+
+ KABC::AddressBook *addressBook = KABC::StdAddressBook::self();
+ for( KABC::AddressBook::Iterator itAddr = addressBook->begin();
+ itAddr != addressBook->end(); ++itAddr )
+ {
+
+ QStringList entryCategories = itAddr->categories();
+ for ( QStringList::Iterator itCat = entryCategories.begin();
+ itCat != entryCategories.end(); ++itCat )
+ {
+ int i = categories.findIndex(*itCat);
+
+ // Create category, if not yet in listview and append item to it.
+ if( i == -1 )
+ {
+ QListViewItem* category = new QListViewItem( _ui->mAvailableView, *itCat );
+ categories.append( *itCat );
+
+ KWMailMergeKABCConfigListItem* item = new KWMailMergeKABCConfigListItem(
+ category, *itAddr );
+ }
+ // Append item to existing category in listview.
+ else
+ {
+ KWMailMergeKABCConfigListItem* item = new KWMailMergeKABCConfigListItem(
+ _ui->mAvailableView->findItem(
+ *itCat, 0, Qt::ExactMatch),
+ *itAddr );
+ }
+
+ }
+ // If Addressee does not belong to any category, append it to "no category".
+ if( entryCategories.isEmpty() )
+ {
+ KWMailMergeKABCConfigListItem* item = new KWMailMergeKABCConfigListItem(
+ noCategory, *itAddr );
+ }
+ }
+
+ //
+ // Now append the distribution lists
+ //
+ KABC::DistributionListManager dlm ( addressBook );
+ dlm.load();
+
+ QStringList distributionLists = dlm.listNames();
+ QListViewItem* distributionListsItem = new QListViewItem( _ui->mAvailableView,
+ i18n("Distribution Lists") );
+
+ QStringList::Iterator itDistributionLists;
+
+ for( itDistributionLists = distributionLists.begin();
+ itDistributionLists != distributionLists.end(); ++itDistributionLists )
+ {
+ KABC::DistributionList* list = dlm.list( *itDistributionLists );
+
+ KABC::DistributionList::Entry::List entries = list->entries();
+
+ QListViewItem* listItem = new QListViewItem( distributionListsItem,
+ *itDistributionLists );
+
+ KABC::DistributionList::Entry::List::Iterator itList;
+ for ( itList = entries.begin(); itList != entries.end(); ++itList )
+ {
+ // Create a normal QListViewItem and disable it, because this is not a
+ // distribution-list-editor. KAddressbook should be used instead.
+ QListViewItem* item = new QListViewItem(
+ listItem, (*itList).addressee.formattedName() );
+ item->setEnabled( false );
+ }
+
+ }
+}
+
+
+
+KWMailMergeKABCConfigListItem::KWMailMergeKABCConfigListItem( QListView *parent,
+ const KABC::Addressee& addressEntry ) : QListViewItem( parent )
+{
+ setText( 0, addressEntry.formattedName() );
+ _addressEntry = addressEntry;
+}
+
+KWMailMergeKABCConfigListItem::KWMailMergeKABCConfigListItem( QListViewItem *parent,
+ const KABC::Addressee& addressEntry ) : QListViewItem( parent )
+{
+ setText( 0, addressEntry.formattedName() );
+ _addressEntry = addressEntry;
+}
+
+KWMailMergeKABCConfigListItem::~KWMailMergeKABCConfigListItem()
+{}
+
+KABC::Addressee KWMailMergeKABCConfigListItem::addressee() const
+{
+ return _addressEntry;
+}
+
+QString KWMailMergeKABCConfigListItem::text( int column ) const
+{
+ if( column == -1 )
+ {
+ return _addressEntry.uid();
+ }
+ else
+ {
+ return QListViewItem::text( column );
+ }
+}
+
+#include "KWMailMergeKABCConfig.moc"
diff --git a/kword/mailmerge/kabc/KWMailMergeKABCConfig.h b/kword/mailmerge/kabc/KWMailMergeKABCConfig.h
new file mode 100644
index 00000000..335574b8
--- /dev/null
+++ b/kword/mailmerge/kabc/KWMailMergeKABCConfig.h
@@ -0,0 +1,149 @@
+/*
+ This file is part of the KDE project
+ Copyright (C) 2004 Dirk Schmidt <fs@dirk-schmidt.net>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+*/
+
+#ifndef _KWMAILMERGE_KABC_CONFIG_H_
+#define _KWMAILMERGE_KABC_CONFIG_H_
+
+#include <kdialogbase.h>
+#include <klistview.h>
+#include <kabc/stdaddressbook.h>
+
+#include "KWMailMergeKABC.h"
+
+
+class AddressPickerUI;
+class KWMailMergeKABC;
+
+class KWMailMergeKABCConfig: public KDialogBase
+{
+ Q_OBJECT
+public:
+ KWMailMergeKABCConfig( QWidget *parent, KWMailMergeKABC *db_ );
+ virtual ~KWMailMergeKABCConfig();
+
+
+private slots:
+
+ /**
+ Moves selected items from the left Listview to the right one.
+ */
+ void addSelectedContacts();
+
+ /**
+ Moves selected items from the right Listview to the left one.
+ */
+ void removeSelectedContacts();
+
+ /**
+ Executes KAddressbook as external application.
+ */
+ void launchAddressbook() const;
+
+ /**
+ Updates the parent's mail merge list from items in the right Listview.
+ */
+ void acceptSelection();
+
+ /**
+ Hides items in the left listview, which are not matching @p txt.
+ */
+ void filterChanged( const QString& txt );
+
+ /**
+ Saves the selected single entries to a new KABC::DistributionList in KAddressbook.
+ */
+ void saveDistributionList();
+private:
+ /**
+ The addresspicker widget.
+ */
+ AddressPickerUI *_ui;
+
+ /**
+ Store all categories used in the addressbook, to avoid some iterator cycles.
+ */
+ QStringList _usedCategories;
+
+ /**
+ The mail merge list.
+ */
+ KWMailMergeKABC *_db;
+
+ /**
+ Removes duplicates in the left QListView, when moving an item to the right.
+ */
+ void destroyAvailableClones( const QString& uid );
+
+ /**
+ Appends the previously selected entries to the right QListView.
+ */
+ void initSelectedAddressees();
+
+ /**
+ Appends the previously selected distribution lists to the right QListView.
+ */
+ void initSelectedLists();
+
+ /**
+ Just connects signals and slots.
+ */
+ void initSlotSignalConnections();
+
+ /**
+ Moves @p item from the right Listview to the left one.
+
+ Called by KWMailMergeKABCConfig::removeSelectedContacts().
+ */
+ void removeContact( QListViewItem* item );
+
+ /**
+ Appends all KAddressbook entries in KABC::StdAddressBook::self() and all
+ KABC::DistributionLists to the left QListView.
+ */
+ void updateAvailable();
+};
+
+
+class KWMailMergeKABCConfigListItem : public QListViewItem
+{
+
+public:
+ KWMailMergeKABCConfigListItem( QListView *parent, const KABC::Addressee& addressEntry );
+ KWMailMergeKABCConfigListItem( QListViewItem *parent, const KABC::Addressee& addressEntry );
+ virtual ~KWMailMergeKABCConfigListItem();
+
+ /**
+ Returns the KABC::Addressee of a KWMailMergeKABCConfigListItem.
+ */
+ KABC::Addressee addressee() const;
+
+ /**
+ This is an overloaded member function of QListViewItem::text( int column ).
+ It Returns the KABC::Addressee::uid(), if column is set to -1.
+ Otherwise QListViewItem::text( int column ) is returned.
+ */
+ QString text( int column ) const;
+
+
+private:
+ KABC::Addressee _addressEntry;
+
+};
+#endif
diff --git a/kword/mailmerge/kabc/Makefile.am b/kword/mailmerge/kabc/Makefile.am
new file mode 100644
index 00000000..9231a371
--- /dev/null
+++ b/kword/mailmerge/kabc/Makefile.am
@@ -0,0 +1,17 @@
+
+KDE_CXXFLAGS = $(USE_RTTI)
+INCLUDES = $(KOFFICE_INCLUDES) -I$(top_srcdir)/lib/kformula \
+ $(KOTEXT_INCLUDES) -I$(top_srcdir)/kword $(all_includes)
+
+kde_module_LTLIBRARIES = kwmailmerge_kabc.la
+
+## Plugin encapsulating the QT SQL database interface
+kwmailmerge_kabc_la_SOURCES = KWMailMergeKABC.cpp KWMailMergeKABCConfig.cpp addresspicker.ui
+kwmailmerge_kabc_la_LDFLAGS = $(all_libraries) -module $(KDE_PLUGIN)
+kwmailmerge_kabc_la_LIBADD = ../../libkwmailmerge_interface.la $(LIB_KDEUI) $(LIB_KABC)
+
+METASOURCES = AUTO
+
+services_DATA=kwmailmerge_kabc.desktop
+servicesdir=$(kde_servicesdir)
+
diff --git a/kword/mailmerge/kabc/addresspicker.ui b/kword/mailmerge/kabc/addresspicker.ui
new file mode 100644
index 00000000..ec179c3b
--- /dev/null
+++ b/kword/mailmerge/kabc/addresspicker.ui
@@ -0,0 +1,297 @@
+<!DOCTYPE UI><UI version="3.2" stdsetdef="1">
+<class>AddressPickerUI</class>
+<widget class="QWidget">
+ <property name="name">
+ <cstring>AddressPickerUI</cstring>
+ </property>
+ <property name="geometry">
+ <rect>
+ <x>0</x>
+ <y>0</y>
+ <width>617</width>
+ <height>434</height>
+ </rect>
+ </property>
+ <property name="caption">
+ <string>Address Selection</string>
+ </property>
+ <grid>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="QLayoutWidget" row="1" column="1">
+ <property name="name">
+ <cstring>layout10</cstring>
+ </property>
+ <vbox>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <spacer>
+ <property name="name">
+ <cstring>spacer1</cstring>
+ </property>
+ <property name="orientation">
+ <enum>Vertical</enum>
+ </property>
+ <property name="sizeType">
+ <enum>Expanding</enum>
+ </property>
+ <property name="sizeHint">
+ <size>
+ <width>20</width>
+ <height>16</height>
+ </size>
+ </property>
+ </spacer>
+ <widget class="KPushButton">
+ <property name="name">
+ <cstring>mAddButton</cstring>
+ </property>
+ <property name="enabled">
+ <bool>true</bool>
+ </property>
+ <property name="text">
+ <string>&amp;Add &gt;&gt;</string>
+ </property>
+ </widget>
+ <widget class="KPushButton">
+ <property name="name">
+ <cstring>mRemoveButton</cstring>
+ </property>
+ <property name="enabled">
+ <bool>true</bool>
+ </property>
+ <property name="text">
+ <string>&lt;&lt; &amp;Remove</string>
+ </property>
+ </widget>
+ <spacer>
+ <property name="name">
+ <cstring>spacer2_2</cstring>
+ </property>
+ <property name="orientation">
+ <enum>Vertical</enum>
+ </property>
+ <property name="sizeType">
+ <enum>Expanding</enum>
+ </property>
+ <property name="sizeHint">
+ <size>
+ <width>20</width>
+ <height>20</height>
+ </size>
+ </property>
+ </spacer>
+ </vbox>
+ </widget>
+ <widget class="QPushButton" row="2" column="2">
+ <property name="name">
+ <cstring>mSaveList</cstring>
+ </property>
+ <property name="enabled">
+ <bool>true</bool>
+ </property>
+ <property name="text">
+ <string>Save as &amp;Distribution List...</string>
+ </property>
+ <property name="toolTip" stdset="0">
+ <string>Save selected single entries to a new distribution list.</string>
+ </property>
+ </widget>
+ <widget class="QLayoutWidget" row="2" column="0">
+ <property name="name">
+ <cstring>layout1</cstring>
+ </property>
+ <hbox>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="QLabel">
+ <property name="name">
+ <cstring>TextLabel2</cstring>
+ </property>
+ <property name="text">
+ <string>&amp;Filter on:</string>
+ </property>
+ <property name="buddy" stdset="0">
+ <cstring>mFilterEdit</cstring>
+ </property>
+ </widget>
+ <widget class="QLineEdit">
+ <property name="name">
+ <cstring>mFilterEdit</cstring>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy>
+ <hsizetype>1</hsizetype>
+ <vsizetype>0</vsizetype>
+ <horstretch>1</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="text">
+ <string></string>
+ </property>
+ </widget>
+ </hbox>
+ </widget>
+ <widget class="KListView" row="1" column="2">
+ <column>
+ <property name="text">
+ <string>Name</string>
+ </property>
+ <property name="clickable">
+ <bool>true</bool>
+ </property>
+ <property name="resizable">
+ <bool>true</bool>
+ </property>
+ </column>
+ <item>
+ <property name="text">
+ <string>Distribution Lists</string>
+ </property>
+ <property name="pixmap">
+ <pixmap></pixmap>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string>Single Entries</string>
+ </property>
+ <property name="pixmap">
+ <pixmap></pixmap>
+ </property>
+ </item>
+ <property name="name">
+ <cstring>mSelectedView</cstring>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy>
+ <hsizetype>7</hsizetype>
+ <vsizetype>1</vsizetype>
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="selectionMode" stdset="0">
+ <enum>Extended</enum>
+ </property>
+ <property name="allColumnsShowFocus">
+ <bool>true</bool>
+ </property>
+ <property name="showSortIndicator">
+ <bool>true</bool>
+ </property>
+ <property name="rootIsDecorated">
+ <bool>true</bool>
+ </property>
+ <property name="resizeMode">
+ <enum>AllColumns</enum>
+ </property>
+ <property name="fullWidth">
+ <bool>true</bool>
+ </property>
+ </widget>
+ <widget class="QPushButton" row="2" column="1">
+ <property name="name">
+ <cstring>mAddressBook</cstring>
+ </property>
+ <property name="text">
+ <string>Address B&amp;ook</string>
+ </property>
+ <property name="toolTip" stdset="0">
+ <string>Launch KAddressbook</string>
+ </property>
+ </widget>
+ <widget class="QLabel" row="0" column="0">
+ <property name="name">
+ <cstring>textLabel1</cstring>
+ </property>
+ <property name="font">
+ <font>
+ <bold>1</bold>
+ </font>
+ </property>
+ <property name="text">
+ <string>&amp;Address Book</string>
+ </property>
+ <property name="alignment">
+ <set>WordBreak|AlignCenter</set>
+ </property>
+ <property name="buddy" stdset="0">
+ <cstring>mAvailableView</cstring>
+ </property>
+ </widget>
+ <widget class="QLabel" row="0" column="2">
+ <property name="name">
+ <cstring>textLabel2</cstring>
+ </property>
+ <property name="font">
+ <font>
+ <bold>1</bold>
+ </font>
+ </property>
+ <property name="text">
+ <string>&amp;Selected Addresses</string>
+ </property>
+ <property name="alignment">
+ <set>WordBreak|AlignCenter</set>
+ </property>
+ <property name="buddy" stdset="0">
+ <cstring>mSelectedView</cstring>
+ </property>
+ </widget>
+ <widget class="KListView" row="1" column="0">
+ <column>
+ <property name="text">
+ <string>Name</string>
+ </property>
+ <property name="clickable">
+ <bool>true</bool>
+ </property>
+ <property name="resizable">
+ <bool>true</bool>
+ </property>
+ </column>
+ <property name="name">
+ <cstring>mAvailableView</cstring>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy>
+ <hsizetype>7</hsizetype>
+ <vsizetype>7</vsizetype>
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="selectionMode" stdset="0">
+ <enum>Extended</enum>
+ </property>
+ <property name="allColumnsShowFocus">
+ <bool>true</bool>
+ </property>
+ <property name="showSortIndicator">
+ <bool>true</bool>
+ </property>
+ <property name="rootIsDecorated">
+ <bool>true</bool>
+ </property>
+ <property name="resizeMode">
+ <enum>AllColumns</enum>
+ </property>
+ <property name="fullWidth">
+ <bool>true</bool>
+ </property>
+ </widget>
+ </grid>
+</widget>
+<layoutdefaults spacing="6" margin="11"/>
+<includehints>
+ <includehint>kpushbutton.h</includehint>
+ <includehint>kpushbutton.h</includehint>
+ <includehint>klistview.h</includehint>
+ <includehint>klistview.h</includehint>
+</includehints>
+</UI>
diff --git a/kword/mailmerge/kabc/kwmailmerge_kabc.desktop b/kword/mailmerge/kabc/kwmailmerge_kabc.desktop
new file mode 100644
index 00000000..77dd7d4a
--- /dev/null
+++ b/kword/mailmerge/kabc/kwmailmerge_kabc.desktop
@@ -0,0 +1,105 @@
+[Desktop Entry]
+Type=Service
+ServiceTypes=KWord/MailMergePlugin
+
+Name=KDE Addressbook Plugin
+Name[bg]=Приставка за адресника на KDE
+Name[br]=Lugent Karned chomlec'hioù KDE
+Name[ca]=Connector de llibreta d'adreces KDE
+Name[cs]=Modul Knihy adres KDE
+Name[cy]=Ategyn Llyfr Cyfeiriadau KDE
+Name[da]=KDE's adressebog Plugin
+Name[de]=KDE Adressbuch-Modul
+Name[el]=Πρόσθετο βιβλίου διευθύνσεων του KDE
+Name[eo]=KDE Adresaro-kromprogramo
+Name[es]=Accesorio de la libreta de direcciones de KDE
+Name[et]=KDE aadressiraamatu plugin
+Name[eu]=KDE-ren helbide-liburuaren plugina
+Name[fa]=وصلۀ کتاب نشانی KDE
+Name[fi]=KDE:n osoitekirjan liitännäinen
+Name[fr]=Module externe de carnet d'adresses de KDE
+Name[fy]=Adresboekplugin foar KDE
+Name[gl]=Plugin do Libro de Enderezos de KDE
+Name[he]=תוסף של פנקס הכתובות של KDE
+Name[hi]=केडीई पतापुस्तिका प्लगिन
+Name[hr]=KDE dodatak adresara
+Name[hu]=Illesztőmodul a KDE címjegyzékhez
+Name[is]=KDE vistfanga íforrit
+Name[it]=Plugin per la rubrica degli indirizzi KDE
+Name[ja]=KDE アドレス帳プラグイン
+Name[km]=កម្មវិធី​ជំនួយ​សៀវភៅ​អាសយដ្ឋាន KDE
+Name[lv]=KDE adrešu grāmatiņas spraudnis
+Name[ms]=Plugin Buku Alamat KDE
+Name[nb]=Programtillegg for KDE-adresseboka
+Name[nds]=Adressbook-Moduul för KDE
+Name[ne]=KDE ठेगानापुस्तक प्लगइन
+Name[nl]=Adresboekplugin voor KDE
+Name[nn]=Programtillegg for KDE-adresseboka
+Name[pl]=Wtyczka Książki adresowej KDE
+Name[pt]='Plugin' do Livro de Endereços do KDE
+Name[pt_BR]=Livro de Endereços do KDE
+Name[ru]=Модуль адресной книги KDE
+Name[se]=KDE:a čujuhusgirjemoduvla
+Name[sk]=Modul pre KDE adresár
+Name[sl]=Vstavek Adresar KDE
+Name[sr]=Прикључак за KDE-ов адресар
+Name[sr@Latn]=Priključak za KDE-ov adresar
+Name[sv]=Insticksprogram för KDE:s adressbok
+Name[ta]= KDE முகவரிப்புத்தகம் சொருகு
+Name[tg]=Дарҷ кардани KDE Китоби Адресҳо
+Name[tr]=KDE Adres Defteri Eklentisi
+Name[uk]=Втулок адресної книги KDE
+Name[uz]=KDE manzillar daftari plagini
+Name[uz@cyrillic]=KDE манзиллар дафтари плагини
+Name[wa]=Tchôke-divins calpin d' adresses KDE
+Name[zh_CN]=KDE 地址簿插件
+Name[zh_TW]=KDE 通訊錄外掛程式
+Comment=This datasource type lets you use your KDE Address Book entries.
+Comment[bg]=Този източник на данни се свързва директно с адресника на KDE и чете данните от там.
+Comment[ca]=Aquest tipus de font de dades permet usar les entrades de la llibreta d'adreces del KDE.
+Comment[cs]=Tento zdroj dat umožňuje využít položky z Knihy adres.
+Comment[cy]=Mae'r math yma o ffynhonell ddata yn eich galluogi i ddefnyddio eich cofnodion Llyfr Cyfeiriadau KDE.
+Comment[da]=Denne datakildetype lader dig bruge dine KDE adressebogsindgange.
+Comment[de]=Dieser Quellentyp ermöglicht die Verwendung von KDE-Adressbucheinträgen.
+Comment[el]=Αυτή η πηγή δεδομένων σας επιτρέπει να χρησιμοποιήσετε τις καταχωρήσεις σας από το βιβλίο διευθύνσεων του KDE.
+Comment[es]=Este tipo de fuente de datos le permite usar las entradas de su libreta de direcciones de KDE.
+Comment[et]=See andmeallika tüüp võimaldab kasutada KDE aadressiraamatu kirjeid.
+Comment[eu]=Datu-iturburu honek zure KDE-ko helbide-liburuko sarrerak erabiltzeko aukera ematen dizu.
+Comment[fa]=این نوع متن داده‌ به شما اجازۀ استفاده از مدخلهای کتاب نشانی KDE را می‌دهد.
+Comment[fi]=Tämän tietolähteen avulla voit käyttää KDE:n osoitekirjan tietoja.
+Comment[fr]=Ce type de source de données vous permet d'utiliser votre carnet d'adresses KDE.
+Comment[fy]=Mei dizze plugin ha jo taging ta jo KDE adresboek.
+Comment[gl]=Este tipo de fonte de datos armacena os datos directamente no Libro de Enderezos de KDE.
+Comment[he]=טיפוס מקור נתונים זה מאפשר לך להשתמש ברשומות שלך מתוך פנקס הכתובות של KDE.
+Comment[hi]=यह डाटा स्रोत क़िस्म आपको केडीई पता पुस्तिका प्रविष्टियों को इस्तेमाल करने देती है.
+Comment[hu]=Ez az adatforrástípus a KDE címjegyzék adatait teszi hozzáférhetővé.
+Comment[is]=Þessi auðlindategund gerir þér kleyft að nota færslur frá KDE vistfangaskránni þinni.
+Comment[it]=Questo tipo di fonte di dati permette di usare le voci della rubrica degli indirizzi di KDE.
+Comment[ja]=KDE アドレス帳のデータを使用できるようにします。
+Comment[km]=ប្រភេទ​ប្រភព​ទិន្នន័យ​នេះ​អនុញ្ញាត​ឲ្យ​អ្នក​ប្រើ​ធាតុ​សៀវភៅ​អាសយដ្ឋាន KDE របស់​អ្នក ។
+Comment[ms]=Jenis sumber data ini membenarkan anda menggunakan entri Buku Alamat KDE anda.
+Comment[nb]=Med denne datakildetypen kan du få tilgang til oppføringene i KDE-adresseboka.
+Comment[nds]=Mit dissen Datenborntyp laat sik KDE-Adressbookindrääg bruken.
+Comment[ne]=यो डेटासंसाधनले तपाईंलाई तपाईंको KDE ठेगाना पुस्तक प्रविष्टिहरू प्रयोग गर्न दिन्छ ।
+Comment[nl]=Via deze plugin hebt u toegang tot uw KDE-adresboek.
+Comment[nn]=Med denne datakjeldetypen kan du få tilgang til oppføringane i KDE-adresseboka.
+Comment[pl]=To źródło danych pozwala Ci używać Twoich wpisów z Książki adresowej KDE.
+Comment[pt]=Este tipo de fonte de dados armazena os dados directamente no Livro de Endereços do KDE.
+Comment[pt_BR]=Este tipo de fonte de dados permite-lhe usar suas entradas do Livro de Endereços do KDE.
+Comment[ru]=Источник данных, работающий с записями адресной книги KDE
+Comment[se]=Dát dáhtagáldu diktá du geavahit KDE-čujuhusgirjemerkošiid.
+Comment[sk]=Tento typ zdroja dát umožňuje používať záznamy z KDE adresára.
+Comment[sl]=Ta tip vira podatkov vam omogoča uporabljati vnose vašega Adresarja KDE.
+Comment[sr]=Овај тип извора података омогућава вам да користите ставке из KDE-овог адресара.
+Comment[sr@Latn]=Ovaj tip izvora podataka omogućava vam da koristite stavke iz KDE-ovog adresara.
+Comment[sv]=Den här typen av datakälla låter dig använda information från KDE:s adressbok
+Comment[ta]=பலகத்தின் தோற்றத்தை நீங்கள் இங்கே வடிவமைக்கலாம்.
+Comment[tg]=Ин намуди манбаъи маълумот гузоштани шумо истифода кардан шуморо воридҳои Китоби Адресҳои KDE.
+Comment[tr]=Bu veri kaynağı biçimi KDE Adres Defteri girdilerini kullanmanızı sağlar.
+Comment[uk]=Цей тип джерела даних дає доступ до записів адресної книги KDE.
+Comment[zh_CN]=该数据源类型允许您使用您的 KDE 地址簿条目。
+Comment[zh_TW]=這個資料來源類別讓您使用您的 KDE 通訊錄項目。
+
+X-KDE-Library=kwmailmerge_kabc
+X-KDE-Capabilities=open
+X-KDE-InternalName=KABC
diff --git a/kword/mailmerge/kspread/Makefile.am b/kword/mailmerge/kspread/Makefile.am
new file mode 100644
index 00000000..d69e9469
--- /dev/null
+++ b/kword/mailmerge/kspread/Makefile.am
@@ -0,0 +1,16 @@
+
+KDE_CXXFLAGS = $(USE_RTTI)
+INCLUDES = $(KOFFICE_INCLUDES) $(KOTEXT_INCLUDES) \
+ -I$(top_srcdir)/kspread -I$(top_srcdir)/kword $(all_includes)
+
+kde_module_LTLIBRARIES = kwmailmerge_kspread.la
+
+kwmailmerge_kspread_la_SOURCES = kwmailmerge_kspread.cpp kwmailmerge_kspread_config.cpp
+kwmailmerge_kspread_la_LDFLAGS = $(all_libraries) -module $(KDE_PLUGIN)
+kwmailmerge_kspread_la_LIBADD = ../../libkwmailmerge_interface.la \
+ $(top_builddir)/kspread/libkspreadcommon.la $(LIB_KDEUI)
+
+METASOURCES = AUTO
+
+services_DATA = kwmailmerge_kspread.desktop
+servicesdir = $(kde_servicesdir)
diff --git a/kword/mailmerge/kspread/kwmailmerge_kspread.cpp b/kword/mailmerge/kspread/kwmailmerge_kspread.cpp
new file mode 100644
index 00000000..738cf6d7
--- /dev/null
+++ b/kword/mailmerge/kspread/kwmailmerge_kspread.cpp
@@ -0,0 +1,211 @@
+/*
+ This file is part of the KDE project
+ Copyright (C) 2004 Tobias Koenig <tokoe@kde.org>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+*/
+
+#include <kdebug.h>
+#include <kglobal.h>
+#include <klocale.h>
+
+#include <kspread_map.h>
+
+#include "kwmailmerge_kspread.h"
+#include "kwmailmerge_kspread_config.h"
+
+using namespace KSpread;
+
+KWMailMergeKSpread::KWMailMergeKSpread( KInstance *instance, QObject *parent )
+ : KWMailMergeDataSource( instance, parent ), _spreadSheetNumber( 1 )
+{
+}
+
+KWMailMergeKSpread::~KWMailMergeKSpread()
+{
+}
+
+int KWMailMergeKSpread::getNumRecords() const
+{
+ return rows() - 2;
+}
+
+QString KWMailMergeKSpread::getValue( const QString &name, int record ) const
+{
+ if ( record < 0 )
+ return name;
+
+ const Cell* cell = _sheet->cellAt( _columnMap[ name ], record + 2 );
+
+ if ( cell )
+ return cellText( cell );
+ else
+ return i18n( "Unkown mail merge variable: %1" ).arg( name );
+}
+
+void KWMailMergeKSpread::load( QDomElement& parentElem )
+{
+ QDomNode contentNode = parentElem.namedItem( "CONTENT" );
+ if ( contentNode.isNull() )
+ return;
+
+ QDomElement element = contentNode.toElement();
+ if ( element.isNull() )
+ return;
+
+ _url = element.attribute( QString::fromLatin1( "URL" ) );
+ _spreadSheetNumber = element.attribute( QString::fromLatin1( "SpreadSheetNumber" ) ).toInt();
+
+ initDocument();
+}
+
+void KWMailMergeKSpread::save( QDomDocument& doc, QDomElement& parent )
+{
+ QDomElement content = doc.createElement( QString::fromLatin1( "CONTENT" ) );
+ parent.appendChild( content );
+
+ content.setAttribute( "URL", _url.url() );
+ content.setAttribute( "SpreadSheetNumber", _spreadSheetNumber );
+}
+
+void KWMailMergeKSpread::refresh( bool )
+{
+}
+
+bool KWMailMergeKSpread::showConfigDialog( QWidget *parent, int )
+{
+ KWMailMergeKSpreadConfig dlg( parent, this );
+
+ int retval = dlg.exec();
+ if ( retval )
+ initDocument();
+
+ return retval;
+}
+
+void KWMailMergeKSpread::initDocument()
+{
+ _document = new Doc();
+
+ connect( _document, SIGNAL( completed() ), SLOT( initSpreadSheets() ) );
+
+ _document->openURL( _url );
+}
+
+void KWMailMergeKSpread::initSpreadSheets()
+{
+
+ _columnMap.clear();
+ sampleRecord.clear();
+
+ QPtrListIterator<Sheet> it( _document->map()->sheetList() );
+ int counter = 0;
+ for ( it.toFirst(); it.current(), counter < _spreadSheetNumber; ++it ) {
+ _sheet = it.current();
+ counter++;
+ }
+
+ if ( !_sheet ) {
+ kdError() << "No spread sheet available" << endl;
+ return;
+ }
+
+ if ( rows() < 2 ) // empty table
+ return;
+
+ int cols = columns();
+ for ( int i = 1; i < cols; ++i ) {
+ const Cell* cell = _sheet->cellAt( i, 1 );
+
+ // init record list
+ sampleRecord[ cellText( cell ) ] = cellText( cell );
+ _columnMap.insert( cellText( cell ), i );
+ }
+}
+
+int KWMailMergeKSpread::rows() const
+{
+ if ( !_sheet )
+ return 0;
+
+ int row = 1;
+
+ for (; row < _sheet->maxRow(); ) {
+ const Cell* cell = _sheet->cellAt( 1, row );
+ if ( cellText( cell ).isEmpty() )
+ break;
+
+ row++;
+ }
+
+ return row;
+}
+
+int KWMailMergeKSpread::columns() const
+{
+ if ( !_sheet )
+ return 0;
+
+ int col = 1;
+
+ for (; col < _sheet->maxColumn(); ) {
+ const Cell* cell = _sheet->cellAt( col, 1 );
+ if ( cellText( cell ).isEmpty() )
+ break;
+
+ col++;
+ }
+
+ return col;
+}
+
+QString KWMailMergeKSpread::cellText( const Cell *cell ) const
+{
+ QString text = QString::null;
+
+ if ( !cell->isDefault() && !cell->isEmpty() ) {
+ if ( cell->isFormula() )
+ text = cell->strOutText();
+ else if ( !cell->link().isEmpty() )
+ text = cell->link();
+ else
+ text = cell->text();
+ }
+#if 0
+ switch( cell->content() ) {
+ case Cell::Text:
+ case Cell::Formula:
+ text = cell->strOutText();
+ break;
+ case Cell::RichText:
+ case Cell::VisualFormula:
+ text = cell->text(); // untested
+ break;
+ }
+ }
+#endif
+ return text;
+}
+
+extern "C"
+{
+ KWORD_MAILMERGE_EXPORT KWMailMergeDataSource *create_kwmailmerge_kspread( KInstance *instance, QObject *parent )
+ {
+ return new KWMailMergeKSpread( instance, parent );
+ }
+}
+
+#include "kwmailmerge_kspread.moc"
diff --git a/kword/mailmerge/kspread/kwmailmerge_kspread.desktop b/kword/mailmerge/kspread/kwmailmerge_kspread.desktop
new file mode 100644
index 00000000..06dd45ec
--- /dev/null
+++ b/kword/mailmerge/kspread/kwmailmerge_kspread.desktop
@@ -0,0 +1,101 @@
+[Desktop Entry]
+Type=Service
+ServiceTypes=KWord/MailMergePlugin
+
+Name=KSpread Table Source
+Name[bg]=Източник на данни от KSpread
+Name[ca]=Font de taula de KSpread
+Name[cy]=Ffynhonell Dabl KSpread
+Name[da]=KSpread-tabelkilde
+Name[de]=KSpread-Tabelle
+Name[el]=Πηγή πίνακα του KSpread
+Name[eo]=KSpread tabelfonto
+Name[es]=Origen de tablas de KSpread
+Name[et]=KSpreadi tabel
+Name[eu]=KSpread-en taula-iturburua
+Name[fa]=متن جدول KSpread
+Name[fi]=KSpread-taulukkolähde
+Name[fr]=Source de tableaux KSpread
+Name[fy]=KSpread Tabelboarne
+Name[gl]=Fonte en Táboa de KSpread
+Name[he]=מקור טבלאות של KSpread
+Name[hi]=के-स्प्रेड तालिका स्रोत
+Name[hr]=KSpread izvor tablice
+Name[hu]=KSpread táblaforrás
+Name[is]=KSpread töflu auðlind
+Name[it]=Fonte tabella di KSpread
+Name[ja]=KSpread テーブルソース
+Name[km]=ប្រភព​តារាង​របស់ KSpread
+Name[lv]=KSpread tabulas avots
+Name[ms]=Sumber Jadual KSpread
+Name[nb]=KSpread Tabellkilde
+Name[nds]=KSpread-Tabellenborn
+Name[ne]=केडीई स्प्रिेड तालिका स्रोत
+Name[nl]=KSpread Tabelbron
+Name[nn]=KSpread-tabellkjelde
+Name[pl]=Źródło tabeli KSpread
+Name[pt]=Fonte de Tabela do KSpread
+Name[pt_BR]=Tabela do KSpread
+Name[ru]=Источник таблиц KSpread
+Name[se]=KSpread-tabeallagáldu
+Name[sk]=Zdroj tabuliek KSpread
+Name[sl]=Vir tabel KSpread
+Name[sr]=KSpread-ов извор табеле
+Name[sr@Latn]=KSpread-ov izvor tabele
+Name[sv]=Kspread-tabellkällfil
+Name[ta]=கேஸ்பிரிட் அட்டவணை மூலம்
+Name[tg]=Сарчашмаи ҷадвали KSpread
+Name[tr]=KSpread Tablo Kaynağı
+Name[uk]=Джерело таблиць KSpread
+Name[uz]=KSpread jadvali manbasi
+Name[uz@cyrillic]=KSpread жадвали манбаси
+Name[zh_CN]=KSpread 表源
+Name[zh_TW]=KSpread 表格來源
+Comment=This datasource type lets you use your entries from a kspread file.
+Comment[bg]=Този източник на данни чете данните директно от файл на KSpread.
+Comment[ca]=Aquest tipus de font de dades permet usar les entrades d'un fitxer kspread.
+Comment[cy]=Mae'r math yma o ffynhonell ddata yn eich galluogi i ddefnyddio eich cofnodion o ffeil kspread.
+Comment[da]=Denne datakildetype lader dig bruge dine indgange fra en kspread-fil.
+Comment[de]=Mit diesem Datenquellentyp können Sie Einträge aus einer KSpread-Tabelle verwenden.
+Comment[el]=Αυτή η πηγή δεδομένων σας επιτρέπει να χρησιμοποιήσετε τις καταχωρήσεις σας από ένα αρχείο του KSpread.
+Comment[es]=Este tipo de fuente de datos le permite usar las entradas de un archivo de kspread.
+Comment[et]=See andmeallika tüüp võimaldab kasutada KSpreadi faili kirjeid.
+Comment[eu]=Datu-iturburu honek kspread fitxategi bateko sarrerako erabiltzeko aukera ematen dizu.
+Comment[fa]=این نوع متن داده‌ به شما اجازۀ استفاده از مدخلهایتان از یک پروندۀ kspread را می‌دهد.
+Comment[fi]=Tämän tietolähteen avulla voit käyttää tietoja KSPread-taulukosta.
+Comment[fr]=Ce type de source de données vous permet d'utiliser vos saisies depuis un fichier KSpread.
+Comment[fy]=Mei dit type gegevensboarne kinne jo, jo yngongen út in Kspreadtriem brûke.
+Comment[gl]=Este tipo de fonte de datos permite utilizar datos dun ficheiro de KSpread.
+Comment[he]=טיפוס מקור נתונים זה מאפשר לך להשתמש ברשומות שלך מתוך קובץ של kspread.
+Comment[hi]=यह डाटा स्रोत क़िस्म आपको केडीई पता के-स्प्रेड फ़ाइल की प्रविष्टियों को इस्तेमाल करने देती है.
+Comment[hr]=Ova vrsta izvora podataka omogućuje upotrebu unusa iz KSpread datoteke.
+Comment[hu]=Ezzel az adatforrástípussal KSpread-fájlok adataihoz lehet hozzáférni.
+Comment[is]=Þessi auðlindategund gerir þér kleyft að nota færslur frá kspread skrá.
+Comment[it]=Questo tipo di fonte di dati permette di usare le voci di un file KSpread.
+Comment[ja]=KSpread ファイルのデータを使用できるようにします。
+Comment[km]=ប្រភេទ​ប្រភព​ទិន្នន័យ​នេះ​អនុញ្ញាត​ឲ្យ​អ្នក​ប្រើ​ធាតុ​របស់​អ្នក​ពី​ឯកសារ kspread ។
+Comment[ms]=Jenis sumber data ini membenarkan anda menggunakan entri anda dari fail kspread.
+Comment[nb]=Denne datakilden lar deg bruke data fra en kspread fil.
+Comment[nds]=Mit dissen Datenborntyp laat sik Indrääg ut en KSpread-Datei bruken.
+Comment[ne]=यो डेटासंसाधन प्रकारले तपाईंलाई केडीई स्प्रिेड फाइलबाट तपाईंको प्रविष्टिहरू प्रयोग गर्न दिन्छ ।
+Comment[nl]=Met dit type databron kunt u uw ingangen uit een Kspread-bestand gebruiken.
+Comment[nn]=Med denne datakjeldetypen kan du få tilgang til oppføringane i ei KSpread-fil.
+Comment[pl]=To źródło danych pozwala Ci używać Twoich wpisów z plików KSpread.
+Comment[pt]=Este tipo de fonte de dados permite utilizar dados de um ficheiro do kspread.
+Comment[pt_BR]=Este tipo de fonte de dados permite-lhe usar os dados de um arquivo KSpread.
+Comment[ru]=Источник данных, работающий с таблицами KSpread
+Comment[sk]=Tento typ zdroja dát umožňuje používať záznamy zo súboru kspread.
+Comment[sl]=Ta vrsta podatkovnega izvora vam omogoča uporabo vnosov iz datoteke KSpread.
+Comment[sr]=Овај тип извора података омогућава вам да користите ставке из KSpread-овог фајла.
+Comment[sr@Latn]=Ovaj tip izvora podataka omogućava vam da koristite stavke iz KSpread-ovog fajla.
+Comment[sv]=Den här typen av datakälla låter dig använda information från en Kspread-fil.
+Comment[ta]=இந்த தகவல்மூலம் கேஸ்ப்ரெட் கோப்பில் இருந்து உங்கள் உள்ளீடுகளை பயன்படுத்த செய்கிறது.
+Comment[tg]=Ин намуди манбаъи маълумот гузоштани шумо истифода кардан шуморо воридҳои аз файли kspread.
+Comment[tr]=Bu veri kaynağı biçimi bir kspread dosyasındaki girdileri kullanmanızı sağlar.
+Comment[uk]=Цей тип джерела даних дає доступ до записів файла kspread.
+Comment[zh_CN]=该数据源类型允许您从 kspead 文件中使用您的条目。
+Comment[zh_TW]=這個資料來源類別讓您可以使用 kspread 檔案的項目。
+
+X-KDE-Library=kwmailmerge_kspread
+X-KDE-Capabilities=open
+X-KDE-InternalName=KSpread
diff --git a/kword/mailmerge/kspread/kwmailmerge_kspread.h b/kword/mailmerge/kspread/kwmailmerge_kspread.h
new file mode 100644
index 00000000..2d639074
--- /dev/null
+++ b/kword/mailmerge/kspread/kwmailmerge_kspread.h
@@ -0,0 +1,106 @@
+/*
+ This file is part of the KDE project
+ Copyright (C) 2004 Tobias Koenig <tokoe@kde.org>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+*/
+
+#ifndef _KWMAILMERGE_KSPREAD_H_
+#define _KWMAILMERGE_KSPREAD_H_
+
+#include <qdom.h>
+#include <qmap.h>
+
+#include <kspread_doc.h>
+#include <kspread_sheet.h>
+
+#include "KWMailMergeDataSource.h"
+
+class KWMailMergeKSpread: public KWMailMergeDataSource
+{
+ Q_OBJECT
+
+ public:
+ KWMailMergeKSpread( KInstance *inst, QObject *parent );
+ ~KWMailMergeKSpread();
+
+ /**
+ Saves the mail merge list to the kword document.
+ */
+ virtual void save( QDomDocument&, QDomElement& );
+
+ /**
+ Loads the mail merge list stored in the kword document.
+ */
+ virtual void load( QDomElement& );
+
+ /**
+ @param name The name of the value e.g. "Family name".
+ @param record The position of the the entry in mail merge list.
+ @return The value of the mail merge variable.
+
+ If @p record equals -1, @p name is returned.
+ */
+ virtual class QString getValue( const class QString &name, int record = -1 ) const;
+
+ /**
+ @return The number of available contacts in mail merge list.
+ */
+ virtual int getNumRecords() const;
+
+ /**
+ Only for compatability reasons.
+
+ @param force Hasn't any effect.
+ */
+ virtual void refresh( bool force );
+
+ /**
+ Shows a KWMailMergeKSpreadConfig dialog for selecting entries from KAddressbook.
+ */
+ virtual bool showConfigDialog( QWidget*, int action);
+
+
+ void setURL( const KURL &url ) { _url = url; }
+ KURL url() const { return _url; }
+
+ void setSpreadSheetNumber( int number ) { _spreadSheetNumber = number; }
+ int spreadSheetNumber() const { return _spreadSheetNumber; }
+
+ protected:
+ friend class KWMailMergeKSpreadConfig;
+
+ private slots:
+ void initSpreadSheets();
+
+ private:
+ void initDocument();
+
+ int rows() const;
+ int columns() const;
+
+ QString cellText( const KSpread::Cell* ) const;
+
+ KSpread::Doc *_document;
+ KSpread::Sheet* _sheet;
+ KURL _url;
+ int _spreadSheetNumber;
+
+ QMap<QString, int> _columnMap;
+};
+
+#endif
+
diff --git a/kword/mailmerge/kspread/kwmailmerge_kspread_config.cpp b/kword/mailmerge/kspread/kwmailmerge_kspread_config.cpp
new file mode 100644
index 00000000..fc170780
--- /dev/null
+++ b/kword/mailmerge/kspread/kwmailmerge_kspread_config.cpp
@@ -0,0 +1,125 @@
+/*
+ This file is part of the KDE project
+ Copyright (C) 2004 Tobias Koenig <tokoe@kde.org>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+*/
+
+
+#include <qlabel.h>
+#include <qlayout.h>
+
+#include <kcombobox.h>
+#include <klineedit.h>
+#include <klocale.h>
+#include <kurlrequester.h>
+
+#include <kspread_map.h>
+
+#include "kwmailmerge_kspread.h"
+#include "kwmailmerge_kspread_config.h"
+
+using namespace KSpread;
+
+KWMailMergeKSpreadConfig::KWMailMergeKSpreadConfig( QWidget *parent, KWMailMergeKSpread *object )
+ : KDialogBase( Plain, i18n( "Mail Merge - Editor" ),
+ Ok | Cancel, Ok, parent, "", true ),
+ _document( 0 ), _initialPage( 1 )
+{
+ _object = object;
+
+ initGUI();
+
+ _urlRequester->setURL( _object->url().url() );
+ _initialPage = _object->spreadSheetNumber();
+
+ connect( _urlRequester, SIGNAL( urlSelected( const QString& ) ),
+ SLOT( loadDocument() ) );
+
+ loadDocument();
+ slotTextChanged( _urlRequester->lineEdit()->text() );
+}
+
+
+KWMailMergeKSpreadConfig::~KWMailMergeKSpreadConfig()
+{
+}
+
+void KWMailMergeKSpreadConfig::slotOk()
+{
+ _object->setURL( _urlRequester->url() );
+ _object->setSpreadSheetNumber( _pageNumber->currentText().toInt() );
+
+ KDialogBase::slotOk();
+}
+
+void KWMailMergeKSpreadConfig::loadDocument()
+{
+ delete _document;
+ _document = 0;
+
+ _pageNumber->setEnabled( false );
+
+ if ( !_urlRequester->url().isEmpty() ) {
+ _document = new Doc();
+ connect( _document, SIGNAL( completed() ), SLOT( documentLoaded() ) );
+
+ _document->openURL( _urlRequester->url() );
+ }
+}
+
+void KWMailMergeKSpreadConfig::documentLoaded()
+{
+ _pageNumber->clear();
+
+ QPtrListIterator<Sheet> it( _document->map()->sheetList() );
+ int counter = 1;
+ for ( it.toFirst(); it.current(); ++it ) {
+ _pageNumber->insertItem( QString::number( counter ) );
+ counter++;
+ }
+
+ _pageNumber->setEnabled( true );
+ _pageNumber->setCurrentText( QString::number( _initialPage ) );
+}
+
+void KWMailMergeKSpreadConfig::initGUI()
+{
+ QFrame *page = plainPage();
+
+ QGridLayout *layout = new QGridLayout( page, 2, 2, marginHint(), spacingHint() );
+
+ QLabel *label = new QLabel( i18n( "URL:" ), page );
+ layout->addWidget( label, 0, 0 );
+
+ _urlRequester = new KURLRequester( page );
+ layout->addWidget( _urlRequester, 0, 1 );
+
+ label = new QLabel( i18n( "Page number:" ), page );
+ layout->addWidget( label, 1, 0 );
+
+ _pageNumber = new KComboBox( page );
+ _pageNumber->setEnabled( false );
+ layout->addWidget( _pageNumber, 1, 1 );
+ connect( _urlRequester->lineEdit() , SIGNAL( textChanged ( const QString & ) ), this, SLOT( slotTextChanged( const QString & ) ) );
+}
+
+void KWMailMergeKSpreadConfig::slotTextChanged( const QString & _text )
+{
+ enableButtonOK( !_text.isEmpty() );
+}
+
+#include "kwmailmerge_kspread_config.moc"
diff --git a/kword/mailmerge/kspread/kwmailmerge_kspread_config.h b/kword/mailmerge/kspread/kwmailmerge_kspread_config.h
new file mode 100644
index 00000000..6aacff63
--- /dev/null
+++ b/kword/mailmerge/kspread/kwmailmerge_kspread_config.h
@@ -0,0 +1,61 @@
+/*
+ This file is part of the KDE project
+ Copyright (C) 2004 Tobias Koenig <tokoe@kde.org>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+*/
+
+#ifndef _KWMAILMERGE_KSPREAD_CONFIG_H_
+#define _KWMAILMERGE_KSPREAD_CONFIG_H_
+
+#include <kdialogbase.h>
+
+#include "kwmailmerge_kspread.h"
+
+class KComboBox;
+class KURLRequester;
+
+class KWMailMergeKSpread;
+
+class KWMailMergeKSpreadConfig: public KDialogBase
+{
+ Q_OBJECT
+
+ public:
+ KWMailMergeKSpreadConfig( QWidget *parent, KWMailMergeKSpread *object );
+ virtual ~KWMailMergeKSpreadConfig();
+
+
+ protected slots:
+ virtual void slotOk();
+
+ void loadDocument();
+ void documentLoaded();
+ void slotTextChanged( const QString & _text );
+
+ private:
+ void initGUI();
+
+ KWMailMergeKSpread *_object;
+ KSpread::Doc *_document;
+
+ KURLRequester *_urlRequester;
+ KComboBox *_pageNumber;
+
+ int _initialPage;
+};
+
+#endif
diff --git a/kword/mailmerge/kwserialletter_classic.desktop b/kword/mailmerge/kwserialletter_classic.desktop
new file mode 100644
index 00000000..030c56b9
--- /dev/null
+++ b/kword/mailmerge/kwserialletter_classic.desktop
@@ -0,0 +1,122 @@
+[Desktop Entry]
+Type=Service
+ServiceTypes=KWord/MailMergePlugin
+
+Name=Internal Storage
+Name[af]=Intern Stoorplek
+Name[ar]=تخزين داخليّ
+Name[az]=Daxili Ambar
+Name[bg]=Вътрешно съхранение
+Name[bs]=Interna pohrana
+Name[ca]=Emmagatzemament intern
+Name[cs]=Interní uložení
+Name[cy]=Storfa Fewnol
+Name[da]=Intern opbevaring
+Name[de]=Interner Speicher
+Name[el]=Εσωτερική αποθήκευση
+Name[eo]=Interna memoro
+Name[es]=Almacenamiento interno
+Name[et]=Sisemine säilitamine
+Name[eu]=Barneko biltegia
+Name[fa]=ذخیره‌سازی درونی
+Name[fi]=Sisäinen tietovarasto
+Name[fr]=Stockage interne
+Name[fy]=Ynterne opslach
+Name[gl]=Armacenamento Interno
+Name[he]=איחסון פנימי
+Name[hi]=आंतरिक भंडार
+Name[hr]=Interna pohrana
+Name[hu]=Belső tároló
+Name[is]=Innbyggð geymsla
+Name[it]=Memorizzazione interna
+Name[ja]=内部ストレージ
+Name[km]=កន្លែង​ផ្ទុក​ខាង​ក្នុង
+Name[lo]=ສື່ເກັບຂໍ້ມູນພາຍໃນ
+Name[lt]=Vidinė atmintinė
+Name[lv]=Iekšējā glabātuve
+Name[ms]=Storan Dalaman
+Name[mt]=Ħażna interna
+Name[nb]=Internt lagring
+Name[nds]=Intern Spieker
+Name[ne]=आन्तरिक भण्डारण
+Name[nl]=Interne opslag
+Name[nn]=Intern lagring
+Name[pl]=Przechowywanie wewnętrzne
+Name[pt]=Armazenamento na Internet
+Name[pt_BR]=Armazenamento Interno
+Name[ro]=Stocare internă
+Name[ru]=Внутреннее хранилище
+Name[se]=Siskkildas vurken
+Name[sk]=Interný sklad
+Name[sl]=Notranja shramba
+Name[sr]=Интерни простор за смештај
+Name[sr@Latn]=Interni prostor za smeštaj
+Name[sv]=Internlagring
+Name[ta]=உள்ளகச் சேமிப்பு
+Name[tg]=Нигоҳдории Дарунӣ
+Name[th]=สื่อเก็บข้อมูลภายใน
+Name[tr]=İç Depo
+Name[uk]=Внутрішнє сховище
+Name[uz]=Ichki saqlash joyi
+Name[uz@cyrillic]=Ички сақлаш жойи
+Name[xh]=Indawo yokugcina Yangaphakathi
+Name[zh_CN]=内部存储
+Name[zh_TW]=內部存儲器
+Comment=This datasource type stores the data directly in the KWord file
+Comment[ar]=هذا النّوع من المصادر البيانيّة يُخزِّن البيانات مباشرة في ملف KWord
+Comment[az]=Bu mənbə verilənləri düz KWord fayl içinə qeyd edir.
+Comment[bg]=Този източник на данни запазва данните директно във файл на KWord
+Comment[bs]=Ovaj tip izvora podataka spašava podatke direktno u KWord datoteku
+Comment[ca]=Aquest tipus de font de dades guarda les dades directament en el fitxer KWord
+Comment[cs]=Tento typ zdroje dat ukládá údaje přímo do souboru ve formátu KWordu
+Comment[cy]=Mae'r math yma o ffynhonnell ddata yn cadw'r data yn uniongyrchol yn y ffeil KWord
+Comment[da]=Denne datakildetype gemmer sine data direkte i KWord-filen
+Comment[de]=Dieser Datenquellentyp speichert seine Daten direkt in die KWord-Datei
+Comment[el]=Αυτός ο τύπος πηγής δεδομένων αποθηκεύει τα δεδομένα απευθείας σε ένα αρχείο KWord
+Comment[eo]=Tiu datumfonta tipo konservas la datumojn rekte ne la KWord-dosiero
+Comment[es]=Este tipo de fuente de datos almacena los datos directamente en el archivo de KWord
+Comment[et]=See andmeallika tüüp hoiab andmeid otse KWordi failis
+Comment[eu]=Datu-iturburu honek datuak zuzenean kspread fitxategi batean gordetzen ditu
+Comment[fa]=این نوع متن داده، مستقیماً داده را در پروندۀ KWord ذخیره می‌کند
+Comment[fi]=Tämä tietolähde tallentaa tiedot suoraan KWord-tiedostoon.
+Comment[fr]=Ce type de source de données enregistre les données directement dans le document KWord
+Comment[fy]=Dit type gegevensboarne bewarret de gegevens rjochtstreeeks op yn in KWord-triem.
+Comment[gl]=Este tipo de fonte de datos armacena os datos directamente no ficheiro de KWord
+Comment[he]=טיפוס מקור נתונים זה מאחסן את הנתונים ישירות בקובץ של KWord
+Comment[hi]=यह डेटा स्रोत क़िस्म डेटा को सीधे ही के-वर्ड फ़ाइल में भंडारित करती है
+Comment[hr]=Ova vrsta izvora podataka pohranjuje podatke izravno u KWord datoteku
+Comment[hu]=Ennél az adatforrástípusnál az adatok közvetlenül a KWord fájlba kerülnek
+Comment[is]=Þessi auðlindategund geymir gögnin í sjálfri KWord skránni
+Comment[it]=Questo tipo di fonte di dati memorizza i dati direttamente nel documento KWord
+Comment[ja]=このデータソースタイプは KWord ファイルに直接データを保持します
+Comment[km]=ប្រភេទ​ប្រភព​ទិន្នន័យ​នេះ​រក្សា​ទិន្នន័យ​ដោយ​ផ្ទាល់​ក្នុង​ឯកសារ KWord
+Comment[lt]=Šis duomenų šaltinio tipas išsaugo duomenis tiesiog KWord byloje
+Comment[lv]=Šis datuavota tips saglabā datus pa taisno KWord failā
+Comment[ms]=Jenis sumber data ini menyimpan data terus ke dalam fail KWord
+Comment[mt]=Dan it-tip ta' sors jikteb l-informazzjoni direttament fid-dokument tal-KWord
+Comment[nb]=Denne datakilden lagrer data rett i KWord-fila
+Comment[nds]=Disse Datenborntyp sekert Daten direktemang na en KWord-Datei
+Comment[ne]=यो डेटासंसाधन प्रकारले डेटालाई सीधै केडीई शब्द फाइलमा संग्रह गर्दछ
+Comment[nl]=Dit type gegevensbron slaat de gegevens rechtstreeks op in een KWord-bestand.
+Comment[nn]=Denne datakjeldetypen lagrar informasjonen rett i KWord-fila
+Comment[pl]=To źródło sprawia, że dane są przechowywane bezpośrednio w pliku KWord
+Comment[pt]=Este tipo de fonte de dados armazena os dados directamente no ficheiro do KWord
+Comment[pt_BR]=Este tipo de fonte de dados armazena os dados diretamente no arquivo do KWord.
+Comment[ro]=Acest tip de sursă de date stochează datele direct în fişierul KWord
+Comment[ru]=Источник данных в документе KWord
+Comment[se]=Dát diehtogáldušládja vurke dáhtaid njuolgga KWord-fiilii
+Comment[sk]=Tento typ zdroja dát ukladá údaje priamo do súboru KWord
+Comment[sl]=Ta tip vira podatkov shrani podatke neposredno v datoteko KWord
+Comment[sr]=Овај тип извора података складишти податке директно у KWord-овом фајлу
+Comment[sr@Latn]=Ovaj tip izvora podataka skladišti podatke direktno u KWord-ovom fajlu
+Comment[sv]=Den här typen av datakälla lagrar data direkt i Kword-filen
+Comment[tg]=Ин намуди манбаъи маълумот нигоҳ доштани таърихро фавран дар файли KWord
+Comment[tr]=Bu veri kaynağı veriyi doğrudan KWord dosyasında saklar.
+Comment[uk]=Цей тип джерела даних зберігає дані напряму в файлі KWord
+Comment[xh]=Uhlobo lwe mvelaphi ye data igcina idata ngqo kwifayile ye KWord
+Comment[zh_CN]=该数据源类型将数据直接保存在 KWord 文件中
+Comment[zh_TW]=這個資料來源類別將資料直接以 KWord 檔案儲純
+
+X-KDE-Library=kwmailmerge_classic
+X-KDE-Capabilities=edit,create
+X-KDE-InternalName=Classic
diff --git a/kword/mailmerge/sql/KWMySqlCursor.h b/kword/mailmerge/sql/KWMySqlCursor.h
new file mode 100644
index 00000000..e5e998b6
--- /dev/null
+++ b/kword/mailmerge/sql/KWMySqlCursor.h
@@ -0,0 +1,69 @@
+/* This file is part of the KDE project
+ Copyright (C) 2001 Joseph Wenninger <jowenn@kde.org>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+*/
+
+#ifndef _SERIALLETTER_QtSql_SQLCURSOR_H_
+#define _SERIALLETTER_QtSql_SQLCURSOR_H_
+
+/* FOR THE DIRTY HACK */
+#include <qsqlcursor.h>
+#include <qsqldriver.h>
+/* END FOR THE DIRTY HACK */
+
+/******************************************************************
+ *
+ * DIRTY HACK FOR SOME INFLEXIBILITY IN QT3's SQL stuff
+ *
+ * This class is rom some Trolltech guy on QT-interest
+ ******************************************************************/
+
+
+
+class KWMySqlCursor: public QSqlCursor
+{
+public:
+ KWMySqlCursor( const QString & query = QString::null, bool autopopulate =
+TRUE, QSqlDatabase* db = 0 ): QSqlCursor( QString::null, autopopulate, db )
+ {
+ exec( query );
+ if ( autopopulate )
+ *(QSqlRecord*)this = ((QSqlQuery*)this)->driver()->record(
+*(QSqlQuery*)this );
+ setMode( QSqlCursor::ReadOnly );
+ }
+ KWMySqlCursor( const KWMySqlCursor & other ): QSqlCursor( other ) {}
+ KWMySqlCursor( const QSqlQuery & query, bool autopopulate = TRUE ):
+QSqlCursor( QString::null, autopopulate )
+ {
+ *(QSqlQuery*)this = query;
+ if ( autopopulate )
+ *(QSqlRecord*)this = query.driver()->record( query );
+ setMode( QSqlCursor::ReadOnly );
+ }
+ bool select( const QString & /*filter*/, const QSqlIndex & /*sort*/ =
+QSqlIndex() ) { return exec( lastQuery() ); }
+ QSqlIndex primaryIndex( bool /*prime*/ = TRUE ) const { return
+QSqlIndex(); }
+ int insert( bool /*invalidate*/ = TRUE ) { return FALSE; }
+ int update( bool /*invalidate*/ = TRUE ) { return FALSE; }
+ int del( bool /*invalidate*/ = TRUE ) { return FALSE; }
+ void setName( const QString& /*name*/, bool /*autopopulate*/ = TRUE ) {}
+};
+
+
+#endif
diff --git a/kword/mailmerge/sql/KWQtSqlEasyFilter.cpp b/kword/mailmerge/sql/KWQtSqlEasyFilter.cpp
new file mode 100644
index 00000000..0f5e5ffb
--- /dev/null
+++ b/kword/mailmerge/sql/KWQtSqlEasyFilter.cpp
@@ -0,0 +1,98 @@
+#include "KWQtSqlEasyFilter.h"
+#include "KWQtSqlEasyFilter.moc"
+#include <qtable.h>
+#include <qscrollview.h>
+#include <klocale.h>
+#include <qlayout.h>
+#include <qcheckbox.h>
+
+KWQtSqlEasyFilter::KWQtSqlEasyFilter( QWidget *parent)
+ :KDialogBase( Swallow, i18n( "Mail Merge - Editor" ), Ok | Cancel, Ok, parent, "", true)
+{
+ m_fieldList << "" <<"one" << "two" << "three" << "four";
+ m_sortingList << ""<<i18n("ascending")<<i18n("descending");
+ m_operationList <<"="<<i18n("contains")<< "<" << ">";
+
+ m_table=new QTable(6,3,this);
+ setMainWidget(m_table);
+
+ m_table->verticalHeader()->setLabel(0,i18n("Field"));
+ m_table->verticalHeader()->setLabel(1,i18n("Sorting Order"));
+ m_table->verticalHeader()->setLabel(2,i18n("Include"));
+ m_table->verticalHeader()->setLabel(3,i18n("Operator"));
+ m_table->verticalHeader()->setLabel(4,i18n("Condition"));
+ m_table->verticalHeader()->setLabel(5,i18n("Value"));
+ m_table->setSelectionMode(QTable::NoSelection);
+ m_table->setColumnMovingEnabled(true);
+ m_table->setSorting(false);
+
+ for (int i=0; i<3; i++)
+ {
+ createColumn(i);
+ }
+
+ int h=m_table->rowHeight(0);
+ for (int i=0;i<6;i++) h+=m_table->rowHeight(i);
+ h+=m_table->horizontalHeader()->sizeHint().height();
+ m_table->setMinimumHeight(h);
+
+ int w=0;
+ for (int i=0;i<3;i++) w+=m_table->columnWidth(i);
+ w+=m_table->verticalHeader()->headerWidth();
+ m_table->setMinimumWidth(w);
+ connect(m_table,SIGNAL(valueChanged ( int, int)),this,SLOT(slotValueChanged ( int, int)));
+}
+
+void KWQtSqlEasyFilter::createColumn(int i)
+{
+ QTableItem *it;
+ m_table->setItem(0,i,it=new QComboTableItem(m_table,m_fieldList,false));
+ m_table->setItem(1,i,it=new QComboTableItem(m_table,m_sortingList,false));
+ it->setEnabled(false);
+ m_table->setItem(2,i,it=new QCheckTableItem(m_table,i18n("Yes")));
+ it->setEnabled(false);
+ m_table->setItem(3,i,it=new QCheckTableItem(m_table,i18n("NOT")));
+ it->setEnabled(false);
+ m_table->setItem(4,i,it=new QComboTableItem(m_table,m_operationList,false));
+ it->setEnabled(false);
+ m_table->setItem(5,i,it=new QTableItem(m_table,QTableItem::WhenCurrent,""));
+ it->setEnabled(false);
+ m_table->ensureCellVisible(0,i);
+}
+
+
+void KWQtSqlEasyFilter::slotValueChanged ( int row, int col )
+{
+ switch (row)
+ {
+ case 0:
+ if ( !m_table->item(row,col)->text().isEmpty() )
+ {
+ if (col==m_table->numCols()-1)
+ {
+ m_table->insertColumns(col+1,1);
+ createColumn(col+1);
+ }
+ m_table->item(1,col)->setEnabled(true);
+ m_table->item(2,col)->setEnabled(true);
+ bool enableSearch=(static_cast<QCheckTableItem*>(m_table->item(2,col))->isChecked());
+ m_table->item(3,col)->setEnabled(enableSearch);
+ m_table->item(4,col)->setEnabled(enableSearch);
+ m_table->item(5,col)->setEnabled(enableSearch);
+ }
+ else
+ {
+ for (int i=1;i<6;i++) m_table->item(i,col)->setEnabled(false);
+ }
+ break;
+ case 2:
+ bool enSearch=static_cast<QCheckTableItem*>(m_table->item(row,col))->isChecked();
+ m_table->item(3,col)->setEnabled(enSearch);
+ m_table->item(4,col)->setEnabled(enSearch);
+ m_table->item(5,col)->setEnabled(enSearch);
+ break;
+ }
+}
+
+KWQtSqlEasyFilter::~KWQtSqlEasyFilter(){;}
+
diff --git a/kword/mailmerge/sql/KWQtSqlEasyFilter.h b/kword/mailmerge/sql/KWQtSqlEasyFilter.h
new file mode 100644
index 00000000..aa20d494
--- /dev/null
+++ b/kword/mailmerge/sql/KWQtSqlEasyFilter.h
@@ -0,0 +1,29 @@
+#ifndef MAILMERGE_QtSqlPLUGIN_EASYFILTER
+#define MAILMERGE_QtSqlPLUGIN_EASYFILTER
+
+#include <kdialogbase.h>
+
+class QTable;
+class QScrollView;
+class QStringList;
+
+class KWQtSqlEasyFilter: public KDialogBase
+{
+ Q_OBJECT
+public:
+ KWQtSqlEasyFilter( QWidget *parent);
+ virtual ~KWQtSqlEasyFilter();
+protected:
+ void createColumn(int i);
+
+protected slots:
+ void slotValueChanged ( int, int);
+private:
+ QTable *m_table;
+ QScrollView *m_view;
+ QStringList m_fieldList,m_sortingList,m_operationList;
+
+
+};
+
+#endif
diff --git a/kword/mailmerge/sql/KWQtSqlMailMergeOpen.cpp b/kword/mailmerge/sql/KWQtSqlMailMergeOpen.cpp
new file mode 100644
index 00000000..099e92a8
--- /dev/null
+++ b/kword/mailmerge/sql/KWQtSqlMailMergeOpen.cpp
@@ -0,0 +1,123 @@
+/* This file is part of the KDE project
+ Copyright (C) 2001 Joseph Wenninger <jowenn@kde.org>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+*/
+
+#include "KWQtSqlMailMergeOpen.h"
+#include "KWQtSqlMailMergeOpen.moc"
+#include <kcombobox.h>
+#include <klineedit.h>
+#include <kdebug.h>
+#include <qlayout.h>
+#include <kconfig.h>
+#include <kpushbutton.h>
+#include <klineeditdlg.h>
+#include <kiconloader.h>
+#include <qsqldatabase.h>
+#include <qguardedptr.h>
+#include <klocale.h>
+
+/******************************************************************
+ *
+ * Class: KWQtSqlMailMergeOpen
+ *
+ ******************************************************************/
+
+KWQtSqlMailMergeOpen::KWQtSqlMailMergeOpen( QWidget *parent, KWQtSqlSerialDataSourceBase *db_ )
+ :KDialogBase( Plain, i18n( "Mail Merge - Setup Database Connection" ), Ok | Cancel, Ok, parent, "", true ), db( db_ ){
+ (new QVBoxLayout(plainPage()))->setAutoAdd(true);
+ setMainWidget(widget=new KWQtSqlOpenWidget(plainPage()));
+ widget->drivers->insertStringList(QSqlDatabase::drivers());
+ widget->hostname->setText(db->hostname);
+ widget->username->setText(db->username);
+ widget->port->setText(db->port);
+ widget->databasename->setText(db->databasename);
+ fillSavedProperties();
+ connect(this,SIGNAL(okClicked()),this,SLOT(handleOk()));
+ connect(widget->savedProperties,SIGNAL(activated(const QString&)),
+ this, SLOT(savedPropertiesChanged(const QString&)));
+ connect(widget->rememberButton,SIGNAL(clicked()),
+ this, SLOT(slotSave()));
+}
+
+KWQtSqlMailMergeOpen::~KWQtSqlMailMergeOpen(){;}
+
+void KWQtSqlMailMergeOpen::savedPropertiesChanged(const QString& name)
+{
+ if (name!=i18n("<not saved>"))
+ {
+ KConfig conf("kwmailmergerc");
+ conf.setGroup("KWSLQTDB:"+name);
+ widget->hostname->setText(conf.readEntry("hostname",""));
+ widget->username->setText(conf.readEntry("username",""));
+ widget->port->setText(conf.readEntry("port",""));
+ widget->databasename->setText(conf.readEntry("databasename",""));
+ }
+ else
+ {
+ widget->hostname->setText("");
+ widget->username->setText("");
+ widget->port->setText(i18n("default"));
+ widget->databasename->setText("");
+ }
+
+}
+
+void KWQtSqlMailMergeOpen::fillSavedProperties()
+{
+ widget->savedProperties->clear();
+ widget->savedProperties->insertItem(i18n("<not saved>"));
+ //Read data from configuration file and add entries
+ KConfig conf("kwmailmergerc");
+ QStringList list=conf.groupList();
+ for (QStringList::Iterator it=list.begin();it!=list.end();++it)
+ {
+ if ((*it).startsWith("KWSLQTDB:"))
+ widget->savedProperties->insertItem((*it).right((*it).length()-9));
+ }
+}
+
+void KWQtSqlMailMergeOpen::slotSave()
+{
+ QString value;
+ bool ok;
+ value=KLineEditDlg::getText(i18n("Store Settings"),i18n("Name:"),
+ QString::null, &ok,this);
+ if (!ok) kdDebug()<<"Cancel was pressed"<<endl;
+ if (value.isEmpty()) kdDebug()<<"Name value was empty"<<endl;
+ if ((ok) && (!value.isEmpty()))
+ {
+ KConfig conf("kwmailmergerc");
+ conf.setGroup("KWSLQTDB:"+value);
+ conf.writeEntry("hostname",widget->hostname->text());
+ conf.writeEntry("username",widget->username->text());
+ conf.writeEntry("port",widget->port->text());
+ conf.writeEntry("databasename",widget->databasename->text());
+ conf.sync();
+ fillSavedProperties();
+ widget->savedProperties->setCurrentText(value);
+ }
+}
+
+void KWQtSqlMailMergeOpen::handleOk()
+{
+ db->hostname=widget->hostname->text();
+ db->username=widget->username->text();
+ db->port=widget->port->text();
+ db->databasename=widget->databasename->text();
+ db->driver=widget->drivers->currentText();
+}
diff --git a/kword/mailmerge/sql/KWQtSqlMailMergeOpen.h b/kword/mailmerge/sql/KWQtSqlMailMergeOpen.h
new file mode 100644
index 00000000..66b3c329
--- /dev/null
+++ b/kword/mailmerge/sql/KWQtSqlMailMergeOpen.h
@@ -0,0 +1,57 @@
+/* This file is part of the KDE project
+ Copyright (C) 2001 Joseph Wenninger <jowenn@kde.org>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+*/
+
+#ifndef _SERIALLETTER_QtSql_OPEN_EDITOR_H_
+#define _SERIALLETTER_QtSql_OPEN_EDITOR_H_
+
+#include <qdom.h>
+#include <kdialogbase.h>
+#include <qwidget.h>
+
+#include "KWMailMergeDataSource.h"
+#include "KWQtSqlSerialDataSourceBase.h"
+#include "qtsqlopenwidget.h"
+
+/******************************************************************
+ *
+ * Class: KWQtSqlMailMergeOpen
+ *
+ ******************************************************************/
+class KWQtSqlMailMergeOpen : public KDialogBase
+{
+ Q_OBJECT
+
+public:
+ KWQtSqlMailMergeOpen( QWidget *parent, KWQtSqlSerialDataSourceBase *db_ );
+ ~KWQtSqlMailMergeOpen();
+private:
+ KWQtSqlSerialDataSourceBase *db;
+ KWQtSqlOpenWidget *widget;
+
+ void fillSavedProperties();
+
+private slots:
+void handleOk();
+public slots:
+void savedPropertiesChanged(const QString&);
+void slotSave();
+};
+
+#endif
+
diff --git a/kword/mailmerge/sql/KWQtSqlPowerSerialDataSource.cpp b/kword/mailmerge/sql/KWQtSqlPowerSerialDataSource.cpp
new file mode 100644
index 00000000..8f89274a
--- /dev/null
+++ b/kword/mailmerge/sql/KWQtSqlPowerSerialDataSource.cpp
@@ -0,0 +1,256 @@
+/* This file is part of the KDE project
+ Copyright (C) 2001 Joseph Wenninger <jowenn@kde.org>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+*/
+
+#include "KWQtSqlPowerSerialDataSource.h"
+#include "KWQtSqlPowerSerialDataSource.moc"
+#include "KWQtSqlMailMergeOpen.h"
+#include <qlayout.h>
+#include <qdom.h>
+#include <kcombobox.h>
+#include <klineedit.h>
+#include <kpushbutton.h>
+#include <qsqldatabase.h>
+#include <qmessagebox.h>
+#include <kpassdlg.h>
+#include <qsqlrecord.h>
+#include <qsqlcursor.h>
+#include <qdatatable.h>
+#include <kdebug.h>
+
+#define KWQtSqlBarIcon( x ) BarIcon( x, db->KWInstance() )
+
+/******************************************************************
+ *
+ * Class: KWQtSqlSerialDataSource
+ *
+ ******************************************************************/
+
+KWQtSqlPowerSerialDataSource::KWQtSqlPowerSerialDataSource(KInstance *inst,QObject *parent)
+ : KWQtSqlSerialDataSourceBase(inst,parent),myquery(0)
+{
+ port=i18n("default");
+}
+
+KWQtSqlPowerSerialDataSource::~KWQtSqlPowerSerialDataSource()
+{
+ if (myquery) delete myquery;
+ QSqlDatabase::removeDatabase("KWQTSQLPOWER");
+}
+
+void KWQtSqlPowerSerialDataSource::refresh(bool force)
+{
+ if ((force) || (myquery==0))
+ {
+ if (myquery)
+ {
+ delete myquery;
+ myquery=0;
+ }
+ QString tmp=query.upper();
+ if (!tmp.startsWith("SELECT")) return;
+ if ((!database) || (!database->isOpen()))openDatabase();
+ myquery=new KWMySqlCursor(query,true,database);
+ myquery->setMode(QSqlCursor::ReadOnly);
+ }
+ kdDebug()<<QString("There were %1 rows in the query").arg(myquery->size())<<endl;
+}
+
+QString KWQtSqlPowerSerialDataSource::getValue( const QString &name, int record ) const
+{
+ int num=record;
+
+ if (!myquery) return name;
+ if ( num < 0 || num > (int)myquery->size() )
+ return name;
+ if (!myquery->seek(num,false)) return i18n(">>>Illegal position within datasource<<<");
+ if (!myquery->contains(name)) return i18n(">>>Field %1 is unknown in the current database query<<<").arg(name);
+ return (myquery->value(name)).toString();
+}
+
+void KWQtSqlPowerSerialDataSource::save( QDomDocument &doc, QDomElement &parent)
+{
+ QDomElement def=doc.createElement(QString::fromLatin1("DEFINITION"));
+ parent.appendChild(def);
+ {
+ QDomElement defEnt=doc.createElement(QString::fromLatin1("DATABASE"));
+ defEnt.setAttribute(QString::fromLatin1("hostname"),hostname);
+ defEnt.setAttribute(QString::fromLatin1("port"),port);
+ defEnt.setAttribute(QString::fromLatin1("driver"),driver);
+ defEnt.setAttribute(QString::fromLatin1("databasename"),databasename);
+ defEnt.setAttribute(QString::fromLatin1("username"),username);
+ def.appendChild(defEnt);
+
+ defEnt=doc.createElement(QString::fromLatin1("QUERY"));
+ defEnt.setAttribute(QString::fromLatin1("value"),query);
+ def.appendChild(defEnt);
+
+ QDomElement sampleEnt=doc.createElement(QString::fromLatin1("SAMPLERECORD"));
+ parent.appendChild(sampleEnt);
+ for (DbRecord::Iterator it=sampleRecord.begin();it!=sampleRecord.end();++it)
+ {
+ QDomElement fieldEnt=doc.createElement(QString::fromLatin1("FIELD"));
+ fieldEnt.setAttribute(QString::fromLatin1("name"),it.key());
+ sampleEnt.appendChild(fieldEnt);
+ }
+ }
+}
+
+void KWQtSqlPowerSerialDataSource::load( QDomElement& parentElem )
+{
+ clearSampleRecord();
+ QDomNode defNd=parentElem.namedItem("DEFINITION");
+ if (!defNd.isNull())
+ {
+ QDomElement def=defNd.toElement();
+ QDomNode dbNd=def.namedItem("DATABASE");
+ if (!dbNd.isNull())
+ {
+ QDomElement dbEnt=dbNd.toElement();
+ if (dbEnt.tagName()==QString::fromLatin1("DATABASE"))
+ {
+ hostname=dbEnt.attribute(QString::fromLatin1("hostname"));
+ port=dbEnt.attribute(QString::fromLatin1("port"));
+ driver=dbEnt.attribute(QString::fromLatin1("driver"));
+ databasename=dbEnt.attribute(QString::fromLatin1("databasename"));
+ username=dbEnt.attribute(QString::fromLatin1("username"));
+ }
+ }
+ QDomNode queryNd=def.namedItem("QUERY");
+ if (!queryNd.isNull())
+ {
+ query=queryNd.toElement().attribute(QString::fromLatin1("value"));
+ }
+ }
+
+ defNd=parentElem.namedItem("SAMPLERECORD");
+ if (!defNd.isNull())
+ {
+ QDomElement def1=defNd.toElement();
+ for (QDomElement defEnt=defNd.firstChild().toElement();!defEnt.isNull();defEnt=defEnt.nextSibling().toElement())
+ {
+ addSampleRecordEntry(defEnt.attribute(QString::fromLatin1("name")));
+ }
+ }
+}
+
+bool KWQtSqlPowerSerialDataSource::showConfigDialog(QWidget *par,int action)
+{
+ bool ret=false;
+ if (action==KWSLEdit)
+ {
+ if ((!database) || (!database->isOpen()))openDatabase();
+ KWQtSqlPowerMailMergeEditor *dia=new KWQtSqlPowerMailMergeEditor(par,this);
+ ret=dia->exec();
+ delete dia;
+ }
+ else ret=KWQtSqlSerialDataSourceBase::showConfigDialog(par,action);
+ return ret;
+}
+
+void KWQtSqlPowerSerialDataSource::clearSampleRecord() {sampleRecord.clear();}
+
+void KWQtSqlPowerSerialDataSource::addSampleRecordEntry(QString name)
+{sampleRecord[name]=name; }//i18n("No Value");}
+
+
+/******************************************************************
+ *
+ * Class: KWQtSqlMailMergeEditor
+ *
+ ******************************************************************/
+
+KWQtSqlPowerMailMergeEditor::KWQtSqlPowerMailMergeEditor( QWidget *parent, KWQtSqlPowerSerialDataSource *db_ )
+ :KDialogBase( Plain, i18n( "Mail Merge - Editor" ), Ok | Cancel, Ok, parent, "", true ), db( db_ )
+{
+ (new QVBoxLayout(plainPage()))->setAutoAdd(true);
+ setMainWidget(widget=new KWQtSqlPowerWidget(plainPage()));
+ connect(widget->setup,SIGNAL(clicked()),this,SLOT(openSetup()));
+ connect(widget->tables,SIGNAL(currentChanged(QListBoxItem*)),this,SLOT(slotTableChanged(QListBoxItem*)));
+ connect(widget->execute,SIGNAL(clicked()),this,SLOT(slotExecute()));
+ connect(this,SIGNAL(okClicked()),this,SLOT(slotSetQuery()));
+ widget->query->setText(db->query);
+ updateDBViews();
+}
+
+void KWQtSqlPowerMailMergeEditor::slotSetQuery()
+{
+ db->query=widget->query->text();
+ db->refresh(true);
+}
+
+void KWQtSqlPowerMailMergeEditor::slotExecute()
+{
+ if (!db->database) if (!db->openDatabase()) return;
+ QString tmp=widget->query->text().upper();
+ if (!tmp.startsWith("SELECT")) return;
+ KWMySqlCursor *cur=new KWMySqlCursor(widget->query->text(),true,db->database);
+ cur->setMode(QSqlCursor::ReadOnly);
+
+ db->clearSampleRecord();
+ kdDebug()<<QString("Fieldname count %1").arg(cur->count())<<endl;
+ for (uint i=0;i<cur->count();i++)
+ db->addSampleRecordEntry(cur->fieldName(i));
+
+ widget->queryresult->setSqlCursor(cur,true,true);
+ widget->queryresult->refresh(QDataTable::RefreshAll);
+}
+
+void KWQtSqlPowerMailMergeEditor::slotTableChanged ( QListBoxItem * item )
+{
+ widget->fields->clear();
+ if (item)
+ {
+ if (!db->database) return;
+ QSqlRecord rec=db->database->record(item->text());
+ for (uint i=0;i<rec.count();i++)
+ {
+ widget->fields->insertItem(rec.fieldName(i));
+ }
+ }
+}
+
+void KWQtSqlPowerMailMergeEditor::openSetup()
+{
+ KWQtSqlMailMergeOpen *dia=new KWQtSqlMailMergeOpen(this,db);
+ if (dia->exec())
+ {
+ db->openDatabase();
+ updateDBViews();
+ }
+ delete dia;
+}
+
+
+void KWQtSqlPowerMailMergeEditor::updateDBViews()
+{
+ widget->fields->clear();
+ widget->tables->clear();
+ if (!db->database) return;
+ widget->tables->insertStringList(db->database->tables());
+}
+
+KWQtSqlPowerMailMergeEditor::~KWQtSqlPowerMailMergeEditor(){;}
+
+
+extern "C" {
+ KWORD_MAILMERGE_EXPORT KWMailMergeDataSource *create_kwmailmerge_qtsqldb_power(KInstance *inst,QObject *parent)
+ {
+ return new KWQtSqlPowerSerialDataSource(inst,parent);
+ }
+}
diff --git a/kword/mailmerge/sql/KWQtSqlPowerSerialDataSource.h b/kword/mailmerge/sql/KWQtSqlPowerSerialDataSource.h
new file mode 100644
index 00000000..d7587eea
--- /dev/null
+++ b/kword/mailmerge/sql/KWQtSqlPowerSerialDataSource.h
@@ -0,0 +1,96 @@
+/* This file is part of the KDE project
+ Copyright (C) 2001 Joseph Wenninger <jowenn@kde.org>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+*/
+
+#ifndef _SERIALLETTER_QtSql_POWER_PLUGIN_H_
+#define _SERIALLETTER_QtSql_POWER_PLUGIN_H_
+
+#include <qdom.h>
+#include <klocale.h>
+#include <kiconloader.h>
+#include <kdialogbase.h>
+#include <qsqldatabase.h>
+/* FOR THE DIRTY HACK */
+#include <qsqlcursor.h>
+#include <qsqldriver.h>
+/* END FOR THE DIRTY HACK */
+#include <qguardedptr.h>
+
+#include "defs.h"
+#include "KWMailMergeDataSource.h"
+#include "KWQtSqlSerialDataSourceBase.h"
+#include "kwqtsqlpower.h"
+#include "KWMySqlCursor.h"
+
+/******************************************************************
+ *
+ * Class: KWQtSqlSerialDataSource
+ *
+ ******************************************************************/
+class KWQtSqlPowerSerialDataSource: public KWQtSqlSerialDataSourceBase
+{
+ Q_OBJECT
+ public:
+ KWQtSqlPowerSerialDataSource(KInstance *inst,QObject *parent);
+ ~KWQtSqlPowerSerialDataSource();
+
+ virtual void save( QDomDocument &doc,QDomElement&);
+ virtual void load( QDomElement& elem );
+ virtual class QString getValue( const class QString &name, int record = -1 ) const;
+ virtual int getNumRecords() const {
+ return (myquery?((myquery->size()<0)?0:myquery->size()):0);
+ }
+ virtual bool showConfigDialog(QWidget *,int);
+ virtual void refresh(bool force);
+
+ protected:
+ friend class KWQtSqlPowerMailMergeEditor;
+ QString query;
+ KWMySqlCursor *myquery;
+
+ void clearSampleRecord();
+ void addSampleRecordEntry(QString name);
+
+};
+
+/******************************************************************
+ *
+ * Class: KWQtSqlPowerMailMergeEditor
+ *
+ ******************************************************************/
+
+class KWQtSqlPowerMailMergeEditor : public KDialogBase
+{
+ Q_OBJECT
+
+public:
+ KWQtSqlPowerMailMergeEditor( QWidget *parent, KWQtSqlPowerSerialDataSource *db_ );
+ ~KWQtSqlPowerMailMergeEditor();
+private:
+ KWQtSqlPowerSerialDataSource *db;
+ KWQtSqlPowerWidget *widget;
+private slots:
+ void openSetup();
+ void updateDBViews();
+ void slotTableChanged ( QListBoxItem * item );
+ void slotExecute();
+ void slotSetQuery();
+};
+
+
+#endif
diff --git a/kword/mailmerge/sql/KWQtSqlSerialDataSource.cpp b/kword/mailmerge/sql/KWQtSqlSerialDataSource.cpp
new file mode 100644
index 00000000..8835bf49
--- /dev/null
+++ b/kword/mailmerge/sql/KWQtSqlSerialDataSource.cpp
@@ -0,0 +1,218 @@
+/* This file is part of the KDE project
+ Copyright (C) 2001 Joseph Wenninger <jowenn@kde.org>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+*/
+
+#include "KWQtSqlSerialDataSource.h"
+#include "KWQtSqlSerialDataSource.moc"
+#include "KWQtSqlEasyFilter.h"
+
+#include <klocale.h>
+#include <qlayout.h>
+#include <qsqlcursor.h>
+#include <qdatatable.h>
+#include <qcheckbox.h>
+#include <qsqlrecord.h>
+#include <qsqlquery.h>
+#include <kdebug.h>
+
+#define KWQtSqlBarIcon( x ) BarIcon( x, db->KWInstance() )
+
+/******************************************************************
+ *
+ * Class: KWQtSqlSerialDataSource
+ *
+ ******************************************************************/
+
+KWQtSqlSerialDataSource::KWQtSqlSerialDataSource(KInstance *inst,QObject *parent)
+ : KWQtSqlSerialDataSourceBase(inst,parent)
+{
+ myquery=0;
+}
+
+KWQtSqlSerialDataSource::~KWQtSqlSerialDataSource()
+{
+ delete myquery;
+ QSqlDatabase::removeDatabase("KWQTSQLPOWER");
+}
+
+
+QString KWQtSqlSerialDataSource::getValue( const QString &name, int record ) const
+{
+ int num=record;
+
+ if (!myquery) return name;
+ if ( num < 0 || num > (int)myquery->size() )
+ return name;
+ if (!myquery->seek(num,false)) return i18n(">>>Illegal position within datasource<<<");
+ if (!myquery->contains(name)) return i18n(">>>Field %1 is unknown in the current database query<<<").arg(name);
+ return (myquery->value(name)).toString();
+}
+
+void KWQtSqlSerialDataSource::save( QDomDocument & /*doc*/, QDomElement & /*parent*/)
+{
+/*
+ QDomElement def=doc.createElement(QString::fromLatin1("DEFINITION"));
+ parent.appendChild(def);
+ for (DbRecord::Iterator it=sampleRecord.begin();it!=sampleRecord.end();++it)
+ {
+ QDomElement defEnt=doc.createElement(QString::fromLatin1("FIELD"));
+ defEnt.setAttribute(QString::fromLatin1("name"),it.key());
+ def.appendChild(defEnt);
+ }
+ QDomElement cont=doc.createElement(QString::fromLatin1("CONTENT"));
+ parent.appendChild(cont);
+ for (Db::Iterator dbI=db.begin();dbI!=db.end();++dbI)
+ {
+ QDomElement rec=doc.createElement(QString::fromLatin1("RECORD"));
+ cont.appendChild(rec);
+ for (DbRecord::Iterator it=sampleRecord.begin();it!=sampleRecord.end();++it)
+ {
+ QDomElement recEnt=doc.createElement(QString::fromLatin1("ITEM"));
+ recEnt.setAttribute(QString::fromLatin1("name"),it.key());
+ recEnt.setAttribute(QString::fromLatin1("data"),(*dbI)[it.key()]);
+ rec.appendChild(recEnt);
+ }
+ }
+*/
+}
+
+void KWQtSqlSerialDataSource::load( QDomElement& /*parentElem*/ )
+{
+/*
+ db.clear();
+ sampleRecord.clear();
+ QDomNode defNd=parentElem.namedItem("DEFINITION");
+ if (defNd.isNull()) return;
+ QDomElement def=defNd.toElement();
+ for (QDomElement defEnt=def.firstChild().toElement();!defEnt.isNull();defEnt=defEnt.nextSibling().toElement())
+ {
+ sampleRecord[defEnt.attribute(QString::fromLatin1("name"))]=defEnt.attribute(QString::fromLatin1("name"));//i18n( "No Value" );
+ }
+ QDomNode contNd=parentElem.namedItem("CONTENT");
+ if (contNd.isNull()) return;
+ for (QDomNode rec=contNd.firstChild();!rec.isNull();rec=rec.nextSibling())
+ {
+ appendRecord();
+ for (QDomElement recEnt=rec.firstChild().toElement();!recEnt.isNull();recEnt=recEnt.nextSibling().toElement())
+ {
+ setValue(recEnt.attribute(QString::fromLatin1("name")),
+ recEnt.attribute(QString::fromLatin1("data")),db.count()-1);
+ }
+ }
+*/
+}
+
+bool KWQtSqlSerialDataSource::showConfigDialog(QWidget *par,int action)
+{
+ bool ret=false;
+ if (action==KWSLEdit)
+ {
+ KWQtSqlDataSourceEditor *dia=new KWQtSqlDataSourceEditor(par,this);
+ ret=dia->exec();
+ delete dia;
+ }
+ else ret=KWQtSqlSerialDataSourceBase::showConfigDialog(par,action);
+
+ return ret;
+}
+
+void KWQtSqlSerialDataSource::refresh(bool force)
+{
+ if ((force) || (myquery==0))
+ {
+ if (myquery)
+ {
+ delete myquery;
+ myquery=0;
+ }
+ if ((!database) || (!database->isOpen())) openDatabase();
+ if ((!database) || (!database->isOpen())) return;
+ myquery=new QSqlCursor(tableName,true,database);
+ myquery->setMode(QSqlCursor::ReadOnly);
+ myquery->select(filter);
+ }
+ kdDebug()<<QString("There were %1 rows in the query").arg(myquery->size())<<endl;
+
+}
+
+
+
+
+
+/******************************************************************
+ *
+ * Class: KWQtSqlDataSourceEditor
+ *
+ ******************************************************************/
+
+
+
+KWQtSqlDataSourceEditor::KWQtSqlDataSourceEditor( QWidget *parent, KWQtSqlSerialDataSource *db_ )
+ :KDialogBase( Plain, i18n( "Mail Merge - Editor" ), Ok | Cancel, Ok, parent, "", true ), db( db_ )
+{
+ tableName=db->tableName;
+ filter=db->filter;
+ (new QVBoxLayout(plainPage()))->setAutoAdd(true);
+ setMainWidget(widget=new QtSqlDataSourceEditor(plainPage()));
+ connect(widget->tableCombo,SIGNAL(activated(int)),this,SLOT(tableChanged(int)));
+ connect(widget->editFilter,SIGNAL(clicked()),this,SLOT(editFilter()));
+ updateTableCombo();
+
+// connect(this,SIGNAL(okClicked()),this,SLOT(slotSetQuery()));
+}
+
+void KWQtSqlDataSourceEditor::tableChanged(int item)
+{
+ tableName=widget->tableCombo->text(item);
+ QSqlCursor *tmpCursor=new QSqlCursor(tableName,true,db->database);
+ tmpCursor->setMode(QSqlCursor::ReadOnly);
+
+ if (widget->filterCheckBox->isChecked()) tmpCursor->select(filter);
+
+ widget->DataTable->setSqlCursor(tmpCursor,true,true);
+ widget->DataTable->refresh(QDataTable::RefreshAll);
+}
+
+void KWQtSqlDataSourceEditor::updateTableCombo()
+{
+ widget->tableCombo->clear();
+ if (!db->database) return;
+ widget->tableCombo->insertItem("");
+ widget->tableCombo->insertStringList(db->database->tables());
+}
+
+void KWQtSqlDataSourceEditor::slotSetQuery()
+{
+ db->tableName=tableName;
+ db->filter=filter;
+ db->refresh(true);
+}
+
+
+void KWQtSqlDataSourceEditor::editFilter()
+{
+ KWQtSqlEasyFilter *f=new KWQtSqlEasyFilter(static_cast<QWidget*>(parent()));
+ f->exec();
+}
+
+extern "C" {
+ KWORD_MAILMERGE_EXPORT KWMailMergeDataSource *create_kwmailmerge_qtsqldb(KInstance *inst,QObject *parent)
+ {
+ return new KWQtSqlSerialDataSource(inst,parent);
+ }
+}
diff --git a/kword/mailmerge/sql/KWQtSqlSerialDataSource.h b/kword/mailmerge/sql/KWQtSqlSerialDataSource.h
new file mode 100644
index 00000000..e2051a2f
--- /dev/null
+++ b/kword/mailmerge/sql/KWQtSqlSerialDataSource.h
@@ -0,0 +1,85 @@
+/* This file is part of the KDE project
+ Copyright (C) 2001 Joseph Wenninger <jowenn@kde.org>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+*/
+
+#ifndef _SERIALLETTER_QtSql_PLUGIN_H_
+#define _SERIALLETTER_QtSql_PLUGIN_H_
+
+#include <qdom.h>
+#include <qsqlcursor.h>
+#include "KWMailMergeDataSource.h"
+#include "KWQtSqlSerialDataSourceBase.h"
+#include "qtsqldatasourceeditor.h"
+
+
+/******************************************************************
+ *
+ * Class: KWQtSqlSerialDataSource
+ *
+ ******************************************************************/
+
+class KWQtSqlSerialDataSource: public KWQtSqlSerialDataSourceBase
+{
+ public:
+ KWQtSqlSerialDataSource(KInstance *inst,QObject *parent);
+ ~KWQtSqlSerialDataSource();
+
+ virtual void save( QDomDocument &doc,QDomElement&);
+ virtual void load( QDomElement& elem );
+ virtual class QString getValue( const class QString &name, int record = -1 ) const;
+ virtual int getNumRecords() const {
+ return (myquery?((myquery->size()<0)?0:myquery->size()):0);
+ }
+ virtual void refresh(bool);
+ virtual bool showConfigDialog(QWidget *,int);
+
+ protected:
+ friend class KWQtSqlDataSourceEditor;
+ QString tableName;
+ QString filter;
+ QSqlCursor *myquery;
+};
+
+/******************************************************************
+ *
+ * Class: KWQtSqlDataSourceEditor
+ *
+ ******************************************************************/
+
+class KWQtSqlDataSourceEditor : public KDialogBase
+{
+ Q_OBJECT
+
+public:
+ KWQtSqlDataSourceEditor( QWidget *parent, KWQtSqlSerialDataSource *db_ );
+ ~KWQtSqlDataSourceEditor(){;}
+private:
+ KWQtSqlSerialDataSource *db;
+ QtSqlDataSourceEditor *widget;
+ void updateTableCombo();
+ QString filter;
+ QString tableName;
+
+private slots:
+ void tableChanged(int);
+ void slotSetQuery();
+ void editFilter();
+};
+
+
+#endif
diff --git a/kword/mailmerge/sql/KWQtSqlSerialDataSourceBase.cpp b/kword/mailmerge/sql/KWQtSqlSerialDataSourceBase.cpp
new file mode 100644
index 00000000..781c1ab5
--- /dev/null
+++ b/kword/mailmerge/sql/KWQtSqlSerialDataSourceBase.cpp
@@ -0,0 +1,105 @@
+/* This file is part of the KDE project
+ Copyright (C) 2001 Joseph Wenninger <jowenn@kde.org>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+*/
+
+#include "KWQtSqlSerialDataSourceBase.h"
+#include "KWQtSqlSerialDataSourceBase.moc"
+#include "KWQtSqlMailMergeOpen.h"
+#include <qlayout.h>
+#include <qdom.h>
+#include <kcombobox.h>
+#include <klineedit.h>
+#include <kpushbutton.h>
+#include <qsqldatabase.h>
+#include <qmessagebox.h>
+#include <kpassdlg.h>
+#include <qsqlrecord.h>
+#include <qsqlcursor.h>
+#include <qdatatable.h>
+#include <kdebug.h>
+#include <klocale.h>
+#include <kiconloader.h>
+
+
+
+
+/******************************************************************
+ *
+ * Class: KWQtSqlSerialDataSourceBase
+ *
+ ******************************************************************/
+
+int KWQtSqlSerialDataSourceBase::connectionId=0;
+
+KWQtSqlSerialDataSourceBase::KWQtSqlSerialDataSourceBase(KInstance *inst,QObject *parent)
+ : KWMailMergeDataSource(inst,parent)
+{
+ DataBaseConnection=QString("KWQTSQLPOWER")+parent->name()+QString("--%1").arg(connectionId++);
+ port=i18n("default");
+}
+
+KWQtSqlSerialDataSourceBase::~KWQtSqlSerialDataSourceBase()
+{
+ QSqlDatabase::removeDatabase(DataBaseConnection);
+}
+
+
+bool KWQtSqlSerialDataSourceBase::showConfigDialog(QWidget *par,int action)
+{
+ bool ret=false;
+ if (action==KWSLOpen)
+ {
+ KWQtSqlMailMergeOpen *dia=new KWQtSqlMailMergeOpen(par,this);
+
+ ret=dia->exec();
+ if (ret) openDatabase();
+ delete dia;
+ }
+ return ret;
+}
+
+bool KWQtSqlSerialDataSourceBase::openDatabase()
+{
+ QCString pwd;
+ QSqlDatabase::removeDatabase(DataBaseConnection);
+ database=QSqlDatabase::addDatabase(driver,DataBaseConnection);
+ if (database)
+ {
+ if (database->lastError().type()!=QSqlError::None)
+ {
+ QMessageBox::critical(0,i18n("Error"),database->lastError().databaseText(),QMessageBox::Abort,QMessageBox::NoButton,QMessageBox::NoButton);
+ return false;
+ }
+ database->setDatabaseName(databasename);
+ database->setUserName(username);
+ database->setHostName(hostname);
+ if ((port!=i18n("default"))&& (!port.isEmpty()))
+ database->setPort(port.toInt());
+
+ if (KPasswordDialog::getPassword(pwd, i18n("Please enter the password for the database connection"))
+ == KPasswordDialog::Accepted) database->setPassword(pwd);
+ if (database->open())
+ {
+ return true;
+ }
+ QMessageBox::critical(0,i18n("Error"),database->lastError().databaseText(),QMessageBox::Abort,QMessageBox::NoButton,QMessageBox::NoButton);
+ return false;
+ }
+ QMessageBox::critical(0,i18n("Error"),i18n("Unable to create database object"),QMessageBox::Abort,QMessageBox::NoButton,QMessageBox::NoButton);
+ return false;
+}
diff --git a/kword/mailmerge/sql/KWQtSqlSerialDataSourceBase.h b/kword/mailmerge/sql/KWQtSqlSerialDataSourceBase.h
new file mode 100644
index 00000000..0e4586c3
--- /dev/null
+++ b/kword/mailmerge/sql/KWQtSqlSerialDataSourceBase.h
@@ -0,0 +1,63 @@
+/* This file is part of the KDE project
+ Copyright (C) 2001 Joseph Wenninger <jowenn@kde.org>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+*/
+
+#ifndef _SERIALLETTER_QtSql_BASE_H_
+#define _SERIALLETTER_QtSql_BASE_H_
+
+#include <qdom.h>
+#include <kdialogbase.h>
+#include <qsqldatabase.h>
+#include <qguardedptr.h>
+
+#include "KWMailMergeDataSource.h"
+#include "qtsqlopenwidget.h"
+
+
+
+/******************************************************************
+ *
+ * Class: KWQtSqlSerialDataSourceBase
+ *
+ ******************************************************************/
+class KWQtSqlSerialDataSourceBase: public KWMailMergeDataSource
+{
+ Q_OBJECT
+ K_DCOP
+ public:
+ KWQtSqlSerialDataSourceBase(KInstance *inst,QObject *parent);
+ ~KWQtSqlSerialDataSourceBase();
+
+ virtual bool showConfigDialog(QWidget *par,int action);
+
+ protected:
+ friend class KWQtSqlMailMergeOpen;
+ QString hostname;
+ QString username;
+ QString driver;
+ QString port;
+ QString databasename;
+ QGuardedPtr<QSqlDatabase> database;
+ QString DataBaseConnection;
+ static int connectionId;
+ k_dcop:
+ bool openDatabase();
+
+};
+
+#endif
diff --git a/kword/mailmerge/sql/Makefile.am b/kword/mailmerge/sql/Makefile.am
new file mode 100644
index 00000000..0c8595e0
--- /dev/null
+++ b/kword/mailmerge/sql/Makefile.am
@@ -0,0 +1,28 @@
+AM_CPPFLAGS = $(KOFFICE_INCLUDES) -I$(top_srcdir)/lib/kformula \
+ $(KOTEXT_INCLUDES) -I$(top_srcdir)/kword $(all_includes)
+
+kde_module_LTLIBRARIES = kwmailmerge_qtsqldb.la kwmailmerge_qtsqldb_power.la
+
+## Plugin encapsulating the QT SQL database interface
+kwmailmerge_qtsqldb_la_SOURCES = KWQtSqlSerialDataSource.cpp qtsqldatasourceeditor.ui \
+ KWQtSqlEasyFilter.cpp
+kwmailmerge_qtsqldb_la_LDFLAGS = $(all_libraries) -module $(KDE_PLUGIN)
+kwmailmerge_qtsqldb_la_LIBADD = libmailmergesqlcommon.la ../../libkwmailmerge_interface.la $(LIB_KDEUI)
+kwmailmerge_qtsqldb_la_COMPILE_FIRST = qtsqlopenwidget.h
+
+## 2. Plugin encapsulating the QT SQL database interface
+kwmailmerge_qtsqldb_power_la_SOURCES = KWQtSqlPowerSerialDataSource.cpp kwqtsqlpower.ui KWQtSqlPowerSerialDataSource.skel
+kwmailmerge_qtsqldb_power_la_LDFLAGS = $(all_libraries) -module $(KDE_PLUGIN)
+kwmailmerge_qtsqldb_power_la_LIBADD = libmailmergesqlcommon.la ../../libkwmailmerge_interface.la $(LIB_KDEUI)
+kwmailmerge_qtsqldb_power_la_COMPILE_FIRST = qtsqlopenwidget.h
+
+# Common files
+noinst_LTLIBRARIES = libmailmergesqlcommon.la
+libmailmergesqlcommon_la_SOURCES = KWQtSqlMailMergeOpen.cpp KWQtSqlSerialDataSourceBase.skel qtsqlopenwidget.ui KWQtSqlSerialDataSourceBase.cpp
+
+METASOURCES = AUTO
+
+#services_DATA=kwserialletter_qtsqldb.desktop kwserialletter_qtsqldb_power.desktop
+services_DATA=kwserialletter_qtsqldb_power.desktop
+servicesdir=$(kde_servicesdir)
+
diff --git a/kword/mailmerge/sql/kwqtsqlpower.ui b/kword/mailmerge/sql/kwqtsqlpower.ui
new file mode 100644
index 00000000..4979166e
--- /dev/null
+++ b/kword/mailmerge/sql/kwqtsqlpower.ui
@@ -0,0 +1,233 @@
+<!DOCTYPE UI><UI version="3.0" stdsetdef="1">
+<class>KWQtSqlPowerWidget</class>
+<widget class="QWidget">
+ <property name="name">
+ <cstring>KWQtSqlPowerWidget</cstring>
+ </property>
+ <property name="geometry">
+ <rect>
+ <x>0</x>
+ <y>0</y>
+ <width>545</width>
+ <height>403</height>
+ </rect>
+ </property>
+ <property name="acceptDrops">
+ <bool>false</bool>
+ </property>
+ <vbox>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <property name="margin">
+ <number>11</number>
+ </property>
+ <property name="spacing">
+ <number>6</number>
+ </property>
+ <widget class="QGroupBox">
+ <property name="name">
+ <cstring>GroupBox3</cstring>
+ </property>
+ <property name="title">
+ <string>Information</string>
+ </property>
+ <grid>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <property name="margin">
+ <number>11</number>
+ </property>
+ <property name="spacing">
+ <number>6</number>
+ </property>
+ <widget class="KListBox" row="1" column="1">
+ <property name="name">
+ <cstring>fields</cstring>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy>
+ <hsizetype>7</hsizetype>
+ <vsizetype>0</vsizetype>
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="minimumSize">
+ <size>
+ <width>0</width>
+ <height>120</height>
+ </size>
+ </property>
+ </widget>
+ <widget class="KListBox" row="1" column="0">
+ <property name="name">
+ <cstring>tables</cstring>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy>
+ <hsizetype>7</hsizetype>
+ <vsizetype>0</vsizetype>
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="minimumSize">
+ <size>
+ <width>0</width>
+ <height>120</height>
+ </size>
+ </property>
+ </widget>
+ <widget class="QLabel" row="0" column="0">
+ <property name="name">
+ <cstring>TextLabel1_2</cstring>
+ </property>
+ <property name="text">
+ <string>&amp;Available tables:</string>
+ </property>
+ <property name="buddy" stdset="0">
+ <cstring>tables</cstring>
+ </property>
+ </widget>
+ <widget class="QLabel" row="0" column="1">
+ <property name="name">
+ <cstring>TextLabel2</cstring>
+ </property>
+ <property name="text">
+ <string>&amp;Fields of the selected table:</string>
+ </property>
+ <property name="buddy" stdset="0">
+ <cstring>fields</cstring>
+ </property>
+ </widget>
+ </grid>
+ </widget>
+ <widget class="QGroupBox">
+ <property name="name">
+ <cstring>GroupBox6</cstring>
+ </property>
+ <property name="title">
+ <string>Query Result</string>
+ </property>
+ <hbox>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <property name="margin">
+ <number>11</number>
+ </property>
+ <property name="spacing">
+ <number>6</number>
+ </property>
+ <widget class="QDataTable">
+ <property name="name">
+ <cstring>queryresult</cstring>
+ </property>
+ <property name="rowMovingEnabled">
+ <bool>false</bool>
+ </property>
+ </widget>
+ </hbox>
+ </widget>
+ <widget class="QLayoutWidget">
+ <property name="name">
+ <cstring>Layout11</cstring>
+ </property>
+ <hbox>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <property name="margin">
+ <number>0</number>
+ </property>
+ <property name="spacing">
+ <number>6</number>
+ </property>
+ <widget class="QLabel">
+ <property name="name">
+ <cstring>TextLabel1</cstring>
+ </property>
+ <property name="text">
+ <string>&amp;Query:</string>
+ </property>
+ <property name="buddy" stdset="0">
+ <cstring>query</cstring>
+ </property>
+ </widget>
+ <widget class="KLineEdit">
+ <property name="name">
+ <cstring>query</cstring>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy>
+ <hsizetype>3</hsizetype>
+ <vsizetype>0</vsizetype>
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="minimumSize">
+ <size>
+ <width>300</width>
+ <height>0</height>
+ </size>
+ </property>
+ <property name="lineWidth">
+ <number>2</number>
+ </property>
+ <property name="frame">
+ <bool>true</bool>
+ </property>
+ </widget>
+ <widget class="KPushButton">
+ <property name="name">
+ <cstring>execute</cstring>
+ </property>
+ <property name="text">
+ <string>&amp;Execute</string>
+ </property>
+ <property name="default">
+ <bool>true</bool>
+ </property>
+ </widget>
+ <widget class="Line">
+ <property name="name">
+ <cstring>Line2</cstring>
+ </property>
+ <property name="minimumSize">
+ <size>
+ <width>0</width>
+ <height>0</height>
+ </size>
+ </property>
+ <property name="frameShape">
+ <enum>VLine</enum>
+ </property>
+ <property name="frameShadow">
+ <enum>Sunken</enum>
+ </property>
+ <property name="orientation">
+ <enum>Vertical</enum>
+ </property>
+ </widget>
+ <widget class="KPushButton">
+ <property name="name">
+ <cstring>setup</cstring>
+ </property>
+ <property name="text">
+ <string>&amp;Setup</string>
+ </property>
+ </widget>
+ </hbox>
+ </widget>
+ </vbox>
+</widget>
+<includes>
+ <include location="global" impldecl="in declaration">klineedit.h</include>
+ <include location="global" impldecl="in declaration">klistbox.h</include>
+ <include location="global" impldecl="in declaration">kpushbutton.h</include>
+</includes>
+<layoutdefaults spacing="6" margin="11"/>
+</UI>
diff --git a/kword/mailmerge/sql/kwserialletter_qtsqldb.desktop b/kword/mailmerge/sql/kwserialletter_qtsqldb.desktop
new file mode 100644
index 00000000..3b06c655
--- /dev/null
+++ b/kword/mailmerge/sql/kwserialletter_qtsqldb.desktop
@@ -0,0 +1,106 @@
+[Desktop Entry]
+Type=Service
+ServiceTypes=KWord/MailMergePlugin
+
+Name=Qt-SQL Source (single table)
+Name[bg]=Източник Qt-SQL (една таблица)
+Name[ca]=Font Qt-SQL (taula única)
+Name[cy]=Ffynhonell Qt-SQL (tabl sengl)
+Name[da]=Qt-SQL-kilde (enkelt tabel)
+Name[de]=Qt-SQL (Einzeltabelle)
+Name[el]=Πηγή Qt-SQL (απλός πίνακας)
+Name[eo]=Qt-SQL-fonto (sola tabelo)
+Name[es]=Fuente Qt-SQL (una sola tabla)
+Name[et]=Qt-SQL allikas (üksik tabel)
+Name[eu]=Qt-SQL iturburua (taula bakarra)
+Name[fa]=متن Qt-SQL )جدول تک (
+Name[fi]=Qt-SQL lähde (ykai taulu)
+Name[fr]=Source Qt-SQL (table simple)
+Name[fy]=Qt-SQL-boarne (inkelfâldige tabel)
+Name[gl]=Fonte de Qt-SQL (táboa única)
+Name[he]=מקור Qt-SQL (טבלה בודדת)
+Name[hr]=Qt-SQL izvor (jedna tablica)
+Name[hu]=Qt-SQL adatforrás (egy tábla)
+Name[is]=QT-SQL ská (ein tafla)
+Name[it]=Fonte Qt-SQL (tabella singola)
+Name[ja]=Qt-SQL ソース (シングルテーブル)
+Name[km]=ប្រភព Qt-SQL (តារាង​តែ​មួយ)
+Name[lv]=Qt-SQL avots (viena tabula)
+Name[ms]=Sumber Qt-SQL (jadual tunggal)
+Name[nb]=Qt-SQL-kilde (en tabell)
+Name[nds]=Qt-SQL-Born (Enkeltabell)
+Name[ne]=Qt-SQL स्रोत (एकल तालिका)
+Name[nl]=Qt-SQL-bron (enkelvoudige tabel)
+Name[nn]=Qt-SQL-kjelde (enkel tabell)
+Name[pl]=Źródło Qt-SQL (pojedyncza tabela)
+Name[pt]=Fonte do Qt-SQL (tabela única)
+Name[pt_BR]=Qt-SQL (tabela única)
+Name[ru]=Исходный текст Qt-SQL (одна таблица)
+Name[se]=Qt-SQL-gáldu (oktageardanis tabealla)
+Name[sk]=Qt-SQL zdroj (jedna tabuľka)
+Name[sl]=Vir Qt-SQL (enojna tabela)
+Name[sr]=Qt-SQL извор (једна табела)
+Name[sr@Latn]=Qt-SQL izvor (jedna tabela)
+Name[sv]=QT-SQL-källa (enkel tabell)
+Name[uk]=Джерело Qt-SQL (одна таблиця)
+Name[uz]=Qt-SQL manbasi (bitta jadval)
+Name[uz@cyrillic]=Qt-SQL манбаси (битта жадвал)
+Name[zh_CN]=Qt-SQL 源(单表)
+Name[zh_TW]=Qt-SQL 來源 (單一表格)
+Comment=This datasource type lets you use SQL database tables stored on a SQL Server. Depending on your system configuration, MySQL, PostgreSQL and UnixODBC are among the supported database backends. There might even be more (Oracle in commercial Qt versions or 3rd party backends).
+Comment[ar]=هذا النّوع من المصادر البيانيّة يتيح لك إمكانية استخدام جداول قاعدة بيانيّة SQL مُخَزَّنة على خادم SQL. بحسب تهيئة نظامك، فإنّ MySQL، PostgreSQL و UnixODBC تُعتبر من بين ما هو مدعوم من وُجهات خلفيّة للقواعد البيانيّة. يمكن حتى أن يتواجد المزيد (Oracle في إصدارات Qt التِّجاريّة أو الوُجهات الخلفيّة المملوكة لطرف ثالث).
+Comment[az]=Bu mənbə sizə SQL verilənlər bazasını istifadə etməyə imkan verir. Sistem qurğularınızdan asılı olaraq : MySQL,Postgres,(Oracle, lisenziyalı QT buraxılışını işlədirsinizsə),....
+Comment[bg]=Този източник на данни използва таблица за съхранение на данните в СУБД (сървър SQL). В зависимост от настройките, поддръжка имат MySQL, PostgreSQL и UnixODBC. Може да има и още (Oracle в комерсиалните версии на Qt или други).
+Comment[bs]=Ovaj tip izvora podataka vam omogućuje da koristiti SQL tabele smještene na SQL serveru. Ovisno o konfiguraciji vašeg sistema, MySQL, PostgreSQL i UnixODBC su među podržanim bazama podataka. Možda čak i više od toga (Oracle u komercijalnim verzijama Qt-a ili backendima iz trećeg izvora).
+Comment[ca]=Aquest tipus de font de dades permet usar una base de dades SQL guardada a un servidor SQL. Depenent de la configuració del sistema, MySQL, PostgreSQL i UnixODBC estan entre les bases de dades permeses. Inclús n'hi poden haver més(Oracle comercial a la versió Qt i d'altres servidors).
+Comment[cs]=Tento zdroj dat vám umožní požívat tabulky SQL databází uložených na SQL serveru. V závislosti na vašem nastavení systému jsou podporovány databázové systémy MySQL, PostgreSQL a UnixODBC (Oracle je podporována v komerční verzi Qt nebo v databázových systémech jiných výrobců).
+Comment[cy]=Mae'r math yma o ffynhonnell ddata yn eich galluogi i ddefnyddio tablau cronfa ddata SQL sydd wedi eu storio ar weinydd SQL. Yn dibynnu ar ffurfweddiad eich system, mae MySQL, PostgreSQL a UnixODBC ymysg y cronfeydd data cefndirol a gynhelir. Efallai bod mwy ohonynt (Oracle mewn fersiynau masnachol Qt neu ôl-wynebau 3ydd blaid).
+Comment[da]=Denne datakildetype lader dig bruge SQL-databasetabeller gemt på en SQL-server. Afhængig af dine systemindstillinger er MySQL, PostgreSQL og UnixODBC blandt de understøttede underliggende databaser. Der er måske endda flere (Oracle i kommercielle Qt-versioner eller underliggende programmer fra tredjepartsudviklere).
+Comment[de]= Mit diesem Datenquellentyp können Sie Tabellen von SQL-Datenbanken verwenden, die sich auf einem SQL-Server befinden. Abhängig von der Systemeinrichtung: MySQL, PostgresSQL oder UnixODBC. Möglicherweise sogar weitere (etwa Oracle bei einer kommerziellen QT-Version oder Paketen von Drittanbietern).
+Comment[el]=Αυτός ο τύπος πηγής δεδομένων σας επιτρέπει να χρησιμοποιείτε πίνακες βάσεων δεδομένων SQL αποθηκευμένες σε έναν εξυπηρετητή SQL. Ανάλογα με τη ρύθμιση του συστήματος σας, οι MySQL, PostgreSQL και UnixODBC είναι μέσα στις υποστηριζόμενες βάσεις δεδομένων. Μπορεί να υπάρχουν και περισσότερες (Η Oracle σε εμπορικές εκδόσεις της Qt ή άλλες τρίτων κατασκευαστών).
+Comment[eo]=Tiu datumfonta tipo permesas uzi SQL-datumbazan tabelon en SQL-servilo. Depende de la konfiguraĵo de via sistemo estas subtenataj MySQL, PostgreSQL kaj UnixODBC. Povas esti pliaj (Orakolo en komercaj Qt-versioj aŭ triapartiaj datumbazajinterfacoj).
+Comment[es]=Este tipo de fuente de datos le permite utilizar tablas de bases de datos almacenadas en un servidor SQL. Dependiendo de la configuración de su sistema, MySQL, PostgreSQL, y UnixODBC están entre los interfaces de bases de datos soportados. Puede que haya incluso más (Oracle, si utiliza una versión de QT con licencia o interfaces de terceras partes).
+Comment[et]=See andmeallika tüüp lubab kasutada SQL-andmebaasi tabeleid, mida hoitakse SQL-serveris. Sõltuvalt süsteemi seadistustest on MySQL, PostgreSQL ja UnixODBC toetatud andmebaasisüsteemide hulgas. Neid võib olla isegi rohkem (Oracle kommertslikes Qt versioonides või kolmandate osapoolte mootorites).
+Comment[eu]=Datu-iturburu honek SQL zerbitzari batean gordetako SQL datu-baseko taulak erabiltzeko aukera ematen dizu. Zure sistemaren konfigurazioaren arabera, MySQL, PostgreSQL eta UnixODBC euskarriak onartzen dira. Gehiago ere egon daitezke (Oracle (Qt-ren bertsio komertzialetan) edo hirugarrenen beste euskarri batzuk).
+Comment[fa]=این نوع متن داده به شما اجازۀ استفاده از جدولهای دادگان SQL ذخیره‌شده در یک کارساز SQL را می‌دهد. بسته به پیکربندی سیستمتان، MySQL، PostgreSQL و UnixODBC، در میان پایانه‌های دادگان پشتیبانی‌شده می‌باشند. حتی ممکن است بیشتر باشند )Oracle در نسخه‌های تجاری Qt یا پایانه‌های گروه 3rd(.
+Comment[fi]=Tämä tietolähde käyttää SQL-tietokantojen tauluja. Riippuen järjestelmäsi asetuksista tuetaan MySQL, Postgres ja UnixODBC -tietokantoja. Kantoja voi myös olla enemmän (Oracle, jos omistat kaupallisen version QT:sta).
+Comment[fr]=Ce type de source de données vous permet d'utiliser des tables de base de données SQL stockées sur un serveur SQL. Selon votre configuration, ces tables peuvent venir de MySQL, PostgreSQL et UnixODBC, et d'autres encore (comme Oracle, si vous avez la licence commerciale de Qt, par exemple).
+Comment[fy]=Mei dit type gegevensboarne kinne jo SQL-databanktabellen dy bewarre binne op in SQL-tsjinner brûke. Ofhinklik fan jo systeemkonfiguraasje hearre MySQL, PostgreSQL en UnixOBC ta de stipe backends. Der binne mooglik mear (bgl. Oracle yn de kommersje Qt-ferzjes fan backends fan tredden).
+Comment[gl]=Este tipo de fonte de datos permítelle usar as táboas de base de datos armacenadas nun servidor de SQL. Dependendo da configuración do seu sistema, MySQL, PostgreSQL e UnixODBC encóntranse entre os sistemas soportados. Poden até existir máis (Oracle nas versións comerciais de Qt ou mesmo sistemas de terceiros).
+Comment[he]=טיפוס מקור נתונים זה מאפשר לך להשתמש בטבלאות של מסדי נתונים של SQL שמאוחסנות בשרת SQL. בין ממשקי מסדי הנתונים הנתמכים ניתן למנות את MySQL ,PostgreSQL ו־UnixODBC (התמיכה תלויה בהגדרות המערכת שלך). עשויים להיות אף ממשקים נתמכים נוספים, כמו Oracle בגירסאות מסחריות של Qt או ממשקי צד שלישי.
+Comment[hu]=Ez az adatforrástípus SQL-kiszolgálón tárolt SQL táblák elérését teszi lehetővé. A rendszer konfigurációjától függően MySQL, PostgreSQL és UnixODBC adatbázistípust lehet választani. Ezeken felül még más is előfordulhat (pl. Oracle a Qt fizetős változatában).
+Comment[is]=Þessi tegund gerir þér kleyft að nota SQL gagnagrunnstöflur sem liggja á SQL þjóni. MySQL, PostgreSQL og UnixODBC eru meðal studdra gagnagrunnsbakenda, háð kerfisuppsetningu þinni. Það gætu jafnvel verið fleiri (Oracle í verslunarútgáfu Qt eða þriðja aðila bakendar).
+Comment[it]=Questa fonte di dati permette di usare le tabelle di banche dati SQL memorizzate in un server SQL. A seconda della configurazione del tuo sistema, MySQL, PostgreSQL e UnixODBC potrebbero essere alcune delle banche dati supportate. Potrebbero essere supportate anche altre banche dati (Oracle nelle versioni commerciali di Qt o moduli di terze parti).
+Comment[ja]=このデータソースタイプは SQL サーバに保存されている SQL データベーステーブルを使用します。システム設定によりますが、MySQL, PostgreSQL, UnixODBC がサポートされているデータベース バックエンドです。他のものも使用可能かもしれません (Qt の商用バージョンでの Oracle や、サードパーティのバックエンドなど)。
+Comment[km]=ប្រភេទ​ប្រភព​ទិន្នន័យ​នេះ​អនុញ្ញាត​ឲ្យ​អ្នក​ប្រើ​តារាង​មូលដ្ឋាន​ទិន្នន័យ SQL ដែល​បាន​រក្សា​លើ​ម៉ាស៊ីន​បម្រើ SQL ។ ការ​ពឹងផ្អែក​លើ​ការ​កំណត់​រចនា​សម្ព័ន្ធ​ប្រព័ន្ធ​របស់​អ្នក MySQL, PostgreSQL និង UnixODBC គឺ​ក្នុង​ចំណោម​មូលដ្ឋាន​ទិន្នន័យ​ខាងក្រោយ​ដែល​បាន​គាំទ្រ ។ ប្រហែល​ជា​មាន​ច្រើន (Oracle ក្នុង​កំណែ​ពាណិជ្ជកម្ម Qt ឬ ភាគី​ខាងក្រោយ​ទីបី) ។
+Comment[lt]=Šis duomenų šaltinio tipas leidžia jums naudoti SQL duombazės lenteles išsaugotas SQL serveryje. Priklausomai nuo jūsų sistemos konfigūracijos MySQL, PostgreSQL ir UnixODBC yra tarp palaikomų duombazių tipų. Jų gali būti ir daugiau (Oracle komercinėse Qt versijose ar trečių šalių duombazių tipai).
+Comment[lv]=Šis datu avota tips ļauj jums izmantot SQL datubāzes tabulas, kas glabājas uz SQL servera. Atkarībā no jūsu sistēmas konfigurācijas: MySQL,PostgreSQL un UnixODBC ir starp atbalstītajām datubāzēm. Šeit var būt arī vairāk (Oracle, ja jūs izmantojiet komerciālu QT versiju vai trešo pušu risinājumus).
+Comment[ms]=Jenis sumber data ini membenarkan anda menggunakan jadual pangkalan data SQL yang distor dalam Pelayan SQL. Bergantung kepada konfigurasi sistem anda, MySQL, PostgreSQL dan UnixODBC antara bahagian belakang pangkalan data yang disokong. Mungkin terdapat lebih banyak lagi pilihan (Oracle dalam versi Qt komersil atau bahagian belakang pihak ketiga).
+Comment[mt]=Dan it-tip ta' sors iħallik tuża tabelli minn databases SQL fuq server SQL. Skond il-konfigurazzjoni tas-sistema tiegħek, jista' jkollok MySQL, PostgreSQL jew UnixODBC bħala sistemi sapportiti, u jista' jkun hemm oħrajn (Oracle fuq verżjonijiet kummerċjali ta' Qt jew oħrajn ta' terzi partiti).
+Comment[nb]=Datakilden lar deg bruke en databasetabell lagret på en SQL-tjener. Avhengig av oppsettet støttes databasetjenere som MySQL, PostgreSQL og UnixODBC. I tillegg finnes støtte for flere system (som Oracle i den kommersielle QT-utgaven eller tredjepartsystem).
+Comment[nds]= Mit dissen Datenborntyp laat sik SQL-Datenbanken vun en SQL-Server bruken. Afhängig vun Dien Systeeminstellen warrt Datenbankplegers för MySQL, PostgresSQL un UnixODBC ünnerstütt. Villicht ok mehr (t.B. Oracle in en warflich Qt-Verschoon oder Plegers vun anner Anbeders).
+Comment[ne]=यो डेटासंसाधन प्रकारले तपाईंलाई एसक्यूएल सर्भरमा संग्रह भएको एसक्यूएल डाटाबेस प्रयोग गर्न दिन्छ ।तपाईंको प्रणाली कन्फिगरेसनमा, माइएसक्यूएल, पोस्टग्रेएसक्यूएल र युनीक्सओडीबीसी भर परेर जुन समर्थित डाटाबेस ब्याकेन्डहरू हुन् । त्यहाँ पक्कै पनि अझ बढी (व्यापारिक क्यूटी संस्करणहरू वा तेस्रो पार्टीको ब्याकेन्डमा आकाशवाणी हुन्छन्)
+Comment[nl]=Met dit type gegevensbron kunt u SQL-databasetabellen die zijn opgeslagen op een SQL-server gebruiken. Afhankelijk van uw systeemconfiguratie behoren MySQL, PostgreSQL en UnixOBC tot de ondersteunde backends. Er zijn er mogelijk meer (bijv. Oracle in de commerciële Qt-versies of backends van derden).
+Comment[nn]=Med denne datakjeldetypen kan du bruka SQL-databasetabellar lagra på ein SQL-tenar. Avhengig av systemoppsettet kan du bruka MySQL, PostgreSQL og UnixODBC. Det finst kanskje til og med fleire. (Oracle i kommersielle Qt-versjonar eller tredjepartstillegg.)
+Comment[pl]=To źródło danych pozwala na przechowywanie tabel w bazach danych na serwerze SQL. W zależności od konfiguracji systemu: MySQL, PostgreSQL oraz UnixODBC są obsługiwane. Oczywiście może ich być więcej, np. Oracle w komercyjnej wersji Qt lub poprzez rozszerzenia innych firm.
+Comment[pt]=Este tipo de fonte de dados permite-lhe usar as tabelas de base de dados armazenadas num servidor de SQL. Dependendo da configuração do seu sistema, o MySQL, o PostgreSQL e o UnixODBC encontram-se entre os sistemas suportados. Podem até existir mais (o Oracle nas versões comerciais do Qt ou mesmo sistemas de terceiros).
+Comment[pt_BR]=Esta fonte de dados deixa você usar as tabelas do banco de dados SQL em seu Servidor SQL. Dependendo da configuração do seu sistema, MySQL, PostgreSQL e Unix ODBC estão entre os bancos de dados suportados. Podem existir outros (o Oracle em versões comerciais da Qt).
+Comment[ro]=Acest tip de sursă de date vă permite să utilizaţi tabelele SQL dintr-o bază de date a unui server SQL. În funcţie de configuraţia sistemului dumneavoastră aveţi acces la subsistemul MySQL, PostgreSQL şi UnixODBC. S-ar putea să existe chiar şi mai multe(Oracle în versiunile comerciale Qt sau subsisteme terţe).
+Comment[ru]=Этот тип данных позволит вам использовать таблицы на сервере баз данных. В зависимости от наличия в системе поддерживаются MySQL, PostgreSQL и UnixODBC. Помимо этого могут быть доступны Oracle в коммерческом Qt и прочие драйвера к базам данным от сторонних производителей
+Comment[se]=Dáinna diehtogáldošlájain sáhtát geavahit SQL-diehtovuođuid SQL-bálvás. MySQL, PostgreSQL ja UnixODBC leat dorjojuvvon diehtovuođđoduogážat. Dáidá gávdnot vel eanet, omd. Oracle kommersiealla QT-veršuvnnain dahje eará moduvllain.
+Comment[sk]=Tento zdroj dát umožňuje používať databázové tabuľky SQL. Podporované databáze sú MySQL, PostgreSQL, UnixODBC. (Prípadne aj Oracle, ak máte licencovanú verziu Qt alebo databáze iných výrobcov),...
+Comment[sl]=Ta tip vira podatkov vam omogoča uporabo zbirke tabel SQL, ki so shranjene na strežniku SQL. Glede na vašo konfiguracijo sistema so podprte med drugim zbirke MySQL, PostgreSQL in UnixODBC. Mogoče bodo tudi druge (Oracle v komercialnih različicah Qt ali podpore tretjih strani).
+Comment[sr]=Овај тип извора података вам омогућава да користите табеле из SQL базе података која се налази на SQL серверу. У зависности од подешавања вашег рачунара, MySQL, PostgreSQL и UnixODBC се налазе међу подржаним приступима бази. Могуће је да постоје и додатни приступи (Oracle у комерцијалним Qt верзијама итд.)
+Comment[sr@Latn]=Ovaj tip izvora podataka vam omogućava da koristite tabele iz SQL baze podataka koja se nalazi na SQL serveru. U zavisnosti od podešavanja vašeg računara, MySQL, PostgreSQL i UnixODBC se nalaze među podržanim pristupima bazi. Moguće je da postoje i dodatni pristupi (Oracle u komercijalnim Qt verzijama itd.)
+Comment[sv]=Den här typen av datakälla låter dig använda SQL-databastabeller lagrade på en SQL-server. Beroende på systeminställningarna finns MySQL, Postgres och UnixODBC bland de databaser som stöds. Det kan till och med finnas ännu fler (Oracle, om du använder en licensierad version av QT eller tredjepartsdatabaser).
+Comment[tg]=Ин намуди манбаъи маълумот ба шумо имкони истифодаи SQL асоси маълумот мизҳои дар Сервери SQL ҷойгир шуда.Аз шакли системаи шумо вобастааст, MySQL,PostSQL ва UnixODBC дар мобайни асоси маълумот дар анҷом.Дар он ҷо мумкин,ки бошад(Oracle дар коммерсияи Qt тафсир ё 3-ум қисми анҷом).
+Comment[tr]=Bu verikaynağı tipi bir SQL sunucusundaki SQL veritabanı tablolarını kullanmanıza izin verir.Sistem ayarlarınıza bağlı olarak MySQL, PostgreSQL ve UnixODBC desteklenen veritabanları arasındadır. Daha fazlası da olabilir. (Ticari Qt sürümlerindeki Oracle veya 3. şahıs veritabanları)
+Comment[uk]=Цей тип джерела даних дозволяє вам використовувати таблиці баз даних в серверах SQL. Відповідно до конфігурації вашої системи, підтримуються MySQL, PostgreSQL та UnixODBC. Можливо підтримуються і інші сервери БД (Oracle в комерційній поставці Qt або сервери сторонніх компаній).
+Comment[xh]=Uhlobo lwe mvelaphi ye data ikuvumela ukuba usebenzise iitafile zesiseko sedata ze SQL ezigcinwe Kumncedisi we SQL.Kuxhomekeke kuqwalaselo lwendlela yokusebenza, I SQL yam, PostgreSQL ne UnixODBC zikunye neziphelo zesiseko sedata esixhasiweyo. Kusenokuba nezingaphezulu (I Oracle ekwi thengiso lwenguqulelo ye QT okanye iziphelo zomntu wesithathu).
+Comment[zh_CN]=此数据库类型允许您使用存储于 SQL 服务器的 SQL 数据库表。根据您的系统配置不同,MySQL、PostgreSQL 和 UnixODBC 都是支持的后端数据库。可能还有更多(Qt 商业版中附带 Oracle 支持,或使用第三方后端)。
+Comment[zh_TW]=這個資料來源類別讓你使用在一個 SQL 伺服器上面的 SQL 資料表格。根據你的系統設定,MySQL、PostgreSQL 與 UnixODBC 都在支援之列。還會有更多(例如在商業版本的 QT 或是第三廠商提供相關支援)。
+
+X-KDE-Library=kwmailmerge_qtsqldb
+X-KDE-Capabilities=edit,open
+X-KDE-InternalName=QtSqlEasy
+X-KDE-PluginVersion=1
diff --git a/kword/mailmerge/sql/kwserialletter_qtsqldb_power.desktop b/kword/mailmerge/sql/kwserialletter_qtsqldb_power.desktop
new file mode 100644
index 00000000..7f45df9b
--- /dev/null
+++ b/kword/mailmerge/sql/kwserialletter_qtsqldb_power.desktop
@@ -0,0 +1,107 @@
+[Desktop Entry]
+Type=Service
+ServiceTypes=KWord/MailMergePlugin
+
+Name=Qt-SQL Source (power user)
+Name[bg]=Източник Qt-SQL (за напреднали)
+Name[ca]=Font Qt-SQL (usuari expert)
+Name[cs]=Qt-SQL zdroj (pokročilé)
+Name[cy]=Ffynhonell Qt-SQL (defnyddiwr medrus)
+Name[da]=Qt-SQL-kilde (avanceret bruger)
+Name[de]=Qt-SQL (für fortgeschrittene Benutzer)
+Name[el]=Πηγή Qt-SQL (προχωρημένου χρήστη)
+Name[eo]=Qt-SQL-fonto (sperta uzanto)
+Name[es]=Fuente Qt-SQL (usuario avanzado)
+Name[et]=Qt-SQL allikas (nõudlikule kasutajale)
+Name[eu]=Qt-SQL iturburua (erabiltzaile aurreratua)
+Name[fa]=متن Qt-SQL )کاربر توان(
+Name[fi]=Qt-SQL-lähde (tehokäyttäjä)
+Name[fr]=Source Qt-SQL (utilisateur expérimenté)
+Name[fy]=QT-SQL-boarne (avansearre brûkers)
+Name[gl]=Fonte de Qt-SQL (administración)
+Name[he]=מקור של Qt-SQL (משתמש מיומן)
+Name[hi]=क्यूटी-एसक्यूएल स्रोत (बड़े उपयोक्ता)
+Name[hu]=Qt-SQL-forrás (kiemelt felhasználó)
+Name[is]=QT-SQL skrá (lengra komnir notendur)
+Name[it]=Fonte Qt-SQL (utente esperto)
+Name[ja]=Qt-SQL ソース (パワーユーザ)
+Name[km]=ប្រភព Qt-SQL (អ្នកប្រើ​មាន​អំណាច)
+Name[lv]=Qt-SQL avots (power lietotājs)
+Name[ms]=Sumber Qt-SQL (pengguna kuasa)
+Name[nb]=Qt-SQL kilde (sjefsbruker)
+Name[nds]=Qt-SQL-Born (för künnige Brukers)
+Name[ne]=Qt-SQL स्रोत (पावर प्रयोगकर्ता)
+Name[nl]=QT-SQL-bron (geavanceerde gebruiker)
+Name[nn]=Qt-SQL-kjelde (kraftbrukar)
+Name[pl]=Źródło Qt-SQL (dla zaawansowanych użytkowników)
+Name[pt]=Fonte do Qt-SQL (administração)
+Name[pt_BR]=Qt-SQL (usuário avançado)
+Name[ru]=Исходный текст Qt-SQL (продвинутый пользователь)
+Name[se]=Qt-SQL-gáldu (áhppegeavaheaddji)
+Name[sk]=Qt-SQL zdroj (power user)
+Name[sl]=Vir Qt-SQL (zahtevni uporabnik)
+Name[sr]=Qt-SQL извор (администратор)
+Name[sr@Latn]=Qt-SQL izvor (administrator)
+Name[sv]=Qt-SQL-källa (avancerade användare)
+Name[tg]=Манбаъи Qt-SQL (истифодакунандаи зӯр)
+Name[tr]=Qt-SQL Kaynağı (sistem yöneticisi)
+Name[uk]=Джерело Qt-SQL (досвідчений користувач)
+Name[zh_CN]=Qt-SQL 源(高级用户)
+Name[zh_TW]=Qt-SQL 來源 (超級使用者)
+Comment=This datasource type lets you use SQL database tables stored on a SQL Server. Depending on your system configuration, MySQL, PostgreSQL and UnixODBC are among the supported database backends. There might even be more (Oracle in commercial Qt versions or 3rd party backends).
+Comment[ar]=هذا النّوع من المصادر البيانيّة يتيح لك إمكانية استخدام جداول قاعدة بيانيّة SQL مُخَزَّنة على خادم SQL. بحسب تهيئة نظامك، فإنّ MySQL، PostgreSQL و UnixODBC تُعتبر من بين ما هو مدعوم من وُجهات خلفيّة للقواعد البيانيّة. يمكن حتى أن يتواجد المزيد (Oracle في إصدارات Qt التِّجاريّة أو الوُجهات الخلفيّة المملوكة لطرف ثالث).
+Comment[az]=Bu mənbə sizə SQL verilənlər bazasını istifadə etməyə imkan verir. Sistem qurğularınızdan asılı olaraq : MySQL,Postgres,(Oracle, lisenziyalı QT buraxılışını işlədirsinizsə),....
+Comment[bg]=Този източник на данни използва таблица за съхранение на данните в СУБД (сървър SQL). В зависимост от настройките, поддръжка имат MySQL, PostgreSQL и UnixODBC. Може да има и още (Oracle в комерсиалните версии на Qt или други).
+Comment[bs]=Ovaj tip izvora podataka vam omogućuje da koristiti SQL tabele smještene na SQL serveru. Ovisno o konfiguraciji vašeg sistema, MySQL, PostgreSQL i UnixODBC su među podržanim bazama podataka. Možda čak i više od toga (Oracle u komercijalnim verzijama Qt-a ili backendima iz trećeg izvora).
+Comment[ca]=Aquest tipus de font de dades permet usar una base de dades SQL guardada a un servidor SQL. Depenent de la configuració del sistema, MySQL, PostgreSQL i UnixODBC estan entre les bases de dades permeses. Inclús n'hi poden haver més(Oracle comercial a la versió Qt i d'altres servidors).
+Comment[cs]=Tento zdroj dat vám umožní požívat tabulky SQL databází uložených na SQL serveru. V závislosti na vašem nastavení systému jsou podporovány databázové systémy MySQL, PostgreSQL a UnixODBC (Oracle je podporována v komerční verzi Qt nebo v databázových systémech jiných výrobců).
+Comment[cy]=Mae'r math yma o ffynhonnell ddata yn eich galluogi i ddefnyddio tablau cronfa ddata SQL sydd wedi eu storio ar weinydd SQL. Yn dibynnu ar ffurfweddiad eich system, mae MySQL, PostgreSQL a UnixODBC ymysg y cronfeydd data cefndirol a gynhelir. Efallai bod mwy ohonynt (Oracle mewn fersiynau masnachol Qt neu ôl-wynebau 3ydd blaid).
+Comment[da]=Denne datakildetype lader dig bruge SQL-databasetabeller gemt på en SQL-server. Afhængig af dine systemindstillinger er MySQL, PostgreSQL og UnixODBC blandt de understøttede underliggende databaser. Der er måske endda flere (Oracle i kommercielle Qt-versioner eller underliggende programmer fra tredjepartsudviklere).
+Comment[de]= Mit diesem Datenquellentyp können Sie Tabellen von SQL-Datenbanken verwenden, die sich auf einem SQL-Server befinden. Abhängig von der Systemeinrichtung: MySQL, PostgresSQL oder UnixODBC. Möglicherweise sogar weitere (etwa Oracle bei einer kommerziellen QT-Version oder Paketen von Drittanbietern).
+Comment[el]=Αυτός ο τύπος πηγής δεδομένων σας επιτρέπει να χρησιμοποιείτε πίνακες βάσεων δεδομένων SQL αποθηκευμένες σε έναν εξυπηρετητή SQL. Ανάλογα με τη ρύθμιση του συστήματος σας, οι MySQL, PostgreSQL και UnixODBC είναι μέσα στις υποστηριζόμενες βάσεις δεδομένων. Μπορεί να υπάρχουν και περισσότερες (Η Oracle σε εμπορικές εκδόσεις της Qt ή άλλες τρίτων κατασκευαστών).
+Comment[eo]=Tiu datumfonta tipo permesas uzi SQL-datumbazan tabelon en SQL-servilo. Depende de la konfiguraĵo de via sistemo estas subtenataj MySQL, PostgreSQL kaj UnixODBC. Povas esti pliaj (Orakolo en komercaj Qt-versioj aŭ triapartiaj datumbazajinterfacoj).
+Comment[es]=Este tipo de fuente de datos le permite utilizar tablas de bases de datos almacenadas en un servidor SQL. Dependiendo de la configuración de su sistema, MySQL, PostgreSQL, y UnixODBC están entre los interfaces de bases de datos soportados. Puede que haya incluso más (Oracle, si utiliza una versión de QT con licencia o interfaces de terceras partes).
+Comment[et]=See andmeallika tüüp lubab kasutada SQL-andmebaasi tabeleid, mida hoitakse SQL-serveris. Sõltuvalt süsteemi seadistustest on MySQL, PostgreSQL ja UnixODBC toetatud andmebaasisüsteemide hulgas. Neid võib olla isegi rohkem (Oracle kommertslikes Qt versioonides või kolmandate osapoolte mootorites).
+Comment[eu]=Datu-iturburu honek SQL zerbitzari batean gordetako SQL datu-baseko taulak erabiltzeko aukera ematen dizu. Zure sistemaren konfigurazioaren arabera, MySQL, PostgreSQL eta UnixODBC euskarriak onartzen dira. Gehiago ere egon daitezke (Oracle (Qt-ren bertsio komertzialetan) edo hirugarrenen beste euskarri batzuk).
+Comment[fa]=این نوع متن داده به شما اجازۀ استفاده از جدولهای دادگان SQL ذخیره‌شده در یک کارساز SQL را می‌دهد. بسته به پیکربندی سیستمتان، MySQL، PostgreSQL و UnixODBC، در میان پایانه‌های دادگان پشتیبانی‌شده می‌باشند. حتی ممکن است بیشتر باشند )Oracle در نسخه‌های تجاری Qt یا پایانه‌های گروه 3rd(.
+Comment[fi]=Tämä tietolähde käyttää SQL-tietokantojen tauluja. Riippuen järjestelmäsi asetuksista tuetaan MySQL, Postgres ja UnixODBC -tietokantoja. Kantoja voi myös olla enemmän (Oracle, jos omistat kaupallisen version QT:sta).
+Comment[fr]=Ce type de source de données vous permet d'utiliser des tables de base de données SQL stockées sur un serveur SQL. Selon votre configuration, ces tables peuvent venir de MySQL, PostgreSQL et UnixODBC, et d'autres encore (comme Oracle, si vous avez la licence commerciale de Qt, par exemple).
+Comment[fy]=Mei dit type gegevensboarne kinne jo SQL-databanktabellen dy bewarre binne op in SQL-tsjinner brûke. Ofhinklik fan jo systeemkonfiguraasje hearre MySQL, PostgreSQL en UnixOBC ta de stipe backends. Der binne mooglik mear (bgl. Oracle yn de kommersje Qt-ferzjes fan backends fan tredden).
+Comment[gl]=Este tipo de fonte de datos permítelle usar as táboas de base de datos armacenadas nun servidor de SQL. Dependendo da configuración do seu sistema, MySQL, PostgreSQL e UnixODBC encóntranse entre os sistemas soportados. Poden até existir máis (Oracle nas versións comerciais de Qt ou mesmo sistemas de terceiros).
+Comment[he]=טיפוס מקור נתונים זה מאפשר לך להשתמש בטבלאות של מסדי נתונים של SQL שמאוחסנות בשרת SQL. בין ממשקי מסדי הנתונים הנתמכים ניתן למנות את MySQL ,PostgreSQL ו־UnixODBC (התמיכה תלויה בהגדרות המערכת שלך). עשויים להיות אף ממשקים נתמכים נוספים, כמו Oracle בגירסאות מסחריות של Qt או ממשקי צד שלישי.
+Comment[hu]=Ez az adatforrástípus SQL-kiszolgálón tárolt SQL táblák elérését teszi lehetővé. A rendszer konfigurációjától függően MySQL, PostgreSQL és UnixODBC adatbázistípust lehet választani. Ezeken felül még más is előfordulhat (pl. Oracle a Qt fizetős változatában).
+Comment[is]=Þessi tegund gerir þér kleyft að nota SQL gagnagrunnstöflur sem liggja á SQL þjóni. MySQL, PostgreSQL og UnixODBC eru meðal studdra gagnagrunnsbakenda, háð kerfisuppsetningu þinni. Það gætu jafnvel verið fleiri (Oracle í verslunarútgáfu Qt eða þriðja aðila bakendar).
+Comment[it]=Questa fonte di dati permette di usare le tabelle di banche dati SQL memorizzate in un server SQL. A seconda della configurazione del tuo sistema, MySQL, PostgreSQL e UnixODBC potrebbero essere alcune delle banche dati supportate. Potrebbero essere supportate anche altre banche dati (Oracle nelle versioni commerciali di Qt o moduli di terze parti).
+Comment[ja]=このデータソースタイプは SQL サーバに保存されている SQL データベーステーブルを使用します。システム設定によりますが、MySQL, PostgreSQL, UnixODBC がサポートされているデータベース バックエンドです。他のものも使用可能かもしれません (Qt の商用バージョンでの Oracle や、サードパーティのバックエンドなど)。
+Comment[km]=ប្រភេទ​ប្រភព​ទិន្នន័យ​នេះ​អនុញ្ញាត​ឲ្យ​អ្នក​ប្រើ​តារាង​មូលដ្ឋាន​ទិន្នន័យ SQL ដែល​បាន​រក្សា​លើ​ម៉ាស៊ីន​បម្រើ SQL ។ ការ​ពឹងផ្អែក​លើ​ការ​កំណត់​រចនា​សម្ព័ន្ធ​ប្រព័ន្ធ​របស់​អ្នក MySQL, PostgreSQL និង UnixODBC គឺ​ក្នុង​ចំណោម​មូលដ្ឋាន​ទិន្នន័យ​ខាងក្រោយ​ដែល​បាន​គាំទ្រ ។ ប្រហែល​ជា​មាន​ច្រើន (Oracle ក្នុង​កំណែ​ពាណិជ្ជកម្ម Qt ឬ ភាគី​ខាងក្រោយ​ទីបី) ។
+Comment[lt]=Šis duomenų šaltinio tipas leidžia jums naudoti SQL duombazės lenteles išsaugotas SQL serveryje. Priklausomai nuo jūsų sistemos konfigūracijos MySQL, PostgreSQL ir UnixODBC yra tarp palaikomų duombazių tipų. Jų gali būti ir daugiau (Oracle komercinėse Qt versijose ar trečių šalių duombazių tipai).
+Comment[lv]=Šis datu avota tips ļauj jums izmantot SQL datubāzes tabulas, kas glabājas uz SQL servera. Atkarībā no jūsu sistēmas konfigurācijas: MySQL,PostgreSQL un UnixODBC ir starp atbalstītajām datubāzēm. Šeit var būt arī vairāk (Oracle, ja jūs izmantojiet komerciālu QT versiju vai trešo pušu risinājumus).
+Comment[ms]=Jenis sumber data ini membenarkan anda menggunakan jadual pangkalan data SQL yang distor dalam Pelayan SQL. Bergantung kepada konfigurasi sistem anda, MySQL, PostgreSQL dan UnixODBC antara bahagian belakang pangkalan data yang disokong. Mungkin terdapat lebih banyak lagi pilihan (Oracle dalam versi Qt komersil atau bahagian belakang pihak ketiga).
+Comment[mt]=Dan it-tip ta' sors iħallik tuża tabelli minn databases SQL fuq server SQL. Skond il-konfigurazzjoni tas-sistema tiegħek, jista' jkollok MySQL, PostgreSQL jew UnixODBC bħala sistemi sapportiti, u jista' jkun hemm oħrajn (Oracle fuq verżjonijiet kummerċjali ta' Qt jew oħrajn ta' terzi partiti).
+Comment[nb]=Datakilden lar deg bruke en databasetabell lagret på en SQL-tjener. Avhengig av oppsettet støttes databasetjenere som MySQL, PostgreSQL og UnixODBC. I tillegg finnes støtte for flere system (som Oracle i den kommersielle QT-utgaven eller tredjepartsystem).
+Comment[nds]= Mit dissen Datenborntyp laat sik SQL-Datenbanken vun en SQL-Server bruken. Afhängig vun Dien Systeeminstellen warrt Datenbankplegers för MySQL, PostgresSQL un UnixODBC ünnerstütt. Villicht ok mehr (t.B. Oracle in en warflich Qt-Verschoon oder Plegers vun anner Anbeders).
+Comment[ne]=यो डेटासंसाधन प्रकारले तपाईंलाई एसक्यूएल सर्भरमा संग्रह भएको एसक्यूएल डाटाबेस प्रयोग गर्न दिन्छ ।तपाईंको प्रणाली कन्फिगरेसनमा, माइएसक्यूएल, पोस्टग्रेएसक्यूएल र युनीक्सओडीबीसी भर परेर जुन समर्थित डाटाबेस ब्याकेन्डहरू हुन् । त्यहाँ पक्कै पनि अझ बढी (व्यापारिक क्यूटी संस्करणहरू वा तेस्रो पार्टीको ब्याकेन्डमा आकाशवाणी हुन्छन्)
+Comment[nl]=Met dit type gegevensbron kunt u SQL-databasetabellen die zijn opgeslagen op een SQL-server gebruiken. Afhankelijk van uw systeemconfiguratie behoren MySQL, PostgreSQL en UnixOBC tot de ondersteunde backends. Er zijn er mogelijk meer (bijv. Oracle in de commerciële Qt-versies of backends van derden).
+Comment[nn]=Med denne datakjeldetypen kan du bruka SQL-databasetabellar lagra på ein SQL-tenar. Avhengig av systemoppsettet kan du bruka MySQL, PostgreSQL og UnixODBC. Det finst kanskje til og med fleire. (Oracle i kommersielle Qt-versjonar eller tredjepartstillegg.)
+Comment[pl]=To źródło danych pozwala na przechowywanie tabel w bazach danych na serwerze SQL. W zależności od konfiguracji systemu: MySQL, PostgreSQL oraz UnixODBC są obsługiwane. Oczywiście może ich być więcej, np. Oracle w komercyjnej wersji Qt lub poprzez rozszerzenia innych firm.
+Comment[pt]=Este tipo de fonte de dados permite-lhe usar as tabelas de base de dados armazenadas num servidor de SQL. Dependendo da configuração do seu sistema, o MySQL, o PostgreSQL e o UnixODBC encontram-se entre os sistemas suportados. Podem até existir mais (o Oracle nas versões comerciais do Qt ou mesmo sistemas de terceiros).
+Comment[pt_BR]=Esta fonte de dados deixa você usar as tabelas do banco de dados SQL em seu Servidor SQL. Dependendo da configuração do seu sistema, MySQL, PostgreSQL e Unix ODBC estão entre os bancos de dados suportados. Podem existir outros (o Oracle em versões comerciais da Qt).
+Comment[ro]=Acest tip de sursă de date vă permite să utilizaţi tabelele SQL dintr-o bază de date a unui server SQL. În funcţie de configuraţia sistemului dumneavoastră aveţi acces la subsistemul MySQL, PostgreSQL şi UnixODBC. S-ar putea să existe chiar şi mai multe(Oracle în versiunile comerciale Qt sau subsisteme terţe).
+Comment[ru]=Этот тип данных позволит вам использовать таблицы на сервере баз данных. В зависимости от наличия в системе поддерживаются MySQL, PostgreSQL и UnixODBC. Помимо этого могут быть доступны Oracle в коммерческом Qt и прочие драйвера к базам данным от сторонних производителей
+Comment[se]=Dáinna diehtogáldošlájain sáhtát geavahit SQL-diehtovuođuid SQL-bálvás. MySQL, PostgreSQL ja UnixODBC leat dorjojuvvon diehtovuođđoduogážat. Dáidá gávdnot vel eanet, omd. Oracle kommersiealla QT-veršuvnnain dahje eará moduvllain.
+Comment[sk]=Tento zdroj dát umožňuje používať databázové tabuľky SQL. Podporované databáze sú MySQL, PostgreSQL, UnixODBC. (Prípadne aj Oracle, ak máte licencovanú verziu Qt alebo databáze iných výrobcov),...
+Comment[sl]=Ta tip vira podatkov vam omogoča uporabo zbirke tabel SQL, ki so shranjene na strežniku SQL. Glede na vašo konfiguracijo sistema so podprte med drugim zbirke MySQL, PostgreSQL in UnixODBC. Mogoče bodo tudi druge (Oracle v komercialnih različicah Qt ali podpore tretjih strani).
+Comment[sr]=Овај тип извора података вам омогућава да користите табеле из SQL базе података која се налази на SQL серверу. У зависности од подешавања вашег рачунара, MySQL, PostgreSQL и UnixODBC се налазе међу подржаним приступима бази. Могуће је да постоје и додатни приступи (Oracle у комерцијалним Qt верзијама итд.)
+Comment[sr@Latn]=Ovaj tip izvora podataka vam omogućava da koristite tabele iz SQL baze podataka koja se nalazi na SQL serveru. U zavisnosti od podešavanja vašeg računara, MySQL, PostgreSQL i UnixODBC se nalaze među podržanim pristupima bazi. Moguće je da postoje i dodatni pristupi (Oracle u komercijalnim Qt verzijama itd.)
+Comment[sv]=Den här typen av datakälla låter dig använda SQL-databastabeller lagrade på en SQL-server. Beroende på systeminställningarna finns MySQL, Postgres och UnixODBC bland de databaser som stöds. Det kan till och med finnas ännu fler (Oracle, om du använder en licensierad version av QT eller tredjepartsdatabaser).
+Comment[tg]=Ин намуди манбаъи маълумот ба шумо имкони истифодаи SQL асоси маълумот мизҳои дар Сервери SQL ҷойгир шуда.Аз шакли системаи шумо вобастааст, MySQL,PostSQL ва UnixODBC дар мобайни асоси маълумот дар анҷом.Дар он ҷо мумкин,ки бошад(Oracle дар коммерсияи Qt тафсир ё 3-ум қисми анҷом).
+Comment[tr]=Bu verikaynağı tipi bir SQL sunucusundaki SQL veritabanı tablolarını kullanmanıza izin verir.Sistem ayarlarınıza bağlı olarak MySQL, PostgreSQL ve UnixODBC desteklenen veritabanları arasındadır. Daha fazlası da olabilir. (Ticari Qt sürümlerindeki Oracle veya 3. şahıs veritabanları)
+Comment[uk]=Цей тип джерела даних дозволяє вам використовувати таблиці баз даних в серверах SQL. Відповідно до конфігурації вашої системи, підтримуються MySQL, PostgreSQL та UnixODBC. Можливо підтримуються і інші сервери БД (Oracle в комерційній поставці Qt або сервери сторонніх компаній).
+Comment[xh]=Uhlobo lwe mvelaphi ye data ikuvumela ukuba usebenzise iitafile zesiseko sedata ze SQL ezigcinwe Kumncedisi we SQL.Kuxhomekeke kuqwalaselo lwendlela yokusebenza, I SQL yam, PostgreSQL ne UnixODBC zikunye neziphelo zesiseko sedata esixhasiweyo. Kusenokuba nezingaphezulu (I Oracle ekwi thengiso lwenguqulelo ye QT okanye iziphelo zomntu wesithathu).
+Comment[zh_CN]=此数据库类型允许您使用存储于 SQL 服务器的 SQL 数据库表。根据您的系统配置不同,MySQL、PostgreSQL 和 UnixODBC 都是支持的后端数据库。可能还有更多(Qt 商业版中附带 Oracle 支持,或使用第三方后端)。
+Comment[zh_TW]=這個資料來源類別讓你使用在一個 SQL 伺服器上面的 SQL 資料表格。根據你的系統設定,MySQL、PostgreSQL 與 UnixODBC 都在支援之列。還會有更多(例如在商業版本的 QT 或是第三廠商提供相關支援)。
+
+X-KDE-Library=kwmailmerge_qtsqldb_power
+X-KDE-Capabilities=edit,open
+X-KDE-InternalName=QtSqlPower
+X-KDE-PluginVersion=1
diff --git a/kword/mailmerge/sql/qtsqldatasourceeditor.ui b/kword/mailmerge/sql/qtsqldatasourceeditor.ui
new file mode 100644
index 00000000..d0ad9902
--- /dev/null
+++ b/kword/mailmerge/sql/qtsqldatasourceeditor.ui
@@ -0,0 +1,158 @@
+<!DOCTYPE UI><UI version="3.0" stdsetdef="1">
+<class>QtSqlDataSourceEditor</class>
+<widget class="QWidget">
+ <property name="name">
+ <cstring>QtSqlDataSourceEditor</cstring>
+ </property>
+ <property name="geometry">
+ <rect>
+ <x>0</x>
+ <y>0</y>
+ <width>493</width>
+ <height>270</height>
+ </rect>
+ </property>
+ <vbox>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <property name="margin">
+ <number>0</number>
+ </property>
+ <property name="spacing">
+ <number>6</number>
+ </property>
+ <widget class="QLayoutWidget">
+ <property name="name">
+ <cstring>Layout5</cstring>
+ </property>
+ <hbox>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <property name="margin">
+ <number>0</number>
+ </property>
+ <property name="spacing">
+ <number>6</number>
+ </property>
+ <widget class="QLabel">
+ <property name="name">
+ <cstring>TextLabel1</cstring>
+ </property>
+ <property name="text">
+ <string>&amp;Table:</string>
+ </property>
+ <property name="buddy" stdset="0">
+ <cstring>tableCombo</cstring>
+ </property>
+ </widget>
+ <widget class="QComboBox">
+ <property name="name">
+ <cstring>tableCombo</cstring>
+ </property>
+ </widget>
+ <widget class="QCheckBox">
+ <property name="name">
+ <cstring>filterCheckBox</cstring>
+ </property>
+ <property name="text">
+ <string>&amp;Filter output</string>
+ </property>
+ </widget>
+ <widget class="QPushButton">
+ <property name="name">
+ <cstring>editFilter</cstring>
+ </property>
+ <property name="text">
+ <string>View or Edit Filter &amp;Rules</string>
+ </property>
+ </widget>
+ <spacer>
+ <property name="name">
+ <cstring>Spacer1</cstring>
+ </property>
+ <property name="orientation">
+ <enum>Horizontal</enum>
+ </property>
+ <property name="sizeType">
+ <enum>Expanding</enum>
+ </property>
+ </spacer>
+ </hbox>
+ </widget>
+ <widget class="Line">
+ <property name="name">
+ <cstring>Line1</cstring>
+ </property>
+ <property name="frameShape">
+ <enum>HLine</enum>
+ </property>
+ <property name="frameShadow">
+ <enum>Sunken</enum>
+ </property>
+ <property name="orientation">
+ <enum>Horizontal</enum>
+ </property>
+ </widget>
+ <widget class="QLayoutWidget">
+ <property name="name">
+ <cstring>Layout6</cstring>
+ </property>
+ <hbox>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <property name="margin">
+ <number>0</number>
+ </property>
+ <property name="spacing">
+ <number>6</number>
+ </property>
+ <widget class="QLabel">
+ <property name="name">
+ <cstring>TextLabel2</cstring>
+ </property>
+ <property name="text">
+ <string>&amp;Used database records:</string>
+ </property>
+ <property name="buddy" stdset="0">
+ <cstring>DataTable</cstring>
+ </property>
+ </widget>
+ <spacer>
+ <property name="name">
+ <cstring>Spacer2</cstring>
+ </property>
+ <property name="orientation">
+ <enum>Horizontal</enum>
+ </property>
+ <property name="sizeType">
+ <enum>Expanding</enum>
+ </property>
+ </spacer>
+ </hbox>
+ </widget>
+ <widget class="QDataTable">
+ <property name="name">
+ <cstring>DataTable</cstring>
+ </property>
+ </widget>
+ </vbox>
+</widget>
+<connections>
+ <connection>
+ <sender>filterCheckBox</sender>
+ <signal>toggled(bool)</signal>
+ <receiver>QtSqlDataSourceEditor</receiver>
+ <slot>filterCheckBox_toggled(bool)</slot>
+ </connection>
+</connections>
+<includes>
+ <include location="local" impldecl="in implementation">qtsqldatasourceeditor.ui.h</include>
+</includes>
+<slots>
+ <slot>filterCheckBox_toggled( bool fcb_state )</slot>
+</slots>
+<layoutdefaults spacing="6" margin="11"/>
+</UI>
diff --git a/kword/mailmerge/sql/qtsqldatasourceeditor.ui.h b/kword/mailmerge/sql/qtsqldatasourceeditor.ui.h
new file mode 100644
index 00000000..23d90812
--- /dev/null
+++ b/kword/mailmerge/sql/qtsqldatasourceeditor.ui.h
@@ -0,0 +1,13 @@
+/****************************************************************************
+** ui.h extension file, included from the uic-generated form implementation.
+**
+** If you wish to add, delete or rename slots use Qt Designer which will
+** update this file, preserving your code. Create an init() slot in place of
+** a constructor, and a destroy() slot in place of a destructor.
+*****************************************************************************/
+
+
+void QtSqlDataSourceEditor::filterCheckBox_toggled( bool fcb_state )
+{
+ editFilter->setEnabled(fcb_state);
+}
diff --git a/kword/mailmerge/sql/qtsqlopenwidget.ui b/kword/mailmerge/sql/qtsqlopenwidget.ui
new file mode 100644
index 00000000..1b635131
--- /dev/null
+++ b/kword/mailmerge/sql/qtsqlopenwidget.ui
@@ -0,0 +1,301 @@
+<!DOCTYPE UI><UI version="3.0" stdsetdef="1">
+<class>KWQtSqlOpenWidget</class>
+<widget class="QWidget">
+ <property name="name">
+ <cstring>KWQtSqlOpenWidget</cstring>
+ </property>
+ <property name="geometry">
+ <rect>
+ <x>0</x>
+ <y>0</y>
+ <width>319</width>
+ <height>177</height>
+ </rect>
+ </property>
+ <vbox>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <property name="margin">
+ <number>0</number>
+ </property>
+ <property name="spacing">
+ <number>6</number>
+ </property>
+ <widget class="QLayoutWidget">
+ <property name="name">
+ <cstring>Layout10</cstring>
+ </property>
+ <hbox>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <property name="margin">
+ <number>0</number>
+ </property>
+ <property name="spacing">
+ <number>6</number>
+ </property>
+ <widget class="QComboBox">
+ <property name="name">
+ <cstring>savedProperties</cstring>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy>
+ <hsizetype>3</hsizetype>
+ <vsizetype>0</vsizetype>
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ </widget>
+ <widget class="KPushButton">
+ <property name="name">
+ <cstring>rememberButton</cstring>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy>
+ <hsizetype>5</hsizetype>
+ <vsizetype>5</vsizetype>
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="text">
+ <string>&amp;Keep Settings...</string>
+ </property>
+ </widget>
+ </hbox>
+ </widget>
+ <widget class="QGroupBox">
+ <property name="name">
+ <cstring>GroupBox1</cstring>
+ </property>
+ <property name="title">
+ <string></string>
+ </property>
+ <grid>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <property name="margin">
+ <number>11</number>
+ </property>
+ <property name="spacing">
+ <number>6</number>
+ </property>
+ <widget class="QLayoutWidget" row="0" column="0">
+ <property name="name">
+ <cstring>Layout8</cstring>
+ </property>
+ <hbox>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <property name="margin">
+ <number>0</number>
+ </property>
+ <property name="spacing">
+ <number>6</number>
+ </property>
+ <widget class="QLayoutWidget">
+ <property name="name">
+ <cstring>Layout7</cstring>
+ </property>
+ <vbox>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <property name="margin">
+ <number>0</number>
+ </property>
+ <property name="spacing">
+ <number>6</number>
+ </property>
+ <widget class="QLabel">
+ <property name="name">
+ <cstring>TextLabel1</cstring>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy>
+ <hsizetype>5</hsizetype>
+ <vsizetype>1</vsizetype>
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="text">
+ <string>&amp;Hostname:</string>
+ </property>
+ <property name="buddy" stdset="0">
+ <cstring>hostname</cstring>
+ </property>
+ </widget>
+ <widget class="QLabel">
+ <property name="name">
+ <cstring>TextLabel2_2</cstring>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy>
+ <hsizetype>5</hsizetype>
+ <vsizetype>1</vsizetype>
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="text">
+ <string>&amp;Driver:</string>
+ </property>
+ <property name="buddy" stdset="0">
+ <cstring>drivers</cstring>
+ </property>
+ </widget>
+ <widget class="QLabel">
+ <property name="name">
+ <cstring>TextLabel2</cstring>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy>
+ <hsizetype>5</hsizetype>
+ <vsizetype>1</vsizetype>
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="text">
+ <string>Database &amp;name:</string>
+ </property>
+ <property name="buddy" stdset="0">
+ <cstring>databasename</cstring>
+ </property>
+ </widget>
+ <widget class="QLabel">
+ <property name="name">
+ <cstring>TextLabel3</cstring>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy>
+ <hsizetype>5</hsizetype>
+ <vsizetype>1</vsizetype>
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="text">
+ <string>&amp;Username:</string>
+ </property>
+ <property name="buddy" stdset="0">
+ <cstring>username</cstring>
+ </property>
+ </widget>
+ <widget class="QLabel">
+ <property name="name">
+ <cstring>TextLabel4</cstring>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy>
+ <hsizetype>5</hsizetype>
+ <vsizetype>1</vsizetype>
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="text">
+ <string>&amp;Port:</string>
+ </property>
+ <property name="buddy" stdset="0">
+ <cstring>port</cstring>
+ </property>
+ </widget>
+ </vbox>
+ </widget>
+ <widget class="QLayoutWidget">
+ <property name="name">
+ <cstring>Layout6</cstring>
+ </property>
+ <vbox>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <property name="margin">
+ <number>0</number>
+ </property>
+ <property name="spacing">
+ <number>6</number>
+ </property>
+ <widget class="KLineEdit">
+ <property name="name">
+ <cstring>hostname</cstring>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy>
+ <hsizetype>5</hsizetype>
+ <vsizetype>5</vsizetype>
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ </widget>
+ <widget class="KComboBox">
+ <property name="name">
+ <cstring>drivers</cstring>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy>
+ <hsizetype>7</hsizetype>
+ <vsizetype>0</vsizetype>
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ </widget>
+ <widget class="KLineEdit">
+ <property name="name">
+ <cstring>databasename</cstring>
+ </property>
+ </widget>
+ <widget class="KLineEdit">
+ <property name="name">
+ <cstring>username</cstring>
+ </property>
+ </widget>
+ <widget class="KLineEdit">
+ <property name="name">
+ <cstring>port</cstring>
+ </property>
+ <property name="text">
+ <string>default</string>
+ </property>
+ </widget>
+ </vbox>
+ </widget>
+ </hbox>
+ </widget>
+ </grid>
+ </widget>
+ <spacer>
+ <property name="name" stdset="0">
+ <cstring>Spacer1</cstring>
+ </property>
+ <property name="orientation">
+ <enum>Vertical</enum>
+ </property>
+ <property name="sizeType">
+ <enum>Expanding</enum>
+ </property>
+ <property name="sizeHint">
+ <size>
+ <width>20</width>
+ <height>20</height>
+ </size>
+ </property>
+ </spacer>
+ </vbox>
+</widget>
+<includes>
+ <include location="global" impldecl="in declaration">klineedit.h</include>
+ <include location="global" impldecl="in declaration">kcombobox.h</include>
+ <include location="global" impldecl="in declaration">kpushbutton.h</include>
+</includes>
+<layoutdefaults spacing="6" margin="11"/>
+</UI>
diff --git a/kword/main.cpp b/kword/main.cpp
new file mode 100644
index 00000000..6f07e68a
--- /dev/null
+++ b/kword/main.cpp
@@ -0,0 +1,43 @@
+/* This file is part of the KDE project
+ Copyright (C) 1998, 1999 Reginald Stadlbauer <reggie@kde.org>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+*/
+
+#include <KoApplication.h>
+#include <kcmdlineargs.h>
+#include <dcopclient.h>
+#include "KWAboutData.h"
+
+static const KCmdLineOptions options[]=
+{
+ {"+[file]", I18N_NOOP("File to open"),0},
+ KCmdLineLastOption
+};
+
+extern "C" KWORD_EXPORT int kdemain( int argc, char **argv )
+{
+ KCmdLineArgs::init( argc, argv, newKWordAboutData());
+ KCmdLineArgs::addCmdLineOptions( options );
+
+ KoApplication app;
+
+ if (!app.start())
+ return 1;
+ app.exec();
+
+ return 0;
+}
diff --git a/kword/pics/Makefile.am b/kword/pics/Makefile.am
new file mode 100644
index 00000000..415e2b29
--- /dev/null
+++ b/kword/pics/Makefile.am
@@ -0,0 +1,3 @@
+
+KDE_ICON = kword
+
diff --git a/kword/pics/hi16-app-kword.png b/kword/pics/hi16-app-kword.png
new file mode 100644
index 00000000..af5f6292
--- /dev/null
+++ b/kword/pics/hi16-app-kword.png
Binary files differ
diff --git a/kword/pics/hi22-app-kword.png b/kword/pics/hi22-app-kword.png
new file mode 100644
index 00000000..2d4ccf2a
--- /dev/null
+++ b/kword/pics/hi22-app-kword.png
Binary files differ
diff --git a/kword/pics/hi32-app-kword.png b/kword/pics/hi32-app-kword.png
new file mode 100644
index 00000000..944e2687
--- /dev/null
+++ b/kword/pics/hi32-app-kword.png
Binary files differ
diff --git a/kword/pics/hi48-app-kword.png b/kword/pics/hi48-app-kword.png
new file mode 100644
index 00000000..66bf1ed6
--- /dev/null
+++ b/kword/pics/hi48-app-kword.png
Binary files differ
diff --git a/kword/stylenames.cpp b/kword/stylenames.cpp
new file mode 100644
index 00000000..2d04d0db
--- /dev/null
+++ b/kword/stylenames.cpp
@@ -0,0 +1,74 @@
+/* This file is part of the KDE project
+ Copyright (C) 2001 David Faure <faure@kde.org>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA
+*/
+
+// This file provides translations for the standard style names
+i18n( "Style name", "Standard" );
+i18n( "Style name", "Head 1" );
+i18n( "Style name", "Head 2" );
+i18n( "Style name", "Head 3" );
+i18n( "Style name", "Enumerated List" );
+i18n( "Style name", "Alphabetical List" );
+i18n( "Style name", "Bullet List" );
+i18n( "Style name", "Contents Title" );
+i18n( "Style name", "Contents Head 1" );
+i18n( "Style name", "Contents Head 2" );
+i18n( "Style name", "Contents Head 3" );
+i18n( "Style name", "Document Title" );
+i18n( "Style name", "Header" );
+i18n( "Style name", "Footer" );
+
+// Translations for the standard framestyle names
+i18n( "Style name", "Plain" );
+i18n( "Style name", "Borders 1" );
+i18n( "Style name", "Borders 2" );
+i18n( "Style name", "Borders 3" );
+i18n( "Style name", "Row" );
+i18n( "Style name", "Column" );
+i18n( "Style name", "Light Gray" );
+i18n( "Style name", "Dark Gray" );
+i18n( "Style name", "Black" );
+i18n( "Style name", "Light Blue" );
+i18n( "Style name", "Dark Blue" );
+i18n( "Style name", "Red" );
+i18n( "Style name", "Yellow" );
+i18n( "Style name", "Colorful" );
+i18n( "Style name", "Bluish" );
+
+// Translations for the standard tablestyle names
+i18n( "Style name", "Simple 1" );
+i18n( "Style name", "Simple 2" );
+i18n( "Style name", "Simple 3" );
+i18n( "Style name", "Header 1" );
+i18n( "Style name", "Header 2" );
+i18n( "Style name", "Header 3" );
+i18n( "Style name", "Header 4" );
+
+// Translations for the standard tabletemplate names
+i18n( "Style name", "Columns 1" );
+i18n( "Style name", "Columns 2" );
+i18n( "Style name", "Grid 1" );
+i18n( "Style name", "Grid 2" );
+i18n( "Style name", "Grid 3" );
+i18n( "Style name", "Gray Heading" );
+i18n( "Style name", "Blue Heading" );
+i18n( "Style name", "Blue Traditional" );
+i18n( "Style name", "Gray Traditional" );
+i18n( "Style name", "Blue Top and Bottom" );
+i18n( "Style name", "Gray Top and Bottom" );
+
diff --git a/kword/templates/CardsAndLabels/.directory b/kword/templates/CardsAndLabels/.directory
new file mode 100644
index 00000000..0d98a813
--- /dev/null
+++ b/kword/templates/CardsAndLabels/.directory
@@ -0,0 +1,47 @@
+[Desktop Entry]
+Name=Cards and Labels
+Name[bg]=Карти и етикети
+Name[br]=Kartennoù ha skridennadoù
+Name[ca]=Targetes i etiquetes
+Name[cy]=Cardiau a Labeli
+Name[da]=Kort og etiketter
+Name[de]=Karten und Etiketten
+Name[el]=Κάρτες και ετικέτες
+Name[eo]=Kartoj kaj Etikedoj
+Name[es]=Tarjetas y etiquetas
+Name[et]=Kaardid ja sildid
+Name[fa]=کارتها و برچسبها
+Name[fr]=Cartes et labels
+Name[fy]=Kaarten en labels
+Name[gl]=Tarxetas e Etiquetas
+Name[he]=תוויות וכרטיסים
+Name[hi]=कार्ड तथा लेबल
+Name[hr]=Kartice i oznake
+Name[hu]=Kártyák és címkék
+Name[is]=Spjöld og merkimiðar
+Name[it]=Biglietti e etichette
+Name[ja]=カードとラベル
+Name[km]=កាត​ និង​ស្លាក​
+Name[nb]=Kort og merkelapper
+Name[nds]=Koorten un Opbackers
+Name[ne]=कार्ड र लेबुल
+Name[nl]=Kaarten en labels
+Name[pl]=Wizytówki i etykiety
+Name[pt]=Cartões e Etiquetas
+Name[pt_BR]=Cartões e Etiquetas
+Name[ru]=Визитки и этикетки
+Name[se]=Goarttat ja mearkunlihput
+Name[sk]=Vizitky a nálepky
+Name[sl]=Kartice in nalepke
+Name[sr]=Картице и етикете
+Name[sr@Latn]=Kartice i etikete
+Name[sv]=Kort och etiketter
+Name[ta]= அட்டை மற்றும் சிட்டைகள்
+Name[tg]=Варақаҳо ва Ёрлиқҳо
+Name[tr]=Kartlar ve Etiketler
+Name[uk]=Картки і клейкі наклейки
+Name[uz]=Guvohnoma va yorliqlar
+Name[uz@cyrillic]=Гувоҳнома ва ёрлиқлар
+Name[wa]=Cåtes eyet etiketes
+Name[zh_CN]=卡片和标签
+Name[zh_TW]=卡片與標籤
diff --git a/kword/templates/CardsAndLabels/BusinessCards10.desktop b/kword/templates/CardsAndLabels/BusinessCards10.desktop
new file mode 100644
index 00000000..7f7baf8c
--- /dev/null
+++ b/kword/templates/CardsAndLabels/BusinessCards10.desktop
@@ -0,0 +1,55 @@
+[Desktop Entry]
+Icon=template_businesscards10
+Name=Business Cards 10
+Name[ar]=بِطاقات تجاريّة 10
+Name[bg]=Визитки 10
+Name[ca]=Targetes comercials 10
+Name[cs]=Vizitky 10
+Name[cy]=Cardiau Busnes 10
+Name[da]=Forretningskort 10
+Name[de]=Visitenkarten (10)
+Name[el]=Κάρτες επιχειρήσεων 10
+Name[eo]=Ofickartoj 10
+Name[es]=Tarjetas comerciales 10
+Name[et]=Visiitkaardid 10
+Name[eu]=Bisita-txartelak 10
+Name[fa]=کارتهای تجاری ۱۰
+Name[fi]=10 käyntikorttia
+Name[fr]=Cartes d'affaires 10
+Name[fy]=Visitekaarten (10)
+Name[gl]=Tarxetas de Negocios 10
+Name[he]=כרטיסי ביקור 10
+Name[hi]=व्यापार कार्ड 10
+Name[hr]=Poslovne posjetnice 10
+Name[hu]=Névjegykártyák (10)
+Name[is]=Nafnspjöld 10
+Name[it]=Biglietti da vista 10
+Name[ja]=名刺 10
+Name[km]=នាមប័ណ្ណ ១០
+Name[lv]=10 vizītkartes
+Name[ms]=Kad Nama 10
+Name[nb]=Visittkort 10
+Name[nds]=Visietkoorten (10)
+Name[ne]=व्यवसाय कार्डहरू १०
+Name[nl]=Visitekaarten (10)
+Name[nn]=Visittkort 10
+Name[pl]=10 wizytówek biznesowych
+Name[pt]=Cartões de Negócios 10
+Name[pt_BR]=Cartões de Negócios 10
+Name[ru]=Визитки (10 шт.)
+Name[sk]=Vizitky 10
+Name[sl]=Poslovne vizitke 10
+Name[sr]=Пословне картице 10
+Name[sr@Latn]=Poslovne kartice 10
+Name[sv]=Visitkort 10
+Name[ta]=வியாபார அட்டை 10
+Name[tg]=Варақаҳои Бизнес 10
+Name[tr]=İş Kartları 10
+Name[uk]=Бізнес-картки 10
+Name[uz]=Oʻnta biznes yorliq
+Name[uz@cyrillic]=Ўнта бизнес ёрлиқ
+Name[zh_CN]=商务卡片 10
+Name[zh_TW]=商業名片 10
+Type=Link
+URL=.source/BusinessCards10.kwt
+X-KDE-Hidden=false
diff --git a/kword/templates/CardsAndLabels/BusinessCards10.kwt b/kword/templates/CardsAndLabels/BusinessCards10.kwt
new file mode 100644
index 00000000..aeb57a22
--- /dev/null
+++ b/kword/templates/CardsAndLabels/BusinessCards10.kwt
Binary files differ
diff --git a/kword/templates/CardsAndLabels/LabelsL16.desktop b/kword/templates/CardsAndLabels/LabelsL16.desktop
new file mode 100644
index 00000000..c3d50a1f
--- /dev/null
+++ b/kword/templates/CardsAndLabels/LabelsL16.desktop
@@ -0,0 +1,56 @@
+[Desktop Entry]
+Icon=template_labelsl16
+Name=Labels L16
+Name[ar]=يافِطات L16
+Name[bg]=Етикети L16
+Name[br]=Skridennadoù L16
+Name[ca]=Targetes L16
+Name[cs]=Štítky L16
+Name[cy]=Labeli L16
+Name[da]=Mærkater L16
+Name[de]=Etiketten (L16)
+Name[el]=Ετικέτες L16
+Name[eo]=Etikedoj L16
+Name[es]=Tarjetas L16
+Name[et]=Sildid L16
+Name[eu]=Etiketak L16
+Name[fa]=برچسبهای L16
+Name[fi]=16 etikettiä
+Name[fr]=Étiquettes L16
+Name[gl]=Etiquetas L16
+Name[he]=תוויות L16
+Name[hi]=लेबल्स एल16
+Name[hr]=Oznake L16
+Name[hu]=Címkék (L16)
+Name[is]=Merkimiðar L16
+Name[it]=Etichette L16
+Name[ja]=ラベル L16
+Name[km]=ស្លាក L16
+Name[ms]=Label L16
+Name[nb]=Merkelapper L16
+Name[nds]=Opbackers (L16)
+Name[ne]=लेबुलहरू L16
+Name[nl]=Etiketten (L16)
+Name[nn]=Etikettar L16
+Name[pl]=16 etykiet
+Name[pt]=Etiquetas L16
+Name[pt_BR]=Etiquetas L16
+Name[ru]=Этикетки L16
+Name[se]=Nammagilkorat L16
+Name[sk]=Nálepky L16
+Name[sl]=Nakepke L16
+Name[sr]=Налепнице L16
+Name[sr@Latn]=Nalepnice L16
+Name[sv]=Etiketter L16
+Name[ta]=சிட்டைகள் L16
+Name[tg]=Ёрлиқҳо L16
+Name[tr]=Etiketler L16
+Name[uk]=Надписи L16
+Name[uz]=Oʻn oltita yorliq
+Name[uz@cyrillic]=Ўн олтита ёрлиқ
+Name[wa]=Etiketes L16
+Name[zh_CN]=L16 标签
+Name[zh_TW]=標籤 L16
+Type=Link
+URL=.source/LabelsL16.kwt
+X-KDE-Hidden=false
diff --git a/kword/templates/CardsAndLabels/LabelsL16.kwt b/kword/templates/CardsAndLabels/LabelsL16.kwt
new file mode 100644
index 00000000..1f923bd1
--- /dev/null
+++ b/kword/templates/CardsAndLabels/LabelsL16.kwt
Binary files differ
diff --git a/kword/templates/CardsAndLabels/Makefile.am b/kword/templates/CardsAndLabels/Makefile.am
new file mode 100644
index 00000000..d64fdfb1
--- /dev/null
+++ b/kword/templates/CardsAndLabels/Makefile.am
@@ -0,0 +1,11 @@
+templatesubdir = CardsAndLabels
+
+templates_DATA = .directory BusinessCards10.desktop LabelsL16.desktop
+templatesdir = $(kde_datadir)/kword/templates/$(templatesubdir)
+
+templatesrc_DATA = BusinessCards10.kwt LabelsL16.kwt
+templatesrcdir = $(kde_datadir)/kword/templates/$(templatesubdir)/.source
+
+kworddir = $(kde_datadir)/kword/icons
+kword_ICON = AUTO
+
diff --git a/kword/templates/CardsAndLabels/cr48-action-template_businesscards10.png b/kword/templates/CardsAndLabels/cr48-action-template_businesscards10.png
new file mode 100644
index 00000000..c138cc79
--- /dev/null
+++ b/kword/templates/CardsAndLabels/cr48-action-template_businesscards10.png
Binary files differ
diff --git a/kword/templates/CardsAndLabels/cr48-action-template_labelsl16.png b/kword/templates/CardsAndLabels/cr48-action-template_labelsl16.png
new file mode 100644
index 00000000..658b57aa
--- /dev/null
+++ b/kword/templates/CardsAndLabels/cr48-action-template_labelsl16.png
Binary files differ
diff --git a/kword/templates/CardsAndLabels/crsc-action-template_businesscards10.svgz b/kword/templates/CardsAndLabels/crsc-action-template_businesscards10.svgz
new file mode 100644
index 00000000..47add8f2
--- /dev/null
+++ b/kword/templates/CardsAndLabels/crsc-action-template_businesscards10.svgz
Binary files differ
diff --git a/kword/templates/CardsAndLabels/crsc-action-template_labelsl16.svgz b/kword/templates/CardsAndLabels/crsc-action-template_labelsl16.svgz
new file mode 100644
index 00000000..2a0a654e
--- /dev/null
+++ b/kword/templates/CardsAndLabels/crsc-action-template_labelsl16.svgz
Binary files differ
diff --git a/kword/templates/Envelopes/.directory b/kword/templates/Envelopes/.directory
new file mode 100644
index 00000000..50cda17d
--- /dev/null
+++ b/kword/templates/Envelopes/.directory
@@ -0,0 +1,48 @@
+[Desktop Entry]
+Name=Envelopes
+Name[ar]=أظرفة
+Name[bg]=Пликове
+Name[br]=Goloioù
+Name[ca]=Sobres
+Name[cy]=Amlenni
+Name[da]=Konvolutter
+Name[de]=Umschläge
+Name[el]=Φάκελοι
+Name[eo]=Kovertoj
+Name[es]=Sobres
+Name[et]=Ümbrikud
+Name[fa]=پاکتها
+Name[fr]=Enveloppes
+Name[fy]=Enveloppen
+Name[ga]=Clúdaigh
+Name[gl]=Sobres
+Name[hi]=लिफ़ाफ़े
+Name[hr]=Omotnice
+Name[hu]=Borítékok
+Name[is]=Umslög
+Name[it]=Buste
+Name[ja]=封筒
+Name[km]=ស្រោម​សំបុត្រ​
+Name[lt]=Vokai
+Name[lv]=Aploksnes
+Name[nb]=Konvolutter
+Name[nds]=Ümslääg
+Name[ne]=खामहरू
+Name[nl]=Enveloppen
+Name[pl]=Koperty
+Name[ru]=Конверты
+Name[se]=Konfaluhtat
+Name[sk]=Obálky
+Name[sl]=Ovojnice
+Name[sr]=Коверти
+Name[sr@Latn]=Koverti
+Name[sv]=Kuvert
+Name[ta]=மேலுரைகள்
+Name[tg]=Конвертҳо
+Name[tr]=Zarflar
+Name[uk]=Конверти
+Name[uz]=Konvertlar
+Name[uz@cyrillic]=Конвертлар
+Name[wa]=Ewalpeures
+Name[zh_CN]=信封
+Name[zh_TW]=信封
diff --git a/kword/templates/Envelopes/EnvelopeC6.desktop b/kword/templates/Envelopes/EnvelopeC6.desktop
new file mode 100644
index 00000000..a523293b
--- /dev/null
+++ b/kword/templates/Envelopes/EnvelopeC6.desktop
@@ -0,0 +1,57 @@
+[Desktop Entry]
+Icon=template_envelopec6
+Name=Envelope C6
+Name[ar]=ظَرف C6
+Name[bg]=Плик C6
+Name[br]=Golo C6
+Name[ca]=Sobre C6
+Name[cs]=Obálka C6
+Name[cy]=Amlen C6
+Name[da]=Konvolut C6
+Name[de]=Umschlag C6
+Name[el]=Φάκελος C6
+Name[eo]=Koverto C6
+Name[es]=Sobre C6
+Name[et]=Ümbrik C6
+Name[eu]=C6 gutun-azala
+Name[fa]=پاکت C6
+Name[fi]=Kirjekuori C6
+Name[fr]=Enveloppe C6
+Name[fy]=Envelop C6
+Name[ga]=Clúdach C6
+Name[gl]=Sobre C6
+Name[hi]=लिफ़ाफ़ा सी6
+Name[hr]=Omotnica C6
+Name[hu]=Boríték (C6)
+Name[is]=Umslög C6
+Name[it]=Busta C6
+Name[ja]=封筒 C6
+Name[km]=ស្រោម​សំបុត្រ​ C6
+Name[lt]=Vokas C6
+Name[lv]=C6 aploksne
+Name[ms]=Sampul C6
+Name[nb]=Konvolutt C6
+Name[nds]=Ümslag C6
+Name[ne]=खाम C6
+Name[nl]=Envelop C6
+Name[nn]=Konvolutt C6
+Name[pl]=Koperta C6
+Name[ru]=Конверт C6
+Name[se]=Konfaluhtta C6
+Name[sk]=Obálka C6
+Name[sl]=Ovojnica C6
+Name[sr]=Коверат Ц6
+Name[sr@Latn]=Koverat C6
+Name[sv]=Kuvert C6
+Name[ta]=மேலுரைC6
+Name[tg]=Конверти C6
+Name[tr]=Zarf C6
+Name[uk]=Конверт C6
+Name[uz]=Konvert C6 (114 × 162 mm)
+Name[uz@cyrillic]=Конверт C6 (114 × 162 мм)
+Name[wa]=Ewalpeure C6
+Name[zh_CN]=C6 信封
+Name[zh_TW]=信封 C6
+Type=Link
+URL=.source/EnvelopeC6.kwt
+X-KDE-Hidden=false
diff --git a/kword/templates/Envelopes/EnvelopeC6.kwt b/kword/templates/Envelopes/EnvelopeC6.kwt
new file mode 100644
index 00000000..9af33890
--- /dev/null
+++ b/kword/templates/Envelopes/EnvelopeC6.kwt
@@ -0,0 +1,250 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE DOC PUBLIC "-//KDE//DTD kword 1.2//EN" "http://www.koffice.org/DTD/kword-1.2.dtd">
+<DOC xmlns="http://www.koffice.org/DTD/kword" mime="application/x-kword" syntaxVersion="2" editor="KWord" >
+ <PAPER width="459.213" spFootNoteBody="10.0063" spHeadBody="8.98584" format="6" slFootNoteWidth="2" height="323.15" fType="0" slFootNoteLength="20" orientation="1" hType="0" columnspacing="3.00473" pages="2" spFootBody="8.98584" columns="1" >
+ <PAPERBORDERS right="14.1733" left="14.1733" bottom="14.1733" top="14.1733" />
+ </PAPER>
+ <ATTRIBUTES hasTOC="0" standardpage="1" hasFooter="0" unit="mm" hasHeader="0" processing="0" tabStopValue="42.5198" />
+ <VARIABLESETTINGS displayfieldcode="0" displaylink="1" displaycomment="1" underlinelink="1" />
+ <FOOTNOTESETTING type="0" depth="0" />
+ <ENDNOTESETTING type="0" depth="0" />
+ <FRAMESETS>
+ <FRAMESET frameType="1" frameInfo="0" protectSize="0" name="Text Frameset 1" visible="1" >
+ <FRAME bRed="0" rRed="0" tGreen="0" bGreen="0" runaround="1" copy="0" rBlue="0" rGreen="0" bBlue="0" right="445.04014106" newFrameBehavior="0" tBlue="0" lRed="0" runaroundSide="biggest" left="14.1732529" lGreen="0" bottom="308.97691322" lBlue="0" runaroundGap="2" top="14.1732529" tRed="0" />
+ <FRAME bRed="0" rRed="0" tGreen="0" bGreen="0" runaround="1" copy="0" rBlue="0" rGreen="0" bBlue="0" right="445.04014106" newFrameBehavior="0" tBlue="0" lRed="0" runaroundSide="biggest" left="14.1732529" lGreen="0" bottom="632.12707934" lBlue="0" runaroundGap="2" top="337.32341902" tRed="0" />
+ <PARAGRAPH>
+ <TEXT xml:space="preserve" > </TEXT>
+ <LAYOUT>
+ <NAME value="Standard" />
+ <FORMAT id="1" pos="0" len="1" >
+ <WEIGHT value="50" />
+ <COLOR blue="-1" red="-1" green="-1" />
+ <SIZE value="8" />
+ <ITALIC value="0" />
+ <VERTALIGN value="0" />
+ <TEXTBACKGROUNDCOLOR blue="-1" red="-1" green="-1" />
+ </FORMAT>
+ </LAYOUT>
+ </PARAGRAPH>
+ </FRAMESET>
+ <FRAMESET frameType="1" frameInfo="0" protectSize="0" name="Box 1" visible="1" >
+ <FRAME bRed="0" bkBlue="255" rRed="0" tGreen="0" bGreen="0" runaround="1" copy="0" bkRed="255" rBlue="0" rGreen="0" bBlue="0" right="318.89819025" newFrameBehavior="1" tBlue="0" lRed="0" runaroundSide="biggest" left="300.47296148" bkStyle="1" lGreen="0" bkGreen="255" bottom="262.20517865" lBlue="0" runaroundGap="2.83465" top="235.27599814" autoCreateNewFrame="2" tRed="0" />
+ <PARAGRAPH>
+ <TEXT xml:space="preserve" > </TEXT>
+ <LAYOUT>
+ <NAME value="Standard" />
+ <FLOW align="center" />
+ <OFFSETS before="5.6693" />
+ <FORMAT id="1" pos="0" len="1" >
+ <WEIGHT value="50" />
+ <COLOR blue="-1" red="-1" green="-1" />
+ <SIZE value="14" />
+ <ITALIC value="0" />
+ <VERTALIGN value="0" />
+ <TEXTBACKGROUNDCOLOR blue="-1" red="-1" green="-1" />
+ </FORMAT>
+ </LAYOUT>
+ </PARAGRAPH>
+ </FRAMESET>
+ <FRAMESET frameType="1" frameInfo="0" protectSize="0" name="Box 2" visible="1" >
+ <FRAME bRed="0" bkBlue="255" rRed="0" tGreen="0" bGreen="0" runaround="1" copy="0" bkRed="255" rBlue="0" rGreen="0" bBlue="0" right="345.82737076" newFrameBehavior="1" tBlue="0" lRed="0" runaroundSide="biggest" left="327.40214199" bkStyle="1" lGreen="0" bkGreen="255" bottom="262.20517865" lBlue="0" runaroundGap="2.83465" top="235.27599814" autoCreateNewFrame="2" tRed="0" />
+ <PARAGRAPH>
+ <TEXT xml:space="preserve" > </TEXT>
+ <LAYOUT>
+ <NAME value="Standard" />
+ <FLOW align="center" />
+ <OFFSETS before="5.6693" />
+ <FORMAT id="1" pos="0" len="1" >
+ <WEIGHT value="50" />
+ <COLOR blue="-1" red="-1" green="-1" />
+ <SIZE value="14" />
+ <ITALIC value="0" />
+ <VERTALIGN value="0" />
+ <TEXTBACKGROUNDCOLOR blue="-1" red="-1" green="-1" />
+ </FORMAT>
+ </LAYOUT>
+ </PARAGRAPH>
+ </FRAMESET>
+ <FRAMESET frameType="1" frameInfo="0" protectSize="0" name="Box 3" visible="1" >
+ <FRAME bRed="0" bkBlue="255" rRed="0" tGreen="0" bGreen="0" runaround="1" copy="0" bkRed="255" rBlue="0" rGreen="0" bBlue="0" right="372.75655127" newFrameBehavior="1" tBlue="0" lRed="0" runaroundSide="biggest" left="354.3313225" bkStyle="1" lGreen="0" bkGreen="255" bottom="262.20517865" lBlue="0" runaroundGap="2.83465" top="235.27599814" autoCreateNewFrame="2" tRed="0" />
+ <PARAGRAPH>
+ <TEXT xml:space="preserve" > </TEXT>
+ <LAYOUT>
+ <NAME value="Standard" />
+ <FLOW align="center" />
+ <OFFSETS before="5.6693" />
+ <FORMAT id="1" pos="0" len="1" >
+ <WEIGHT value="50" />
+ <COLOR blue="-1" red="-1" green="-1" />
+ <SIZE value="14" />
+ <ITALIC value="0" />
+ <VERTALIGN value="0" />
+ <TEXTBACKGROUNDCOLOR blue="-1" red="-1" green="-1" />
+ </FORMAT>
+ </LAYOUT>
+ </PARAGRAPH>
+ </FRAMESET>
+ <FRAMESET frameType="1" frameInfo="0" protectSize="0" name="Box 4" visible="1" >
+ <FRAME bRed="0" bkBlue="255" rRed="0" tGreen="0" bGreen="0" runaround="1" copy="0" bkRed="255" rBlue="0" rGreen="0" bBlue="0" right="399.68573178" newFrameBehavior="1" tBlue="0" lRed="0" runaroundSide="biggest" left="381.26050301" bkStyle="1" lGreen="0" bkGreen="255" bottom="262.20517865" lBlue="0" runaroundGap="2.83465" top="235.27599814" autoCreateNewFrame="2" tRed="0" />
+ <PARAGRAPH>
+ <TEXT xml:space="preserve" > </TEXT>
+ <LAYOUT>
+ <NAME value="Standard" />
+ <FLOW align="center" />
+ <OFFSETS before="5.6693" />
+ <FORMAT id="1" pos="0" len="1" >
+ <WEIGHT value="50" />
+ <COLOR blue="-1" red="-1" green="-1" />
+ <SIZE value="14" />
+ <ITALIC value="0" />
+ <VERTALIGN value="0" />
+ <TEXTBACKGROUNDCOLOR blue="-1" red="-1" green="-1" />
+ </FORMAT>
+ </LAYOUT>
+ </PARAGRAPH>
+ </FRAMESET>
+ <FRAMESET frameType="1" frameInfo="0" protectSize="0" name="Main Text Frameset" visible="1" >
+ <FRAME bkBlue="255" runaround="1" copy="0" bkRed="255" right="399.9975433438" newFrameBehavior="1" runaroundSide="biggest" left="69.9875228202" bkStyle="1" bkGreen="255" bottom="230.0035480612" runaroundGap="2.83465" top="100.0064724624" autoCreateNewFrame="2" />
+ <PARAGRAPH>
+ <TEXT xml:space="preserve" > </TEXT>
+ <LAYOUT>
+ <NAME value="Standard" />
+ <FORMAT id="1" pos="0" len="1" >
+ <WEIGHT value="50" />
+ <COLOR blue="-1" red="-1" green="-1" />
+ <SIZE value="14" />
+ <ITALIC value="0" />
+ <VERTALIGN value="0" />
+ <TEXTBACKGROUNDCOLOR blue="-1" red="-1" green="-1" />
+ </FORMAT>
+ </LAYOUT>
+ </PARAGRAPH>
+ </FRAMESET>
+ </FRAMESETS>
+ <STYLES>
+ <STYLE>
+ <NAME value="Standard" />
+ <FLOW align="auto" />
+ <FOLLOWING name="Standard" />
+ <FORMAT id="1" >
+ <WEIGHT value="50" />
+ <COLOR blue="-1" red="-1" green="-1" />
+ <SIZE value="-1" />
+ <ITALIC value="0" />
+ <VERTALIGN value="0" />
+ <TEXTBACKGROUNDCOLOR blue="-1" red="-1" green="-1" />
+ </FORMAT>
+ </STYLE>
+ <STYLE>
+ <NAME value="Document Title" />
+ <FLOW align="center" />
+ <FOLLOWING name="Standard" />
+ <FORMAT id="1" >
+ <WEIGHT value="75" />
+ <COLOR blue="-1" red="-1" green="-1" />
+ <SIZE value="24" />
+ <ITALIC value="0" />
+ <VERTALIGN value="0" />
+ <TEXTBACKGROUNDCOLOR blue="-1" red="-1" green="-1" />
+ </FORMAT>
+ </STYLE>
+ <STYLE>
+ <NAME value="Head 1" />
+ <FLOW align="auto" />
+ <COUNTER numberingtype="1" righttext="." type="1" depth="0" />
+ <FOLLOWING name="Standard" />
+ <FORMAT id="1" >
+ <WEIGHT value="75" />
+ <COLOR blue="-1" red="-1" green="-1" />
+ <SIZE value="20" />
+ <ITALIC value="0" />
+ <VERTALIGN value="0" />
+ <TEXTBACKGROUNDCOLOR blue="-1" red="-1" green="-1" />
+ </FORMAT>
+ </STYLE>
+ <STYLE>
+ <NAME value="Head 2" />
+ <FLOW align="auto" />
+ <COUNTER numberingtype="1" righttext="." type="1" depth="1" />
+ <FOLLOWING name="Standard" />
+ <FORMAT id="1" >
+ <WEIGHT value="75" />
+ <COLOR blue="-1" red="-1" green="-1" />
+ <SIZE value="16" />
+ <ITALIC value="0" />
+ <VERTALIGN value="0" />
+ <TEXTBACKGROUNDCOLOR blue="-1" red="-1" green="-1" />
+ </FORMAT>
+ </STYLE>
+ <STYLE>
+ <NAME value="Head 3" />
+ <FLOW align="auto" />
+ <COUNTER numberingtype="1" righttext="." type="1" depth="2" />
+ <FOLLOWING name="Standard" />
+ <FORMAT id="1" >
+ <WEIGHT value="75" />
+ <COLOR blue="-1" red="-1" green="-1" />
+ <SIZE value="12" />
+ <ITALIC value="0" />
+ <VERTALIGN value="0" />
+ <TEXTBACKGROUNDCOLOR blue="-1" red="-1" green="-1" />
+ </FORMAT>
+ </STYLE>
+ <STYLE>
+ <NAME value="Enumerated List" />
+ <FLOW align="auto" />
+ <COUNTER numberingtype="0" righttext="." type="1" depth="0" />
+ <FOLLOWING name="Enumerated List" />
+ <FORMAT id="1" >
+ <WEIGHT value="50" />
+ <COLOR blue="-1" red="-1" green="-1" />
+ <SIZE value="-1" />
+ <ITALIC value="0" />
+ <VERTALIGN value="0" />
+ <TEXTBACKGROUNDCOLOR blue="-1" red="-1" green="-1" />
+ </FORMAT>
+ </STYLE>
+ <STYLE>
+ <NAME value="Alphabetical List" />
+ <FLOW align="auto" />
+ <COUNTER numberingtype="0" righttext=")" type="2" depth="0" />
+ <FOLLOWING name="Alphabetical List" />
+ <FORMAT id="1" >
+ <WEIGHT value="50" />
+ <COLOR blue="-1" red="-1" green="-1" />
+ <SIZE value="-1" />
+ <ITALIC value="0" />
+ <VERTALIGN value="0" />
+ <TEXTBACKGROUNDCOLOR blue="-1" red="-1" green="-1" />
+ </FORMAT>
+ </STYLE>
+ <STYLE>
+ <NAME value="Bullet List" />
+ <FLOW align="auto" />
+ <COUNTER numberingtype="0" type="10" depth="0" />
+ <FOLLOWING name="Bullet List" />
+ <FORMAT id="1" >
+ <WEIGHT value="50" />
+ <COLOR blue="-1" red="-1" green="-1" />
+ <SIZE value="-1" />
+ <ITALIC value="0" />
+ <VERTALIGN value="0" />
+ <TEXTBACKGROUNDCOLOR blue="-1" red="-1" green="-1" />
+ </FORMAT>
+ </STYLE>
+ </STYLES>
+ <FRAMESTYLES>
+ <FRAMESTYLE blue="255" red="255" green="255" >
+ <NAME value="Plain" />
+ </FRAMESTYLE>
+ </FRAMESTYLES>
+ <TABLESTYLES>
+ <TABLESTYLE>
+ <NAME value="Plain" />
+ <PFRAMESTYLE name="Plain" />
+ <PSTYLE name="Standard" />
+ </TABLESTYLE>
+ </TABLESTYLES>
+ <PICTURES/>
+ <MAILMERGE/>
+</DOC>
diff --git a/kword/templates/Envelopes/EnvelopeDL.desktop b/kword/templates/Envelopes/EnvelopeDL.desktop
new file mode 100644
index 00000000..a99d9f40
--- /dev/null
+++ b/kword/templates/Envelopes/EnvelopeDL.desktop
@@ -0,0 +1,57 @@
+[Desktop Entry]
+Icon=template_envelopedl
+Name=Envelope DL
+Name[ar]=ظَرف DL
+Name[bg]=Плик DL
+Name[br]=Golo DL
+Name[ca]=Sobre DL
+Name[cs]=Obálka DL
+Name[cy]=Amlen DL
+Name[da]=Konvolut DL
+Name[de]=Umschlag DL
+Name[el]=Φάκελος DL
+Name[eo]=Koverto DL
+Name[es]=Sobre DL
+Name[et]=Ümbrik DL
+Name[eu]=DL gutun-azala
+Name[fa]=پاکت DL
+Name[fi]=Kirjekuori DL
+Name[fr]=Enveloppe DL
+Name[fy]=Envelop DL
+Name[ga]=Clúdach DL
+Name[gl]=Sobre DL
+Name[hi]=लिफ़ाफ़ा डीएल
+Name[hr]=Omotnica DL
+Name[hu]=Boríték (DL)
+Name[is]=Umslög DL
+Name[it]=Busta DL
+Name[ja]=封筒 DL
+Name[km]=ស្រោម​សំបុត្រ​ DL
+Name[lt]=Vokas DL
+Name[lv]=DL aploksne
+Name[ms]=Sampul DL
+Name[nb]=Konvolutt DL
+Name[nds]=Ümslag DL
+Name[ne]=खाम DL
+Name[nl]=Envelop DL
+Name[nn]=Konvolutt DL
+Name[pl]=Koperta DL
+Name[ru]=Конверт DL
+Name[se]=Konfaluhtta DL
+Name[sk]=Obálka DL
+Name[sl]=Ovojnica DL
+Name[sr]=Коверат ДЛ
+Name[sr@Latn]=Koverat DL
+Name[sv]=Kuvert DL
+Name[ta]=மேலுரை DL
+Name[tg]=Конверти DL
+Name[tr]=Zarf DL
+Name[uk]=Конверт DL
+Name[uz]=Konvert DL (110 × 220 mm)
+Name[uz@cyrillic]=Конверт DL (110 × 220 мм)
+Name[wa]=Ewalpeure DL
+Name[zh_CN]=DL 信封
+Name[zh_TW]=信封 DL
+Type=Link
+URL=.source/EnvelopeDL.kwt
+X-KDE-Hidden=false
diff --git a/kword/templates/Envelopes/EnvelopeDL.kwt b/kword/templates/Envelopes/EnvelopeDL.kwt
new file mode 100644
index 00000000..8761a49b
--- /dev/null
+++ b/kword/templates/Envelopes/EnvelopeDL.kwt
@@ -0,0 +1,267 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE DOC PUBLIC "-//KDE//DTD kword 1.2//EN" "http://www.koffice.org/DTD/kword-1.2.dtd">
+<DOC xmlns="http://www.koffice.org/DTD/kword" mime="application/x-kword" syntaxVersion="2" editor="KWord" >
+ <PAPER width="623.623" spFootNoteBody="10.0063" spHeadBody="8.98584" format="6" slFootNoteWidth="2" height="311.812" fType="0" slFootNoteLength="20" orientation="1" hType="0" columnspacing="3.00473" pages="2" spFootBody="8.98584" columns="1" >
+ <PAPERBORDERS right="14.1733" left="14.1733" bottom="14.1733" top="14.1733" />
+ </PAPER>
+ <ATTRIBUTES hasTOC="0" standardpage="1" hasFooter="0" unit="mm" hasHeader="0" cursorIndex="0" processing="0" tabStopValue="42.5198" activeFrameset="Text Frameset 5" cursorParagraph="0" />
+ <VARIABLESETTINGS displayfieldcode="0" displaylink="1" displaycomment="1" underlinelink="1" />
+ <FOOTNOTESETTING type="0" depth="0" />
+ <ENDNOTESETTING type="0" depth="0" />
+ <FRAMESETS>
+ <FRAMESET frameType="1" frameInfo="0" protectSize="0" name="Text Frameset 1" visible="1" >
+ <FRAME bRed="0" rRed="0" tGreen="0" bGreen="0" runaround="1" copy="0" rBlue="0" rGreen="0" bBlue="0" right="609.4498747" newFrameBehavior="0" tBlue="0" lRed="0" runaroundSide="biggest" left="14.1732529" lGreen="0" bottom="297.6383109" lBlue="0" runaroundGap="2" top="14.1732529" tRed="0" />
+ <FRAME bRed="0" rRed="0" tGreen="0" bGreen="0" runaround="1" copy="0" rBlue="0" rGreen="0" bBlue="0" right="609.4498747" newFrameBehavior="0" tBlue="0" lRed="0" runaroundSide="biggest" left="14.1732529" lGreen="0" bottom="609.4498747" lBlue="0" runaroundGap="2" top="325.9848167" tRed="0" />
+ <PARAGRAPH>
+ <TEXT xml:space="preserve" > </TEXT>
+ <LAYOUT>
+ <NAME value="Standard" />
+ <FORMAT id="1" pos="0" len="1" >
+ <WEIGHT value="50" />
+ <COLOR blue="-1" red="-1" green="-1" />
+ <SIZE value="8" />
+ <ITALIC value="0" />
+ <VERTALIGN value="0" />
+ <TEXTBACKGROUNDCOLOR blue="-1" red="-1" green="-1" />
+ </FORMAT>
+ </LAYOUT>
+ </PARAGRAPH>
+ </FRAMESET>
+ <FRAMESET frameType="1" frameInfo="0" protectSize="0" name="Text Frameset 2" visible="1" >
+ <FRAME bRed="0" bkBlue="255" rRed="0" tGreen="0" bGreen="0" runaround="1" copy="0" bkRed="255" rBlue="0" rGreen="0" bBlue="0" right="479.05594802" newFrameBehavior="1" tBlue="0" lRed="0" runaroundSide="biggest" left="460.63071925" bkStyle="1" lGreen="0" bkGreen="255" bottom="250.86657633" lBlue="0" runaroundGap="2.83465" top="223.93739582" autoCreateNewFrame="2" tRed="0" />
+ <PARAGRAPH>
+ <TEXT xml:space="preserve" > </TEXT>
+ <LAYOUT>
+ <NAME value="Standard" />
+ <FLOW align="center" />
+ <OFFSETS before="5.6693" />
+ <FORMAT id="1" pos="0" len="1" >
+ <WEIGHT value="50" />
+ <COLOR blue="-1" red="-1" green="-1" />
+ <SIZE value="14" />
+ <ITALIC value="0" />
+ <VERTALIGN value="0" />
+ <TEXTBACKGROUNDCOLOR blue="-1" red="-1" green="-1" />
+ </FORMAT>
+ </LAYOUT>
+ </PARAGRAPH>
+ </FRAMESET>
+ <FRAMESET frameType="1" frameInfo="0" protectSize="0" name="Copy-Text Frameset 2" visible="1" >
+ <FRAME bRed="0" bkBlue="255" rRed="0" tGreen="0" bGreen="0" runaround="1" copy="0" bkRed="255" rBlue="0" rGreen="0" bBlue="0" right="507.40245382" newFrameBehavior="1" tBlue="0" lRed="0" runaroundSide="biggest" left="488.97722505" bkStyle="1" lGreen="0" bkGreen="255" bottom="250.86657633" lBlue="0" runaroundGap="2.83465" top="223.93739582" autoCreateNewFrame="2" tRed="0" />
+ <PARAGRAPH>
+ <TEXT xml:space="preserve" > </TEXT>
+ <LAYOUT>
+ <NAME value="Standard" />
+ <FLOW align="center" />
+ <OFFSETS before="5.6693" />
+ <FORMAT id="1" pos="0" len="1" >
+ <WEIGHT value="50" />
+ <COLOR blue="-1" red="-1" green="-1" />
+ <SIZE value="14" />
+ <ITALIC value="0" />
+ <VERTALIGN value="0" />
+ <TEXTBACKGROUNDCOLOR blue="-1" red="-1" green="-1" />
+ </FORMAT>
+ </LAYOUT>
+ </PARAGRAPH>
+ </FRAMESET>
+ <FRAMESET frameType="1" frameInfo="0" protectSize="0" name="Copy1-Text Frameset 2" visible="1" >
+ <FRAME bRed="0" bkBlue="255" rRed="0" tGreen="0" bGreen="0" runaround="1" copy="0" bkRed="255" rBlue="0" rGreen="0" bBlue="0" right="535.74895962" newFrameBehavior="1" tBlue="0" lRed="0" runaroundSide="biggest" left="517.32373085" bkStyle="1" lGreen="0" bkGreen="255" bottom="250.86657633" lBlue="0" runaroundGap="2.83465" top="223.93739582" autoCreateNewFrame="2" tRed="0" />
+ <PARAGRAPH>
+ <TEXT xml:space="preserve" > </TEXT>
+ <LAYOUT>
+ <NAME value="Standard" />
+ <FLOW align="center" />
+ <OFFSETS before="5.6693" />
+ <FORMAT id="1" pos="0" len="1" >
+ <WEIGHT value="50" />
+ <COLOR blue="-1" red="-1" green="-1" />
+ <SIZE value="14" />
+ <ITALIC value="0" />
+ <VERTALIGN value="0" />
+ <TEXTBACKGROUNDCOLOR blue="-1" red="-1" green="-1" />
+ </FORMAT>
+ </LAYOUT>
+ </PARAGRAPH>
+ </FRAMESET>
+ <FRAMESET frameType="1" frameInfo="0" protectSize="0" name="Text Frameset 3" visible="1" >
+ <FRAME bRed="0" bkBlue="255" rRed="0" tGreen="0" bGreen="0" runaround="1" copy="0" bkRed="255" rBlue="0" rGreen="0" bBlue="0" right="564.09546542" newFrameBehavior="1" tBlue="0" lRed="0" runaroundSide="biggest" left="545.67023665" bkStyle="1" lGreen="0" bkGreen="255" bottom="250.86657633" lBlue="0" runaroundGap="2.83465" top="223.93739582" autoCreateNewFrame="2" tRed="0" />
+ <PARAGRAPH>
+ <TEXT xml:space="preserve" > </TEXT>
+ <LAYOUT>
+ <NAME value="Standard" />
+ <FLOW align="center" />
+ <OFFSETS before="5.6693" />
+ <FORMAT id="1" pos="0" len="1" >
+ <WEIGHT value="50" />
+ <COLOR blue="-1" red="-1" green="-1" />
+ <SIZE value="14" />
+ <ITALIC value="0" />
+ <VERTALIGN value="0" />
+ <TEXTBACKGROUNDCOLOR blue="-1" red="-1" green="-1" />
+ </FORMAT>
+ </LAYOUT>
+ </PARAGRAPH>
+ </FRAMESET>
+ <FRAMESET frameType="1" frameInfo="0" protectSize="0" name="Text Frameset 5" visible="1" >
+ <FRAME bkBlue="255" runaround="1" copy="0" bkRed="255" right="552.7568631" newFrameBehavior="1" runaroundSide="biggest" left="70.8662645" bkStyle="1" bkGreen="255" bottom="215.0365929988" runaroundGap="2.83465" top="85.0395174" autoCreateNewFrame="2" />
+ <PARAGRAPH>
+ <TEXT xml:space="preserve" > </TEXT>
+ <LAYOUT>
+ <NAME value="Standard" />
+ <FORMAT id="1" pos="0" len="1" >
+ <WEIGHT value="50" />
+ <COLOR blue="-1" red="-1" green="-1" />
+ <SIZE value="14" />
+ <ITALIC value="0" />
+ <VERTALIGN value="0" />
+ <TEXTBACKGROUNDCOLOR blue="-1" red="-1" green="-1" />
+ </FORMAT>
+ </LAYOUT>
+ </PARAGRAPH>
+ </FRAMESET>
+ <FRAMESET frameType="1" frameInfo="0" protectSize="0" name="Text Frameset 6" visible="1" >
+ <FRAME bkBlue="255" runaround="1" copy="0" bkRed="255" right="566.930116" newFrameBehavior="1" runaroundSide="biggest" left="56.6930116" bkStyle="1" bkGreen="255" bottom="399.68573178" runaroundGap="2.83465" top="337.32341902" autoCreateNewFrame="2" />
+ <PARAGRAPH>
+ <TEXT xml:space="preserve" > </TEXT>
+ <LAYOUT>
+ <NAME value="Standard" />
+ <FORMAT id="1" pos="0" len="1" >
+ <WEIGHT value="50" />
+ <COLOR blue="-1" red="-1" green="-1" />
+ <SIZE value="-1" />
+ <ITALIC value="0" />
+ <VERTALIGN value="0" />
+ <TEXTBACKGROUNDCOLOR blue="-1" red="-1" green="-1" />
+ </FORMAT>
+ </LAYOUT>
+ </PARAGRAPH>
+ </FRAMESET>
+ </FRAMESETS>
+ <STYLES>
+ <STYLE>
+ <NAME value="Standard" />
+ <FLOW align="auto" />
+ <FOLLOWING name="Standard" />
+ <FORMAT id="1" >
+ <WEIGHT value="50" />
+ <COLOR blue="-1" red="-1" green="-1" />
+ <SIZE value="-1" />
+ <ITALIC value="0" />
+ <VERTALIGN value="0" />
+ <TEXTBACKGROUNDCOLOR blue="-1" red="-1" green="-1" />
+ </FORMAT>
+ </STYLE>
+ <STYLE>
+ <NAME value="Document Title" />
+ <FLOW align="center" />
+ <FOLLOWING name="Standard" />
+ <FORMAT id="1" >
+ <WEIGHT value="75" />
+ <COLOR blue="-1" red="-1" green="-1" />
+ <SIZE value="24" />
+ <ITALIC value="0" />
+ <VERTALIGN value="0" />
+ <TEXTBACKGROUNDCOLOR blue="-1" red="-1" green="-1" />
+ </FORMAT>
+ </STYLE>
+ <STYLE>
+ <NAME value="Head 1" />
+ <FLOW align="auto" />
+ <COUNTER numberingtype="1" righttext="." type="1" depth="0" />
+ <FOLLOWING name="Standard" />
+ <FORMAT id="1" >
+ <WEIGHT value="75" />
+ <COLOR blue="-1" red="-1" green="-1" />
+ <SIZE value="20" />
+ <ITALIC value="0" />
+ <VERTALIGN value="0" />
+ <TEXTBACKGROUNDCOLOR blue="-1" red="-1" green="-1" />
+ </FORMAT>
+ </STYLE>
+ <STYLE>
+ <NAME value="Head 2" />
+ <FLOW align="auto" />
+ <COUNTER numberingtype="1" righttext="." type="1" depth="1" />
+ <FOLLOWING name="Standard" />
+ <FORMAT id="1" >
+ <WEIGHT value="75" />
+ <COLOR blue="-1" red="-1" green="-1" />
+ <SIZE value="16" />
+ <ITALIC value="0" />
+ <VERTALIGN value="0" />
+ <TEXTBACKGROUNDCOLOR blue="-1" red="-1" green="-1" />
+ </FORMAT>
+ </STYLE>
+ <STYLE>
+ <NAME value="Head 3" />
+ <FLOW align="auto" />
+ <COUNTER numberingtype="1" righttext="." type="1" depth="2" />
+ <FOLLOWING name="Standard" />
+ <FORMAT id="1" >
+ <WEIGHT value="75" />
+ <COLOR blue="-1" red="-1" green="-1" />
+ <SIZE value="12" />
+ <ITALIC value="0" />
+ <VERTALIGN value="0" />
+ <TEXTBACKGROUNDCOLOR blue="-1" red="-1" green="-1" />
+ </FORMAT>
+ </STYLE>
+ <STYLE>
+ <NAME value="Enumerated List" />
+ <FLOW align="auto" />
+ <COUNTER numberingtype="0" righttext="." type="1" depth="0" />
+ <FOLLOWING name="Enumerated List" />
+ <FORMAT id="1" >
+ <WEIGHT value="50" />
+ <COLOR blue="-1" red="-1" green="-1" />
+ <SIZE value="-1" />
+ <ITALIC value="0" />
+ <VERTALIGN value="0" />
+ <TEXTBACKGROUNDCOLOR blue="-1" red="-1" green="-1" />
+ </FORMAT>
+ </STYLE>
+ <STYLE>
+ <NAME value="Alphabetical List" />
+ <FLOW align="auto" />
+ <COUNTER numberingtype="0" righttext=")" type="2" depth="0" />
+ <FOLLOWING name="Alphabetical List" />
+ <FORMAT id="1" >
+ <WEIGHT value="50" />
+ <COLOR blue="-1" red="-1" green="-1" />
+ <SIZE value="-1" />
+ <ITALIC value="0" />
+ <VERTALIGN value="0" />
+ <TEXTBACKGROUNDCOLOR blue="-1" red="-1" green="-1" />
+ </FORMAT>
+ </STYLE>
+ <STYLE>
+ <NAME value="Bullet List" />
+ <FLOW align="auto" />
+ <COUNTER numberingtype="0" type="10" depth="0" />
+ <FOLLOWING name="Bullet List" />
+ <FORMAT id="1" >
+ <WEIGHT value="50" />
+ <COLOR blue="-1" red="-1" green="-1" />
+ <SIZE value="-1" />
+ <ITALIC value="0" />
+ <VERTALIGN value="0" />
+ <TEXTBACKGROUNDCOLOR blue="-1" red="-1" green="-1" />
+ </FORMAT>
+ </STYLE>
+ </STYLES>
+ <FRAMESTYLES>
+ <FRAMESTYLE blue="255" red="255" green="255" >
+ <NAME value="Plain" />
+ </FRAMESTYLE>
+ </FRAMESTYLES>
+ <TABLESTYLES>
+ <TABLESTYLE>
+ <NAME value="Plain" />
+ <PFRAMESTYLE name="Plain" />
+ <PSTYLE name="Standard" />
+ </TABLESTYLE>
+ </TABLESTYLES>
+ <PICTURES/>
+ <MAILMERGE/>
+</DOC>
diff --git a/kword/templates/Envelopes/Makefile.am b/kword/templates/Envelopes/Makefile.am
new file mode 100644
index 00000000..0f1cd4e9
--- /dev/null
+++ b/kword/templates/Envelopes/Makefile.am
@@ -0,0 +1,11 @@
+templatesubdir = Envelopes
+
+templates_DATA = .directory EnvelopeC6.desktop EnvelopeDL.desktop
+templatesdir = $(kde_datadir)/kword/templates/$(templatesubdir)
+
+templatesrc_DATA = EnvelopeC6.kwt EnvelopeDL.kwt
+templatesrcdir = $(kde_datadir)/kword/templates/$(templatesubdir)/.source
+
+kworddir = $(kde_datadir)/kword/icons
+kword_ICON = AUTO
+
diff --git a/kword/templates/Envelopes/cr48-action-template_envelopec6.png b/kword/templates/Envelopes/cr48-action-template_envelopec6.png
new file mode 100644
index 00000000..3357c813
--- /dev/null
+++ b/kword/templates/Envelopes/cr48-action-template_envelopec6.png
Binary files differ
diff --git a/kword/templates/Envelopes/cr48-action-template_envelopedl.png b/kword/templates/Envelopes/cr48-action-template_envelopedl.png
new file mode 100644
index 00000000..128d7786
--- /dev/null
+++ b/kword/templates/Envelopes/cr48-action-template_envelopedl.png
Binary files differ
diff --git a/kword/templates/Envelopes/crsc-action-template_envelopec6.svgz b/kword/templates/Envelopes/crsc-action-template_envelopec6.svgz
new file mode 100644
index 00000000..c4b8a57f
--- /dev/null
+++ b/kword/templates/Envelopes/crsc-action-template_envelopec6.svgz
Binary files differ
diff --git a/kword/templates/Envelopes/crsc-action-template_envelopedl.svgz b/kword/templates/Envelopes/crsc-action-template_envelopedl.svgz
new file mode 100644
index 00000000..54e046a9
--- /dev/null
+++ b/kword/templates/Envelopes/crsc-action-template_envelopedl.svgz
Binary files differ
diff --git a/kword/templates/Makefile.am b/kword/templates/Makefile.am
new file mode 100644
index 00000000..c4ebea1b
--- /dev/null
+++ b/kword/templates/Makefile.am
@@ -0,0 +1 @@
+SUBDIRS = Wordprocessing Envelopes CardsAndLabels
diff --git a/kword/templates/Wordprocessing/.directory b/kword/templates/Wordprocessing/.directory
new file mode 100644
index 00000000..7911ed6a
--- /dev/null
+++ b/kword/templates/Wordprocessing/.directory
@@ -0,0 +1,46 @@
+[Desktop Entry]
+Name=Blank Document
+Name[bg]=Празен документ
+Name[br]=Teul goullo
+Name[ca]=Document buit
+Name[da]=Blankt dokument
+Name[de]=Leeres Dokument
+Name[el]=Κενό έγγραφο
+Name[eo]=Malplena dokumento
+Name[es]=Documento vacío
+Name[et]=Tühi dokument
+Name[fa]=سند خالی
+Name[fr]=Document vide
+Name[fy]=Leech dokumint
+Name[ga]=Cáipéis Fholamh
+Name[gl]=Documento Valeiro
+Name[he]=מסמך ריק
+Name[hr]=Prazan dokument
+Name[hu]=Üres dokumentum
+Name[is]=Tómt skjal
+Name[it]=Documento vuoto
+Name[ja]=空のドキュメント
+Name[km]=ឯកសារ​ទទេ​
+Name[lt]=Tuščias dokumentas
+Name[lv]=Tukšs dokuments
+Name[nb]=Tomt dokument
+Name[nds]=Leddid Dokment
+Name[ne]=खाली कागजात
+Name[nl]=Leeg document
+Name[pl]=Pusty dokument
+Name[pt]=Documento Vazio
+Name[pt_BR]=Documento em Branco
+Name[ru]=Чистый лист
+Name[se]=Guorus dokumeanta
+Name[sk]=Prázdny dokument
+Name[sl]=Prazen dokument
+Name[sr]=Празан документ
+Name[sr@Latn]=Prazan dokument
+Name[sv]=Tomt dokument
+Name[uk]=Порожній документ
+Name[uz]=Boʻsh hujjat
+Name[uz@cyrillic]=Бўш ҳужжат
+Name[zh_CN]=空文档
+Name[zh_TW]=空白文件
+X-KDE-DefaultTab=true
+X-KDE-SortingWeight=10
diff --git a/kword/templates/Wordprocessing/A4.desktop b/kword/templates/Wordprocessing/A4.desktop
new file mode 100644
index 00000000..cadcfcfc
--- /dev/null
+++ b/kword/templates/Wordprocessing/A4.desktop
@@ -0,0 +1,85 @@
+[Desktop Entry]
+Type=Link
+URL=.source/A4.kwt
+Name=Blank Document
+Name[bg]=Празен документ
+Name[br]=Teul goullo
+Name[ca]=Document buit
+Name[da]=Blankt dokument
+Name[de]=Leeres Dokument
+Name[el]=Κενό έγγραφο
+Name[eo]=Malplena dokumento
+Name[es]=Documento vacío
+Name[et]=Tühi dokument
+Name[fa]=سند خالی
+Name[fr]=Document vide
+Name[fy]=Leech dokumint
+Name[ga]=Cáipéis Fholamh
+Name[gl]=Documento Valeiro
+Name[he]=מסמך ריק
+Name[hr]=Prazan dokument
+Name[hu]=Üres dokumentum
+Name[is]=Tómt skjal
+Name[it]=Documento vuoto
+Name[ja]=空のドキュメント
+Name[km]=ឯកសារ​ទទេ​
+Name[lt]=Tuščias dokumentas
+Name[lv]=Tukšs dokuments
+Name[nb]=Tomt dokument
+Name[nds]=Leddid Dokment
+Name[ne]=खाली कागजात
+Name[nl]=Leeg document
+Name[pl]=Pusty dokument
+Name[pt]=Documento Vazio
+Name[pt_BR]=Documento em Branco
+Name[ru]=Чистый лист
+Name[se]=Guorus dokumeanta
+Name[sk]=Prázdny dokument
+Name[sl]=Prazen dokument
+Name[sr]=Празан документ
+Name[sr@Latn]=Prazan dokument
+Name[sv]=Tomt dokument
+Name[uk]=Порожній документ
+Name[uz]=Boʻsh hujjat
+Name[uz@cyrillic]=Бўш ҳужжат
+Name[zh_CN]=空文档
+Name[zh_TW]=空白文件
+Comment=Creates a blank A4 document, with a small page margin.
+Comment[bg]=Създаване на документ във формат A4 с две колони на страница.
+Comment[ca]=Crea un document A4 amb un petit marge de pàgina.
+Comment[da]=Opretter et blankt A4-dokument med en lille sidemargen.
+Comment[de]=Erstellt ein leeres A4-Dokument mit einem schmalen Seitenrand
+Comment[el]=Δημιουργεί ένα έγγραφο A4, με μικρό περιθώριο σελίδας.
+Comment[es]=Crea un documento A4 vacío, con un pequeño margen de página.
+Comment[et]=Loob tühja A4 dokumendi väikese veerisega.
+Comment[fa]=یک سند خالی A4 با یک حاشیۀ کوچک صفحه ایجاد می‌کند.
+Comment[fr]=Crée un document A4 vide avec une petite marge
+Comment[fy]=Makket in leech A4-documint oan mei in lytse sidemmarzje.
+Comment[gl]=Cría un documento A4 en branco, cunha pequena marxe na páxina.
+Comment[hu]=Létrehoz egy üres A4-es dokumentumot, keskeny margóval
+Comment[is]=Býr til tómt A4 skjal með litlum spássíum.
+Comment[it]=Crea un documento A4 vuoto, con un piccolo margine di pagina.
+Comment[ja]=余白の少ない A4 サイズの空のドキュメントを作成
+Comment[km]=បង្កើត​ឯកសារ A4 ទទេ ដែល​មាន​រឹម​ទំព័រ​តូច ។
+Comment[lv]=Izveido tukšu A4 dokumentu ar mazām lapas maliņām.
+Comment[nb]=Lager et tomt A4 dokument med en liten sidemarg.
+Comment[nds]=Stellt en leddig A4-Dokment mit en smallen Rand op.
+Comment[ne]=सानो पृष्ठ सीमा सहित, खाली A4 कागजात सिर्जना गर्दछ ।
+Comment[nl]=Maakt een leeg A4-document aan met een kleine paginamarge.
+Comment[pl]=Tworzy pusty dokument formatu A4 z małym marginesem strony.
+Comment[pt]=Cria um documento A4 em branco, com uma pequena margem na página.
+Comment[pt_BR]=Cria um documento A4 em branco, com uma pequena margem na página.
+Comment[ru]=Пустой документ формата A4 с двумя колонками
+Comment[se]=Ráhkada guorus A4-dokumeanta mas lea siekkes siidoravda.
+Comment[sk]=Vytvorí prázdny dokument A4 s malými okrajmi.
+Comment[sl]=Ustvari dokument A4 z malo praznega prostora ob robovih
+Comment[sr]=Прави празан A4 документ са малом маргином стране.
+Comment[sr@Latn]=Pravi prazan A4 dokument sa malom marginom strane.
+Comment[sv]=Skapar ett tomt A4-dokument med liten sidmarginal.
+Comment[uk]=Створює порожній документ A4 з малими полями.
+Comment[uz]=Boʻsh A4 hujjatini yaratish.
+Comment[uz@cyrillic]=Бўш A4 ҳужжатини яратиш.
+Comment[zh_CN]=创建带有小页边距的空 A4 文档。
+Comment[zh_TW]=建立一個每頁兩欄的 A4 文件。
+Icon=template_a4
+X-KDE-MeasureSystem=metric
diff --git a/kword/templates/Wordprocessing/A4.kwt b/kword/templates/Wordprocessing/A4.kwt
new file mode 100644
index 00000000..bd540dab
--- /dev/null
+++ b/kword/templates/Wordprocessing/A4.kwt
@@ -0,0 +1,84 @@
+<?xml version="1.0" encoding="UTF-8"?><!DOCTYPE DOC ><DOC mime="application/x-kword" syntaxVersion="3" editor="KWord" >
+ <PAPER width="595.277" zoom="100" spHeadBody="9" format="1" height="841.891" fType="0" orientation="0" hType="0" columnspacing="2" spFootBody="9" columns="1" >
+ <PAPERBORDERS right="57" left="57" bottom="42" top="42" />
+ </PAPER>
+ <ATTRIBUTES standardpage="1" hasFooter="0" unit="mm" hasHeader="0" processing="0" />
+ <FRAMESETS>
+ <FRAMESET removable="0" frameType="1" frameInfo="0" visible="1" >
+ <FRAME runaround="1" right="566" left="28" bottom="798" runaroundGap="2" top="42" />
+ </FRAMESET>
+ </FRAMESETS>
+ <STYLES>
+ <STYLE>
+ <NAME value="Standard" />
+ <FOLLOWING name="Standard" />
+ <FORMAT id="1">
+ <!-- Use KDE settings for the font -->
+ </FORMAT>
+ </STYLE>
+ <STYLE>
+ <NAME value="Document Title" />
+ <FLOW align="center" />
+ <FOLLOWING name="Standard" />
+ <FORMAT id="1" >
+ <!-- Use KDE settings for the font family -->
+ <WEIGHT value="75" />
+ <SIZE value="24" />
+ </FORMAT>
+ </STYLE>
+ <STYLE outline="true">
+ <NAME value="Head 1" />
+ <COUNTER numberingtype="1" righttext="." type="1" start="1" depth="0" display-levels="1"/>
+ <FOLLOWING name="Standard" />
+ <FORMAT id="1">
+ <!-- Use KDE settings for the font family -->
+ <SIZE value="20" />
+ <WEIGHT value="75" />
+ </FORMAT>
+ </STYLE>
+ <STYLE outline="true">
+ <NAME value="Head 2" />
+ <COUNTER numberingtype="1" righttext="." type="1" start="1" depth="1" display-levels="2"/>
+ <FOLLOWING name="Standard" />
+ <FORMAT id="1">
+ <!-- Use KDE settings for the font family -->
+ <SIZE value="16" />
+ <WEIGHT value="75" />
+ </FORMAT>
+ </STYLE>
+ <STYLE outline="true">
+ <NAME value="Head 3" />
+ <COUNTER numberingtype="1" righttext="." type="1" start="1" depth="2" display-levels="3"/>
+ <FOLLOWING name="Standard" />
+ <FORMAT id="1">
+ <!-- Use KDE settings for the font family -->
+ <SIZE value="12" />
+ <WEIGHT value="75" />
+ </FORMAT>
+ </STYLE>
+ <STYLE>
+ <NAME value="Enumerated List" />
+ <COUNTER numberingtype="0" righttext="." type="1" start="1" depth="0" />
+ <FOLLOWING name="Enumerated List" />
+ <FORMAT id="1">
+ <!-- Use KDE settings for the font -->
+ </FORMAT>
+ </STYLE>
+ <STYLE>
+ <NAME value="Alphabetical List" />
+ <COUNTER numberingtype="0" righttext=")" type="2" start="1" depth="0" />
+ <FOLLOWING name="Alphabetical List" />
+ <FORMAT id="1">
+ <!-- Use KDE settings for the font -->
+ </FORMAT>
+ </STYLE>
+ <STYLE>
+ <NAME value="Bullet List" />
+ <COUNTER numberingtype="0" type="10" start="1" depth="0" />
+ <FOLLOWING name="Bullet List" />
+ <FORMAT id="1">
+ <!-- Use KDE settings for the font -->
+ </FORMAT>
+ </STYLE>
+ </STYLES>
+</DOC>
diff --git a/kword/templates/Wordprocessing/ColorfulA4.desktop b/kword/templates/Wordprocessing/ColorfulA4.desktop
new file mode 100644
index 00000000..e42ec637
--- /dev/null
+++ b/kword/templates/Wordprocessing/ColorfulA4.desktop
@@ -0,0 +1,84 @@
+[Desktop Entry]
+Type=Link
+URL=.source/ColorfulA4.odt
+Name=Colorful Document
+Name[bg]=Цветен документ
+Name[br]=Teul livet
+Name[ca]=Document a tot color
+Name[da]=Farverigt dokument
+Name[de]=Buntes Dokument
+Name[el]=Χρωματιστό έγγραφο
+Name[en_GB]=Colourful Document
+Name[eo]=Kolora dokumento
+Name[es]=Documento a todo color
+Name[et]=Värviline dokument
+Name[fa]=سند رنگی
+Name[fr]=Document coloré
+Name[fy]=Kleurryk dokumint
+Name[ga]=Cáipéis Ildathach
+Name[gl]=Documento Colorido
+Name[he]=מסמך צבעוני
+Name[hr]=Šareni dokument
+Name[hu]=Színes dokumentum
+Name[is]=Litríkt skjal
+Name[it]=Documento colorito
+Name[ja]=カラフルなドキュメント
+Name[km]=ឯកសារ​ពណ៌​ស្រស់
+Name[lt]=Spalvingas dokumentas
+Name[lv]=Krāsains dokuments
+Name[nb]=Fargerikt dokument
+Name[nds]=Bunt Dokment
+Name[ne]=रङिन कागजात
+Name[nl]=Kleurrijk document
+Name[pl]=Kolorowy dokument
+Name[pt]=Documento Colorido
+Name[pt_BR]=Documento Colorido
+Name[ru]=Буклет
+Name[se]=Ivdnás dokumeanta
+Name[sk]=Farebný dokument
+Name[sl]=Barvit dokument
+Name[sr]=Разнобојан документ
+Name[sr@Latn]=Raznobojan dokument
+Name[sv]=Färgstarkt dokument
+Name[uk]=Барвистий документ
+Name[uz]=Rangli hujjat
+Name[uz@cyrillic]=Рангли ҳужжат
+Name[zh_CN]=多彩文档
+Name[zh_TW]=彩色文件
+Comment=A two-column template with stylishly colored headers and footers
+Comment[bg]=Шаблон с две колони със стилни цветни колонтитули
+Comment[ca]=Una plantilla de dues columnes amb capçaleres i peus de colors i amb estil
+Comment[da]=En tosøjlers skabelon med elegant farvet sidehoved og sidefod
+Comment[de]=Eine zweispaltige Vorlage mit stilvoll kolorierten Kopf- und Fußzeilen
+Comment[el]=Ένα πρότυπο δύο στηλών με στυλιζαρισμένα χρωματιστά υποσέλιδα και κεφαλίδες
+Comment[en_GB]=A two-column template with stylishly coloured headers and footers
+Comment[es]=Una plantilla con dos columnas con encabezados y pies con colores elegantes
+Comment[et]=Kahe veeruga dokument stiilselt värviliste päiste ja jalustega
+Comment[fa]=قالب دو ستونی با عناوین و زیرنویسهای رنگی شیک
+Comment[fi]=Kaksipalstainen pohja, tyylikäät värilliset ylä- ja alatunnisteet
+Comment[fr]=Un modèle à deux colonnes avec des en-têtes colorées et des pieds de page
+Comment[fy]=In twakoloms sjabloan mei stylfolle kleurde kop- en foetteksten
+Comment[gl]=Un modelo a dúas colunas, con cabeceiras e rodapés con estilos coloridos
+Comment[hu]=Kétoszlopos sablon stílusos, színes fejléccel és lábléccel
+Comment[is]=Tveggja dálka snið með skreytilegum hausum og fótum
+Comment[it]=Un modello a due colonne con intestazioni e piè di pagina colorati elegantemente
+Comment[ja]=カラフルなヘッダとフッタの付いた 2 列のテンプレート
+Comment[km]=ពុម្ព​ជួរ​ឈរ​ពី​ដែល​មាន​បថមកថា​និង​បាតកថា​ដែល​លម្អរ​ដោយ​ពណ៌​មាន​រចនាប័ទ្ម
+Comment[nb]=En tospalters mal med stilig farget topptekst og bunntekst
+Comment[nds]=En Vörlaag mit twee Striepen un smucke Klören för Kopp- un Footregen
+Comment[ne]=रङिन शैलीका हेडर र फुटरहरू सहितको दुई-स्तम्भ टेम्प्लेट
+Comment[nl]=Een tweekoloms sjabloon met stijlvolle gekleurde kop- en voetteksten
+Comment[pl]=Dwukolumnowy szablon ze stylowo pokolorowanymi nagłówkami i stopkami
+Comment[pt]=Um modelo de duas colunas, com cabeçalhos e rodapés com estilos coloridos
+Comment[pt_BR]=Um modelo de duas colunas, com cabeçalhos e rodapés com estilos coloridos
+Comment[ru]=Шаблон цветного буклета с двумя колонками
+Comment[sk]=Šablóna s dvoma stĺpcami a štýlovým záhlavím a pätou
+Comment[sl]=Predloga z dvema stoplcema in modno obarvanimi glavami in nogami
+Comment[sr]=Шаблон са две колоне и стилски обојеним заглављем и подножјем
+Comment[sr@Latn]=Šablon sa dve kolone i stilski obojenim zaglavljem i podnožjem
+Comment[sv]=En tvåkolumners mall med elegant färgat sidhuvud och sidfot
+Comment[uk]=Двостовпчиковий шаблон зі стильними верхнім і нижнім колонтитулом
+Comment[zh_CN]=页眉和页脚颜色多彩的两栏模板
+Comment[zh_TW]=一個兩欄的樣本,有彩色的標頭與註腳
+Icon=template_colorful
+X-KDE-MeasureSystem=metric
diff --git a/kword/templates/Wordprocessing/ColorfulA4.odt b/kword/templates/Wordprocessing/ColorfulA4.odt
new file mode 100644
index 00000000..9fd1d153
--- /dev/null
+++ b/kword/templates/Wordprocessing/ColorfulA4.odt
Binary files differ
diff --git a/kword/templates/Wordprocessing/ColorfulLetter.desktop b/kword/templates/Wordprocessing/ColorfulLetter.desktop
new file mode 100644
index 00000000..4d32f930
--- /dev/null
+++ b/kword/templates/Wordprocessing/ColorfulLetter.desktop
@@ -0,0 +1,84 @@
+[Desktop Entry]
+Type=Link
+URL=.source/ColorfulLetter.odt
+Name=Colorful Document
+Name[bg]=Цветен документ
+Name[br]=Teul livet
+Name[ca]=Document a tot color
+Name[da]=Farverigt dokument
+Name[de]=Buntes Dokument
+Name[el]=Χρωματιστό έγγραφο
+Name[en_GB]=Colourful Document
+Name[eo]=Kolora dokumento
+Name[es]=Documento a todo color
+Name[et]=Värviline dokument
+Name[fa]=سند رنگی
+Name[fr]=Document coloré
+Name[fy]=Kleurryk dokumint
+Name[ga]=Cáipéis Ildathach
+Name[gl]=Documento Colorido
+Name[he]=מסמך צבעוני
+Name[hr]=Šareni dokument
+Name[hu]=Színes dokumentum
+Name[is]=Litríkt skjal
+Name[it]=Documento colorito
+Name[ja]=カラフルなドキュメント
+Name[km]=ឯកសារ​ពណ៌​ស្រស់
+Name[lt]=Spalvingas dokumentas
+Name[lv]=Krāsains dokuments
+Name[nb]=Fargerikt dokument
+Name[nds]=Bunt Dokment
+Name[ne]=रङिन कागजात
+Name[nl]=Kleurrijk document
+Name[pl]=Kolorowy dokument
+Name[pt]=Documento Colorido
+Name[pt_BR]=Documento Colorido
+Name[ru]=Буклет
+Name[se]=Ivdnás dokumeanta
+Name[sk]=Farebný dokument
+Name[sl]=Barvit dokument
+Name[sr]=Разнобојан документ
+Name[sr@Latn]=Raznobojan dokument
+Name[sv]=Färgstarkt dokument
+Name[uk]=Барвистий документ
+Name[uz]=Rangli hujjat
+Name[uz@cyrillic]=Рангли ҳужжат
+Name[zh_CN]=多彩文档
+Name[zh_TW]=彩色文件
+Comment=A two-column template with stylishly colored headers and footers
+Comment[bg]=Шаблон с две колони със стилни цветни колонтитули
+Comment[ca]=Una plantilla de dues columnes amb capçaleres i peus de colors i amb estil
+Comment[da]=En tosøjlers skabelon med elegant farvet sidehoved og sidefod
+Comment[de]=Eine zweispaltige Vorlage mit stilvoll kolorierten Kopf- und Fußzeilen
+Comment[el]=Ένα πρότυπο δύο στηλών με στυλιζαρισμένα χρωματιστά υποσέλιδα και κεφαλίδες
+Comment[en_GB]=A two-column template with stylishly coloured headers and footers
+Comment[es]=Una plantilla con dos columnas con encabezados y pies con colores elegantes
+Comment[et]=Kahe veeruga dokument stiilselt värviliste päiste ja jalustega
+Comment[fa]=قالب دو ستونی با عناوین و زیرنویسهای رنگی شیک
+Comment[fi]=Kaksipalstainen pohja, tyylikäät värilliset ylä- ja alatunnisteet
+Comment[fr]=Un modèle à deux colonnes avec des en-têtes colorées et des pieds de page
+Comment[fy]=In twakoloms sjabloan mei stylfolle kleurde kop- en foetteksten
+Comment[gl]=Un modelo a dúas colunas, con cabeceiras e rodapés con estilos coloridos
+Comment[hu]=Kétoszlopos sablon stílusos, színes fejléccel és lábléccel
+Comment[is]=Tveggja dálka snið með skreytilegum hausum og fótum
+Comment[it]=Un modello a due colonne con intestazioni e piè di pagina colorati elegantemente
+Comment[ja]=カラフルなヘッダとフッタの付いた 2 列のテンプレート
+Comment[km]=ពុម្ព​ជួរ​ឈរ​ពី​ដែល​មាន​បថមកថា​និង​បាតកថា​ដែល​លម្អរ​ដោយ​ពណ៌​មាន​រចនាប័ទ្ម
+Comment[nb]=En tospalters mal med stilig farget topptekst og bunntekst
+Comment[nds]=En Vörlaag mit twee Striepen un smucke Klören för Kopp- un Footregen
+Comment[ne]=रङिन शैलीका हेडर र फुटरहरू सहितको दुई-स्तम्भ टेम्प्लेट
+Comment[nl]=Een tweekoloms sjabloon met stijlvolle gekleurde kop- en voetteksten
+Comment[pl]=Dwukolumnowy szablon ze stylowo pokolorowanymi nagłówkami i stopkami
+Comment[pt]=Um modelo de duas colunas, com cabeçalhos e rodapés com estilos coloridos
+Comment[pt_BR]=Um modelo de duas colunas, com cabeçalhos e rodapés com estilos coloridos
+Comment[ru]=Шаблон цветного буклета с двумя колонками
+Comment[sk]=Šablóna s dvoma stĺpcami a štýlovým záhlavím a pätou
+Comment[sl]=Predloga z dvema stoplcema in modno obarvanimi glavami in nogami
+Comment[sr]=Шаблон са две колоне и стилски обојеним заглављем и подножјем
+Comment[sr@Latn]=Šablon sa dve kolone i stilski obojenim zaglavljem i podnožjem
+Comment[sv]=En tvåkolumners mall med elegant färgat sidhuvud och sidfot
+Comment[uk]=Двостовпчиковий шаблон зі стильними верхнім і нижнім колонтитулом
+Comment[zh_CN]=页眉和页脚颜色多彩的两栏模板
+Comment[zh_TW]=一個兩欄的樣本,有彩色的標頭與註腳
+Icon=template_colorful
+X-KDE-MeasureSystem=imperial
diff --git a/kword/templates/Wordprocessing/ColorfulLetter.odt b/kword/templates/Wordprocessing/ColorfulLetter.odt
new file mode 100644
index 00000000..14c5638b
--- /dev/null
+++ b/kword/templates/Wordprocessing/ColorfulLetter.odt
Binary files differ
diff --git a/kword/templates/Wordprocessing/FaxA4.desktop b/kword/templates/Wordprocessing/FaxA4.desktop
new file mode 100644
index 00000000..04c190d7
--- /dev/null
+++ b/kword/templates/Wordprocessing/FaxA4.desktop
@@ -0,0 +1,98 @@
+[Desktop Entry]
+Type=Link
+URL=.source/FaxA4.odt
+Name=Fax Template
+Name[af]=Faks Werkvoorbeeld
+Name[ar]=قالب فاكس
+Name[bg]=Факс шаблон
+Name[br]=Patrom faks
+Name[bs]=Šablon za fax
+Name[ca]=Plantilla per a Fax
+Name[cs]=Šablona faxu
+Name[cy]=Patrymlun Ffacs
+Name[da]=Fax-skabelon
+Name[de]=Faxvorlage
+Name[el]=Πρότυπο φαξ
+Name[eo]=Fakso-Ŝablono
+Name[es]=Plantilla de fax
+Name[et]=Faksimall
+Name[eu]=Fax-txantiloia
+Name[fa]=قالب دورنگار
+Name[fi]=Faksipohja
+Name[fr]=Modèle de fax
+Name[fy]=Faks-sjabloan
+Name[ga]=Teimpléad Facs
+Name[gl]=Modelo de Fax
+Name[he]=תבנית פקס
+Name[hi]=फैक्स टैम्प्लेट
+Name[hr]=Predložak za faks
+Name[hu]=Faxsablon
+Name[is]=Fax snið
+Name[it]=Modello fax
+Name[ja]=ファクステンプレート
+Name[km]=ពុម្ព​ទូរសារ​
+Name[lo]=ຕົ້ນແບບໂທລະສານ
+Name[lt]=Fakso šablonas
+Name[lv]=Faksa šablons
+Name[ms]=Templat Faks
+Name[mt]=Mudell ta' faks
+Name[nb]=Faksmal
+Name[nds]=Faxvörlag
+Name[ne]=फ्याक्स टेम्प्लेट
+Name[nl]=Faxsjabloon
+Name[nn]=Faksmal
+Name[pl]=Szablon faksu
+Name[pt]=Modelo de Fax
+Name[pt_BR]=Modelo de Fax
+Name[ru]=Факс
+Name[se]=Fáksamálle
+Name[sk]=Šablóna faxu
+Name[sl]=Predloga za faks
+Name[sr]=Шаблон за факс
+Name[sr@Latn]=Šablon za faks
+Name[sv]=Faxmall
+Name[ta]=Fax வார்ப்புரு
+Name[tg]=Намунаи Факс
+Name[th]=ต้นแบบโทรสาร
+Name[tr]=Faks Şablonu
+Name[uk]=Шаблон факсу
+Name[uz]=Faks namunasi
+Name[uz@cyrillic]=Факс намунаси
+Name[wa]=Modele di facs
+Name[zh_CN]=传真模板
+Name[zh_TW]=傳真樣板
+Comment=A template to quickly create a facsimile communication
+Comment[bg]=Шаблон за бързо създаване на факсимиле
+Comment[ca]=Una plantilla per a crear ràpidament una comunicació per fax
+Comment[da]=En skabelon til hurtigt at oprette en faxmeddelelse
+Comment[de]=Eine Vorlage, um schnell ein Fax zu erstellen
+Comment[el]=Ένα πρότυπο για τη γρήγορη δημιουργία ενός φαξ
+Comment[es]=Una plantilla para crear rápidamente una comunicación facsímil
+Comment[et]=Mall kiireks faksi koostamiseks
+Comment[fa]=قالبی برای ایجاد سریع یک ارتباط عینی
+Comment[fi]=Pohja, jonka avulla luot nopeasti telefaksin
+Comment[fr]=Un modèle pour communiquer par fax
+Comment[fy]=In sjabloan om fluch in faks op te meitsjen
+Comment[gl]=Un modelo básico para criar rapidamente un fax
+Comment[hu]=Sablon faxdokumentum gyors létrehozásához
+Comment[is]=Sniðmát til að búa til fax á einfaldan hátt
+Comment[it]=Un modello per creare rapidamente una comunicazione fax
+Comment[ja]=ファクス送信用の文書を素早く作成するためのテンプレート
+Comment[km]=ពុម្ព​ត្រូវ​បង្កើត​ទំនាក់ទំនង​នៃ​សំណៅ​យ៉ាង​លឿន
+Comment[nb]=En mal som fort lager en telefaks
+Comment[nds]=En Vörlaag för gaue Fax-Överdregen
+Comment[ne]=प्रतिरूप सञ्चार द्रुत सिर्जना गर्न टेम्प्लेट
+Comment[nl]=Een sjabloon om snel een fax op te stellen
+Comment[pl]=Szablon pozwalający szybko sporządzić odpowiedź
+Comment[pt]=Modelo básico para criar rapidamente uma comunicação facsimile
+Comment[pt_BR]=Modelo básico para criar rapidamente uma comunicação por fax
+Comment[ru]=Шаблон факса
+Comment[sk]=Šablóna na rýchle vytvorenie facsimile
+Comment[sl]=Predloga za hitro izdelavo faksa
+Comment[sr]=Шаблон за брзо прављење факсимила
+Comment[sr@Latn]=Šablon za brzo pravljenje faksimila
+Comment[sv]=En mall för att snabbt skapa ett telefaxmeddelande
+Comment[uk]=Шаблон для швидкого створення факсу
+Comment[zh_TW]=一個樣本,以便快速建立傳真聯繫
+Icon=template_fax
+X-KDE-MeasureSystem=metric
diff --git a/kword/templates/Wordprocessing/FaxA4.odt b/kword/templates/Wordprocessing/FaxA4.odt
new file mode 100644
index 00000000..cfecc5f4
--- /dev/null
+++ b/kword/templates/Wordprocessing/FaxA4.odt
Binary files differ
diff --git a/kword/templates/Wordprocessing/FaxLetter.desktop b/kword/templates/Wordprocessing/FaxLetter.desktop
new file mode 100644
index 00000000..4198562d
--- /dev/null
+++ b/kword/templates/Wordprocessing/FaxLetter.desktop
@@ -0,0 +1,98 @@
+[Desktop Entry]
+Type=Link
+URL=.source/FaxLetter.odt
+Name=Fax Template
+Name[af]=Faks Werkvoorbeeld
+Name[ar]=قالب فاكس
+Name[bg]=Факс шаблон
+Name[br]=Patrom faks
+Name[bs]=Šablon za fax
+Name[ca]=Plantilla per a Fax
+Name[cs]=Šablona faxu
+Name[cy]=Patrymlun Ffacs
+Name[da]=Fax-skabelon
+Name[de]=Faxvorlage
+Name[el]=Πρότυπο φαξ
+Name[eo]=Fakso-Ŝablono
+Name[es]=Plantilla de fax
+Name[et]=Faksimall
+Name[eu]=Fax-txantiloia
+Name[fa]=قالب دورنگار
+Name[fi]=Faksipohja
+Name[fr]=Modèle de fax
+Name[fy]=Faks-sjabloan
+Name[ga]=Teimpléad Facs
+Name[gl]=Modelo de Fax
+Name[he]=תבנית פקס
+Name[hi]=फैक्स टैम्प्लेट
+Name[hr]=Predložak za faks
+Name[hu]=Faxsablon
+Name[is]=Fax snið
+Name[it]=Modello fax
+Name[ja]=ファクステンプレート
+Name[km]=ពុម្ព​ទូរសារ​
+Name[lo]=ຕົ້ນແບບໂທລະສານ
+Name[lt]=Fakso šablonas
+Name[lv]=Faksa šablons
+Name[ms]=Templat Faks
+Name[mt]=Mudell ta' faks
+Name[nb]=Faksmal
+Name[nds]=Faxvörlag
+Name[ne]=फ्याक्स टेम्प्लेट
+Name[nl]=Faxsjabloon
+Name[nn]=Faksmal
+Name[pl]=Szablon faksu
+Name[pt]=Modelo de Fax
+Name[pt_BR]=Modelo de Fax
+Name[ru]=Факс
+Name[se]=Fáksamálle
+Name[sk]=Šablóna faxu
+Name[sl]=Predloga za faks
+Name[sr]=Шаблон за факс
+Name[sr@Latn]=Šablon za faks
+Name[sv]=Faxmall
+Name[ta]=Fax வார்ப்புரு
+Name[tg]=Намунаи Факс
+Name[th]=ต้นแบบโทรสาร
+Name[tr]=Faks Şablonu
+Name[uk]=Шаблон факсу
+Name[uz]=Faks namunasi
+Name[uz@cyrillic]=Факс намунаси
+Name[wa]=Modele di facs
+Name[zh_CN]=传真模板
+Name[zh_TW]=傳真樣板
+Comment=A template to quickly create a facsimile communication
+Comment[bg]=Шаблон за бързо създаване на факсимиле
+Comment[ca]=Una plantilla per a crear ràpidament una comunicació per fax
+Comment[da]=En skabelon til hurtigt at oprette en faxmeddelelse
+Comment[de]=Eine Vorlage, um schnell ein Fax zu erstellen
+Comment[el]=Ένα πρότυπο για τη γρήγορη δημιουργία ενός φαξ
+Comment[es]=Una plantilla para crear rápidamente una comunicación facsímil
+Comment[et]=Mall kiireks faksi koostamiseks
+Comment[fa]=قالبی برای ایجاد سریع یک ارتباط عینی
+Comment[fi]=Pohja, jonka avulla luot nopeasti telefaksin
+Comment[fr]=Un modèle pour communiquer par fax
+Comment[fy]=In sjabloan om fluch in faks op te meitsjen
+Comment[gl]=Un modelo básico para criar rapidamente un fax
+Comment[hu]=Sablon faxdokumentum gyors létrehozásához
+Comment[is]=Sniðmát til að búa til fax á einfaldan hátt
+Comment[it]=Un modello per creare rapidamente una comunicazione fax
+Comment[ja]=ファクス送信用の文書を素早く作成するためのテンプレート
+Comment[km]=ពុម្ព​ត្រូវ​បង្កើត​ទំនាក់ទំនង​នៃ​សំណៅ​យ៉ាង​លឿន
+Comment[nb]=En mal som fort lager en telefaks
+Comment[nds]=En Vörlaag för gaue Fax-Överdregen
+Comment[ne]=प्रतिरूप सञ्चार द्रुत सिर्जना गर्न टेम्प्लेट
+Comment[nl]=Een sjabloon om snel een fax op te stellen
+Comment[pl]=Szablon pozwalający szybko sporządzić odpowiedź
+Comment[pt]=Modelo básico para criar rapidamente uma comunicação facsimile
+Comment[pt_BR]=Modelo básico para criar rapidamente uma comunicação por fax
+Comment[ru]=Шаблон факса
+Comment[sk]=Šablóna na rýchle vytvorenie facsimile
+Comment[sl]=Predloga za hitro izdelavo faksa
+Comment[sr]=Шаблон за брзо прављење факсимила
+Comment[sr@Latn]=Šablon za brzo pravljenje faksimila
+Comment[sv]=En mall för att snabbt skapa ett telefaxmeddelande
+Comment[uk]=Шаблон для швидкого створення факсу
+Comment[zh_TW]=一個樣本,以便快速建立傳真聯繫
+Icon=template_fax
+X-KDE-MeasureSystem=imperial
diff --git a/kword/templates/Wordprocessing/FaxLetter.odt b/kword/templates/Wordprocessing/FaxLetter.odt
new file mode 100644
index 00000000..a4ca7d5c
--- /dev/null
+++ b/kword/templates/Wordprocessing/FaxLetter.odt
Binary files differ
diff --git a/kword/templates/Wordprocessing/Letter.desktop b/kword/templates/Wordprocessing/Letter.desktop
new file mode 100644
index 00000000..98457552
--- /dev/null
+++ b/kword/templates/Wordprocessing/Letter.desktop
@@ -0,0 +1,86 @@
+[Desktop Entry]
+Type=Link
+URL=.source/Letter.kwt
+Name=Blank Page
+Name[bg]=Празна страница
+Name[br]=Goullonderiñ ar bajenn
+Name[ca]=Pàgina buida
+Name[da]=Blank side
+Name[de]=Leere Seite
+Name[el]=Κενή σελίδα
+Name[eo]=Malplena Paĝo
+Name[es]=Página vacía
+Name[et]=Tühi lehekülg
+Name[fa]=صفحۀ خالی
+Name[fr]=Page vide
+Name[fy]=Lege side
+Name[ga]=Leathanach Folamh
+Name[gl]=Páxina en Branco
+Name[he]=דף ריק
+Name[hr]=Prazna stranica
+Name[hu]=Üres oldal
+Name[is]=Tóm síða
+Name[it]=Pagina vuota
+Name[ja]=空のページ
+Name[km]=ទំព័រ​ទទេ​
+Name[lt]=Tuščias puslapis
+Name[lv]=Tukša lapa
+Name[nb]=Tom side
+Name[nds]=Leddig Siet
+Name[ne]=खाली पृष्ठ
+Name[nl]=Leeg pagina
+Name[pl]=Pusta strona
+Name[pt]=Página em Branco
+Name[pt_BR]=Página em Branco
+Name[ru]=Чистый лист
+Name[se]=Guorus siidu
+Name[sk]=Prázdna stránka
+Name[sl]=Prazen list
+Name[sr]=Празна страна
+Name[sr@Latn]=Prazna strana
+Name[sv]=Tom sida
+Name[uk]=Порожня сторінка
+Name[uz]=Boʻsh bet
+Name[uz@cyrillic]=Бўш бет
+Name[zh_CN]=空页面
+Name[zh_TW]=空白頁面
+Comment=Creates a blank US Letter document.
+Comment[bg]=Създаване на празен документ във формат US Letter.
+Comment[ca]=Crea un document de carta US buit.
+Comment[da]=Opretter et blankt US Letter-dokument.
+Comment[de]=Erstellt ein leeres US-Letter-Dokument.
+Comment[el]=Δημιουργεί ένα κενό έγγραφο US Letter.
+Comment[es]=Crea un documento vacío tamaño US Letter.
+Comment[et]=Loob tühja US Letter dokumendi.
+Comment[fa]=سند خالی حروف امریکایی را ایجاد می‌کند.
+Comment[fi]=Luo tyhjän US Letter -asiakirjan
+Comment[fr]=Crée un document US Letter vide.
+Comment[fy]=Makket in leech US Letter-dokumint oan.
+Comment[gl]=Cría un documento vacío para unha páxina Carta dos EUA.
+Comment[he]=יצירת מכתב אמריקאי ריק
+Comment[hu]=Létrehoz egy üres US Letter-méretű dokumentumot.
+Comment[is]=Býr til tómt US Letter skjal
+Comment[it]=Crea un documento US Letter vuoto.
+Comment[ja]=空のドキュメント (US Letter) を作成
+Comment[km]=បង្កើត​ឯកសារ​សំបុត្រ​អាមេរិក​ទទេ​មួយ ។
+Comment[nb]=Lager et tomt dokument i US Letter-format.
+Comment[nds]=Stellt en leddig Dokment in'n Formaat "US-Letter" op.
+Comment[ne]=खाली यूएस अक्षर कागजात सिर्जना गर्दछ ।
+Comment[nl]=Maakt een leeg US Letter-document aan.
+Comment[pl]=Tworzy pusty dokument z rozmiarem papieru US Letter.
+Comment[pt]=Cria um documento Carta dos EUA vazio.
+Comment[pt_BR]=Cria um documento Carta dos EUA vazio.
+Comment[ru]=Пустой документ формата US Letter
+Comment[se]=Ráhkada guorus dokumeanta US Letter-formáhtta
+Comment[sk]=Vytvorí prázdny dokument veľkosti US Letter.
+Comment[sl]=Ustvari prazen dokument velikosti »US Letter«.
+Comment[sr]=Прави празан документ формата US Letter.
+Comment[sr@Latn]=Pravi prazan dokument formata US Letter.
+Comment[sv]=Skapar ett tomt US Letter-dokument.
+Comment[uk]=Створює порожній документ US Letter.
+Comment[uz]=Oʻlchami 279 × 216 millimetr boʻlgan (US Letter) boʻsh hujjatni yaratish.
+Comment[uz@cyrillic]=Ўлчами 279 × 216 миллиметр бўлган (US Letter) бўш ҳужжатни яратиш.
+Comment[zh_CN]=创建空的美式信函文档。
+Comment[zh_TW]=建立一個空白 US Letter 文件。
+Icon=template_letter
+X-KDE-MeasureSystem=imperial
diff --git a/kword/templates/Wordprocessing/Letter.kwt b/kword/templates/Wordprocessing/Letter.kwt
new file mode 100644
index 00000000..a07b6e68
--- /dev/null
+++ b/kword/templates/Wordprocessing/Letter.kwt
@@ -0,0 +1,84 @@
+<?xml version="1.0" encoding="UTF-8"?><!DOCTYPE DOC ><DOC mime="application/x-kword" syntaxVersion="3" editor="KWord" >
+ <PAPER width="612.285" zoom="100" spHeadBody="9.92128" format="3" height="790.868" fType="0" orientation="0" hType="0" columnspacing="2.83465" spFootBody="9.92128" columns="1" >
+ <PAPERBORDERS right="56.693" left="56.693" bottom="42.5198" top="42.5198" />
+ </PAPER>
+ <ATTRIBUTES standardpage="1" hasFooter="0" unit="inch" hasHeader="0" processing="0" />
+ <FRAMESETS>
+ <FRAMESET removable="0" frameType="1" frameInfo="0" visible="1" >
+ <FRAME runaround="1" right="553" left="56" bottom="746" runaroundGap="0" top="42" />
+ </FRAMESET>
+ </FRAMESETS>
+ <STYLES>
+ <STYLE>
+ <NAME value="Standard" />
+ <FOLLOWING name="Standard" />
+ <FORMAT id="1">
+ <!-- Use KDE settings for the font -->
+ </FORMAT>
+ </STYLE>
+ <STYLE>
+ <NAME value="Document Title" />
+ <FLOW align="center" />
+ <FOLLOWING name="Standard" />
+ <FORMAT id="1" >
+ <!-- Use KDE settings for the font family -->
+ <WEIGHT value="75" />
+ <SIZE value="24" />
+ </FORMAT>
+ </STYLE>
+ <STYLE outline="true">
+ <NAME value="Head 1" />
+ <COUNTER numberingtype="1" righttext="." type="1" start="1" depth="0" display-levels="1"/>
+ <FOLLOWING name="Standard" />
+ <FORMAT id="1">
+ <!-- Use KDE settings for the font family -->
+ <SIZE value="20" />
+ <WEIGHT value="75" />
+ </FORMAT>
+ </STYLE>
+ <STYLE outline="true">
+ <NAME value="Head 2" />
+ <COUNTER numberingtype="1" righttext="." type="1" start="1" depth="1" display-levels="2"/>
+ <FOLLOWING name="Standard" />
+ <FORMAT id="1">
+ <!-- Use KDE settings for the font family -->
+ <SIZE value="16" />
+ <WEIGHT value="75" />
+ </FORMAT>
+ </STYLE>
+ <STYLE outline="true">
+ <NAME value="Head 3" />
+ <COUNTER numberingtype="1" righttext="." type="1" start="1" depth="2" display-levels="3"/>
+ <FOLLOWING name="Standard" />
+ <FORMAT id="1">
+ <!-- Use KDE settings for the font family -->
+ <SIZE value="12" />
+ <WEIGHT value="75" />
+ </FORMAT>
+ </STYLE>
+ <STYLE>
+ <NAME value="Enumerated List" />
+ <COUNTER numberingtype="0" righttext="." type="1" start="1" depth="0" />
+ <FOLLOWING name="Enumerated List" />
+ <FORMAT id="1">
+ <!-- Use KDE settings for the font -->
+ </FORMAT>
+ </STYLE>
+ <STYLE>
+ <NAME value="Alphabetical List" />
+ <COUNTER numberingtype="0" righttext=")" type="2" start="1" depth="0" />
+ <FOLLOWING name="Alphabetical List" />
+ <FORMAT id="1">
+ <!-- Use KDE settings for the font -->
+ </FORMAT>
+ </STYLE>
+ <STYLE>
+ <NAME value="Bullet List" />
+ <COUNTER numberingtype="0" type="10" start="1" depth="0" />
+ <FOLLOWING name="Bullet List" />
+ <FORMAT id="1">
+ <!-- Use KDE settings for the font -->
+ </FORMAT>
+ </STYLE>
+ </STYLES>
+</DOC>
diff --git a/kword/templates/Wordprocessing/Makefile.am b/kword/templates/Wordprocessing/Makefile.am
new file mode 100644
index 00000000..119559cd
--- /dev/null
+++ b/kword/templates/Wordprocessing/Makefile.am
@@ -0,0 +1,13 @@
+templates_DATA = .directory TwoColumns.desktop Letter.desktop A4.desktop Memo.desktop \
+ TwoColumnsLetter.desktop ProfessionalLetter.desktop ProfessionalA4.desktop \
+ FaxA4.desktop FaxLetter.desktop \
+ ColorfulA4.desktop ColorfulLetter.desktop
+templatesdir = $(kde_datadir)/kword/templates/Normal
+
+templatesrc_DATA = TwoColumns.kwt Letter.kwt A4.kwt Memo.kwt TwoColumnsLetter.kwt \
+ ProfessionalLetter.odt ProfessionalA4.odt FaxA4.odt FaxLetter.odt \
+ ColorfulA4.odt ColorfulLetter.odt PlainText.kwt
+templatesrcdir = $(kde_datadir)/kword/templates/Normal/.source
+
+kworddir = $(kde_datadir)/kword/icons
+kword_ICON = AUTO
diff --git a/kword/templates/Wordprocessing/Memo.desktop b/kword/templates/Wordprocessing/Memo.desktop
new file mode 100644
index 00000000..4ed08d19
--- /dev/null
+++ b/kword/templates/Wordprocessing/Memo.desktop
@@ -0,0 +1,69 @@
+[Desktop Entry]
+Type=Link
+URL=.source/Memo.kwt
+Name=Memorandum
+Name[bg]=Меморандум
+Name[ca]=Memoràndum
+Name[el]=Υπόμνημα
+Name[es]=Memorando
+Name[et]=Memo
+Name[fa]=نامۀ غیررسمی
+Name[fr]=Mémo
+Name[ga]=Meamram
+Name[gl]=Memorando
+Name[hu]=Beadvány
+Name[is]=Minnisblað
+Name[ja]=メモ
+Name[km]=អនុស្សរណៈ
+Name[lt]=Memorandumas
+Name[lv]=Memorands
+Name[nb]=Notat
+Name[nds]=Notiz
+Name[ne]=ज्ञापनपत्र
+Name[pl]=Przypomnienie
+Name[pt]=Memorando
+Name[pt_BR]=Memorando
+Name[ru]=Записка
+Name[se]=Notáhta
+Name[sr]=Меморандум
+Name[sv]=Promemoria
+Name[uk]=Службова записка
+Name[uz@cyrillic]=Меморандум
+Name[zh_CN]=备忘录
+Name[zh_TW]=記事便條
+Comment=Basic template for quickly writing a good-looking memo
+Comment[bg]=Основен шаблон за бързо писане на добре изглеждаща бележка
+Comment[ca]=Plantilla bàsica per a escriure ràpidament una nota amb bon aspecte
+Comment[da]=Basal skabelon for hurtigt at skrive et godt udseende memo
+Comment[de]=Eine einfache Vorlage, um schnell ein gut aussehendes Memo zu schreiben
+Comment[el]=Βασικό πρότυπο για τη γρήγορη γραφή ενός όμορφου υπομνήματος
+Comment[es]=Plantilla básica para escribir rápidamente un memorando con buen aspecto.
+Comment[et]=Mall korraliku memo kiireks kirjapanemiseks
+Comment[fa]=قالب پایه‌ای برای نوشتن سریع یک نامۀ غیررسمی زیبا
+Comment[fi]=Yksinkertainen pohja muistioita varten
+Comment[fr]=Modèle de base pour écrire rapidement un joli mémo
+Comment[fy]=In sjabloan om fluch in moaie memo te skriuwen
+Comment[gl]=Modelo básico para criar rapidamente un memorando con bon aspeito
+Comment[hu]=Egyszerű sablon elegáns megjelenésű beadvány gyors létrehozásához
+Comment[is]=Sniðmát til að búa til flott minnisblað á einfaldan hátt
+Comment[it]=Modello di base per scrivere alla svelta una nota di buon aspetto
+Comment[ja]=体裁のよいメモを素早く作成するための基本的なテンプレート
+Comment[km]=ពុម្ព​មូលដ្ឋាន​សម្រាប់​សរសេរ​អនុសារណ​ដែល​ល្អ​យ៉ាង​លឿន
+Comment[lv]=Vienkārša sagatave ātrai laba izskata piezīmju rakstīšanai
+Comment[nb]=Grunnleggende mal for fort å kunne skrive et notat som ser bra ut
+Comment[nds]=En eenfach Vörlaag för smucke Notizen
+Comment[ne]=राम्रो-हेराई मेमो द्रुत रूपमा लेख्नका लागि आधारभूत टेम्प्लेट
+Comment[nl]=Een sjabloon om snel een mooie memo te schrijven
+Comment[pl]=Prosty szablon pozwalający na szybkie sporządzenie dobrze wyglądającego przypomnienia
+Comment[pt]=Modelo básico para criar rapidamente um memorando com bom aspecto
+Comment[pt_BR]=Modelo básico para criar rapidamente um memorando com boa aparência
+Comment[ru]=Шаблон хорошо оформленной записки
+Comment[sk]=Jednoduchá šablóna na rýchle vytvorenie štýlového obežníka (memo)
+Comment[sl]=Osnovna predloga za hitro pisanje memoranduma
+Comment[sr]=Основни шаблон за брзо писање меморандума доброг изгледа
+Comment[sr@Latn]=Osnovni šablon za brzo pisanje memoranduma dobrog izgleda
+Comment[sv]=Grundläggande mall för att snabbt skriva en snygg promemoria
+Comment[uk]=Простий шаблон для швидкого написання гарної службової записки
+Comment[zh_CN]=速写备忘录的基本模板
+Comment[zh_TW]=基本樣本,以便快速寫一個好看的便條
+Icon=template_memo
diff --git a/kword/templates/Wordprocessing/Memo.kwt b/kword/templates/Wordprocessing/Memo.kwt
new file mode 100644
index 00000000..7bf09f8e
--- /dev/null
+++ b/kword/templates/Wordprocessing/Memo.kwt
@@ -0,0 +1,806 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE DOC>
+<DOC mime="application/x-kword" syntaxVersion="3" editor="KWord" >
+ <PAPER width="595" spHeadBody="9" format="1" height="841" fType="0" orientation="0" hType="0" columnspacing="3" spFootBody="9" columns="1" >
+ <PAPERBORDERS right="28" left="28" bottom="42" top="28.4444" />
+ </PAPER>
+ <ATTRIBUTES hasTOC="0" standardpage="1" hasFooter="0" unit="mm" hasHeader="0" processing="0" />
+ <VARIABLESETTINGS displaylink="1" />
+ <FRAMESETS>
+ <FRAMESET frameType="1" frameInfo="0" name="Text Frameset 1" visible="1" >
+ <FRAME runaround="1" copy="0" right="567" newFrameBehavior="0" left="28" bottom="799" runaroundGap="2" top="28.4444" />
+ <PARAGRAPH>
+ <TEXT>MEMORANDUM</TEXT> <!-- NOT TRANSLATED! -->
+ <FORMATS>
+ <FORMAT id="1" pos="0" len="10" >
+ <SIZE value="30" />
+ </FORMAT>
+ </FORMATS>
+ <LAYOUT>
+ <NAME value="Standard" />
+ <FLOW align="right" />
+ <SHADOW direction="5" blue="200" red="195" green="198" distance="4" />
+ <FORMAT id="1" pos="0" len="10" >
+ <WEIGHT value="50" />
+ <SIZE value="12" />
+ <ITALIC value="0" />
+ <UNDERLINE value="0" />
+ <STRIKEOUT value="0" />
+ <VERTALIGN value="0" />
+ </FORMAT>
+ </LAYOUT>
+ </PARAGRAPH>
+ <PARAGRAPH>
+ <TEXT></TEXT>
+ <LAYOUT>
+ <NAME value="Standard" />
+ <TOPBORDER width="1" style="0" blue="0" red="0" green="0" />
+ <TABULATOR ptpos="28.4444" type="0" />
+ <TABULATOR ptpos="510.222" type="0" />
+ <FORMAT id="1" >
+ <WEIGHT value="50" />
+ <SIZE value="12" />
+ <ITALIC value="0" />
+ <UNDERLINE value="0" />
+ <STRIKEOUT value="0" />
+ <VERTALIGN value="0" />
+ </FORMAT>
+ </LAYOUT>
+ </PARAGRAPH>
+ <PARAGRAPH>
+ <TEXT>TO: &lt;Title>. &lt;FirstName> &lt;LastName></TEXT>
+ <FORMATS>
+ <FORMAT id="1" pos="0" len="5" >
+ <WEIGHT value="75" />
+ </FORMAT>
+ <FORMAT id="1" pos="5" len="31" >
+ </FORMAT>
+ </FORMATS>
+ <LAYOUT>
+ <NAME value="Standard" />
+ <TABULATOR ptpos="28.4444" type="0" />
+ <TABULATOR ptpos="72" type="0" />
+ <TABULATOR ptpos="510.222" type="0" />
+ <FORMAT id="1" pos="0" len="36" >
+ <WEIGHT value="50" />
+ <SIZE value="12" />
+ <ITALIC value="0" />
+ <UNDERLINE value="0" />
+ <STRIKEOUT value="0" />
+ <VERTALIGN value="0" />
+ </FORMAT>
+ </LAYOUT>
+ </PARAGRAPH>
+ <PARAGRAPH>
+ <TEXT></TEXT>
+ <LAYOUT>
+ <NAME value="Standard" />
+ <TABULATOR ptpos="28.4444" type="0" />
+ <TABULATOR ptpos="72" type="0" />
+ <TABULATOR ptpos="510.222" type="0" />
+ <FORMAT id="1" >
+ <WEIGHT value="50" />
+ <SIZE value="12" />
+ <ITALIC value="0" />
+ <UNDERLINE value="0" />
+ <STRIKEOUT value="0" />
+ <VERTALIGN value="0" />
+ </FORMAT>
+ </LAYOUT>
+ </PARAGRAPH>
+ <PARAGRAPH>
+ <TEXT>FROM: &lt;FirstName> &lt;LastName></TEXT>
+ <FORMATS>
+ <FORMAT id="1" pos="0" len="5" >
+ <WEIGHT value="75" />
+ </FORMAT>
+ <FORMAT id="1" pos="5" len="23" >
+ </FORMAT>
+ </FORMATS>
+ <LAYOUT>
+ <NAME value="Standard" />
+ <TABULATOR ptpos="28.4444" type="0" />
+ <TABULATOR ptpos="72" type="0" />
+ <TABULATOR ptpos="510.222" type="0" />
+ <FORMAT id="1" pos="0" len="28" >
+ <WEIGHT value="50" />
+ <SIZE value="12" />
+ <ITALIC value="0" />
+ <UNDERLINE value="0" />
+ <STRIKEOUT value="0" />
+ <VERTALIGN value="0" />
+ </FORMAT>
+ </LAYOUT>
+ </PARAGRAPH>
+ <PARAGRAPH>
+ <TEXT></TEXT>
+ <LAYOUT>
+ <NAME value="Standard" />
+ <TABULATOR ptpos="28.4444" type="0" />
+ <TABULATOR ptpos="72" type="0" />
+ <TABULATOR ptpos="510.222" type="0" />
+ <FORMAT id="1" >
+ <WEIGHT value="50" />
+ <SIZE value="12" />
+ <ITALIC value="0" />
+ <UNDERLINE value="0" />
+ <STRIKEOUT value="0" />
+ <VERTALIGN value="0" />
+ </FORMAT>
+ </LAYOUT>
+ </PARAGRAPH>
+ <PARAGRAPH>
+ <TEXT>DATE: #</TEXT>
+ <FORMATS>
+ <FORMAT id="1" pos="0" len="6" >
+ </FORMAT>
+ <FORMAT id="4" pos="6" len="1" >
+ <WEIGHT value="50" />
+ <VARIABLE>
+ <TYPE key="DATE0MMMM dd, yyyy" type="0" text="marzec 25, 2002" />
+ <DATE day="25" month="3" year="2002" fix="0" />
+ </VARIABLE>
+ </FORMAT>
+ </FORMATS>
+ <LAYOUT>
+ <NAME value="Standard" />
+ <TABULATOR ptpos="28.4444" type="0" />
+ <TABULATOR ptpos="72" type="0" />
+ <TABULATOR ptpos="510.222" type="0" />
+ <FORMAT id="1" pos="0" len="7" >
+ <WEIGHT value="75" />
+ <SIZE value="12" />
+ <ITALIC value="0" />
+ <UNDERLINE value="0" />
+ <STRIKEOUT value="0" />
+ <VERTALIGN value="0" />
+ </FORMAT>
+ </LAYOUT>
+ </PARAGRAPH>
+ <PARAGRAPH>
+ <TEXT></TEXT>
+ <LAYOUT>
+ <NAME value="Standard" />
+ <TABULATOR ptpos="28.4444" type="0" />
+ <TABULATOR ptpos="72" type="0" />
+ <TABULATOR ptpos="510.222" type="0" />
+ <FORMAT id="1" >
+ <WEIGHT value="75" />
+ <SIZE value="12" />
+ <ITALIC value="0" />
+ <UNDERLINE value="0" />
+ <STRIKEOUT value="0" />
+ <VERTALIGN value="0" />
+ </FORMAT>
+ </LAYOUT>
+ </PARAGRAPH>
+ <PARAGRAPH>
+ <TEXT>SUBJECT: &lt;Subject></TEXT>
+ <FORMATS>
+ <FORMAT id="1" pos="0" len="9" >
+ </FORMAT>
+ <FORMAT id="1" pos="9" len="9" >
+ <WEIGHT value="50" />
+ </FORMAT>
+ </FORMATS>
+ <LAYOUT>
+ <NAME value="Standard" />
+ <TABULATOR ptpos="28.4444" type="0" />
+ <TABULATOR ptpos="72" type="0" />
+ <TABULATOR ptpos="510.222" type="0" />
+ <FORMAT id="1" pos="0" len="18" >
+ <WEIGHT value="75" />
+ <SIZE value="12" />
+ <ITALIC value="0" />
+ <UNDERLINE value="0" />
+ <STRIKEOUT value="0" />
+ <VERTALIGN value="0" />
+ </FORMAT>
+ </LAYOUT>
+ </PARAGRAPH>
+ <PARAGRAPH>
+ <TEXT></TEXT>
+ <LAYOUT>
+ <NAME value="Standard" />
+ <TABULATOR ptpos="28.4444" type="0" />
+ <TABULATOR ptpos="72" type="0" />
+ <TABULATOR ptpos="510.222" type="0" />
+ <FORMAT id="1" >
+ <WEIGHT value="75" />
+ <SIZE value="12" />
+ <ITALIC value="0" />
+ <UNDERLINE value="0" />
+ <STRIKEOUT value="0" />
+ <VERTALIGN value="0" />
+ </FORMAT>
+ </LAYOUT>
+ </PARAGRAPH>
+ <PARAGRAPH>
+ <TEXT></TEXT>
+ <LAYOUT>
+ <NAME value="Standard" />
+ <TABULATOR ptpos="28.4444" type="0" />
+ <TABULATOR ptpos="72" type="0" />
+ <TABULATOR ptpos="510.222" type="0" />
+ <FORMAT id="1" >
+ <WEIGHT value="50" />
+ <SIZE value="12" />
+ <ITALIC value="0" />
+ <UNDERLINE value="0" />
+ <STRIKEOUT value="0" />
+ <VERTALIGN value="0" />
+ </FORMAT>
+ </LAYOUT>
+ </PARAGRAPH>
+ <PARAGRAPH>
+ <TEXT>Memorandum - A record of something which it is desired to remember; a note to help the memory. A brief or informal note in writing of some transaction, or an outline of an intended instrument; an instrument drawn up in a brief and compendious form.</TEXT>
+ <FORMATS>
+ <FORMAT id="1" pos="0" len="249" >
+ </FORMAT>
+ </FORMATS>
+ <LAYOUT>
+ <NAME value="Standard" />
+ <TABULATOR ptpos="28.4444" type="0" />
+ <TABULATOR ptpos="72" type="0" />
+ <TABULATOR ptpos="510.222" type="0" />
+ <FORMAT id="1" pos="0" len="249" >
+ <WEIGHT value="50" />
+ <SIZE value="12" />
+ <ITALIC value="0" />
+ <UNDERLINE value="0" />
+ <STRIKEOUT value="0" />
+ <VERTALIGN value="0" />
+ </FORMAT>
+ </LAYOUT>
+ </PARAGRAPH>
+ <PARAGRAPH>
+ <TEXT></TEXT>
+ <LAYOUT>
+ <NAME value="Standard" />
+ <TABULATOR ptpos="28.4444" type="0" />
+ <TABULATOR ptpos="72" type="0" />
+ <TABULATOR ptpos="510.222" type="0" />
+ <FORMAT id="1" >
+ <WEIGHT value="50" />
+ <SIZE value="12" />
+ <ITALIC value="0" />
+ <UNDERLINE value="0" />
+ <STRIKEOUT value="0" />
+ <VERTALIGN value="0" />
+ </FORMAT>
+ </LAYOUT>
+ </PARAGRAPH>
+ <PARAGRAPH>
+ <TEXT>Memorandum check, a check given as an acknowledgment of indebtedness, but with the understanding that it will not be presented at bank unless the maker fails to take it up on the day the debt becomes due. It usually has Mem. written on its face. </TEXT>
+ <FORMATS>
+ <FORMAT id="1" pos="0" len="246" >
+ </FORMAT>
+ </FORMATS>
+ <LAYOUT>
+ <NAME value="Standard" />
+ <TABULATOR ptpos="28.4444" type="0" />
+ <TABULATOR ptpos="72" type="0" />
+ <TABULATOR ptpos="510.222" type="0" />
+ <FORMAT id="1" pos="0" len="246" >
+ <WEIGHT value="50" />
+ <SIZE value="12" />
+ <ITALIC value="0" />
+ <UNDERLINE value="0" />
+ <STRIKEOUT value="0" />
+ <VERTALIGN value="0" />
+ </FORMAT>
+ </LAYOUT>
+ </PARAGRAPH>
+ <PARAGRAPH>
+ <TEXT>(Webster's Revised Unabridged Dictionary (1913))</TEXT>
+ <FORMATS>
+ <FORMAT id="1" pos="0" len="48" >
+ </FORMAT>
+ </FORMATS>
+ <LAYOUT>
+ <NAME value="Standard" />
+ <TABULATOR ptpos="28.4444" type="0" />
+ <TABULATOR ptpos="72" type="0" />
+ <TABULATOR ptpos="510.222" type="0" />
+ <FORMAT id="1" pos="0" len="48" >
+ <WEIGHT value="50" />
+ <SIZE value="12" />
+ <ITALIC value="0" />
+ <UNDERLINE value="0" />
+ <STRIKEOUT value="0" />
+ <VERTALIGN value="0" />
+ </FORMAT>
+ </LAYOUT>
+ </PARAGRAPH>
+ <PARAGRAPH>
+ <TEXT></TEXT>
+ <LAYOUT>
+ <NAME value="Standard" />
+ <TABULATOR ptpos="28.4444" type="0" />
+ <TABULATOR ptpos="72" type="0" />
+ <TABULATOR ptpos="510.222" type="0" />
+ <FORMAT id="1" >
+ <WEIGHT value="50" />
+ <SIZE value="12" />
+ <ITALIC value="0" />
+ <UNDERLINE value="0" />
+ <STRIKEOUT value="0" />
+ <VERTALIGN value="0" />
+ </FORMAT>
+ </LAYOUT>
+ </PARAGRAPH>
+ <PARAGRAPH>
+ <TEXT></TEXT>
+ <LAYOUT>
+ <NAME value="Standard" />
+ <TABULATOR ptpos="28.4444" type="0" />
+ <TABULATOR ptpos="72" type="0" />
+ <TABULATOR ptpos="510.222" type="0" />
+ <FORMAT id="1" >
+ <WEIGHT value="50" />
+ <SIZE value="12" />
+ <ITALIC value="0" />
+ <UNDERLINE value="0" />
+ <STRIKEOUT value="0" />
+ <VERTALIGN value="0" />
+ </FORMAT>
+ </LAYOUT>
+ </PARAGRAPH>
+ <PARAGRAPH>
+ <TEXT>xx</TEXT>
+ <FORMATS>
+ <FORMAT id="1" pos="0" len="2" >
+ </FORMAT>
+ </FORMATS>
+ <LAYOUT>
+ <NAME value="Standard" />
+ <TABULATOR ptpos="28.4444" type="0" />
+ <TABULATOR ptpos="72" type="0" />
+ <TABULATOR ptpos="510.222" type="0" />
+ <FORMAT id="1" pos="0" len="2" >
+ <WEIGHT value="50" />
+ <SIZE value="12" />
+ <ITALIC value="0" />
+ <UNDERLINE value="0" />
+ <STRIKEOUT value="0" />
+ <VERTALIGN value="0" />
+ </FORMAT>
+ </LAYOUT>
+ </PARAGRAPH>
+ <PARAGRAPH>
+ <TEXT></TEXT>
+ <LAYOUT>
+ <NAME value="Standard" />
+ <TABULATOR ptpos="28.4444" type="0" />
+ <TABULATOR ptpos="72" type="0" />
+ <TABULATOR ptpos="510.222" type="0" />
+ <FORMAT id="1" >
+ <WEIGHT value="50" />
+ <SIZE value="12" />
+ <ITALIC value="0" />
+ <UNDERLINE value="0" />
+ <STRIKEOUT value="0" />
+ <VERTALIGN value="0" />
+ </FORMAT>
+ </LAYOUT>
+ </PARAGRAPH>
+ <PARAGRAPH>
+ <TEXT></TEXT>
+ <LAYOUT>
+ <NAME value="Standard" />
+ <TABULATOR ptpos="28.4444" type="0" />
+ <TABULATOR ptpos="72" type="0" />
+ <TABULATOR ptpos="510.222" type="0" />
+ <FORMAT id="1" >
+ <WEIGHT value="50" />
+ <SIZE value="12" />
+ <ITALIC value="0" />
+ <UNDERLINE value="0" />
+ <STRIKEOUT value="0" />
+ <VERTALIGN value="0" />
+ </FORMAT>
+ </LAYOUT>
+ </PARAGRAPH>
+ <PARAGRAPH>
+ <TEXT>Attachment</TEXT>
+ <FORMATS>
+ <FORMAT id="1" pos="0" len="10" >
+ </FORMAT>
+ </FORMATS>
+ <LAYOUT>
+ <NAME value="Standard" />
+ <TABULATOR ptpos="28.4444" type="0" />
+ <TABULATOR ptpos="72" type="0" />
+ <TABULATOR ptpos="510.222" type="0" />
+ <FORMAT id="1" pos="0" len="10" >
+ <WEIGHT value="50" />
+ <SIZE value="12" />
+ <ITALIC value="0" />
+ <UNDERLINE value="0" />
+ <STRIKEOUT value="0" />
+ <VERTALIGN value="0" />
+ </FORMAT>
+ </LAYOUT>
+ </PARAGRAPH>
+ <PARAGRAPH>
+ <TEXT></TEXT>
+ <LAYOUT>
+ <NAME value="Standard" />
+ <TABULATOR ptpos="28.4444" type="0" />
+ <TABULATOR ptpos="72" type="0" />
+ <TABULATOR ptpos="510.222" type="0" />
+ <FORMAT id="1" >
+ <WEIGHT value="50" />
+ <SIZE value="12" />
+ <ITALIC value="0" />
+ <UNDERLINE value="0" />
+ <STRIKEOUT value="0" />
+ <VERTALIGN value="0" />
+ </FORMAT>
+ </LAYOUT>
+ </PARAGRAPH>
+ <PARAGRAPH>
+ <TEXT></TEXT>
+ <LAYOUT>
+ <NAME value="Standard" />
+ <TABULATOR ptpos="28.4444" type="0" />
+ <TABULATOR ptpos="72" type="0" />
+ <TABULATOR ptpos="510.222" type="0" />
+ <FORMAT id="1" >
+ <WEIGHT value="50" />
+ <SIZE value="12" />
+ <ITALIC value="0" />
+ <UNDERLINE value="0" />
+ <STRIKEOUT value="0" />
+ <VERTALIGN value="0" />
+ </FORMAT>
+ </LAYOUT>
+ </PARAGRAPH>
+ <PARAGRAPH>
+ <TEXT></TEXT>
+ <LAYOUT>
+ <NAME value="Standard" />
+ <TABULATOR ptpos="28.4444" type="0" />
+ <TABULATOR ptpos="72" type="0" />
+ <TABULATOR ptpos="510.222" type="0" />
+ <FORMAT id="1" >
+ <WEIGHT value="50" />
+ <SIZE value="12" />
+ <ITALIC value="0" />
+ <UNDERLINE value="0" />
+ <STRIKEOUT value="0" />
+ <VERTALIGN value="0" />
+ </FORMAT>
+ </LAYOUT>
+ </PARAGRAPH>
+ <PARAGRAPH>
+ <TEXT></TEXT>
+ <LAYOUT>
+ <NAME value="Standard" />
+ <TABULATOR ptpos="28.4444" type="0" />
+ <TABULATOR ptpos="72" type="0" />
+ <TABULATOR ptpos="510.222" type="0" />
+ <FORMAT id="1" >
+ <WEIGHT value="50" />
+ <SIZE value="12" />
+ <ITALIC value="0" />
+ <UNDERLINE value="0" />
+ <STRIKEOUT value="0" />
+ <VERTALIGN value="0" />
+ </FORMAT>
+ </LAYOUT>
+ </PARAGRAPH>
+ <PARAGRAPH>
+ <TEXT></TEXT>
+ <LAYOUT>
+ <NAME value="Standard" />
+ <TABULATOR ptpos="28.4444" type="0" />
+ <TABULATOR ptpos="72" type="0" />
+ <TABULATOR ptpos="510.222" type="0" />
+ <FORMAT id="1" >
+ <WEIGHT value="50" />
+ <SIZE value="12" />
+ <ITALIC value="0" />
+ <UNDERLINE value="0" />
+ <STRIKEOUT value="0" />
+ <VERTALIGN value="0" />
+ </FORMAT>
+ </LAYOUT>
+ </PARAGRAPH>
+ <PARAGRAPH>
+ <TEXT></TEXT>
+ <LAYOUT>
+ <NAME value="Standard" />
+ <TABULATOR ptpos="28.4444" type="0" />
+ <TABULATOR ptpos="72" type="0" />
+ <TABULATOR ptpos="510.222" type="0" />
+ <FORMAT id="1" >
+ <WEIGHT value="50" />
+ <SIZE value="12" />
+ <ITALIC value="0" />
+ <UNDERLINE value="0" />
+ <STRIKEOUT value="0" />
+ <VERTALIGN value="0" />
+ </FORMAT>
+ </LAYOUT>
+ </PARAGRAPH>
+ <PARAGRAPH>
+ <TEXT></TEXT>
+ <LAYOUT>
+ <NAME value="Standard" />
+ <TABULATOR ptpos="28.4444" type="0" />
+ <TABULATOR ptpos="72" type="0" />
+ <TABULATOR ptpos="510.222" type="0" />
+ <FORMAT id="1" >
+ <WEIGHT value="50" />
+ <SIZE value="12" />
+ <ITALIC value="0" />
+ <UNDERLINE value="0" />
+ <STRIKEOUT value="0" />
+ <VERTALIGN value="0" />
+ </FORMAT>
+ </LAYOUT>
+ </PARAGRAPH>
+ <PARAGRAPH>
+ <TEXT></TEXT>
+ <LAYOUT>
+ <NAME value="Standard" />
+ <TABULATOR ptpos="28.4444" type="0" />
+ <TABULATOR ptpos="72" type="0" />
+ <TABULATOR ptpos="510.222" type="0" />
+ <FORMAT id="1" >
+ <WEIGHT value="50" />
+ <SIZE value="12" />
+ <ITALIC value="0" />
+ <UNDERLINE value="0" />
+ <STRIKEOUT value="0" />
+ <VERTALIGN value="0" />
+ </FORMAT>
+ </LAYOUT>
+ </PARAGRAPH>
+ <PARAGRAPH>
+ <TEXT></TEXT>
+ <LAYOUT>
+ <NAME value="Standard" />
+ <TABULATOR ptpos="28.4444" type="0" />
+ <TABULATOR ptpos="72" type="0" />
+ <TABULATOR ptpos="510.222" type="0" />
+ <FORMAT id="1" >
+ <WEIGHT value="50" />
+ <SIZE value="12" />
+ <ITALIC value="0" />
+ <UNDERLINE value="0" />
+ <STRIKEOUT value="0" />
+ <VERTALIGN value="0" />
+ </FORMAT>
+ </LAYOUT>
+ </PARAGRAPH>
+ </FRAMESET>
+ <FRAMESET frameType="1" frameInfo="1" name="First Page Header" visible="0" >
+ <FRAME runaround="1" copy="0" right="567" newFrameBehavior="2" left="28" bottom="62" runaroundGap="2.83465" top="42" autoCreateNewFrame="0" />
+ <PARAGRAPH>
+ <TEXT></TEXT>
+ <LAYOUT>
+ <NAME value="Standard" />
+ <FORMAT id="1" >
+ <WEIGHT value="50" />
+ <SIZE value="12" />
+ <ITALIC value="0" />
+ <UNDERLINE value="0" />
+ <STRIKEOUT value="0" />
+ <VERTALIGN value="0" />
+ </FORMAT>
+ </LAYOUT>
+ </PARAGRAPH>
+ </FRAMESET>
+ <FRAMESET frameType="1" frameInfo="3" name="Even Pages Header" visible="0" >
+ <FRAME runaround="1" copy="0" right="567" newFrameBehavior="2" left="28" bottom="62" runaroundGap="2.83465" top="42" autoCreateNewFrame="0" />
+ <PARAGRAPH>
+ <TEXT></TEXT>
+ <LAYOUT>
+ <NAME value="Standard" />
+ <FORMAT id="1" >
+ <WEIGHT value="50" />
+ <SIZE value="12" />
+ <ITALIC value="0" />
+ <UNDERLINE value="0" />
+ <STRIKEOUT value="0" />
+ <VERTALIGN value="0" />
+ </FORMAT>
+ </LAYOUT>
+ </PARAGRAPH>
+ </FRAMESET>
+ <FRAMESET frameType="1" frameInfo="2" name="Odd Pages Header" visible="0" >
+ <FRAME runaround="1" copy="0" right="567" newFrameBehavior="2" left="28" bottom="62" runaroundGap="2.83465" top="42" autoCreateNewFrame="0" />
+ <PARAGRAPH>
+ <TEXT></TEXT>
+ <LAYOUT>
+ <NAME value="Standard" />
+ <FORMAT id="1" >
+ <WEIGHT value="50" />
+ <SIZE value="12" />
+ <ITALIC value="0" />
+ <UNDERLINE value="0" />
+ <STRIKEOUT value="0" />
+ <VERTALIGN value="0" />
+ </FORMAT>
+ </LAYOUT>
+ </PARAGRAPH>
+ </FRAMESET>
+ <FRAMESET frameType="1" frameInfo="4" name="First Page Footer" visible="0" >
+ <FRAME runaround="1" copy="0" right="567" newFrameBehavior="2" left="28" bottom="799" runaroundGap="2.83465" top="779" autoCreateNewFrame="0" />
+ <PARAGRAPH>
+ <TEXT></TEXT>
+ <LAYOUT>
+ <NAME value="Standard" />
+ <FORMAT id="1" >
+ <WEIGHT value="50" />
+ <SIZE value="12" />
+ <ITALIC value="0" />
+ <UNDERLINE value="0" />
+ <STRIKEOUT value="0" />
+ <VERTALIGN value="0" />
+ </FORMAT>
+ </LAYOUT>
+ </PARAGRAPH>
+ </FRAMESET>
+ <FRAMESET frameType="1" frameInfo="6" name="Even Pages Footer" visible="0" >
+ <FRAME runaround="1" copy="0" right="567" newFrameBehavior="2" left="28" bottom="799" runaroundGap="2.83465" top="779" autoCreateNewFrame="0" />
+ <PARAGRAPH>
+ <TEXT></TEXT>
+ <LAYOUT>
+ <NAME value="Standard" />
+ <FORMAT id="1" >
+ <WEIGHT value="50" />
+ <SIZE value="12" />
+ <ITALIC value="0" />
+ <UNDERLINE value="0" />
+ <STRIKEOUT value="0" />
+ <VERTALIGN value="0" />
+ </FORMAT>
+ </LAYOUT>
+ </PARAGRAPH>
+ </FRAMESET>
+ <FRAMESET frameType="1" frameInfo="5" name="Odd Pages Footer" visible="0" >
+ <FRAME runaround="1" copy="0" right="567" newFrameBehavior="2" left="28" bottom="799" runaroundGap="2.83465" top="779" autoCreateNewFrame="0" />
+ <PARAGRAPH>
+ <TEXT></TEXT>
+ <LAYOUT>
+ <NAME value="Standard" />
+ <FORMAT id="1" >
+ <WEIGHT value="50" />
+ <SIZE value="12" />
+ <ITALIC value="0" />
+ <UNDERLINE value="0" />
+ <STRIKEOUT value="0" />
+ <VERTALIGN value="0" />
+ </FORMAT>
+ </LAYOUT>
+ </PARAGRAPH>
+ </FRAMESET>
+ <FRAMESET frameType="1" frameInfo="7" name="Footnotes" visible="0" >
+ <FRAME runaround="1" copy="0" right="567" newFrameBehavior="0" left="28" bottom="799" runaroundGap="2.83465" top="779" autoCreateNewFrame="0" />
+ <PARAGRAPH>
+ <TEXT></TEXT>
+ <LAYOUT>
+ <NAME value="Standard" />
+ <FORMAT id="1" >
+ <WEIGHT value="50" />
+ <SIZE value="12" />
+ <ITALIC value="0" />
+ <UNDERLINE value="0" />
+ <STRIKEOUT value="0" />
+ <VERTALIGN value="0" />
+ </FORMAT>
+ </LAYOUT>
+ </PARAGRAPH>
+ </FRAMESET>
+ </FRAMESETS>
+ <STYLES>
+ <STYLE>
+ <NAME value="Standard" />
+ <FOLLOWING name="Standard" />
+ <FORMAT id="1" >
+ <WEIGHT value="50" />
+ <ITALIC value="0" />
+ <UNDERLINE value="0" />
+ <STRIKEOUT value="0" />
+ <VERTALIGN value="0" />
+ </FORMAT>
+ </STYLE>
+ <STYLE>
+ <NAME value="Document Title" />
+ <FLOW align="center" />
+ <FOLLOWING name="Document Title" />
+ <FORMAT id="1" >
+ <WEIGHT value="75" />
+ <SIZE value="24" />
+ <ITALIC value="0" />
+ <UNDERLINE value="0" />
+ <STRIKEOUT value="0" />
+ <VERTALIGN value="0" />
+ </FORMAT>
+ </STYLE>
+ <STYLE outline="true">
+ <NAME value="Head 1" />
+ <COUNTER numberingtype="1" righttext="." type="1" depth="0" display-levels="1"/>
+ <FOLLOWING name="Head 1" />
+ <FORMAT id="1" >
+ <WEIGHT value="75" />
+ <SIZE value="20" />
+ <ITALIC value="0" />
+ <UNDERLINE value="0" />
+ <STRIKEOUT value="0" />
+ <VERTALIGN value="0" />
+ </FORMAT>
+ </STYLE>
+ <STYLE outline="true">
+ <NAME value="Head 2" />
+ <COUNTER numberingtype="1" righttext="." type="1" depth="1" display-levels="2" />
+ <FOLLOWING name="Head 2" />
+ <FORMAT id="1" >
+ <WEIGHT value="75" />
+ <SIZE value="16" />
+ <ITALIC value="0" />
+ <UNDERLINE value="0" />
+ <STRIKEOUT value="0" />
+ <VERTALIGN value="0" />
+ </FORMAT>
+ </STYLE>
+ <STYLE outline="true">
+ <NAME value="Head 3" />
+ <COUNTER numberingtype="1" righttext="." type="1" depth="2" display-levels="3"/>
+ <FOLLOWING name="Head 3" />
+ <FORMAT id="1" >
+ <WEIGHT value="75" />
+ <SIZE value="12" />
+ <ITALIC value="0" />
+ <UNDERLINE value="0" />
+ <STRIKEOUT value="0" />
+ <VERTALIGN value="0" />
+ </FORMAT>
+ </STYLE>
+ <STYLE>
+ <NAME value="Enumerated List" />
+ <COUNTER numberingtype="0" righttext="." type="1" depth="0" />
+ <FOLLOWING name="Enumerated List" />
+ <FORMAT id="1" >
+ <WEIGHT value="50" />
+ <SIZE value="12" />
+ <ITALIC value="0" />
+ <UNDERLINE value="0" />
+ <STRIKEOUT value="0" />
+ <VERTALIGN value="0" />
+ </FORMAT>
+ </STYLE>
+ <STYLE>
+ <NAME value="Alphabetical List" />
+ <COUNTER numberingtype="0" righttext=")" type="2" depth="0" />
+ <FOLLOWING name="Alphabetical List" />
+ <FORMAT id="1" >
+ <WEIGHT value="50" />
+ <SIZE value="12" />
+ <ITALIC value="0" />
+ <UNDERLINE value="0" />
+ <STRIKEOUT value="0" />
+ <VERTALIGN value="0" />
+ </FORMAT>
+ </STYLE>
+ <STYLE>
+ <NAME value="Bullet List" />
+ <COUNTER numberingtype="0" type="10" depth="0" />
+ <FOLLOWING name="Bullet List" />
+ <FORMAT id="1" >
+ <WEIGHT value="50" />
+ <SIZE value="12" />
+ <ITALIC value="0" />
+ <UNDERLINE value="0" />
+ <STRIKEOUT value="0" />
+ <VERTALIGN value="0" />
+ </FORMAT>
+ </STYLE>
+ </STYLES>
+ <PIXMAPS/>
+ <CLIPARTS/>
+ <SERIALL/>
+</DOC>
diff --git a/kword/templates/Wordprocessing/PlainText.kwt b/kword/templates/Wordprocessing/PlainText.kwt
new file mode 100644
index 00000000..d23e4046
--- /dev/null
+++ b/kword/templates/Wordprocessing/PlainText.kwt
@@ -0,0 +1,85 @@
+<?xml version="1.0" encoding="UTF-8"?><!DOCTYPE DOC >
+<DOC mime="application/x-kword" syntaxVersion="3" editor="KWord" >
+ <PAPER width="595.277" zoom="100" spHeadBody="9" format="1" height="841.891" fType="0" orientation="0" hType="0" spFootBody="9" columns="1" >
+ <PAPERBORDERS right="57" left="57" bottom="42" top="42" />
+ </PAPER>
+ <ATTRIBUTES standardpage="1" hasFooter="0" unit="mm" hasHeader="0" processing="0" />
+ <FRAMESETS>
+ <FRAMESET removable="0" frameType="1" frameInfo="0" visible="1" >
+ <FRAME runaround="1" right="566" left="28" bottom="798" runaroundGap="2" top="42" />
+ </FRAMESET>
+ </FRAMESETS>
+ <STYLES>
+ <STYLE>
+ <NAME value="Standard" />
+ <FOLLOWING name="Standard" />
+ <FORMAT id="1">
+ <!-- Use KDE settings for the font -->
+ </FORMAT>
+ </STYLE>
+ <STYLE>
+ <NAME value="Document Title" />
+ <FLOW align="center" />
+ <FOLLOWING name="Standard" />
+ <FORMAT id="1" >
+ <!-- Use KDE settings for the font family -->
+ <WEIGHT value="75" />
+ <SIZE value="24" />
+ </FORMAT>
+ </STYLE>
+ <STYLE outline="true">
+ <NAME value="Head 1" />
+ <COUNTER numberingtype="1" righttext="." type="1" start="1" depth="0" display-levels="1"/>
+ <FOLLOWING name="Standard" />
+ <FORMAT id="1">
+ <!-- Use KDE settings for the font family -->
+ <SIZE value="20" />
+ <WEIGHT value="75" />
+ </FORMAT>
+ </STYLE>
+ <STYLE outline="true">
+ <NAME value="Head 2" />
+ <COUNTER numberingtype="1" righttext="." type="1" start="1" depth="1" display-levels="2"/>
+ <FOLLOWING name="Standard" />
+ <FORMAT id="1">
+ <!-- Use KDE settings for the font family -->
+ <SIZE value="16" />
+ <WEIGHT value="75" />
+ </FORMAT>
+ </STYLE>
+ <STYLE outline="true">
+ <NAME value="Head 3" />
+ <COUNTER numberingtype="1" righttext="." type="1" start="1" depth="2" display-levels="3"/>
+ <FOLLOWING name="Standard" />
+ <FORMAT id="1">
+ <!-- Use KDE settings for the font family -->
+ <SIZE value="12" />
+ <WEIGHT value="75" />
+ </FORMAT>
+ </STYLE>
+ <STYLE>
+ <NAME value="Enumerated List" />
+ <COUNTER numberingtype="0" righttext="." type="1" start="1" depth="0" />
+ <FOLLOWING name="Enumerated List" />
+ <FORMAT id="1">
+ <!-- Use KDE settings for the font -->
+ </FORMAT>
+ </STYLE>
+ <STYLE>
+ <NAME value="Alphabetical List" />
+ <COUNTER numberingtype="0" righttext=")" type="2" start="1" depth="0" />
+ <FOLLOWING name="Alphabetical List" />
+ <FORMAT id="1">
+ <!-- Use KDE settings for the font -->
+ </FORMAT>
+ </STYLE>
+ <STYLE>
+ <NAME value="Bullet List" />
+ <COUNTER numberingtype="0" type="10" start="1" depth="0" />
+ <FOLLOWING name="Bullet List" />
+ <FORMAT id="1">
+ <!-- Use KDE settings for the font -->
+ </FORMAT>
+ </STYLE>
+ </STYLES>
+</DOC>
diff --git a/kword/templates/Wordprocessing/ProfessionalA4.desktop b/kword/templates/Wordprocessing/ProfessionalA4.desktop
new file mode 100644
index 00000000..5db088ba
--- /dev/null
+++ b/kword/templates/Wordprocessing/ProfessionalA4.desktop
@@ -0,0 +1,85 @@
+[Desktop Entry]
+Type=Link
+URL=.source/ProfessionalA4.odt
+Name=Professional Letter
+Name[bg]=Професионално писмо
+Name[br]=Lizher vicherel
+Name[ca]=Carta professional
+Name[da]=Professionelt brev
+Name[de]=Professioneller Brief
+Name[el]=Επαγγελματική επιστολή
+Name[eo]=Profesia Letero
+Name[es]=Carta profesional
+Name[et]=Professionaalne
+Name[fa]=نامۀ حرفه‌ای
+Name[fr]=Lettre professionnelle
+Name[fy]=profesjonele brief
+Name[ga]=Litir Phroifisiúta
+Name[gl]=Carta Profisional
+Name[he]=מכתב מקצועי
+Name[hr]=Profesionalno pismo
+Name[hu]=Hivatalos levél
+Name[is]=Atvinnumannalegt bréf
+Name[it]=Lettera professionale
+Name[ja]=公式な手紙
+Name[km]=សំបុត្រ​ជំនាញ
+Name[lt]=Profesionalus laiškas
+Name[lv]=Profesionāla vēstule
+Name[nb]=Profesjonelt brev
+Name[nds]=Profeschonell Breef
+Name[ne]=व्यवसायिक पत्र
+Name[nl]=Professionele brief
+Name[pl]=Profesjonalny list
+Name[pt]=Carta Profissional
+Name[pt_BR]=Carta Profissional
+Name[ru]=Письмо
+Name[se]=Profešunealla reive
+Name[sk]=Professionálny list
+Name[sl]=Profesionalno pismo
+Name[sr]=Професионално писмо
+Name[sr@Latn]=Profesionalno pismo
+Name[sv]=Professionellt US Letter
+Name[uk]=Професіійний лист
+Name[uz]=Rasmiy xat
+Name[uz@cyrillic]=Расмий хат
+Name[zh_CN]=专业信函
+Name[zh_TW]=職業信
+Comment=Creates a blank document with wide margins for professional looking documents
+Comment[bg]=Създаване на празен документ с широки полета за професионално изглеждащи документи
+Comment[ca]=Crea un document buit amb marges amples per a documents d'aspecte professional
+Comment[da]=Laver et blankt dokument med brede margener for et professionelt udseende dokument.
+Comment[de]=Erstellt ein leeres Dokument mit breiten Rändern für professionell aussehende Dokumente
+Comment[el]=Δημιουργεί ένα κενό έγγραφο με μεγάλα περιθώρια για επαγγελματική εμφάνιση εγγράφων
+Comment[es]=Crea un documento vacío con márgenes amplios para documentos de aspecto profesional
+Comment[et]=Loob dokumendi professionaalsetele dokumentidele iseloomulike laiade veeristega
+Comment[fa]=سندی خالی با حاشیه‌های عریض برای اسناد به نظر حرفه‌ای ایجاد می‌کند
+Comment[fi]=Luo tyhjän asiakirjan, jossa on leveät marginaalit
+Comment[fr]=Crée un document vide avec de grandes marges pour une apparence professionnelle
+Comment[fy]=Makket in leech dokumint oan mei brede marzjes foar in profesioneel úterlik
+Comment[gl]=Cría un documento en branco con marxes amplas para documentos con aspeito profisional
+Comment[hu]=Létrehoz egy üres dokumentumot széles margókkal hivatalos dokumentumokhoz
+Comment[is]=Býr til tómt skjal með breiðum spássíum fyrir atvinnumannalegt bréf
+Comment[it]=Crea un documento vuoto con ampi margini per documenti dall'aspetto professionale
+Comment[ja]=公式な文書にふさわしい広い余白付きの空のドキュメントを作成
+Comment[km]=បង្កើត​ឯកសារ​ទទេ​មួយ ដែល​មាន​រឹម​ធំទូលាយ សម្រាប់​ឯកសារ​ជំនាញៗ
+Comment[lv]=Izveido tukšu dokumentu ar platām maliņām kam vajadzētu izskatīties profesionāli
+Comment[nb]=Lager et tomt dokument med brede marger som gir profesjonelt utseende dokumenter
+Comment[nds]=Stellt en leddig Dokment mit breede Ränners för Dokmenten mit profeschonell Utsehn op
+Comment[ne]=व्यवसायिक हेराइ कागजातहरूका लागि चौडाइ सीमान्तहरू सहित खाली कागजात सिर्जना गर्दछ
+Comment[nl]=Maakt een leeg document aan met brede margins voor een professioneel uiterlijk
+Comment[pl]=Tworzy pusty dokument z szerokimi marginesami dla profesjonalnie wyglądających dokumentów
+Comment[pt]=Cria um documento em branco com margens largas para documentos com aspecto profissional
+Comment[pt_BR]=Cria um documento em branco com margens largas para documentos com aspecto profissional
+Comment[ru]=Шаблон письма с широкими полями
+Comment[se]=Ráhkada guorus dokumeanta mas leat govddes siidoravddat mii addá profešunealla dokumeanttaid
+Comment[sk]=Vytvára prázdny dokument so širokými okrajmi pre profesionálne dokumenty.
+Comment[sl]=Ustvari dokument z širokimi robovi za dokumente profesionalega videza
+Comment[sr]=Прави празан документ са широким маргинама за документе професионалног изгледа
+Comment[sr@Latn]=Pravi prazan dokument sa širokim marginama za dokumente profesionalnog izgleda
+Comment[sv]=Skapar ett tomt dokument med breda marginaler för dokument med professionellt utseende
+Comment[uk]=Створює порожній документ з широкими полями для професійного вигляду документів
+Comment[uz]=Mukammal koʻrinadigan boʻsh hujjatni yaratish
+Comment[uz@cyrillic]=Мукаммал кўринадиган бўш ҳужжатни яратиш
+Comment[zh_TW]=建立有寬邊界的空白文件
+Icon=template_a4
+X-KDE-MeasureSystem=metric
diff --git a/kword/templates/Wordprocessing/ProfessionalA4.odt b/kword/templates/Wordprocessing/ProfessionalA4.odt
new file mode 100644
index 00000000..6e0e1528
--- /dev/null
+++ b/kword/templates/Wordprocessing/ProfessionalA4.odt
Binary files differ
diff --git a/kword/templates/Wordprocessing/ProfessionalLetter.desktop b/kword/templates/Wordprocessing/ProfessionalLetter.desktop
new file mode 100644
index 00000000..b9d76d9c
--- /dev/null
+++ b/kword/templates/Wordprocessing/ProfessionalLetter.desktop
@@ -0,0 +1,85 @@
+[Desktop Entry]
+Type=Link
+URL=.source/ProfessionalLetter.odt
+Name=Professional Letter
+Name[bg]=Професионално писмо
+Name[br]=Lizher vicherel
+Name[ca]=Carta professional
+Name[da]=Professionelt brev
+Name[de]=Professioneller Brief
+Name[el]=Επαγγελματική επιστολή
+Name[eo]=Profesia Letero
+Name[es]=Carta profesional
+Name[et]=Professionaalne
+Name[fa]=نامۀ حرفه‌ای
+Name[fr]=Lettre professionnelle
+Name[fy]=profesjonele brief
+Name[ga]=Litir Phroifisiúta
+Name[gl]=Carta Profisional
+Name[he]=מכתב מקצועי
+Name[hr]=Profesionalno pismo
+Name[hu]=Hivatalos levél
+Name[is]=Atvinnumannalegt bréf
+Name[it]=Lettera professionale
+Name[ja]=公式な手紙
+Name[km]=សំបុត្រ​ជំនាញ
+Name[lt]=Profesionalus laiškas
+Name[lv]=Profesionāla vēstule
+Name[nb]=Profesjonelt brev
+Name[nds]=Profeschonell Breef
+Name[ne]=व्यवसायिक पत्र
+Name[nl]=Professionele brief
+Name[pl]=Profesjonalny list
+Name[pt]=Carta Profissional
+Name[pt_BR]=Carta Profissional
+Name[ru]=Письмо
+Name[se]=Profešunealla reive
+Name[sk]=Professionálny list
+Name[sl]=Profesionalno pismo
+Name[sr]=Професионално писмо
+Name[sr@Latn]=Profesionalno pismo
+Name[sv]=Professionellt US Letter
+Name[uk]=Професіійний лист
+Name[uz]=Rasmiy xat
+Name[uz@cyrillic]=Расмий хат
+Name[zh_CN]=专业信函
+Name[zh_TW]=職業信
+Comment=Creates a blank document with wide margins for professional looking documents
+Comment[bg]=Създаване на празен документ с широки полета за професионално изглеждащи документи
+Comment[ca]=Crea un document buit amb marges amples per a documents d'aspecte professional
+Comment[da]=Laver et blankt dokument med brede margener for et professionelt udseende dokument.
+Comment[de]=Erstellt ein leeres Dokument mit breiten Rändern für professionell aussehende Dokumente
+Comment[el]=Δημιουργεί ένα κενό έγγραφο με μεγάλα περιθώρια για επαγγελματική εμφάνιση εγγράφων
+Comment[es]=Crea un documento vacío con márgenes amplios para documentos de aspecto profesional
+Comment[et]=Loob dokumendi professionaalsetele dokumentidele iseloomulike laiade veeristega
+Comment[fa]=سندی خالی با حاشیه‌های عریض برای اسناد به نظر حرفه‌ای ایجاد می‌کند
+Comment[fi]=Luo tyhjän asiakirjan, jossa on leveät marginaalit
+Comment[fr]=Crée un document vide avec de grandes marges pour une apparence professionnelle
+Comment[fy]=Makket in leech dokumint oan mei brede marzjes foar in profesioneel úterlik
+Comment[gl]=Cría un documento en branco con marxes amplas para documentos con aspeito profisional
+Comment[hu]=Létrehoz egy üres dokumentumot széles margókkal hivatalos dokumentumokhoz
+Comment[is]=Býr til tómt skjal með breiðum spássíum fyrir atvinnumannalegt bréf
+Comment[it]=Crea un documento vuoto con ampi margini per documenti dall'aspetto professionale
+Comment[ja]=公式な文書にふさわしい広い余白付きの空のドキュメントを作成
+Comment[km]=បង្កើត​ឯកសារ​ទទេ​មួយ ដែល​មាន​រឹម​ធំទូលាយ សម្រាប់​ឯកសារ​ជំនាញៗ
+Comment[lv]=Izveido tukšu dokumentu ar platām maliņām kam vajadzētu izskatīties profesionāli
+Comment[nb]=Lager et tomt dokument med brede marger som gir profesjonelt utseende dokumenter
+Comment[nds]=Stellt en leddig Dokment mit breede Ränners för Dokmenten mit profeschonell Utsehn op
+Comment[ne]=व्यवसायिक हेराइ कागजातहरूका लागि चौडाइ सीमान्तहरू सहित खाली कागजात सिर्जना गर्दछ
+Comment[nl]=Maakt een leeg document aan met brede margins voor een professioneel uiterlijk
+Comment[pl]=Tworzy pusty dokument z szerokimi marginesami dla profesjonalnie wyglądających dokumentów
+Comment[pt]=Cria um documento em branco com margens largas para documentos com aspecto profissional
+Comment[pt_BR]=Cria um documento em branco com margens largas para documentos com aspecto profissional
+Comment[ru]=Шаблон письма с широкими полями
+Comment[se]=Ráhkada guorus dokumeanta mas leat govddes siidoravddat mii addá profešunealla dokumeanttaid
+Comment[sk]=Vytvára prázdny dokument so širokými okrajmi pre profesionálne dokumenty.
+Comment[sl]=Ustvari dokument z širokimi robovi za dokumente profesionalega videza
+Comment[sr]=Прави празан документ са широким маргинама за документе професионалног изгледа
+Comment[sr@Latn]=Pravi prazan dokument sa širokim marginama za dokumente profesionalnog izgleda
+Comment[sv]=Skapar ett tomt dokument med breda marginaler för dokument med professionellt utseende
+Comment[uk]=Створює порожній документ з широкими полями для професійного вигляду документів
+Comment[uz]=Mukammal koʻrinadigan boʻsh hujjatni yaratish
+Comment[uz@cyrillic]=Мукаммал кўринадиган бўш ҳужжатни яратиш
+Comment[zh_TW]=建立有寬邊界的空白文件
+Icon=template_a4
+X-KDE-MeasureSystem=imperial
diff --git a/kword/templates/Wordprocessing/ProfessionalLetter.odt b/kword/templates/Wordprocessing/ProfessionalLetter.odt
new file mode 100644
index 00000000..5fce8188
--- /dev/null
+++ b/kword/templates/Wordprocessing/ProfessionalLetter.odt
Binary files differ
diff --git a/kword/templates/Wordprocessing/TwoColumns.desktop b/kword/templates/Wordprocessing/TwoColumns.desktop
new file mode 100644
index 00000000..4c6d5aeb
--- /dev/null
+++ b/kword/templates/Wordprocessing/TwoColumns.desktop
@@ -0,0 +1,114 @@
+[Desktop Entry]
+Type=Link
+URL=.source/TwoColumns.kwt
+Name=Two Columns
+Name[af]=Twee Kolomme
+Name[ar]=عمودين
+Name[az]=İki Sütun
+Name[bg]=Две колони
+Name[br]=Daou vann
+Name[bs]=Dva stupca
+Name[ca]=Dues columnes
+Name[cs]=Dva sloupce
+Name[cy]=Dwy Golofn
+Name[da]=To søjler
+Name[de]=2-spaltig
+Name[el]=Δύο στήλες
+Name[eo]=Du kolumnoj
+Name[es]=Dos columnas
+Name[et]=Kaks veergu
+Name[eu]=Bi zutabe
+Name[fa]=دو ستون
+Name[fi]=Kaksi palstaa
+Name[fo]=Tveir teigar
+Name[fr]=Deux colonnes
+Name[fy]=Twa kolommen
+Name[ga]=Dhá Cholún
+Name[gl]=Dúas Colunas
+Name[he]=שני טורים
+Name[hi]=दो स्तम्भ
+Name[hr]=Dva stupca
+Name[hu]=Kétoszlopos
+Name[id]=Dua Kolom
+Name[is]=Tveir dálkar
+Name[it]=Due colonne
+Name[ja]=2 列
+Name[km]=ជួរ​ឈរ​ពីរ
+Name[lo]=ສອງຄໍລັມ
+Name[lt]=Dviem stulpeliais
+Name[lv]=Divas kolonnas
+Name[mk]=Две колони
+Name[ms]=Dua Lajur
+Name[mt]=Żewġ Kolonni
+Name[nb]=To spalter
+Name[nds]=Twee Striepen
+Name[ne]=दुई स्तम्भहरू
+Name[nl]=Twee kolommen
+Name[nn]=To kolonnar
+Name[pl]=Dwie kolumny
+Name[pt]=Duas Colunas
+Name[pt_BR]=Duas Colunas
+Name[ro]=Două coloane
+Name[ru]=Две колонки
+Name[se]=Guokte bálsttá
+Name[sk]=Dva stĺpce
+Name[sl]=Dva stolpca
+Name[sr]=Две колоне
+Name[sr@Latn]=Dve kolone
+Name[sv]=Två kolumner
+Name[ta]=இரு நிரல்கள்
+Name[tg]=Ду Сутунҳо
+Name[th]=สองคอลัมน์
+Name[tr]=İki Sütun
+Name[uk]=Два стовпчики
+Name[uz]=Ikkita ustun
+Name[uz@cyrillic]=Иккита устун
+Name[ven]=Kholumu mbili
+Name[wa]=Deus colones
+Name[xh]=Imihlathi Emibini
+Name[zh_CN]=两栏
+Name[zh_TW]=兩列
+Name[zu]=Amakholamu Amabili
+Comment=Creates an A4 document with two columns per page.
+Comment[bg]=Създаване на документ във формат A4 с две колони на страница.
+Comment[ca]=Crea un document A4 amb dues columnes per pàgina.
+Comment[cy]=Creu dogfen A4 efo dwy golofn ar y dudalen.
+Comment[da]=Opretter et A4-dokument med to søjler pr side
+Comment[de]=Erstellt ein zweispaltiges A4-Dokument.
+Comment[el]=Δημιουργεί ένα έγγραφο A4 με δύο στήλες ανά σελίδα.
+Comment[es]=Crea un documento A4 con dos columnas por página.
+Comment[et]=Loob A4 dokumendi, igal leheküljel kaks veergu.
+Comment[fa]=یک سند A4 با دو ستون در هر صفحه ایجاد می‌کند.
+Comment[fi]=Luo kaksipalstaisen A4-asiakirjan
+Comment[fr]=Crée un document A4 avec deux colonnes par page.
+Comment[fy]=Makket in A4-dokumint oan mei twa kolommen de side.
+Comment[ga]=Cruthaigh cáipéis A4 le dhá cholún sa leathanach.
+Comment[gl]=Cría un documento A4 con dúas colunas por páxina.
+Comment[he]=יצירת מסמך A4 עם שני טורים בדף
+Comment[hu]=Létrehoz egy kétoszlopos, A4-es méretű dokumentumot.
+Comment[is]=Býr til A4 skjal með tveimur dálkum á síðu.
+Comment[it]=Crea un documento A4 con due colonne per pagina.
+Comment[ja]=1 ページを 2 列に分割した A4 サイズのドキュメントを作成
+Comment[km]=បង្កើត​ឯកសារ A4 ដែល​មាន​ជួរ​ឈរ​ពីរ​ក្នុង​មួយ​ទំព័រ ។
+Comment[lv]=Izveido A4 formāta dokumentu ar divām kolonnām uz lapas
+Comment[nb]=Lager et A4 dokument med to spalter på hver side.
+Comment[nds]=Stellt en A4-Dokment mit twee Striepen per Siet op.
+Comment[ne]=प्रति पृष्ठ दुई स्तम्भ सहित एउटा A4 कागजात सिर्जना गर्दछ ।
+Comment[nl]=Maakt een A4-document aan met twee kolommen per pagina.
+Comment[pl]=Tworzy dokument formatu A4 w dwoma kolumnami na stronę.
+Comment[pt]=Cria um documento A4 com duas colunas por página.
+Comment[pt_BR]=Cria um documento A4 com duas colunas por página.
+Comment[ru]=Пустой документ формата A4 с двумя колонками
+Comment[se]=Ráhkada A4-dokumeanta mas leat guokte bálstta juohkke siiddus.
+Comment[sk]=Vytvorí dokument A4 s dvoma stĺpcami na stránku.
+Comment[sl]=Ustvari dokument A4 z dvema stolpcema na stran.
+Comment[sr]=Прави A4 документ са две колоне по страни.
+Comment[sr@Latn]=Pravi A4 dokument sa dve kolone po strani.
+Comment[sv]=Skapar ett A4-dokument med två kolumner per sida.
+Comment[uk]=Створює документ A4 з двома стовпчиками на сторінку.
+Comment[uz]=Ikki ustunli boʻsh A4 formatidagi hujjatni yaratish.
+Comment[uz@cyrillic]=Икки устунли бўш A4 форматидаги ҳужжатни яратиш.
+Comment[zh_CN]=创建每页两栏的 A4 文档。
+Comment[zh_TW]=建立一個每頁兩欄的 A4 文件。
+Icon=template_twocolumns
+X-KDE-MeasureSystem=metric
diff --git a/kword/templates/Wordprocessing/TwoColumns.kwt b/kword/templates/Wordprocessing/TwoColumns.kwt
new file mode 100644
index 00000000..f3dd95a1
--- /dev/null
+++ b/kword/templates/Wordprocessing/TwoColumns.kwt
@@ -0,0 +1,85 @@
+<?xml version="1.0" encoding="UTF-8"?><!DOCTYPE DOC >
+<DOC mime="application/x-kword" syntaxVersion="3" editor="KWord" >
+ <PAPER width="595.277" zoom="100" spHeadBody="9" format="1" height="841.891" fType="0" orientation="0" hType="0" columnspacing="5" spFootBody="9" columns="2" >
+ <PAPERBORDERS right="28" left="28" bottom="42" top="42" />
+ </PAPER>
+ <ATTRIBUTES standardpage="1" hasFooter="0" unit="mm" hasHeader="0" processing="0" />
+ <FRAMESETS>
+ <FRAMESET removable="0" frameType="1" frameInfo="0" visible="1" >
+ <FRAME runaround="1" right="294" left="28" bottom="798" runaroundGap="2" top="42" />
+ </FRAMESET>
+ </FRAMESETS>
+ <STYLES>
+ <STYLE>
+ <NAME value="Standard" />
+ <FOLLOWING name="Standard" />
+ <FORMAT id="1">
+ <!-- Use KDE settings for the font -->
+ </FORMAT>
+ </STYLE>
+ <STYLE>
+ <NAME value="Document Title" />
+ <FLOW align="center" />
+ <FOLLOWING name="Standard" />
+ <FORMAT id="1" >
+ <!-- Use KDE settings for the font family -->
+ <WEIGHT value="75" />
+ <SIZE value="24" />
+ </FORMAT>
+ </STYLE>
+ <STYLE outline="true">
+ <NAME value="Head 1" />
+ <COUNTER numberingtype="1" righttext="." type="1" start="1" depth="0" display-levels="1"/>
+ <FOLLOWING name="Standard" />
+ <FORMAT id="1">
+ <!-- Use KDE settings for the font family -->
+ <SIZE value="20" />
+ <WEIGHT value="75" />
+ </FORMAT>
+ </STYLE>
+ <STYLE outline="true">
+ <NAME value="Head 2" />
+ <COUNTER numberingtype="1" righttext="." type="1" start="1" depth="1" display-levels="2"/>
+ <FOLLOWING name="Standard" />
+ <FORMAT id="1">
+ <!-- Use KDE settings for the font family -->
+ <SIZE value="16" />
+ <WEIGHT value="75" />
+ </FORMAT>
+ </STYLE>
+ <STYLE outline="true">
+ <NAME value="Head 3" />
+ <COUNTER numberingtype="1" righttext="." type="1" start="1" depth="2" display-levels="3"/>
+ <FOLLOWING name="Standard" />
+ <FORMAT id="1">
+ <!-- Use KDE settings for the font family -->
+ <SIZE value="12" />
+ <WEIGHT value="75" />
+ </FORMAT>
+ </STYLE>
+ <STYLE>
+ <NAME value="Enumerated List" />
+ <COUNTER numberingtype="0" righttext="." type="1" start="1" depth="0" />
+ <FOLLOWING name="Enumerated List" />
+ <FORMAT id="1">
+ <!-- Use KDE settings for the font -->
+ </FORMAT>
+ </STYLE>
+ <STYLE>
+ <NAME value="Alphabetical List" />
+ <COUNTER numberingtype="0" righttext=")" type="2" start="1" depth="0" />
+ <FOLLOWING name="Alphabetical List" />
+ <FORMAT id="1">
+ <!-- Use KDE settings for the font -->
+ </FORMAT>
+ </STYLE>
+ <STYLE>
+ <NAME value="Bullet List" />
+ <COUNTER numberingtype="0" type="10" start="1" depth="0" />
+ <FOLLOWING name="Bullet List" />
+ <FORMAT id="1">
+ <!-- Use KDE settings for the font -->
+ </FORMAT>
+ </STYLE>
+ </STYLES>
+</DOC>
diff --git a/kword/templates/Wordprocessing/TwoColumnsLetter.desktop b/kword/templates/Wordprocessing/TwoColumnsLetter.desktop
new file mode 100644
index 00000000..fe689f53
--- /dev/null
+++ b/kword/templates/Wordprocessing/TwoColumnsLetter.desktop
@@ -0,0 +1,110 @@
+[Desktop Entry]
+Type=Link
+URL=.source/TwoColumns.kwt
+Name=Two Columns
+Name[af]=Twee Kolomme
+Name[ar]=عمودين
+Name[az]=İki Sütun
+Name[bg]=Две колони
+Name[br]=Daou vann
+Name[bs]=Dva stupca
+Name[ca]=Dues columnes
+Name[cs]=Dva sloupce
+Name[cy]=Dwy Golofn
+Name[da]=To søjler
+Name[de]=2-spaltig
+Name[el]=Δύο στήλες
+Name[eo]=Du kolumnoj
+Name[es]=Dos columnas
+Name[et]=Kaks veergu
+Name[eu]=Bi zutabe
+Name[fa]=دو ستون
+Name[fi]=Kaksi palstaa
+Name[fo]=Tveir teigar
+Name[fr]=Deux colonnes
+Name[fy]=Twa kolommen
+Name[ga]=Dhá Cholún
+Name[gl]=Dúas Colunas
+Name[he]=שני טורים
+Name[hi]=दो स्तम्भ
+Name[hr]=Dva stupca
+Name[hu]=Kétoszlopos
+Name[id]=Dua Kolom
+Name[is]=Tveir dálkar
+Name[it]=Due colonne
+Name[ja]=2 列
+Name[km]=ជួរ​ឈរ​ពីរ
+Name[lo]=ສອງຄໍລັມ
+Name[lt]=Dviem stulpeliais
+Name[lv]=Divas kolonnas
+Name[mk]=Две колони
+Name[ms]=Dua Lajur
+Name[mt]=Żewġ Kolonni
+Name[nb]=To spalter
+Name[nds]=Twee Striepen
+Name[ne]=दुई स्तम्भहरू
+Name[nl]=Twee kolommen
+Name[nn]=To kolonnar
+Name[pl]=Dwie kolumny
+Name[pt]=Duas Colunas
+Name[pt_BR]=Duas Colunas
+Name[ro]=Două coloane
+Name[ru]=Две колонки
+Name[se]=Guokte bálsttá
+Name[sk]=Dva stĺpce
+Name[sl]=Dva stolpca
+Name[sr]=Две колоне
+Name[sr@Latn]=Dve kolone
+Name[sv]=Två kolumner
+Name[ta]=இரு நிரல்கள்
+Name[tg]=Ду Сутунҳо
+Name[th]=สองคอลัมน์
+Name[tr]=İki Sütun
+Name[uk]=Два стовпчики
+Name[uz]=Ikkita ustun
+Name[uz@cyrillic]=Иккита устун
+Name[ven]=Kholumu mbili
+Name[wa]=Deus colones
+Name[xh]=Imihlathi Emibini
+Name[zh_CN]=两栏
+Name[zh_TW]=兩列
+Name[zu]=Amakholamu Amabili
+Comment=Creates a letter document with two columns per page.
+Comment[bg]=Създаване на документ във формат A4 с две колони на страница.
+Comment[ca]=Crea una carta amb dues columnes per pàgina.
+Comment[da]=Opretter et brev-dokument med to søjler pr side
+Comment[de]=Erstellt ein zweispaltiges Letter-Dokument.
+Comment[el]=Δημιουργεί ένα έγγραφο letter με δύο στήλες ανά σελίδα.
+Comment[es]=Crea un documento de carta con dos columnas por página.
+Comment[et]=Loob Letter dokumendi, igal leheküljel kaks veergu.
+Comment[fa]=یک سند نامه با دو ستون در هر صفحه ایجاد می‌کند.
+Comment[fi]=Luo kaksipalstaisen A4-asiakirjan
+Comment[fr]=Crée un document US Letter avec deux colonnes par page
+Comment[fy]=Makket in Letter-dokumint oan mei twa kolommen de side.
+Comment[gl]=Cría unha carta con dúas colunas por páxina.
+Comment[hu]=Létrehoz egy kétoszlopos, Letter méretű dokumentumot.
+Comment[is]=Býr til letter skjal með tveimur dálkum á síðu.
+Comment[it]=Crea un documento US Letter con due colonne per pagina.
+Comment[ja]=1ページを2列に分割したLetterサイズのドキュメントを作成
+Comment[km]=បង្ហាញ​ឯកសារ​សំបុត្រ​មួយ ដោយ​ចែក​ទំព័រ​ជា​ពីរ​ជួរឈរ ។
+Comment[nb]=Lager et letter-dokument med to spalter på hver side.
+Comment[nds]=Stellt en "US Letter"-Dokment mit twee Striepen per Siet op.
+Comment[ne]=प्रति पृष्ठ दुई स्तम्भ सहित चिठ्ठी कागजात सिर्जना गर्दछ ।
+Comment[nl]=Maakt een Letter-document aan met twee kolommen per pagina.
+Comment[pl]=Tworzy list z dwoma kolumnami na stronę.
+Comment[pt]=Cria uma carta com duas colunas por página.
+Comment[pt_BR]=Cria uma carta com duas colunas por página.
+Comment[ru]=Пустой документ формата US Letter с двумя колонками
+Comment[se]=Ráhkada reivve mas leat guokte bálstta juohkke siiddus.
+Comment[sk]=Vytvorí dokument formátu letter s dvoma stĺpcami na stránku.
+Comment[sl]=Ustvari dokument velikosti »letter« z dvema stolpcema na stran.
+Comment[sr]=Прави документ писма са две колоне по страни
+Comment[sr@Latn]=Pravi dokument pisma sa dve kolone po strani
+Comment[sv]=Skapar ett US Letter-dokument med två kolumner per sida.
+Comment[uk]=Створює документ для паперу "letter" з двома стовпчиками на сторінку.
+Comment[uz]=Ikki ustunli boʻsh xat formatidagi hujjatni yaratish.
+Comment[uz@cyrillic]=Икки устунли бўш хат форматидаги ҳужжатни яратиш.
+Comment[zh_CN]=创建每页两栏的信函文档。
+Comment[zh_TW]=建立一個每頁兩欄的 letter 文件。
+Icon=template_twocolumns
+X-KDE-MeasureSystem=imperial
diff --git a/kword/templates/Wordprocessing/TwoColumnsLetter.kwt b/kword/templates/Wordprocessing/TwoColumnsLetter.kwt
new file mode 100644
index 00000000..ba824e39
--- /dev/null
+++ b/kword/templates/Wordprocessing/TwoColumnsLetter.kwt
@@ -0,0 +1,85 @@
+<?xml version="1.0" encoding="UTF-8"?><!DOCTYPE DOC >
+<DOC mime="application/x-kword" syntaxVersion="3" editor="KWord" >
+ <PAPER width="612.285" zoom="100" spHeadBody="9.92128" format="3" height="790.868" fType="0" orientation="0" hType="0" columnspacing="15" spFootBody="9.92128" columns="2" >
+ <PAPERBORDERS right="56.693" left="56.693" bottom="42.5198" top="42.5198" />
+ </PAPER>
+ <ATTRIBUTES standardpage="1" hasFooter="0" unit="mm" hasHeader="0" processing="0" />
+ <FRAMESETS>
+ <FRAMESET removable="0" frameType="1" frameInfo="0" visible="1" >
+ <FRAME runaround="1" right="294" left="28" bottom="798" runaroundGap="2" top="42" />
+ </FRAMESET>
+ </FRAMESETS>
+ <STYLES>
+ <STYLE>
+ <NAME value="Standard" />
+ <FOLLOWING name="Standard" />
+ <FORMAT id="1">
+ <!-- Use KDE settings for the font -->
+ </FORMAT>
+ </STYLE>
+ <STYLE>
+ <NAME value="Document Title" />
+ <FLOW align="center" />
+ <FOLLOWING name="Standard" />
+ <FORMAT id="1" >
+ <!-- Use KDE settings for the font family -->
+ <WEIGHT value="75" />
+ <SIZE value="24" />
+ </FORMAT>
+ </STYLE>
+ <STYLE outline="true">
+ <NAME value="Head 1" />
+ <COUNTER numberingtype="1" righttext="." type="1" start="1" depth="0" display-levels="1"/>
+ <FOLLOWING name="Standard" />
+ <FORMAT id="1">
+ <!-- Use KDE settings for the font family -->
+ <SIZE value="20" />
+ <WEIGHT value="75" />
+ </FORMAT>
+ </STYLE>
+ <STYLE outline="true">
+ <NAME value="Head 2" />
+ <COUNTER numberingtype="1" righttext="." type="1" start="1" depth="1" display-levels="2"/>
+ <FOLLOWING name="Standard" />
+ <FORMAT id="1">
+ <!-- Use KDE settings for the font family -->
+ <SIZE value="16" />
+ <WEIGHT value="75" />
+ </FORMAT>
+ </STYLE>
+ <STYLE outline="true">
+ <NAME value="Head 3" />
+ <COUNTER numberingtype="1" righttext="." type="1" start="1" depth="2" display-levels="3"/>
+ <FOLLOWING name="Standard" />
+ <FORMAT id="1">
+ <!-- Use KDE settings for the font family -->
+ <SIZE value="12" />
+ <WEIGHT value="75" />
+ </FORMAT>
+ </STYLE>
+ <STYLE>
+ <NAME value="Enumerated List" />
+ <COUNTER numberingtype="0" righttext="." type="1" start="1" depth="0" />
+ <FOLLOWING name="Enumerated List" />
+ <FORMAT id="1">
+ <!-- Use KDE settings for the font -->
+ </FORMAT>
+ </STYLE>
+ <STYLE>
+ <NAME value="Alphabetical List" />
+ <COUNTER numberingtype="0" righttext=")" type="2" start="1" depth="0" />
+ <FOLLOWING name="Alphabetical List" />
+ <FORMAT id="1">
+ <!-- Use KDE settings for the font -->
+ </FORMAT>
+ </STYLE>
+ <STYLE>
+ <NAME value="Bullet List" />
+ <COUNTER numberingtype="0" type="10" start="1" depth="0" />
+ <FOLLOWING name="Bullet List" />
+ <FORMAT id="1">
+ <!-- Use KDE settings for the font -->
+ </FORMAT>
+ </STYLE>
+ </STYLES>
+</DOC>
diff --git a/kword/templates/Wordprocessing/cr128-action-template_colorful.png b/kword/templates/Wordprocessing/cr128-action-template_colorful.png
new file mode 100644
index 00000000..8a07c36c
--- /dev/null
+++ b/kword/templates/Wordprocessing/cr128-action-template_colorful.png
Binary files differ
diff --git a/kword/templates/Wordprocessing/cr48-action-template_a4.png b/kword/templates/Wordprocessing/cr48-action-template_a4.png
new file mode 100644
index 00000000..6da59f12
--- /dev/null
+++ b/kword/templates/Wordprocessing/cr48-action-template_a4.png
Binary files differ
diff --git a/kword/templates/Wordprocessing/cr48-action-template_colorful.png b/kword/templates/Wordprocessing/cr48-action-template_colorful.png
new file mode 100644
index 00000000..d518a71d
--- /dev/null
+++ b/kword/templates/Wordprocessing/cr48-action-template_colorful.png
Binary files differ
diff --git a/kword/templates/Wordprocessing/cr48-action-template_fax.png b/kword/templates/Wordprocessing/cr48-action-template_fax.png
new file mode 100644
index 00000000..2a579b02
--- /dev/null
+++ b/kword/templates/Wordprocessing/cr48-action-template_fax.png
Binary files differ
diff --git a/kword/templates/Wordprocessing/cr48-action-template_letter.png b/kword/templates/Wordprocessing/cr48-action-template_letter.png
new file mode 100644
index 00000000..ab392628
--- /dev/null
+++ b/kword/templates/Wordprocessing/cr48-action-template_letter.png
Binary files differ
diff --git a/kword/templates/Wordprocessing/cr48-action-template_memo.png b/kword/templates/Wordprocessing/cr48-action-template_memo.png
new file mode 100644
index 00000000..754e4aad
--- /dev/null
+++ b/kword/templates/Wordprocessing/cr48-action-template_memo.png
Binary files differ
diff --git a/kword/templates/Wordprocessing/cr48-action-template_plaintext.png b/kword/templates/Wordprocessing/cr48-action-template_plaintext.png
new file mode 100644
index 00000000..a7a4a94d
--- /dev/null
+++ b/kword/templates/Wordprocessing/cr48-action-template_plaintext.png
Binary files differ
diff --git a/kword/templates/Wordprocessing/cr48-action-template_twocolumns.png b/kword/templates/Wordprocessing/cr48-action-template_twocolumns.png
new file mode 100644
index 00000000..73abce30
--- /dev/null
+++ b/kword/templates/Wordprocessing/cr48-action-template_twocolumns.png
Binary files differ
diff --git a/kword/templates/Wordprocessing/crsc-action-template_a4.svgz b/kword/templates/Wordprocessing/crsc-action-template_a4.svgz
new file mode 100644
index 00000000..8362cf68
--- /dev/null
+++ b/kword/templates/Wordprocessing/crsc-action-template_a4.svgz
Binary files differ
diff --git a/kword/templates/Wordprocessing/crsc-action-template_fax.svgz b/kword/templates/Wordprocessing/crsc-action-template_fax.svgz
new file mode 100644
index 00000000..1b09b51f
--- /dev/null
+++ b/kword/templates/Wordprocessing/crsc-action-template_fax.svgz
Binary files differ
diff --git a/kword/templates/Wordprocessing/crsc-action-template_letter.svgz b/kword/templates/Wordprocessing/crsc-action-template_letter.svgz
new file mode 100644
index 00000000..3048d4dd
--- /dev/null
+++ b/kword/templates/Wordprocessing/crsc-action-template_letter.svgz
Binary files differ
diff --git a/kword/templates/Wordprocessing/crsc-action-template_memo.svgz b/kword/templates/Wordprocessing/crsc-action-template_memo.svgz
new file mode 100644
index 00000000..2fb27b11
--- /dev/null
+++ b/kword/templates/Wordprocessing/crsc-action-template_memo.svgz
Binary files differ
diff --git a/kword/templates/Wordprocessing/crsc-action-template_plaintext.svgz b/kword/templates/Wordprocessing/crsc-action-template_plaintext.svgz
new file mode 100644
index 00000000..c48b9780
--- /dev/null
+++ b/kword/templates/Wordprocessing/crsc-action-template_plaintext.svgz
Binary files differ
diff --git a/kword/templates/Wordprocessing/crsc-action-template_twocolumns.svgz b/kword/templates/Wordprocessing/crsc-action-template_twocolumns.svgz
new file mode 100644
index 00000000..4070737d
--- /dev/null
+++ b/kword/templates/Wordprocessing/crsc-action-template_twocolumns.svgz
Binary files differ
diff --git a/kword/templates/make_template.pl b/kword/templates/make_template.pl
new file mode 100755
index 00000000..b485e7c1
--- /dev/null
+++ b/kword/templates/make_template.pl
@@ -0,0 +1,35 @@
+#!/usr/bin/perl -w
+
+# This script takes a KWord XML file as entry (as saved by KWord)
+# and generates a KWord XML file that is ready to be used as a template.
+# Usually one will run unzip first, to extract maindoc.xml from the document,
+# and use that as the <inputFile>.
+# David Faure <faure@kde.org>
+
+die "Usage: $0 inputFile outputFile.kwt" unless ($#ARGV == 1);
+open(IN, "<$ARGV[0]") or die "Can't open $ARGV[0] for reading";
+open(OUT, ">$ARGV[1]") or die "Can't open $ARGV[1] for reading";
+
+my $inStyle = 0;
+my $styleName = '';
+while(<IN>)
+{
+ $inStyle = 1 if ( /<STYLE/ );
+ $inStyle = 0 if ( /<\/STYLE/ );
+ $styleName = $1 if ( $inStyle && /<NAME value=\"(.*)\"/ );
+
+ my $ok = 1;
+ # FONT name must be taken from the KDE standard font -> removing
+ # align=left must be removed so that auto is used instead, for RTL users
+ $ok = 0 if ( /FONT name/ || /FLOW align=\"left\"/ );
+
+ # Remove font size from Standard style, comes from KDE standard font
+ $ok = 0 if ( $inStyle && ($styleName eq 'Standard') && /<SIZE value=\"12\"/ );
+
+ if ( $ok ) {
+ print OUT $_;
+ }
+}
+
+close IN;
+close OUT;
diff --git a/kword/tests/FrameTester.cpp b/kword/tests/FrameTester.cpp
new file mode 100644
index 00000000..0a088674
--- /dev/null
+++ b/kword/tests/FrameTester.cpp
@@ -0,0 +1,152 @@
+/* This file is part of the KOffice project
+ * Copyright (C) 2005 Thomas Zander <zander@kde.org>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; version 2.
+
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public License
+ * along with this library; see the file COPYING.LIB. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ */
+#include "FrameTester.h"
+#include <KWFrame.h>
+#include <KWFrameList.h>
+#include <KWDocument.h>
+#include <kunittest/runner.h>
+#include <kunittest/module.h>
+#include <qapplication.h>
+
+using namespace KUnitTest;
+
+KUNITTEST_MODULE(kunittest_FrameTester, "Frame Tester");
+KUNITTEST_MODULE_REGISTER_TESTER(KWFrameTester);
+
+void KWFrameTester::allTests() {
+ int argc = 0;
+ char** argv = 0;
+ QApplication app( argc, argv ); // needed for KWDocument, due to KWCommandHistory -> KToolBarPopupAction -> QPopupMenu -> QWidget
+
+ testSimpleFrame();
+ testFrameList();
+ testDeleteAllCopies();
+ testNestedFrames();
+}
+
+void KWFrameTester::testSimpleFrame() {
+ KWFrameSet *fs = new TestFrameSet();
+ KWFrame *f = new KWFrame(fs, 0, 1, 10, 11);
+
+ KWFrame *f2 = f->getCopy();
+ CHECK(f2->x(), 0.0);
+ CHECK(f2->y(), 1.0);
+ CHECK(f2->width(), 10.0);
+ CHECK(f2->height(), 11.0);
+}
+
+void KWFrameTester::testFrameList()
+{
+ KWDocument* doc = new KWDocument();
+
+ KWFrameSet *fs = new TestFrameSet( doc );
+ // f2 is above f1, f3 doesn't intersect with either
+ KWFrame *f1 = new KWFrame(fs, 0, 1, 10, 11);
+ f1->setZOrder( 1 );
+ fs->addFrame( f1 );
+ KWFrame *f2 = new KWFrame(fs, 1, 5, 10, 12);
+ f2->setZOrder( 10 );
+ fs->addFrame( f2 );
+ KWFrame *f3 = new KWFrame(fs, 100, 101, 10, 12);
+ f3->setZOrder( 5 );
+ fs->addFrame( f3 );
+
+ CHECK( (int)fs->frameCount(), 3 );
+
+ doc->addFrameSet( fs ); // creates frame lists
+
+ KWFrameList* f1List = f1->frameStack();
+ CHECK( f1List != 0, true );
+ CHECK( f1List->framesBelow().isEmpty(), true );
+ CHECK( f1List->framesOnTop().count(), (size_t)1 );
+ CHECK( f1List->framesOnTop().first(), f2 );
+
+ KWFrameList* f2List = f2->frameStack();
+ CHECK( f2List->framesBelow().count(), (size_t)1 );
+ CHECK( f2List->framesBelow().first(), f1 );
+ CHECK( f2List->framesOnTop().isEmpty(), true );
+
+ KWFrameList* f3List = f3->frameStack();
+ CHECK( f3List->framesBelow().isEmpty(), true );
+ CHECK( f3List->framesOnTop().isEmpty(), true );
+
+ delete doc;
+}
+
+void KWFrameTester::testDeleteAllCopies() {
+ KWFrameSet *fs = new TestFrameSet();
+ KWFrame *f = new KWFrame(fs, 0, 1, 10, 11);
+ fs->addFrame(f);
+
+ fs->deleteAllCopies();
+ CHECK(fs->frameCount(), (unsigned int) 1);
+ CHECK(fs->frame(0), f);
+
+ KWFrame *f2 = f->getCopy();
+ f2->setCopy(true);
+ fs->addFrame(f2);
+
+ CHECK(fs->frameCount(), (unsigned int) 2);
+ CHECK(fs->frame(0), f);
+ CHECK(fs->frame(1), f2);
+
+ fs->deleteAllCopies();
+ f2=0;
+ CHECK(fs->frameCount(), (unsigned int) 1);
+ CHECK(fs->frame(0), f);
+}
+
+void KWFrameTester::testNestedFrames() {
+ KWDocument *doc = new KWDocument();
+ CHECK(doc->pageManager() != 0, true);
+
+ KWTextFrameSet *base = new TestTextFrameSet(doc, "base");
+ base->setPageManager(doc->pageManager());
+ KWFrame *f1 = new KWFrame(base, 0, 1, 10, 11);
+ base->addFrame(f1);
+ KWTextFrameSet *nested = new TestTextFrameSet(doc, "nested");
+ nested->setPageManager(doc->pageManager());
+ KWFrame *f2 = new KWFrame(nested, 0, 1, 10, 11);
+ nested->addFrame(f2);
+
+ nested->setAnchorFrameset(base);
+
+ KWFrameSet *deepNested = new TestTextFrameSet(doc, "deepNested");
+ deepNested->setPageManager(doc->pageManager());
+ KWFrame *f3 = new KWFrame(deepNested, 0, 1, 10, 11);
+ deepNested->addFrame(f3);
+
+ deepNested->setAnchorFrameset(nested);
+
+ doc->addFrameSet(base, false);
+ doc->addFrameSet(nested, false);
+ doc->addFrameSet(deepNested, false);
+
+ CHECK(f1->frameStack() != 0, true);
+ CHECK(f2->frameStack() != 0, true);
+ CHECK(f3->frameStack() != 0, true);
+
+ // since nested and deepNested are inline they are 'inside' the base frame and thuse
+ // all above and below lists should be empty.
+ CHECK(f1->frameStack()->framesBelow().isEmpty(), true);
+ CHECK(f2->frameStack()->framesBelow().isEmpty(), true);
+ CHECK(f3->frameStack()->framesBelow().isEmpty(), true);
+ CHECK(f1->frameStack()->framesOnTop().isEmpty(), true);
+ CHECK(f2->frameStack()->framesOnTop().isEmpty(), true);
+ CHECK(f3->frameStack()->framesOnTop().isEmpty(), true);
+}
diff --git a/kword/tests/FrameTester.h b/kword/tests/FrameTester.h
new file mode 100644
index 00000000..9c255829
--- /dev/null
+++ b/kword/tests/FrameTester.h
@@ -0,0 +1,59 @@
+/* This file is part of the KOffice project
+ * Copyright (C) 2005 Thomas Zander <zander@kde.org>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; version 2.
+
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public License
+ * along with this library; see the file COPYING.LIB. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ */
+#include <kunittest/tester.h>
+
+#include <KWFrameSet.h>
+#include <KWTextFrameSet.h>
+
+class KWDocument;
+class KoXmlWriter;
+
+class KWFrameTester : public KUnitTest::Tester {
+ public:
+ void allTests();
+ private:
+ void testSimpleFrame();
+ void testFrameList();
+ void testDeleteAllCopies();
+ void testNestedFrames();
+};
+
+class TestFrameSet : public KWFrameSet {
+public:
+ TestFrameSet( KWDocument* doc = 0 ) : KWFrameSet(doc) {
+ }
+ QDomElement save(QDomElement&, bool) { return QDomElement(); }
+ void saveOasis( KoXmlWriter&, KoSavingContext&, bool) const { };
+ void setProtectContent(bool) { }
+ bool protectContent() const { return true; }
+};
+
+class TestTextFrameSet : public KWTextFrameSet {
+public:
+ TestTextFrameSet(KWDocument *doc, const QString name) : KWTextFrameSet(name) {
+ m_doc = doc;
+ }
+ QDomElement save(QDomElement&, bool) { return QDomElement(); }
+ void saveOasis( KoXmlWriter&, KoSavingContext&, bool) const { };
+ void setProtectContent(bool) { }
+ bool protectContent() const { return true; }
+ void updateFrames( int flags = 0xff ) {
+ flags = UpdateFramesInPage;
+ KWFrameSet::updateFrames(flags);
+ }
+};
diff --git a/kword/tests/FrameViewTester.cpp b/kword/tests/FrameViewTester.cpp
new file mode 100644
index 00000000..652bc50e
--- /dev/null
+++ b/kword/tests/FrameViewTester.cpp
@@ -0,0 +1,295 @@
+/* This file is part of the KOffice project
+ * Copyright (C) 2005 Thomas Zander <zander@kde.org>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; version 2.
+
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public License
+ * along with this library; see the file COPYING.LIB. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ */
+#include <kunittest/runner.h>
+#include <kunittest/module.h>
+#include <kdebug.h>
+
+#include "FrameViewTester.h"
+#include "FrameTester.h"
+
+#include <KWFrame.h>
+#include <KWFrameSet.h>
+#include <KWFrameViewManager.h>
+#include <KWFrameView.h>
+#include <defs.h> // for mousemeaning
+
+using namespace KUnitTest;
+
+KUNITTEST_MODULE(kunittest_FrameViewTester, "FrameView Tester");
+KUNITTEST_MODULE_REGISTER_TESTER(KWFrameViewTester);
+
+void KWFrameViewTester::allTests() {
+ testListeners();
+ testGetView();
+ testMouseMeaning();
+}
+
+class MockListener : public KWFramesListener {
+public:
+ int fsa, fsr, fa,fr;
+ KWFrameSet *lastFs;
+ KWFrame *lastF;
+ MockListener() {
+ fsa=0;
+ fsr=0;
+ fa=0;
+ fr=0;
+ lastFs=0;
+ lastF=0;
+ }
+ void frameSetAdded(KWFrameSet *fs) {
+ fsa++;
+ lastFs=fs;
+ }
+ void frameSetRemoved(KWFrameSet *fs) {
+ fsr++;
+ lastFs=fs;
+ }
+ void frameAdded(KWFrame *f) {
+ fa++;
+ lastF=f;
+ }
+ void frameRemoved(KWFrame *f) {
+ fr++;
+ lastF=f;
+ }
+ void frameMoved(KWFrame *f) {
+ lastF=f;
+ }
+ void frameResized(KWFrame *f) {
+ lastF=f;
+ }
+};
+
+class TestFrameViewManager : public KWFrameViewManager {
+public:
+ TestFrameViewManager() {
+ m_fireEventsRequested = false;
+ }
+ bool m_fireEventsRequested;
+
+ void doFireEvents() { fireEvents(); }
+protected:
+ void requestFireEvents() {
+ m_fireEventsRequested = true;
+ }
+};
+
+void KWFrameViewTester::testListeners() {
+ KWFrameSet *fs = new TestFrameSet();
+ KWFrame *f = new KWFrame(fs, 0, 1, 10, 11);
+
+ TestFrameViewManager *viewManager = new TestFrameViewManager();
+ MockListener *listener = new MockListener();
+ viewManager->addKWFramesListener(listener);
+ CHECK(listener->fsa, 0);
+ // frameSetAdded
+ viewManager->slotFrameSetAdded(fs);
+ CHECK(listener->fsa, 0);
+ CHECK(viewManager->m_fireEventsRequested, true);
+ viewManager->doFireEvents();
+ CHECK(listener->fsa, 1);
+ CHECK(listener->fsr, 0);
+ CHECK(listener->fa, 0);
+ CHECK(listener->fr, 0);
+ CHECK(listener->lastFs, fs);
+
+ // reset
+ listener->fsa = 0;
+ viewManager->m_fireEventsRequested = false;
+ // frameSetRemoved
+ viewManager->slotFrameSetRemoved(fs);
+ CHECK(viewManager->m_fireEventsRequested, true);
+ viewManager->doFireEvents();
+ CHECK(listener->fsa, 0);
+ CHECK(listener->fsr, 1);
+ CHECK(listener->fa, 0);
+ CHECK(listener->fr, 0);
+ CHECK(listener->lastFs, fs);
+
+ // reset
+ listener->fsr = 0;
+ viewManager->m_fireEventsRequested = false;
+ // frameSetRemoved
+ viewManager->slotFrameAdded(f);
+ CHECK(viewManager->m_fireEventsRequested, true);
+ viewManager->doFireEvents();
+ CHECK(listener->fsr, 0);
+ CHECK(listener->fsa, 0);
+ CHECK(listener->fa, 1);
+ CHECK(listener->fr, 0);
+ CHECK(listener->lastF, f);
+
+ // reset
+ listener->fa = 0;
+ viewManager->m_fireEventsRequested = false;
+ // frameSetRemoved
+ viewManager->slotFrameRemoved(f);
+ CHECK(viewManager->m_fireEventsRequested, true);
+ viewManager->doFireEvents();
+ CHECK(listener->fsr, 0);
+ CHECK(listener->fsa, 0);
+ CHECK(listener->fa, 0);
+ CHECK(listener->fr, 1);
+ CHECK(listener->lastF, f);
+
+ // reset
+ listener->fr = 0;
+ viewManager->m_fireEventsRequested = false;
+ // multiple
+ KWFrame *f2 = new KWFrame(fs, 0, 1, 2, 3);
+ viewManager->slotFrameRemoved(f);
+ viewManager->slotFrameSetAdded(fs);
+ viewManager->slotFrameAdded(f);
+ viewManager->slotFrameAdded(f);
+ viewManager->slotFrameAdded(f2);
+ viewManager->doFireEvents();
+ CHECK(listener->fsr, 0);
+ CHECK(listener->fsa, 1);
+ CHECK(listener->fa, 3);
+ CHECK(listener->fr, 1);
+ CHECK(listener->lastF, f2);
+
+ viewManager->slotFrameSetAdded(fs);
+ viewManager->removeKWFramesListener(listener);
+ viewManager->doFireEvents();
+ CHECK(listener->fsr, 0);
+
+ // frame moved
+ // frame resized
+}
+
+void KWFrameViewTester::testGetView() {
+ TestFrameViewManager fvm;
+ KWFrameSet *fs = new TestFrameSet();
+ KWFrame *frame = new KWFrame(fs, 0, 0, 100, 100);
+ fs->addFrame(frame);
+
+ fvm.slotFrameAdded(frame);
+ KWFrameView *fv = fvm.view(frame);
+ CHECK(fv != 0, true);
+ if(!fv) return;
+ CHECK(fv->frame(), frame);
+
+ fv = fvm.view( KoPoint(0,0), KWFrameViewManager::frameOnTop);
+ CHECK(fv != 0, true); // should exist
+ if(!fv) return;
+ CHECK(fv->frame(), frame);
+
+ fv = fvm.view( KoPoint(1,1), KWFrameViewManager::frameOnTop);
+ CHECK(fv != 0, true);
+ if(!fv) return;
+ CHECK(fv->frame(), frame);
+
+ fv = fvm.view( KoPoint(110,110), KWFrameViewManager::frameOnTop);
+ CHECK(fv == 0, true);
+
+ fv = fvm.view( KoPoint(100,100), KWFrameViewManager::frameOnTop); // note that 100,100 _is_ inside 0,0 100x100
+ CHECK(fv != 0, true);
+ if(!fv) return;
+ CHECK(fv->frame(), frame);
+
+ fv->setSelected(true);
+ fv = fvm.view( KoPoint(1,1), KWFrameViewManager::unselected);
+ CHECK(fv == 0, true);
+
+ frame->setZOrder(4);
+ KWFrame *frame2 = new KWFrame(fs, 80, 50, 60, 60);
+ frame2->setZOrder(2);
+ fvm.slotFrameAdded(frame2);
+ KWFrame *frame3 = new KWFrame(fs, 30, 60, 60, 60);
+ frame3->setZOrder(5);
+ fvm.slotFrameAdded(frame3);
+ KWFrame *frame4 = new KWFrame(fs, 200, 0, 100, 100);
+ fvm.slotFrameAdded(frame4);
+ frame4->setZOrder(1);
+
+kdDebug() << "frame:" << frame << ", frame2:" << frame2<< ", frame2:" << frame3<< ", frame2:" << frame4 << endl;
+ fv = fvm.view( KoPoint(90,60), KWFrameViewManager::frameOnTop);
+ CHECK(fv != 0, true);
+ if(!fv) return;
+ CHECK(fv->frame(), frame3);
+ fv = fvm.view( KoPoint(90,60), KWFrameViewManager::frameOnTop); // second time should give the same results
+ CHECK(fv != 0, true);
+ if(!fv) return;
+ CHECK(fv->frame(), frame3);
+ fv = fvm.view( KoPoint(90,60), KWFrameViewManager::selected);
+ CHECK(fv != 0, true);
+ if(!fv) return;
+ CHECK(fv->frame(), frame);
+ fv = fvm.view( KoPoint(90,60), KWFrameViewManager::selected); // second time should give the same results
+ CHECK(fv != 0, true);
+ if(!fv) return;
+ CHECK(fv->frame(), frame);
+
+ fv = fvm.view( KoPoint(90,60), KWFrameViewManager::nextUnselected);
+ CHECK(fv != 0, true);
+ if(!fv) return;
+ CHECK(fv->frame(), frame2); // the one directly below the selected frame
+}
+
+void KWFrameViewTester::testMouseMeaning() {
+ TestFrameViewManager fvm;
+ KWFrameSet *fs = new TestFrameSet();
+ KWFrame *frame = new KWFrame(fs, 50, 50, 50, 50);
+
+ fvm.slotFrameAdded(frame);
+ KWFrameView *fv = fvm.view(frame);
+ if(fv == 0) return; // means previous test already failed a lot.
+
+ MouseMeaning answers[9 * 3] = { MEANING_TOPLEFT, MEANING_LEFT, MEANING_BOTTOMLEFT,
+ MEANING_TOPLEFT, MEANING_LEFT, MEANING_BOTTOMLEFT,
+ MEANING_TOPLEFT, MEANING_LEFT, MEANING_BOTTOMLEFT,
+ MEANING_TOP, MEANING_MOUSE_INSIDE_TEXT, MEANING_BOTTOM,
+ MEANING_TOP, MEANING_MOUSE_INSIDE_TEXT, MEANING_BOTTOM,
+ MEANING_TOP, MEANING_MOUSE_INSIDE_TEXT, MEANING_BOTTOM,
+ MEANING_TOPRIGHT, MEANING_RIGHT, MEANING_BOTTOMRIGHT,
+ MEANING_TOPRIGHT, MEANING_RIGHT, MEANING_BOTTOMRIGHT,
+ MEANING_TOPRIGHT, MEANING_RIGHT, MEANING_BOTTOMRIGHT };
+ int count=0;
+
+ KoPoint point(10, 10);
+ CHECK(fv->mouseMeaning(point, 0), MEANING_NONE);
+ for(int x = 50; x <= 100; x += 25) {
+ for(int offset=-6; offset <= 6; offset+=6) {
+ point.setX(x + offset);
+ for(int y = 50; y <= 100; y += 25) {
+ for(int offset2=-6; offset2 <= 6; offset2+=6) {
+ point.setY(y + offset2);
+ CHECK(fv->contains(point, true), true);
+ if(x < 50 || x > 100 || y < 50 || y > 100)
+ CHECK(fv->contains(point), false);
+ else
+ CHECK(fv->contains(point), true);
+ if(x > 60 && x < 90 && y > 60 && y < 90)
+ CHECK(fv->isBorderHit(point), false);
+ else
+ CHECK(fv->isBorderHit(point), true);
+ CHECK(fv->mouseMeaning(point, 0), answers[count]);
+ }
+ count++;
+ }
+ }
+ }
+
+ point.setX(50);
+ point.setY(120);
+ CHECK(fv->mouseMeaning(point, 0), MEANING_NONE);
+
+}
+// QCursor mouseCursor( const KoPoint &point, int keyState ) const;
diff --git a/kword/tests/FrameViewTester.h b/kword/tests/FrameViewTester.h
new file mode 100644
index 00000000..dceb3835
--- /dev/null
+++ b/kword/tests/FrameViewTester.h
@@ -0,0 +1,27 @@
+/* This file is part of the KOffice project
+ * Copyright (C) 2005 Thomas Zander <zander@kde.org>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; version 2.
+
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public License
+ * along with this library; see the file COPYING.LIB. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ */
+#include <kunittest/tester.h>
+
+class KWFrameViewTester : public KUnitTest::Tester {
+ public:
+ void allTests();
+ private:
+ void testListeners();
+ void testGetView();
+ void testMouseMeaning();
+};
diff --git a/kword/tests/KWPageManagerTester.cpp b/kword/tests/KWPageManagerTester.cpp
new file mode 100644
index 00000000..9b261d90
--- /dev/null
+++ b/kword/tests/KWPageManagerTester.cpp
@@ -0,0 +1,320 @@
+/* This file is part of the KOffice project
+ * Copyright (C) 2005 Thomas Zander <zander@kde.org>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; version 2.
+
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public License
+ * along with this library; see the file COPYING.LIB. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ */
+#include <kunittest/runner.h>
+#include <kunittest/module.h>
+#include <kdebug.h>
+
+#include "KWPageManagerTester.h"
+
+#include <KWPageManager.h>
+#include <KWPage.h>
+
+using namespace KUnitTest;
+
+KUNITTEST_MODULE(kunittest_KWPageManagerTester, "PageManager Tester");
+KUNITTEST_MODULE_REGISTER_TESTER(KWPageManagerTester);
+
+void KWPageManagerTester::allTests() {
+ getAddPages();
+ getAddPages2();
+ createInsertPages();
+ removePages();
+ pageInfo();
+ testClipToDocument();
+}
+
+void KWPageManagerTester::getAddPages() {
+ KWPageManager *pageManager = new KWPageManager();
+ pageManager->setStartPage(1);
+ pageManager->appendPage();
+ KWPage *page = pageManager->page(0);
+ CHECK(page == 0, true);
+ page = pageManager->page(2);
+ CHECK(page == 0, true);
+
+ page = pageManager->page(1);
+ CHECK(page == 0, false);
+ CHECK(page->pageNumber(), 1);
+ CHECK(page->pageSide(), KWPage::Right);
+
+ page->setWidth(134.2);
+ page->setHeight(521.4);
+ CHECK(page->width(), 134.2);
+ CHECK(page->height(), 521.4);
+
+ // test setStartPage
+ pageManager->setStartPage(4);
+ page = pageManager->page(0);
+ CHECK(page == 0, true);
+ page = pageManager->page(3);
+ CHECK(page == 0, true);
+ page = pageManager->page(5);
+ CHECK(page == 0, true);
+ page = pageManager->page(4);
+ CHECK(page == 0, false);
+ CHECK(page->pageNumber(), 4);
+ CHECK(page->pageSide(), KWPage::Left);
+
+ pageManager->setStartPage(1);
+ page = pageManager->page(0);
+ CHECK(page == 0, true);
+ page = pageManager->page(3);
+ CHECK(page == 0, true);
+ page = pageManager->page(2);
+ CHECK(page == 0, true);
+ page = pageManager->page(1);
+ CHECK(page == 0, false);
+ CHECK(page->pageNumber(), 1);
+ CHECK(page->pageSide(), KWPage::Right);
+
+ // adding pages
+ CHECK(pageManager->pageCount(), 1);
+ CHECK(pageManager->lastPageNumber(), 1);
+ pageManager->setStartPage(40);
+ CHECK(pageManager->pageCount(), 1);
+ CHECK(pageManager->lastPageNumber(), 40);
+ page = pageManager->appendPage();
+ CHECK(pageManager->pageCount(), 2);
+ CHECK(pageManager->lastPageNumber(), 41);
+
+ CHECK(page == 0, false);
+ CHECK(page->pageNumber(), 41);
+ CHECK(page->pageSide(), KWPage::Right);
+}
+
+void KWPageManagerTester::getAddPages2() {
+ KWPageManager *pageManager = new KWPageManager();
+ pageManager->setStartPage(1);
+ KWPage *page = pageManager->appendPage();
+ page->setWidth(200);
+ page->setHeight(200);
+
+ CHECK(pageManager->pageNumber(KoRect(0,0,2,2)), 1);
+ CHECK(pageManager->pageNumber(KoRect(90,90,2,2)), 1);
+ CHECK(pageManager->pageNumber(KoRect(190,190,9,9)), 1);
+
+ page = pageManager->appendPage();
+ page->setWidth(600);
+ page->setHeight(600);
+ CHECK(pageManager->pageNumber(KoRect(0,0,2,2)), 1);
+ CHECK(pageManager->pageNumber(KoRect(90,90,2,2)), 1);
+ CHECK(pageManager->pageNumber(KoRect(190,190,9,9)), 1);
+
+ CHECK(pageManager->pageNumber(KoRect(201,201,2,2)), 2);
+#ifdef STRICT_PAGECHECKS // was true before KWPageManager.cpp -r511705:511706
+ CHECK(pageManager->pageNumber(KoRect(300,3,2,2)), -1); // right of page 1
+#else
+ CHECK(pageManager->pageNumber(KoRect(300,3,2,2)), 1); // right of page 1
+#endif
+ CHECK(pageManager->pageNumber(KoRect(2, 690,9,9)), 2);
+ CHECK(pageManager->pageNumber(KoRect(300,300,10,10)), 2);
+#ifdef STRICT_PAGECHECKS // was true before KWPageManager.cpp -r511705:511706
+ CHECK(pageManager->pageNumber(KoRect(600,700,10,10)), -1); // right of page 2
+#else
+ CHECK(pageManager->pageNumber(KoRect(600,700,10,10)), 2); // right of page 2
+#endif
+
+ // KoPoint based
+ CHECK(pageManager->pageNumber(KoPoint(201,201)), 2);
+ // Y based
+ CHECK(pageManager->pageNumber(201.0), 2);
+#ifdef STRICT_PAGECHECKS // was true before KWPageManager.cpp -r511705:511706
+ CHECK(pageManager->pageNumber(900.0), -1);
+#else
+ CHECK(pageManager->pageNumber(900.0), 2);
+#endif
+}
+
+void KWPageManagerTester::createInsertPages() {
+ KWPageManager *pageManager = new KWPageManager();
+ pageManager->setStartPage(1);
+ CHECK(pageManager->pageCount(), 0);
+ KWPage *page1 = pageManager->appendPage();
+ CHECK(pageManager->pageCount(), 1);
+ KWPage *page3 = pageManager->appendPage();
+ CHECK(pageManager->pageCount(), 2);
+ CHECK(page3->pageNumber(), 2);
+
+ KWPage *page2 = pageManager->insertPage(2);
+ CHECK(pageManager->pageCount(), 3);
+ CHECK(page1->pageNumber(), 1);
+ CHECK(page2->pageNumber(), 2);
+ CHECK(page3->pageNumber(), 3);
+
+ KWPage *page4 = pageManager->insertPage(100);
+ CHECK(pageManager->pageCount(), 4);
+ CHECK(page1->pageNumber(), 1);
+ CHECK(page2->pageNumber(), 2);
+ CHECK(page3->pageNumber(), 3);
+ CHECK(page4->pageNumber(), 4);
+
+ KWPage *page = pageManager->insertPage(0);
+ CHECK(pageManager->pageCount(), 5);
+ CHECK(page->pageNumber(), 1);
+ CHECK(page1->pageNumber(), 2);
+ CHECK(page2->pageNumber(), 3);
+ CHECK(page3->pageNumber(), 4);
+ CHECK(page4->pageNumber(), 5);
+
+ pageManager->setOnlyAllowAppend(true);
+ KWPage *page6 = pageManager->insertPage(0);
+ CHECK(pageManager->pageCount(), 6);
+ CHECK(page1->pageNumber(), 2);
+ CHECK(page6->pageNumber(), 6);
+}
+
+void KWPageManagerTester::removePages() {
+ KWPageManager *pageManager = new KWPageManager();
+ pageManager->setStartPage(1);
+ KWPage *page1 = pageManager->appendPage();
+ pageManager->appendPage();
+ KWPage *page2 = pageManager->appendPage();
+ /*KWPage *page3 =*/ pageManager->appendPage();
+ KWPage *page4 = pageManager->appendPage();
+
+ pageManager->removePage(2);
+ CHECK(page1->pageNumber(), 1);
+ CHECK(page2->pageNumber(), 2);
+ CHECK(page4->pageNumber(), 4);
+ pageManager->removePage(page2);
+ CHECK(page1->pageNumber(), 1);
+ CHECK(page4->pageNumber(), 3);
+
+ /* todo: bool tryRemovingPages(); */
+}
+
+void KWPageManagerTester::pageInfo() {
+ KWPageManager *pageManager = new KWPageManager();
+ KoPageLayout layout;
+ layout.ptWidth = 300;
+ layout.ptHeight = 600;
+ layout.format = PG_DIN_A4;
+ pageManager->setDefaultPage(layout);
+ pageManager->setStartPage(1);
+ KWPage *page1 = pageManager->appendPage();
+ page1->setWidth(100);
+ page1->setHeight(200);
+ KWPage *page2 = pageManager->appendPage();
+ page2->setWidth(50);
+ page2->setHeight(100);
+ KWPage *page3 = pageManager->appendPage();
+
+ CHECK(pageManager->topOfPage(3), 300.0);
+ CHECK(pageManager->bottomOfPage(3), 900.0);
+ layout.ptHeight = 500;
+ pageManager->setDefaultPage(layout);
+ CHECK(pageManager->bottomOfPage(3), 800.0);
+ page2->setHeight(-1);
+ CHECK(pageManager->bottomOfPage(3), 1200.0);
+
+ layout.ptTop = 5;
+ layout.ptLeft = 6;
+ layout.ptBottom = 7;
+ layout.ptRight = 8;
+ layout.ptBindingSide = -1;
+ layout.ptPageEdge = -1;
+ pageManager->setDefaultPage(layout);
+ page2->setTopMargin(9);
+ page2->setLeftMargin(10);
+ page2->setBottomMargin(11);
+ page2->setRightMargin(12);
+
+ KoPageLayout lay = pageManager->pageLayout(2);
+ CHECK(lay.ptHeight, 500.0);
+ CHECK(lay.ptWidth, 50.0);
+ CHECK(lay.ptTop, 9.0);
+ CHECK(lay.ptLeft, 10.0);
+ CHECK(lay.ptBottom, 11.0);
+ CHECK(lay.ptRight, 12.0);
+
+ lay = pageManager->pageLayout(3);
+ CHECK(lay.ptHeight, 500.0);
+ CHECK(lay.ptWidth, 300.0);
+ CHECK(lay.ptTop, 5.0);
+ CHECK(lay.ptLeft, 6.0);
+ CHECK(lay.ptBottom, 7.0);
+ CHECK(lay.ptRight, 8.0);
+
+ lay.ptRight = 90; // should have no effect, since its a copy
+ CHECK(page3->rightMargin(), 8.0);
+
+
+ // Page Edge / Page Margin
+ page1->setPageEdgeMargin(14.0);
+ CHECK(page1->pageSide(), KWPage::Right);
+ CHECK(page1->rightMargin(), 14.0);
+ page1->setMarginClosestBinding(15.0);
+ CHECK(page1->rightMargin(), 14.0);
+ CHECK(page1->leftMargin(), 15.0);
+
+ CHECK(page2->rightMargin(), 12.0); // unchanged due to changes in page1
+ CHECK(page2->leftMargin(), 10.0);
+ page2->setPageEdgeMargin(16.0);
+ CHECK(page2->pageSide(), KWPage::Left);
+ CHECK(page2->leftMargin(), 16.0);
+ page2->setMarginClosestBinding(17.0);
+ CHECK(page2->leftMargin(), 16.0);
+ CHECK(page2->rightMargin(), 17.0);
+
+ page2->setLeftMargin(18);
+ CHECK(page2->leftMargin(), 18.0);
+ page2->setRightMargin(19);
+ CHECK(page2->rightMargin(), 19.0);
+ CHECK(page2->leftMargin(), 18.0);
+}
+
+void KWPageManagerTester::testClipToDocument() {
+ KWPageManager *pageManager = new KWPageManager();
+ KoPageLayout lay;
+ lay.ptWidth = 300;
+ lay.ptHeight = 600;
+ lay.format = PG_DIN_A4;
+ pageManager->setDefaultPage(lay);
+ KWPage *page1 = pageManager->appendPage();
+ page1->setWidth(100);
+ page1->setHeight(200);
+ KWPage *page2 = pageManager->appendPage();
+ page2->setWidth(50);
+ page2->setHeight(100);
+ /*KWPage *page3 =*/ pageManager->appendPage();
+
+ KoPoint p(10,10);
+
+ KoPoint result = pageManager->clipToDocument(p);
+ CHECK(p == result, true);
+
+ p.setX(110);
+ result = pageManager->clipToDocument(p);
+ CHECK(p.y(), result.y());
+ CHECK(result.x(), 100.0);
+
+ p.setY(210);
+ result = pageManager->clipToDocument(p);
+ CHECK(p.y(), result.y());
+ CHECK(result.x(), 50.0);
+
+ p.setY(330);
+ result = pageManager->clipToDocument(p);
+ CHECK(p == result, true);
+
+ p.setY(910);
+ p.setX(310);
+ result = pageManager->clipToDocument(p);
+ CHECK(result.y(), 900.0);
+ CHECK(result.x(), 300.0);
+}
diff --git a/kword/tests/KWPageManagerTester.h b/kword/tests/KWPageManagerTester.h
new file mode 100644
index 00000000..2136bdc4
--- /dev/null
+++ b/kword/tests/KWPageManagerTester.h
@@ -0,0 +1,30 @@
+/* This file is part of the KOffice project
+ * Copyright (C) 2005 Thomas Zander <zander@kde.org>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; version 2.
+
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public License
+ * along with this library; see the file COPYING.LIB. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ */
+#include <kunittest/tester.h>
+
+class KWPageManagerTester : public KUnitTest::Tester {
+ public:
+ void allTests();
+ private:
+ void getAddPages();
+ void getAddPages2();
+ void createInsertPages();
+ void removePages();
+ void pageInfo();
+ void testClipToDocument();
+};
diff --git a/kword/tests/Makefile.am b/kword/tests/Makefile.am
new file mode 100644
index 00000000..5b316ce7
--- /dev/null
+++ b/kword/tests/Makefile.am
@@ -0,0 +1,25 @@
+AM_CPPFLAGS = -I$(srcdir)/../ $(KOFFICE_INCLUDES) $(KOPAINTER_INCLUDES) $(all_includes)
+
+INCLUDES = $(KOFFICE_INCLUDES) $(KOTEXT_INCLUDES) $(all_includes)
+
+# The check_ target makes sure we don't install the modules,
+# $(KDE_CHECK_PLUGIN) assures a shared library is created.
+check_LTLIBRARIES = kunittest_KWPageManagerTester.la \
+ kunittest_FrameTester.la \
+ kunittest_FrameViewTester.la
+
+kunittest_KWPageManagerTester_la_SOURCES = KWPageManagerTester.cpp
+kunittest_KWPageManagerTester_la_LIBADD = -lkunittest ../libkwordprivate.la
+kunittest_KWPageManagerTester_la_LDFLAGS = -module $(KDE_CHECK_PLUGIN) $(all_libraries)
+
+kunittest_FrameTester_la_SOURCES = FrameTester.cpp
+kunittest_FrameTester_la_LIBADD = -lkunittest ../libkwordprivate.la
+kunittest_FrameTester_la_LDFLAGS = -module $(KDE_CHECK_PLUGIN) $(all_libraries)
+
+kunittest_FrameViewTester_la_SOURCES = FrameViewTester.cpp
+kunittest_FrameViewTester_la_LIBADD = -lkunittest ../libkwordprivate.la
+kunittest_FrameViewTester_la_LDFLAGS = -module $(KDE_CHECK_PLUGIN) $(all_libraries)
+
+check-local: kunittest_KWPageManagerTester.la kunittest_FrameTester.la kunittest_FrameViewTester.la
+ kunittestmodrunner 2>&1 | perl $(srcdir)/checkFilter.pl
+
diff --git a/kword/tests/README b/kword/tests/README
new file mode 100644
index 00000000..2d9ee0eb
--- /dev/null
+++ b/kword/tests/README
@@ -0,0 +1,26 @@
+When running oasis-kword.sh you can expect the following differences in the diff,
+they are not bugs:
+
+* Background color (bkRed/bkBlue/bkGreen) isn't saved anymore for transparent frames (bkStyle=0)
+ (which makes sense since it doesn't appear)
+
+* Font weight is rounded to a multiple of 10 (if not 75)
+ - <WEIGHT value="48" />
+ + <WEIGHT value="40" />
+No idea how I ended up with a value of 48 in the old .kwd file, Qt mostly knows 50 and 75.
+
+* Picture collection: the keys and filenames are re-generated.
+
+* The direction of a paragraph and its text color are now explicit instead of implicit:
+ <LAYOUT>
+ <NAME value="Standard" />
+- <FLOW align="left" />
++ <FLOW dir="L" align="left" />
+ <FORMAT id="1" pos="0" len="26" >
+ <WEIGHT value="50" />
++ <COLOR blue="0" red="0" green="0" />
+ <FONT name="Bitstream Vera Sans" />
+ <SIZE value="9" />
+ <ITALIC value="0" />
+ This is hidden by oasis-kword.sh though.
+
diff --git a/kword/tests/checkFilter.pl b/kword/tests/checkFilter.pl
new file mode 100755
index 00000000..c3a8cb53
--- /dev/null
+++ b/kword/tests/checkFilter.pl
@@ -0,0 +1,52 @@
+#!/usr/bin/perl
+
+foreach $in (<STDIN>) {
+ if($in=~/^# Running normal tests... #$/) { $testsStarted=1; }
+ elsif($testsStarted != 1 || $in=~/^$/) { print "$in"; }
+ elsif($in=~/^check: (.*?)\[(\d+)\](| failed)$/) {
+#print "++ $_ a: '$1', b: '$2'\n";
+ $file = $1;
+ $line = $2;
+ $failed = $3;
+ if($file ne $currentFile) {
+ print "$file: ";
+ $currentFile = $file;
+ }
+ if($lines ne "") {
+ if($lines=~/\n$/) {
+ $lines = "$lines...";
+ } else {
+ $lines = "$lines, ";
+ }
+ }
+ if($failed ne "") { # it failed!
+ $lines = "$lines\[F:$line\]";
+ } else {
+ $lines = "$lines$line";
+ }
+ }
+ elsif($in=~/ ((\d+) test(|s) passed, (\d+) test(|s) failed)/) {
+#print "passed: '$2' failed: '$4'\n";
+ if($4 ne "0") {
+ print "$lines\n";
+ }
+ print "$1\n";
+ $lines = "";
+ $currentFile = "";
+ }
+ elsif($currentFile eq "") {
+ print $in;
+ } else {
+ # debug output in between lines..
+ if(!($lines eq "" || $lines=~/\n$/)) {
+ $lines = "$lines\n";
+ }
+ $lines = "$lines$in";
+ }
+}
+
+if($lines ne "") {
+ print "$lines\n";
+ print $in;
+ print "WARN: unexpected end of stream, check test $file after line $line\n";
+}
diff --git a/kword/tests/oasis-kword.sh b/kword/tests/oasis-kword.sh
new file mode 100644
index 00000000..d68de47c
--- /dev/null
+++ b/kword/tests/oasis-kword.sh
@@ -0,0 +1,108 @@
+#!/bin/bash
+
+# This script helps finding out problems in the OASIS loading/saving code,
+# by converting .kwd -> .odt -> .kwd and comparing the initial and final .kwd files.
+# We use the kwd format as a "dump" of the KWord data, to check if everything is correct
+# in memory, but the point is of course to ensure that the .odt has all the information.
+
+# To use this script, you need to pass the path to an existing kwd file as argument.
+input="$1"
+
+# Set this to 1 in order to validate the saved oasis document using oasislint
+checkoasis="1"
+
+appname=kword
+oldextension=kwd
+oasisextension=odt
+oasismimetype=application/vnd.oasis.opendocument.text
+
+# dcopstart won't handle a relative path (kdeinit has a different cwd)
+# so make it absolute
+if echo "$input" | grep -v '^/' >/dev/null 2>&1; then
+ input="$PWD/$input"
+fi
+
+test -f "$input" || { echo "No such file $input"; exit 1; }
+
+# Load old native file
+appid=`dcopstart $appname $input`
+test -n "$appid" || { echo "Error starting $appname!"; exit 1; }
+while test "`dcop $appid Document-0 isLoading`" != "false"; do
+ sleep 1;
+done
+
+# Save again (in case of changes in syntax etc.)
+origfile=$PWD/oasisregtest-initial.$oldextension
+dcop $appid Document-0 saveAs $origfile || exit 1
+test -f $origfile || exit 1
+
+# Save to OASIS
+tmpoasisfile=$PWD/oasisregtest.$oasisextension
+dcop $appid Document-0 setOutputMimeType $oasismimetype || exit 1
+dcop $appid Document-0 saveAs $tmpoasisfile || exit 1
+test -f $tmpoasisfile || exit 1
+
+dcopquit $appid
+
+rm -rf oasisregtest-oasis
+mkdir oasisregtest-oasis
+cd oasisregtest-oasis || exit 1
+unzip $tmpoasisfile || exit 1
+cd ..
+
+# Load resulting OASIS file, convert to old native format
+tmpnativefile=$PWD/oasisregtest-final.$oldextension
+appid=`dcopstart $appname $tmpoasisfile`
+while `dcop $appid Document-0 isLoading` == "true"; do
+ sleep 1;
+done
+dcop $appid Document-0 setOutputMimeType "application/x-$appname" || exit 1
+dcop $appid Document-0 saveAs $tmpnativefile || exit 1
+test -f $tmpnativefile || exit 1
+
+# Unpack everything
+rm -rf oasisregtest-orig
+mkdir oasisregtest-orig
+rm -rf oasisregtest-final
+mkdir oasisregtest-final
+cd oasisregtest-orig || exit 1
+unzip $origfile || exit 1
+cd ..
+cd oasisregtest-final || exit 1
+unzip $tmpnativefile || exit 1
+cd ..
+# Validate OASIS format
+cd oasisregtest-oasis || exit 1
+if test "$checkoasis" = "1"; then
+ if type -p oasislint >/dev/null 2>&1; then
+ for f in content.xml styles.xml meta.xml settings.xml; do
+ echo "Checking $f..." ; oasislint $f
+ done
+ fi
+ # Hide warning about non-standard oasis attribute being used for a kword-specific feature
+ perl -pi -e 's/style:frame-behavior-on-new-page="[^\"]*"//' content.xml
+ if type -p oasislint-strict >/dev/null 2>&1; then
+ for f in content.xml styles.xml meta.xml settings.xml; do
+ echo "Checking $f strict..." && oasislint-strict $f
+ done
+ fi
+fi
+cd ..
+
+# Some fixups - kword specific
+# 1) the name of the main text frameset changes, no big deal, so adjust in orig
+# 2) modification time obviously changed, remove it
+# 3) paragraph direction, text color and relativetextsize are now explicitly saved, hide them from the diff
+perl -pi -e 's/\"Text Frameset 1\"/\"Main Text Frameset\"/;s,<WEIGHT value="48" />,<WEIGHT value="40" />,' oasisregtest-orig/maindoc.xml
+perl -pi -e 's/<FLOW dir="L"/<FLOW/ ; s/relativetextsize="0.58" //' oasisregtest-final/maindoc.xml
+perl -pi -e 's/modificationDate=\"[0-9-T:]*\"//; $_="" if (/<COLOR blue=\"0\" red=\"0\" green=\"0\" \/>/);' oasisregtest-final/maindoc.xml oasisregtest-orig/maindoc.xml
+
+# Some generic fixups: documentinfo was updated by the automated 'editing'
+perl -pi -e '$_ = "" if (/<editing-cycles>/ || /<date>/ || /<full-name>/ || /<company>/ || /<email>/ )' oasisregtest-final/documentinfo.xml oasisregtest-orig/documentinfo.xml
+
+# Compare initial and final "native format" files
+diff -urp oasisregtest-orig oasisregtest-final 2>&1 | tee oasisdiff | less
+
+echo "See oasisregtest-oasis for the OASIS xml files."
+echo "For a better diffing mechanism, launch xemacs and paste into a terminal:"
+echo "gnudoit '(ediff-files \"$PWD/oasisregtest-orig/maindoc.xml\" \"$PWD/oasisregtest-final/maindoc.xml\")'"
diff --git a/kword/toolbar/Makefile.am b/kword/toolbar/Makefile.am
new file mode 100644
index 00000000..bfa676d0
--- /dev/null
+++ b/kword/toolbar/Makefile.am
@@ -0,0 +1,3 @@
+kwordicondir = $(kde_datadir)/kword/icons
+kwordicon_ICON = AUTO
+
diff --git a/kword/toolbar/cr22-action-run_bounding.png b/kword/toolbar/cr22-action-run_bounding.png
new file mode 100644
index 00000000..11cfb60e
--- /dev/null
+++ b/kword/toolbar/cr22-action-run_bounding.png
Binary files differ
diff --git a/kword/toolbar/cr22-action-run_not.png b/kword/toolbar/cr22-action-run_not.png
new file mode 100644
index 00000000..2efd5d70
--- /dev/null
+++ b/kword/toolbar/cr22-action-run_not.png
Binary files differ
diff --git a/kword/toolbar/cr22-action-run_skip.png b/kword/toolbar/cr22-action-run_skip.png
new file mode 100644
index 00000000..2650d09c
--- /dev/null
+++ b/kword/toolbar/cr22-action-run_skip.png
Binary files differ
diff --git a/kword/toolbar/cr22-action-sl_addentry.png b/kword/toolbar/cr22-action-sl_addentry.png
new file mode 100644
index 00000000..92fe7d3b
--- /dev/null
+++ b/kword/toolbar/cr22-action-sl_addentry.png
Binary files differ
diff --git a/kword/toolbar/cr22-action-sl_addrecord.png b/kword/toolbar/cr22-action-sl_addrecord.png
new file mode 100644
index 00000000..211d083b
--- /dev/null
+++ b/kword/toolbar/cr22-action-sl_addrecord.png
Binary files differ
diff --git a/kword/toolbar/cr22-action-sl_delentry.png b/kword/toolbar/cr22-action-sl_delentry.png
new file mode 100644
index 00000000..e9213557
--- /dev/null
+++ b/kword/toolbar/cr22-action-sl_delentry.png
Binary files differ
diff --git a/kword/toolbar/cr22-action-sl_delrecord.png b/kword/toolbar/cr22-action-sl_delrecord.png
new file mode 100644
index 00000000..40a08ecc
--- /dev/null
+++ b/kword/toolbar/cr22-action-sl_delrecord.png
Binary files differ